From a4b773af294554c5787f02ebda363c8d9a3eff1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= <43071496+adam-kov@users.noreply.github.com> Date: Tue, 21 Feb 2023 19:14:55 +0100 Subject: [PATCH] feat(frontend): Add image app component (#1213) * fix(frontend): hard type app component config * feat(frontend): Add image app component * feat(frontend): Add upload app input type --- frontend/src/lib/common.ts | 7 ++ .../components/dataDisplay/AppImage.svelte | 34 ++++++++ .../apps/components/helpers/InputValue.svelte | 4 +- .../components/apps/editor/Component.svelte | 74 +++++++++++++++--- .../componentsPanel/componentStaticValues.ts | 3 +- .../settingsPanel/AlignmentEditor.svelte | 78 ++++++++++--------- .../settingsPanel/InputsSpecEditor.svelte | 5 ++ .../settingsPanel/InputsSpecsEditor.svelte | 14 +++- .../inputEditor/UploadInputEditor.svelte | 26 +++++++ frontend/src/lib/components/apps/gridUtils.ts | 9 ++- frontend/src/lib/components/apps/inputType.ts | 42 +++++++--- frontend/src/lib/components/apps/types.ts | 20 +++-- .../common/fileInput/FileInput.svelte | 13 +++- 13 files changed, 257 insertions(+), 72 deletions(-) create mode 100644 frontend/src/lib/components/apps/components/dataDisplay/AppImage.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/UploadInputEditor.svelte diff --git a/frontend/src/lib/common.ts b/frontend/src/lib/common.ts index d569838d70..d7d06b3c98 100644 --- a/frontend/src/lib/common.ts +++ b/frontend/src/lib/common.ts @@ -27,6 +27,13 @@ export type Schema = { export type Meta = { ownerKind: OwnerKind; owner: string; name: string } +type Enumerate = Acc['length'] extends N + ? Acc[number] + : Enumerate + +/** An inclusive range of integer numbers */ +export type IntRange = F | Exclude, Enumerate> | T + export function pathToMeta(path: string): Meta { const splitted = path.split('/') let ownerKind: OwnerKind diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppImage.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppImage.svelte new file mode 100644 index 0000000000..4c2ca28961 --- /dev/null +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppImage.svelte @@ -0,0 +1,34 @@ + + + + + + + +{altText} diff --git a/frontend/src/lib/components/apps/components/helpers/InputValue.svelte b/frontend/src/lib/components/apps/components/helpers/InputValue.svelte index 65174c4cf4..4f6f53c07e 100644 --- a/frontend/src/lib/components/apps/components/helpers/InputValue.svelte +++ b/frontend/src/lib/components/apps/components/helpers/InputValue.svelte @@ -1,7 +1,7 @@ - -
- {#if component.horizontalAlignment} -
-
Horizontal
-
- - - - - - - - - - - +{#if component.horizontalAlignment || component.verticalAlignment} + +
+ {#if component.horizontalAlignment} +
+
Horizontal
+
+ + + + + + + + + + + +
-
- {/if} - {#if component.type !== 'formcomponent' && component.verticalAlignment} -
-
Vertical
-
- - - - - - - - - - - + {/if} + {#if component.type !== 'formcomponent' && component.verticalAlignment} +
+
Vertical
+
+ + + + + + + + + + + +
-
- {/if} -
-
+ {/if} +
+ +{/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecEditor.svelte index ef55d87cc9..dceb0962fc 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecEditor.svelte @@ -4,12 +4,14 @@ EvalAppInput, RowAppInput, StaticAppInput, + UploadAppInput, UserAppInput } from '../../inputType' import ConnectedInputEditor from './inputEditor/ConnectedInputEditor.svelte' import EvalInputEditor from './inputEditor/EvalInputEditor.svelte' import RowInputEditor from './inputEditor/RowInputEditor.svelte' import StaticInputEditor from './inputEditor/StaticInputEditor.svelte' + import UploadInputEditor from './inputEditor/UploadInputEditor.svelte' export let id: string export let componentInput: @@ -18,6 +20,7 @@ | UserAppInput | RowAppInput | EvalAppInput + | UploadAppInput export let hasRows: boolean = false @@ -29,6 +32,8 @@ {:else if componentInput.type === 'eval'} +{:else if componentInput.type === 'upload'} + {:else if componentInput.type === 'user'} Field's value is set by the user {/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte index 444d0677db..94837c3748 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte @@ -1,7 +1,7 @@ + + { + if(componentInput) { + componentInput.value = componentInput?.fileUpload?.multiple + ? detail + : detail?.[0] + } + }} +> + + + + + \ No newline at end of file diff --git a/frontend/src/lib/components/apps/gridUtils.ts b/frontend/src/lib/components/apps/gridUtils.ts index a707570159..5f21554a60 100644 --- a/frontend/src/lib/components/apps/gridUtils.ts +++ b/frontend/src/lib/components/apps/gridUtils.ts @@ -7,9 +7,12 @@ const Breakpoints = { lg: 1024 } +const WIDE_GRID_COLUMNS = 12 as const; +const NARROW_GRID_COLUMNS = 3 as const; + const columnConfiguration: ColumnConfiguration = [ - [Breakpoints.lg, 12], - [Breakpoints.sm, 3] + [Breakpoints.lg, WIDE_GRID_COLUMNS], + [Breakpoints.sm, NARROW_GRID_COLUMNS] ] const gridColumns = columnConfiguration.map((value) => value[1]) @@ -51,6 +54,8 @@ function enableDrag(component: GridItem): GridItem { export { gridColumns, + WIDE_GRID_COLUMNS, + NARROW_GRID_COLUMNS, columnConfiguration, disableDrag, enableDrag, diff --git a/frontend/src/lib/components/apps/inputType.ts b/frontend/src/lib/components/apps/inputType.ts index 96aa491251..3949a21b1d 100644 --- a/frontend/src/lib/components/apps/inputType.ts +++ b/frontend/src/lib/components/apps/inputType.ts @@ -35,7 +35,11 @@ export type UserInput = { value: U | undefined } - +// Input can be uploaded with a file selector +export type UploadInput = { + type: 'upload' + value: string +} export type EvalInput = { type: 'eval' @@ -88,6 +92,7 @@ type AppInputSpec = ( | UserInput | RowInput | EvalInput + | UploadInput | ResultInput | TemplateInput ) & @@ -96,7 +101,28 @@ type AppInputSpec = ( type InputConfiguration = { fieldType: T subFieldType?: V - format?: string | undefined + format?: string | undefined, + fileUpload?: { + /** Use `*` to accept anything. */ + accept: string + /** + * Controls if user is allowed to select multiple files. + * @default false + */ + multiple?: boolean + /** + * Controls if the uploaded file(s) will be returned as `Base64` strings. + * @default false + */ + base64?: boolean + } +} + +type StaticOptions = { + /** + * One of the keys of `staticValues` from `lib/components/apps/editor/componentsPanel/componentStaticValues` + */ + optionValuesKey: keyof typeof staticValues } export type AppInput = @@ -111,12 +137,7 @@ 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<'array', string[], 'text'> | AppInputSpec<'array', string[], 'textarea'> @@ -126,9 +147,7 @@ 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) export type RowAppInput = Extract export type StaticAppInput = Extract @@ -136,5 +155,6 @@ export type ConnectedAppInput = Extract export type UserAppInput = Extract export type ResultAppInput = Extract export type EvalAppInput = Extract +export type UploadAppInput = Extract export type AppInputs = Record diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts index 88cc54a74c..f4d47317d3 100644 --- a/frontend/src/lib/components/apps/types.ts +++ b/frontend/src/lib/components/apps/types.ts @@ -10,6 +10,7 @@ import type { EvalAppInput, RowAppInput, StaticAppInput, + UploadAppInput, UserAppInput } from './inputType' import type { World } from './rx' @@ -23,16 +24,25 @@ export type Aligned = { verticalAlignment: VerticalAlignment } +export interface GeneralAppInput { + onlyStatic?: boolean + evaluatedValue?: boolean + tooltip?: string +} + export interface BaseAppComponent extends Partial { id: ComponentID componentInput: AppInput | undefined configuration: Record< string, - (StaticAppInput | ConnectedAppInput | UserAppInput | RowAppInput | EvalAppInput) & { - onlyStatic?: boolean - evaluatedValue?: boolean - tooltip?: string - } + GeneralAppInput & ( + StaticAppInput + | ConnectedAppInput + | UserAppInput + | RowAppInput + | EvalAppInput + | UploadAppInput + ) > card: boolean | undefined customCss?: Record {#if !hideIcon && !files} - + {/if} {#if files}
-
Selected file{files.length > 1 ? 's' : ''}:
+ +
+ Selected file{files.length > 1 ? 's' : ''}: +
+
    {#each files as {name}, i}