From dfa9e333aa9c991e8cdff6eef2282782b75a0ef9 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 21 Mar 2023 18:22:12 +0100 Subject: [PATCH] feat(apps): add action on form/button/formbutton --- .../apps/components/buttons/AppButton.svelte | 21 +- .../apps/components/buttons/AppForm.svelte | 34 ++-- .../components/buttons/AppFormButton.svelte | 40 ++-- .../apps/components/display/AppImage.svelte | 18 +- .../components/helpers/ResolveConfig.svelte | 34 ++++ .../components/helpers/RunnableWrapper.svelte | 57 ++++-- .../lib/components/apps/editor/appUtils.ts | 101 ++++++++-- .../apps/editor/component/components.ts | 177 +++++++++-------- .../componentsPanel/ComponentList.svelte | 1 - .../componentsPanel/componentStaticValues.ts | 27 --- .../ArrayStaticInputEditor.svelte | 36 ++-- .../settingsPanel/InputsSpecEditor.svelte | 183 +++++++++--------- .../settingsPanel/InputsSpecsEditor.svelte | 18 +- .../OneOfInputSpecsEditor.svelte | 56 ++++++ .../inputEditor/StaticInputEditor.svelte | 25 ++- .../triggerLists/ComponentTriggerList.svelte | 1 - frontend/src/lib/components/apps/inputType.ts | 17 +- frontend/src/lib/components/apps/types.ts | 9 +- 18 files changed, 519 insertions(+), 336 deletions(-) create mode 100644 frontend/src/lib/components/apps/components/helpers/ResolveConfig.svelte delete mode 100644 frontend/src/lib/components/apps/editor/componentsPanel/componentStaticValues.ts create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte diff --git a/frontend/src/lib/components/apps/components/buttons/AppButton.svelte b/frontend/src/lib/components/apps/components/buttons/AppButton.svelte index 116b705e93..e21a498820 100644 --- a/frontend/src/lib/components/apps/components/buttons/AppButton.svelte +++ b/frontend/src/lib/components/apps/components/buttons/AppButton.svelte @@ -4,13 +4,13 @@ import type { AppInput } from '../../inputType' import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types' import AlignWrapper from '../helpers/AlignWrapper.svelte' - import InputValue from '../helpers/InputValue.svelte' import type RunnableComponent from '../helpers/RunnableComponent.svelte' import RunnableWrapper from '../helpers/RunnableWrapper.svelte' import { loadIcon } from '../icon' import { twMerge } from 'tailwind-merge' import { initConfig, initOutput } from '../../editor/appUtils' - import { components, configurationKeys } from '../../editor/component' + import { components } from '../../editor/component' + import ResolveConfig from '../helpers/ResolveConfig.svelte' export let id: string export let componentInput: AppInput | undefined @@ -111,26 +111,27 @@ } -{#each configurationKeys['buttoncomponent'] as key (key)} - {/each} + + | undefined = undefined let isLoading: boolean = false @@ -58,11 +54,14 @@ $: css = concatCustomCss($app.css?.formcomponent, customCss) - - - - - +{#each Object.keys(components['formcomponent'].initialData.configuration) as key (key)} + +{/each} @@ -110,10 +108,10 @@ on:click={() => { runnableComponent?.runComponent() }} - {size} - {color} + size={resolvedConfig.size} + color={resolvedConfig.color} > - {labelValue} + {resolvedConfig.label} {/if} diff --git a/frontend/src/lib/components/apps/components/buttons/AppFormButton.svelte b/frontend/src/lib/components/apps/components/buttons/AppFormButton.svelte index 94ca3b97ca..4ed6b99cf7 100644 --- a/frontend/src/lib/components/apps/components/buttons/AppFormButton.svelte +++ b/frontend/src/lib/components/apps/components/buttons/AppFormButton.svelte @@ -13,7 +13,9 @@ import Portal from 'svelte-portal' import Modal from '$lib/components/common/modal/Modal.svelte' import { concatCustomCss } from '../../utils' - import { initOutput } from '../../editor/appUtils' + import { initConfig, initOutput } from '../../editor/appUtils' + import { components } from '../../editor/component' + import ResolveConfig from '../helpers/ResolveConfig.svelte' export let id: string export let componentInput: AppInput | undefined @@ -32,12 +34,8 @@ loading: false }) - let labelValue: string = '' - let color: ButtonType.Color - let size: ButtonType.Size + let resolvedConfig = initConfig(components['formbuttoncomponent'].initialData.configuration) let runnableComponent: RunnableComponent - let disabled: boolean | undefined = undefined - let setTab: Array<{ id: string; index: number }> | undefined = undefined let isLoading: boolean = false let ownClick: boolean = false @@ -71,21 +69,19 @@ $: css = concatCustomCss($app?.css?.formbuttoncomponent, customCss) - - - - - +{#each Object.keys(components['formbuttoncomponent'].initialData.configuration) as key (key)} + +{/each} { @@ -106,7 +102,7 @@ forceSchemaDisplay={true} runnableClass="!block" {outputs} - {setTab} + doOnSuccess={resolvedConfig.onSuccess} >
@@ -151,15 +147,15 @@
{errorsMessage}
{/if} diff --git a/frontend/src/lib/components/apps/components/display/AppImage.svelte b/frontend/src/lib/components/apps/components/display/AppImage.svelte index e06088c4fb..9763817f1f 100644 --- a/frontend/src/lib/components/apps/components/display/AppImage.svelte +++ b/frontend/src/lib/components/apps/components/display/AppImage.svelte @@ -2,14 +2,11 @@ import { getContext } from 'svelte' import { twMerge } from 'tailwind-merge' import { initConfig, initOutput } from '../../editor/appUtils' - import { components, configurationKeys } from '../../editor/component' - import type { staticValues } from '../../editor/componentsPanel/componentStaticValues' + import { components, selectOptions } from '../../editor/component' import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types' import { concatCustomCss } from '../../utils' - import InputValue from '../helpers/InputValue.svelte' import Loader from '../helpers/Loader.svelte' - - type FitOption = (typeof staticValues)['objectFitOptions'][number] + import ResolveConfig from '../helpers/ResolveConfig.svelte' export let id: string export let configuration: RichConfigurations @@ -17,7 +14,7 @@ export let render: boolean const { app, worldStore } = getContext('AppViewerContext') - const fit: Record = { + const fit: Record = { cover: 'object-cover', contain: 'object-contain', fill: 'object-fill' @@ -31,8 +28,13 @@ $: css = concatCustomCss($app.css?.imagecomponent, customCss) -{#each configurationKeys['imagecomponent'] as key (key)} - +{#each Object.keys(components['imagecomponent'].initialData.configuration) as key (key)} + {/each} {#if render} diff --git a/frontend/src/lib/components/apps/components/helpers/ResolveConfig.svelte b/frontend/src/lib/components/apps/components/helpers/ResolveConfig.svelte new file mode 100644 index 0000000000..ced01cfec9 --- /dev/null +++ b/frontend/src/lib/components/apps/components/helpers/ResolveConfig.svelte @@ -0,0 +1,34 @@ + + +{#if configuration?.type == 'oneOf' && resolvedConfig?.type == 'oneOf'} + {@const choice = resolvedConfig.selected} + {#each Object.keys(configuration.configuration?.[choice] ?? {}) as nestedKey (nestedKey)} + {#if resolvedConfig.configuration?.[choice] != undefined} + + {/if} + {/each} +{:else} + +{/if} diff --git a/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte b/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte index 7383b61875..22e13db40a 100644 --- a/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte +++ b/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte @@ -7,6 +7,7 @@ import NonRunnableComponent from './NonRunnableComponent.svelte' import RunnableComponent from './RunnableComponent.svelte' import { goto } from '$app/navigation' + import { sendUserToast } from '$lib/utils' export let componentInput: AppInput | undefined export let id: string @@ -19,9 +20,21 @@ export let forceSchemaDisplay: boolean = false export let runnableClass = '' export let runnableStyle = '' - export let gotoUrl: string | undefined = undefined - export let gotoNewTab: boolean | undefined = undefined - export let setTab: Array<{ id: string; index: number }> | undefined = undefined + export let doOnSuccess: + | { + selected: 'gotoUrl' | 'none' | 'setTab' | 'sendToast' + configuration: { + gotoUrl: { url: string | undefined; newTab: boolean | undefined } + setTab: { + setTab: { id: string; index: number }[] | undefined + } + sendToast: { + message: string | undefined + } + } + } + | undefined = undefined + export let render: boolean export let recomputeIds: string[] = [] export let outputs: { result: Output; loading: Output } @@ -46,19 +59,35 @@ } export function onSuccess() { - if (Array.isArray(setTab)) { - setTab.forEach((tab) => { - const { id, index } = tab - $componentControl[id].setTab?.(index) - }) - } + if (!doOnSuccess) return - if (gotoUrl && gotoUrl != '' && result?.error == undefined) { - if (gotoNewTab) { - window.open(gotoUrl, '_blank') - } else { - goto(gotoUrl) + if (doOnSuccess.selected == 'none') return + + if (doOnSuccess.selected == 'setTab') { + if (Array.isArray(doOnSuccess.configuration.setTab.setTab)) { + doOnSuccess.configuration.setTab?.setTab?.forEach((tab) => { + if (tab) { + const { id, index } = tab + $componentControl[id].setTab?.(index) + } + }) } + } else if ( + doOnSuccess.selected == 'gotoUrl' && + doOnSuccess.configuration.gotoUrl.url && + doOnSuccess.configuration.gotoUrl.url != '' + ) { + if (doOnSuccess.configuration.gotoUrl.newTab) { + window.open(doOnSuccess.configuration.gotoUrl.url, '_blank') + } else { + goto(doOnSuccess.configuration.gotoUrl.url) + } + } else if ( + doOnSuccess.selected == 'sendToast' && + doOnSuccess.configuration.sendToast.message && + doOnSuccess.configuration.sendToast.message != '' + ) { + sendUserToast(doOnSuccess.configuration.sendToast.message) } if (recomputeIds) { diff --git a/frontend/src/lib/components/apps/editor/appUtils.ts b/frontend/src/lib/components/apps/editor/appUtils.ts index c0fd463112..dece748199 100644 --- a/frontend/src/lib/components/apps/editor/appUtils.ts +++ b/frontend/src/lib/components/apps/editor/appUtils.ts @@ -5,8 +5,7 @@ import type { ConnectingInput, EditorBreakpoint, FocusedGrid, - GridItem, - StaticRichConfigurations + GridItem } from '../types' import { ccomponents, @@ -14,7 +13,7 @@ import { getRecommendedDimensionsByComponent, type AppComponent, type BaseComponent, - type TypedComponent + type InitialAppComponent } from './component' import { gridColumns } from '../gridUtils' import { allItems } from '../utils' @@ -94,8 +93,6 @@ export function getAllRecomputeIdsForComponent(app: App, id: string) { } export function createNewGridItem(grid: GridItem[], id: string, data: AppComponent): GridItem { - console.log('INSERT X') - const newComponent = { fixed: false, x: 0, @@ -135,24 +132,45 @@ export function getGridItems(app: App, focusedGrid: FocusedGrid | undefined): Gr } } +function cleanseValue(key: string, value: { type: 'eval' | 'static'; value?: any; expr?: string }) { + if (!value) { + return [key, undefined] + } + if (value.type === 'static') { + return [key, { type: value.type, value: value.value }] + } else { + return [key, { type: value.type, expr: value.expr }] + } +} export function appComponentFromType( type: T ): (id: string) => BaseAppComponent & BaseComponent { return (id: string) => { - const init = ccomponents[type].initialData + const init = JSON.parse(JSON.stringify(ccomponents[type].initialData)) as InitialAppComponent return { type, //TODO remove tooltip and onlyStatic from there configuration: Object.fromEntries( Object.entries(init.configuration).map(([key, value]) => { - if (value.ctype === undefined) { - if (value.type === 'static') { - return [key, { type: value.type, value: value.value }] - } else if (value.type === 'eval') { - return [key, { type: value.type, expr: value.expr }] - } + if (value.type != 'oneOf') { + return cleanseValue(key, value) + } else { + return [ + key, + { + type: value.type, + selected: value.selected, + configuration: Object.fromEntries( + Object.entries(value.configuration).map(([key, val]) => [ + key, + Object.fromEntries( + Object.entries(val).map(([key, val]) => cleanseValue(key, val)) + ) + ]) + ) + } + ] } - return [key, value] }) ), componentInput: init.componentInput, @@ -370,16 +388,61 @@ export function initOutput>( ) as Outputtable } -export function initConfig>( +export function initConfig< + T extends Record< + string, + | StaticAppInput + | EvalAppInput + | { + type: 'oneOf' + selected: string + configuration: Record> + } + > +>( r: T ): { - [Property in keyof T]: T[Property] extends StaticAppInput ? T[Property]['value'] | undefined : any + [Property in keyof T]: T[Property] extends StaticAppInput + ? T[Property]['value'] | undefined + : T[Property] extends { type: 'oneOf' } + ? { + type: 'oneOf' + selected: keyof T[Property]['configuration'] + configuration: { + [Choice in keyof T[Property]['configuration']]: { + [IT in keyof T[Property]['configuration'][Choice]]: T[Property]['configuration'][Choice][IT] extends StaticAppInput + ? T[Property]['configuration'][Choice][IT]['value'] | undefined + : undefined + } + } + } + : undefined } { - return Object.fromEntries( - Object.entries(r).map(([key, value]) => - value.type == 'static' ? [key, undefined] : [key, undefined] + return JSON.parse( + JSON.stringify( + Object.fromEntries( + Object.entries(r).map(([key, value]) => + value.type == 'static' + ? [key, undefined] + : value.type == 'oneOf' + ? [ + key, + { + selected: value.selected, + type: 'oneOf', + configuration: Object.fromEntries( + Object.entries(value.configuration).map(([choice, config]) => [ + choice, + initConfig(config) + ]) + ) + } + ] + : [key, undefined] + ) + ) as any ) - ) as any + ) } export function expandGriditem( diff --git a/frontend/src/lib/components/apps/editor/component/components.ts b/frontend/src/lib/components/apps/editor/component/components.ts index cd65645fe2..fb6b770017 100644 --- a/frontend/src/lib/components/apps/editor/component/components.ts +++ b/frontend/src/lib/components/apps/editor/component/components.ts @@ -1,5 +1,7 @@ import type { IntRange } from '../../../../common' import type { NARROW_GRID_COLUMNS, WIDE_GRID_COLUMNS } from '../../gridUtils' +import { BUTTON_COLORS } from '../../../common' + import { defaultAlignement } from '../componentsPanel/componentDefaultProps' import { BarChart4, @@ -187,6 +189,80 @@ export interface InitialAppComponent extends Partial { panes?: number[] } +const buttonColorOptions = [...BUTTON_COLORS] + +export const selectOptions = { + buttonColorOptions, + tabsKindOptions: ['tabs', 'sidebar', 'invisibleOnView'], + buttonSizeOptions: ['xs', 'sm', 'md', 'lg', 'xl'], + tableSearchOptions: ['By Component', 'By Runnable', 'Disabled'], + chartThemeOptions: ['theme1', 'theme2', 'theme3'], + textStyleOptions: ['Title', 'Subtitle', 'Body', 'Label', 'Caption'], + currencyOptions: ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY', 'CNY', 'INR', 'BRL'], + localeOptions: [ + 'en-US', + 'en-GB', + 'en-IE', + 'de-DE', + 'fr-FR', + 'br-FR', + 'ja-JP', + 'pt-TL', + 'fr-CA', + 'en-CA' + ], + objectFitOptions: ['contain', 'cover', 'fill'], + splitPanelOptions: ['2', '3', '4'] +} + +const onSuccessClick = { + type: 'oneOf', + tooltip: 'Action to perform on success', + selected: 'none', + labels: { + none: 'Do nothing', + gotoUrl: 'Go to an url', + setTab: 'Set the tab of a tabs component', + sendToast: 'Display a toast notification' + }, + configuration: { + none: {}, + gotoUrl: { + url: { + tooltip: 'Go to the given url, absolute or relative', + fieldType: 'text', + type: 'static', + value: '', + placeholder: '/apps/get/foo' + }, + newTab: { + tooltip: 'Open the url in a new tab', + fieldType: 'boolean', + type: 'static', + value: true + } + }, + setTab: { + setTab: { + type: 'static', + value: [] as Array<{ id: string; index: number }>, + fieldType: 'array', + subFieldType: 'tab-select', + tooltip: 'Set the tabs id and index to go to on success' + } + }, + sendToast: { + message: { + tooltip: 'The message of the toast to diplay', + fieldType: 'text', + type: 'static', + value: '', + placeholder: 'Hello there' + } + } + } +} as const + export const components = { displaycomponent: { name: 'Rich Result', @@ -242,7 +318,7 @@ export const components = { fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'textStyleOptions', + selectOptions: selectOptions.textStyleOptions, value: 'Body' }, copyButton: { @@ -288,14 +364,14 @@ export const components = { fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'buttonColorOptions', + selectOptions: selectOptions.buttonColorOptions, value: 'blue' }, size: { fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'buttonSizeOptions', + selectOptions: selectOptions.buttonSizeOptions, value: 'xs' }, fillContainer: { @@ -309,18 +385,7 @@ export const components = { type: 'eval', expr: 'false' }, - goto: { - tooltip: 'Go to an url on success if not empty', - fieldType: 'text', - type: 'static', - value: '' - }, - gotoNewTab: { - tooltip: 'Go to an url on a new tab', - fieldType: 'boolean', - type: 'static', - value: true - }, + onSuccess: onSuccessClick, beforeIcon: { type: 'static', value: undefined, @@ -338,13 +403,6 @@ export const components = { value: false, fieldType: 'boolean', onlyStatic: true - }, - setTab: { - type: 'static', - value: [] as Array<{ id: string; index: number }>, - fieldType: 'array', - subFieldType: 'tab-select', - tooltip: 'Set the tabs id and index to go to on success' } } } @@ -367,13 +425,6 @@ export const components = { }, recomputeIds: undefined, configuration: { - setTab: { - type: 'static', - value: [] as Array<{ id: string; index: number }>, - fieldType: 'array', - subFieldType: 'tab-select', - tooltip: 'Set the tabs id and index to go to on success' - }, label: { type: 'static', value: 'Submit', @@ -384,21 +435,16 @@ export const components = { type: 'static', onlyStatic: true, value: 'dark', - optionValuesKey: 'buttonColorOptions' + selectOptions: selectOptions.buttonColorOptions }, size: { fieldType: 'select', type: 'static', value: 'xs', onlyStatic: true, - optionValuesKey: 'buttonSizeOptions' + selectOptions: selectOptions.buttonSizeOptions }, - goto: { - tooltip: 'Go to an url on success if not empty', - fieldType: 'text', - type: 'static', - value: '' - } + onSuccess: onSuccessClick } } }, @@ -431,21 +477,20 @@ export const components = { type: 'static', onlyStatic: true, value: 'dark', - optionValuesKey: 'buttonColorOptions' + selectOptions: buttonColorOptions }, size: { fieldType: 'select', type: 'static', value: 'xs', onlyStatic: true, - optionValuesKey: 'buttonSizeOptions' + selectOptions: selectOptions.buttonSizeOptions }, - setTab: { - type: 'static', - value: [] as Array<{ id: string; index: number }>, - fieldType: 'array', - subFieldType: 'tab-select', - tooltip: 'Set the tabs id and index to go to on success' + onSuccess: onSuccessClick, + disabled: { + fieldType: 'boolean', + type: 'eval', + expr: 'false' } } } @@ -463,7 +508,7 @@ export const components = { type: 'static', onlyStatic: true, fieldType: 'select', - optionValuesKey: 'chartThemeOptions', + selectOptions: selectOptions.chartThemeOptions, value: 'theme1' }, doughnutStyle: { @@ -493,7 +538,7 @@ export const components = { type: 'static', onlyStatic: true, fieldType: 'select', - optionValuesKey: 'chartThemeOptions', + selectOptions: selectOptions.chartThemeOptions, value: 'theme1' }, line: { @@ -732,7 +777,7 @@ Hello \${ctx.username} fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'tableSearchOptions', + selectOptions: selectOptions.tableSearchOptions, value: 'Disabled' } }, @@ -1026,14 +1071,14 @@ Hello \${ctx.username} value: 'USD', fieldType: 'select', onlyStatic: true, - optionValuesKey: 'currencyOptions' + selectOptions: selectOptions.currencyOptions }, locale: { type: 'static', value: 'en-US', fieldType: 'select', onlyStatic: true, - optionValuesKey: 'localeOptions', + selectOptions: selectOptions.localeOptions, tooltip: 'Currency format' } } @@ -1217,7 +1262,7 @@ Hello \${ctx.username} fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'tabsKindOptions', + selectOptions: selectOptions.tabsKindOptions, value: 'tabs' } }, @@ -1375,7 +1420,7 @@ Hello \${ctx.username} fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'objectFitOptions', + selectOptions: selectOptions.objectFitOptions, value: 'contain' }, altText: { @@ -1415,14 +1460,14 @@ Hello \${ctx.username} fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'buttonColorOptions', + selectOptions: buttonColorOptions, value: 'blue' }, size: { fieldType: 'select', type: 'static', onlyStatic: true, - optionValuesKey: 'buttonSizeOptions', + selectOptions: selectOptions.buttonSizeOptions, value: 'xs' }, fillContainer: { @@ -1555,30 +1600,6 @@ Hello \${ctx.username} } } as const -export const configurationKeys: Record = Object.fromEntries( - Object.entries(components) - .map(([k, v]) => [ - k, - [ - ...new Set( - Object.entries(v.initialData.configuration).flatMap(([k, v]) => { - if (!v.ctype) { - return [k] - } else if (v.ctype == 'oneOf') { - return [ - k, - ...Object.values(v.configuration ?? {}).flatMap((v) => Object.keys(v ?? {})) - ] - } else if (v.ctype == 'group') { - return Object.keys(v.configuration ?? {}) - } - }) - ) - ] - ]) - .filter(([k, v]) => v != undefined) -) - export const ccomponents: { [Property in keyof typeof components]: AppComponentConfig } = components diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte b/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte index 26c162daeb..fbbf6e1d93 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte +++ b/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte @@ -14,7 +14,6 @@ import { X } from 'lucide-svelte' import { push } from '$lib/history' import { flip } from 'svelte/animate' - import { Badge } from '$lib/components/common' const { app, selectedComponent, focusedGrid, worldStore } = getContext('AppViewerContext') diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/componentStaticValues.ts b/frontend/src/lib/components/apps/editor/componentsPanel/componentStaticValues.ts deleted file mode 100644 index 693be41f0b..0000000000 --- a/frontend/src/lib/components/apps/editor/componentsPanel/componentStaticValues.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BUTTON_COLORS } from '../../../common' - -const buttonColorOptions = [...BUTTON_COLORS] - -export const staticValues = { - buttonColorOptions, - tabsKindOptions: ['tabs', 'sidebar', 'invisibleOnView'], - buttonSizeOptions: ['xs', 'sm', 'md', 'lg', 'xl'], - tableSearchOptions: ['By Component', 'By Runnable', 'Disabled'], - chartThemeOptions: ['theme1', 'theme2', 'theme3'], - textStyleOptions: ['Title', 'Subtitle', 'Body', 'Label', 'Caption'], - currencyOptions: ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY', 'CNY', 'INR', 'BRL'], - localeOptions: [ - 'en-US', - 'en-GB', - 'en-IE', - 'de-DE', - 'fr-FR', - 'br-FR', - 'ja-JP', - 'pt-TL', - 'fr-CA', - 'en-CA' - ], - objectFitOptions: ['contain', 'cover', 'fill'], - splitPanelOptions: ['2', '3', '4'] -} as const diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte index 13b394d720..16b93b12e0 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte @@ -1,19 +1,19 @@ -{#if componentInput?.ctype == undefined} - {#if !(resourceOnly && (fieldType !== 'object' || !format?.startsWith('resource-')))} -
-
- - {shouldCapitalize ? capitalize(addWhitespaceBeforeCapitals(key)) : key} - {#if tooltip} - - {tooltip} - - {/if} - +{#if !(resourceOnly && (fieldType !== 'object' || !format?.startsWith('resource-')))} +
+
+ + {shouldCapitalize ? capitalize(addWhitespaceBeforeCapitals(key)) : key} + {#if tooltip} + + {tooltip} + + {/if} + -
- - {fieldType === 'array' && subFieldType - ? `${capitalize(fieldTypeToTsType(subFieldType))}[]` - : capitalize(fieldTypeToTsType(fieldType))} - +
+ + {fieldType === 'array' && subFieldType + ? `${capitalize(fieldTypeToTsType(subFieldType))}[]` + : capitalize(fieldTypeToTsType(fieldType))} + - {#if !onlyStatic && componentInput?.type && componentInput.type != 'eval'} - { - if (e.detail == 'connected' && !componentInput['connection']) { - $connectingInput = { - opened: true, - input: undefined, - hoveredComponent: undefined - } + {#if !onlyStatic && componentInput?.type && componentInput.type != 'eval'} + { + if (e.detail == 'connected' && !componentInput['connection']) { + $connectingInput = { + opened: true, + input: undefined, + hoveredComponent: undefined } - }} - > + } + }} + > + + + Static + + {#if userInputEnabled && !format?.startsWith('resource-')} - Static + User Input - {#if userInputEnabled && !format?.startsWith('resource-')} - - - User Input - - {/if} - {#if 'fileUpload' in componentInput} - - - Upload - - {/if} + {/if} + {#if 'fileUpload' in componentInput} - Connect + Upload - - {/if} -
+ {/if} + + + Connect + + + {/if}
- - {#if componentInput?.type === 'connected'} - - {:else if componentInput?.type === 'row'} - - {:else if componentInput?.type === 'static'} - - {:else if componentInput?.type === 'eval'} - - {:else if componentInput?.type === 'upload'} - - {:else if componentInput?.type === 'user'} - Field's value is set by the user - {/if}
- {/if} + + {#if componentInput?.type === 'connected'} + + {:else if componentInput?.type === 'row'} + + {:else if componentInput?.type === 'static'} + + {:else if componentInput?.type === 'eval'} + + {:else if componentInput?.type === 'upload'} + + {:else if componentInput?.type === 'user'} + Field's value is set by the user + {/if} +
{/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte index 3a2e6eb97c..eaab3626c2 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte @@ -2,6 +2,7 @@ import type { RichConfigurations } from '../../types' import InputsSpecEditor from './InputsSpecEditor.svelte' + import OneOfInputSpecsEditor from './OneOfInputSpecsEditor.svelte' export let id: string export let inputSpecs: RichConfigurations @@ -15,7 +16,19 @@ {#if inputSpecs}
{#each Object.keys(inputSpecsConfiguration) as k} - {#if inputSpecs[k] && inputSpecs[k]?.ctype == undefined} + {#if inputSpecs[k] && inputSpecs[k]?.type == 'oneOf'} + + {:else} {@const meta = inputSpecsConfiguration?.[k]} {/if} {/each} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte new file mode 100644 index 0000000000..94ae8b7b1f --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte @@ -0,0 +1,56 @@ + + +
+

{key} {tooltip}

+ +
+
+ {#each Object.keys(inputSpecsConfiguration?.[oneOf.selected] ?? {}) as nestedKey} + {@const config = inputSpecsConfiguration?.[oneOf.selected]?.[nestedKey]} + {#if config && oneOf.configuration[oneOf.selected]} + + {/if} + {/each} +
+
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 f479794e19..4722f83898 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte @@ -1,7 +1,6 @@ diff --git a/frontend/src/lib/components/apps/inputType.ts b/frontend/src/lib/components/apps/inputType.ts index 58edc95301..2b9a68ee3d 100644 --- a/frontend/src/lib/components/apps/inputType.ts +++ b/frontend/src/lib/components/apps/inputType.ts @@ -1,5 +1,4 @@ import type { ReadFileAs } from '../common/fileInput/model' -import type { staticValues } from './editor/componentsPanel/componentStaticValues' import type { InlineScript } from './types' export type InputType = @@ -122,11 +121,8 @@ type InputConfiguration = { } } -type StaticOptions = { - /** - * One of the keys of `staticValues` from `lib/components/apps/editor/componentsPanel/componentStaticValues` - */ - optionValuesKey: keyof typeof staticValues +export type StaticOptions = { + selectOptions: string[] | { value: string; label: string }[] } export type AppInput = @@ -141,12 +137,6 @@ export type AppInput = | AppInputSpec<'any', any> | AppInputSpec<'object', Record> | AppInputSpec<'object', string> - | (AppInputSpec<'select', string> & { - /** - * One of the keys of `staticValues` from `lib/components/apps/editor/componentsPanel/componentStaticValues` - */ - optionValuesKey: keyof typeof staticValues - }) | (AppInputSpec<'select', string> & StaticOptions) | AppInputSpec<'icon-select', string> | AppInputSpec<'color', string> @@ -158,9 +148,6 @@ export type AppInput = | AppInputSpec<'array', string[], 'time'> | AppInputSpec<'array', string[], 'datetime'> | AppInputSpec<'array', object[], 'object'> - | (AppInputSpec<'array', string[], 'select'> & { - optionValuesKey: keyof typeof staticValues - }) | (AppInputSpec<'array', string[], 'select'> & StaticOptions) | AppInputSpec<'array', object[], 'labeledresource'> | AppInputSpec<'labeledresource', object> diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts index 4992d0ab97..c44732527f 100644 --- a/frontend/src/lib/components/apps/types.ts +++ b/frontend/src/lib/components/apps/types.ts @@ -29,6 +29,7 @@ export type Aligned = { export interface GeneralAppInput { onlyStatic?: boolean tooltip?: string + placeholder?: string } export type ComponentCssProperty = { @@ -51,14 +52,14 @@ export type Configuration = export type StaticConfiguration = GeneralAppInput & StaticAppInput export type RichConfigurationT = - | (T & { ctype?: undefined }) + | (T & { type: AppInput['type'] }) | { - ctype: 'oneOf' + type: 'oneOf' selected: string + tooltip?: string + labels?: Record configuration: Record> } - | { ctype: 'group'; title: string; configuration: Record } - export type RichConfiguration = RichConfigurationT export type RichConfigurations = Record