diff --git a/frontend/src/lib/components/DateTimeInput.svelte b/frontend/src/lib/components/DateTimeInput.svelte index 41803c1962..73afa53676 100644 --- a/frontend/src/lib/components/DateTimeInput.svelte +++ b/frontend/src/lib/components/DateTimeInput.svelte @@ -6,6 +6,8 @@ export let autofocus: boolean | null = false export let useDropdown: boolean = false + export let minDate: string | undefined = undefined + export let maxDate: string | undefined = undefined let date: string | undefined = undefined let time: string | undefined = undefined @@ -53,9 +55,9 @@ let randomId = 'datetarget-' + Math.random().toString(36).substring(7) -
+
- +
- + {#if markdownTooltip} +
+ +
+ {:else} + + {/if} + {#if documentationLink}
diff --git a/frontend/src/lib/components/apps/components/inputs/AppDateInput.svelte b/frontend/src/lib/components/apps/components/inputs/AppDateInput.svelte index 96d63b89aa..9f2308712f 100644 --- a/frontend/src/lib/components/apps/components/inputs/AppDateInput.svelte +++ b/frontend/src/lib/components/apps/components/inputs/AppDateInput.svelte @@ -38,7 +38,7 @@ result: undefined as string | undefined }) - $: handleDefault(resolvedConfig.defaultValue) + $: !value && handleDefault(resolvedConfig.defaultValue) function formatDate(dateString: string, formatString: string = 'dd.MM.yyyy') { if (formatString === '') { @@ -98,7 +98,7 @@ min={resolvedConfig.minDate} max={resolvedConfig.maxDate} placeholder="Type..." - class={twMerge(css?.input?.class, 'wm-date-input')} + class={twMerge('windmillapp w-full py-1.5 text-sm px-2', css?.input?.class, 'wm-date-input')} style={css?.input?.style ?? ''} /> {/if} diff --git a/frontend/src/lib/components/apps/components/inputs/AppDateTimeInput.svelte b/frontend/src/lib/components/apps/components/inputs/AppDateTimeInput.svelte new file mode 100644 index 0000000000..b12df32600 --- /dev/null +++ b/frontend/src/lib/components/apps/components/inputs/AppDateTimeInput.svelte @@ -0,0 +1,151 @@ + + +{#each Object.keys(components['datetimeinputcomponent'].initialData.configuration) as key (key)} + +{/each} + +{#each Object.keys(css ?? {}) as key (key)} + +{/each} + + + + +
+ {#if inputType === 'date'} + { + e.stopPropagation() + $selectedComponent = [id] + }} + minDate={resolvedConfig.minDateTime + ? formatDate(resolvedConfig.minDateTime, 'yyyy-MM-dd') + : undefined} + maxDate={resolvedConfig.maxDateTime + ? formatDate(resolvedConfig.maxDateTime, 'yyyy-MM-dd') + : undefined} + on:focus={() => ($selectedComponent = [id])} + /> + {/if} +
+
diff --git a/frontend/src/lib/components/apps/components/inputs/AppTimeInput.svelte b/frontend/src/lib/components/apps/components/inputs/AppTimeInput.svelte new file mode 100644 index 0000000000..60a888113f --- /dev/null +++ b/frontend/src/lib/components/apps/components/inputs/AppTimeInput.svelte @@ -0,0 +1,122 @@ + + +{#each Object.keys(components['timeinputcomponent'].initialData.configuration) as key (key)} + +{/each} + +{#each Object.keys(css ?? {}) as key (key)} + +{/each} + + + + + ($selectedComponent = [id])} + on:pointerdown|stopPropagation={() => ($selectedComponent = [id])} + type="time" + bind:value + min={resolvedConfig.minTime} + max={resolvedConfig.maxTime} + placeholder="Type..." + class={twMerge('windmillapp w-full py-1.5 text-sm px-2', css?.input?.class)} + style={css?.input?.style ?? ''} + /> + diff --git a/frontend/src/lib/components/apps/editor/component/Component.svelte b/frontend/src/lib/components/apps/editor/component/Component.svelte index 60e4f1a7c6..7749183b53 100644 --- a/frontend/src/lib/components/apps/editor/component/Component.svelte +++ b/frontend/src/lib/components/apps/editor/component/Component.svelte @@ -71,6 +71,8 @@ import AppS3FileInput from '../../components/inputs/AppS3FileInput.svelte' import AppAlert from '../../components/display/AppAlert.svelte' import AppDateSliderInput from '../../components/inputs/AppDateSliderInput.svelte' + import AppTimeInput from '../../components/inputs/AppTimeInput.svelte' + import AppDateTimeInput from '../../components/inputs/AppDateTimeInput.svelte' export let component: AppComponent export let selected: boolean @@ -494,6 +496,23 @@ customCss={component.customCss} {render} /> + {:else if component.type === 'timeinputcomponent'} + + {:else if component.type === 'datetimeinputcomponent'} + {:else if component.type === 'numberinputcomponent'} export type PasswordInputComponent = BaseComponent<'passwordinputcomponent'> export type EmailInputComponent = BaseComponent<'emailinputcomponent'> export type DateInputComponent = BaseComponent<'dateinputcomponent'> +export type TimeInputComponent = BaseComponent<'timeinputcomponent'> +export type DateTimeInputComponent = BaseComponent<'datetimeinputcomponent'> export type NumberInputComponent = BaseComponent<'numberinputcomponent'> export type CurrencyComponent = BaseComponent<'currencycomponent'> export type SliderComponent = BaseComponent<'slidercomponent'> @@ -291,6 +295,8 @@ export type TypedComponent = | AgChartsComponentEe | AlertComponent | DateSliderComponent + | TimeInputComponent + | DateTimeInputComponent export type AppComponent = BaseAppComponent & TypedComponent @@ -2314,12 +2320,14 @@ This is a paragraph. minDate: { type: 'static', value: '', - fieldType: 'date' + fieldType: 'date', + tooltip: 'The minimum date that can be selected. The format is: "yyyy-MM-dd"' }, maxDate: { type: 'static', value: '', - fieldType: 'date' + fieldType: 'date', + tooltip: 'The maximum date that can be selected. The format is: "yyyy-MM-dd"' }, defaultValue: { type: 'static', @@ -2330,8 +2338,125 @@ This is a paragraph. type: 'static', value: undefined, fieldType: 'text', - tooltip: 'See date-fns format for more information', - documentationLink: 'https://date-fns.org/v1.29.0/docs/format' + markdownTooltip: `### Output format +See date-fns format for more information. By default, it is 'dd.MM.yyyy' + +| Format | Result | Description | +| ----------- | ----------- | ----------- | +| DD | 01, 02, ..., 31 | Day of the month | +| D | 1, 2, ..., 31 | Day of the month | +| MM | 01, 02, ..., 12 | Month | +| MMM | Jan, Feb, ..., Dec | Month | +| MMMM | January, February, ..., December | Month | +| YYYY | 2021, 2022, ... | Year | +`, + + documentationLink: 'https://date-fns.org/v1.29.0/docs/format', + placeholder: 'dd.MM.yyyy' + } + } + } + }, + datetimeinputcomponent: { + name: 'Date & Time', + icon: CalendarClock, + documentationLink: `${documentationBaseUrl}/datetime_input`, + dims: '2:1-6:2' as AppComponentDimensions, + customCss: { + container: { class: '', style: '' } + }, + initialData: { + verticalAlignment: 'center', + componentInput: undefined, + configuration: { + displayPresets: { + type: 'static', + value: false, + fieldType: 'boolean', + tooltip: 'Display presets to select the date for example, in 1 week, in 1 month, etc.' + }, + minDateTime: { + type: 'static', + value: '', + fieldType: 'datetime', + tooltip: + 'The minimum date that can be selected. The format is the ISO 8601 format: "yyyy-MM-ddTHH:mm:ss:SSSZ", for example "2021-11-06T23:39:30.000Z", or toISOString() from a Date' + }, + maxDateTime: { + type: 'static', + value: '', + fieldType: 'datetime', + tooltip: + 'The maximum date that can be selected. The format is the ISO 8601 format: "yyyy-MM-ddTHH:mm:ss:SSSZ", for example "2021-11-06T23:39:30.000Z", or toISOString() from a Date' + }, + outputFormat: { + type: 'static', + value: undefined, + fieldType: 'text', + documentationLink: 'https://date-fns.org/v1.29.0/docs/format', + placeholder: 'dd.MM.yyyy HH:mm', + markdownTooltip: `### Output format +See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm' + +| Format | Result | Description | +| ----------- | ----------- | ----------- | +| DD | 01, 02, ..., 31 | Day of the month | +| D | 1, 2, ..., 31 | Day of the month | +| MM | 01, 02, ..., 12 | Month | +| MMM | Jan, Feb, ..., Dec | Month | +| MMMM | January, February, ..., December | Month | +| YYYY | 2021, 2022, ... | Year | +| HH | 00, 01, ..., 23 | Hours | +| mm | 00, 01, ..., 59 | Minutes | +| ss | 00, 01, ..., 59 | Seconds | + ` + }, + defaultValue: { + type: 'static', + value: undefined, + fieldType: 'datetime' + } + } + } + }, + timeinputcomponent: { + name: 'Time', + icon: Clock, + documentationLink: `${documentationBaseUrl}/time_input`, + dims: '2:1-3:1' as AppComponentDimensions, + customCss: { + input: { class: '', style: '' } + }, + initialData: { + verticalAlignment: 'center', + componentInput: undefined, + configuration: { + minTime: { + type: 'static', + value: '', + fieldType: 'time', + tooltip: + 'The minimum date that can be selected. If the time provided is not valid, it will set the output "validity" to false. The format is: "HH:mm"' + }, + maxTime: { + type: 'static', + value: '', + fieldType: 'time', + tooltip: + 'The maximum date that can be selected. If the time provided is not valid, it will set the output "validity" to false. The format is: "HH:mm"' + }, + defaultValue: { + type: 'static', + value: undefined, + fieldType: 'time' + }, + + ['24hFormat']: { + type: 'static', + value: true, + fieldType: 'boolean', + tooltip: + 'Use 24h format. Will change the format of the output of the component: HH:mm to hh:mm am/pm' } } } diff --git a/frontend/src/lib/components/apps/editor/component/sets.ts b/frontend/src/lib/components/apps/editor/component/sets.ts index 2800257481..d69961d027 100644 --- a/frontend/src/lib/components/apps/editor/component/sets.ts +++ b/frontend/src/lib/components/apps/editor/component/sets.ts @@ -43,6 +43,8 @@ const inputs: ComponentSet = { 'dateslidercomponent', 'rangecomponent', 'dateinputcomponent', + 'timeinputcomponent', + 'datetimeinputcomponent', 'fileinputcomponent', 's3fileinputcomponent', 'checkboxcomponent', diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/componentControlUtils.ts b/frontend/src/lib/components/apps/editor/componentsPanel/componentControlUtils.ts index a1d472fcaf..a4470e2e82 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/componentControlUtils.ts +++ b/frontend/src/lib/components/apps/editor/componentsPanel/componentControlUtils.ts @@ -105,6 +105,8 @@ export function getComponentControl(type: keyof typeof components): Array('AppViewerContext') @@ -80,8 +82,8 @@ {#if loading} {/if} - {#if tooltip} - + {#if tooltip || markdownTooltip} + {tooltip} {/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte index 05a3ad927f..be517a66b5 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte @@ -59,6 +59,8 @@ placeholder={meta?.['placeholder']} customTitle={meta?.['customTitle']} loading={meta?.['loading']} + documentationLink={meta?.['documentationLink']} + markdownTooltip={meta?.['markdownTooltip']} {displayType} {recomputeOnInputChanged} {showOnDemandOnlyToggle} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte index 3fc3e0f38b..9f6c027e4b 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte @@ -101,6 +101,7 @@ tooltip={config?.['tooltip']} fileUpload={config?.['fileUpload']} loading={config?.['loading']} + documentationLink={config?.['documentationLink']} {showOnDemandOnlyToggle} /> {/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte index 995ae0e7e1..9557af3a4e 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte @@ -20,6 +20,7 @@ import AgChartWizard from '$lib/components/wizards/AgChartWizard.svelte' import DBExplorerWizard from '$lib/components/wizards/DBExplorerWizard.svelte' import Label from '$lib/components/Label.svelte' + import DateTimeInput from '$lib/components/DateTimeInput.svelte' export let componentInput: StaticInput | undefined export let fieldType: InputType | undefined = undefined @@ -42,6 +43,10 @@