From e4791c2b7e3a0e6b90c37bc1200f9cd0ab3b6845 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: Fri, 17 Feb 2023 20:20:28 +0100 Subject: [PATCH] feat(frontend): Add icon app component (#1207) * feat(frontend): Add icon app component * fix(frontend): Import only one icon at a time * fix(frontend): Handle file names correctly * feat(frontend): Use all arrow keys in popup navigation * fix(frontend): Close popup after icon select * fix(frontend): Position picker correctly * fix(frontend): Handle empty search --------- Co-authored-by: Ruben Fiszel --- frontend/package-lock.json | 27 ++--- frontend/package.json | 2 +- .../apps/components/AppDivider.svelte | 51 ++++++---- .../components/dataDisplay/AppIcon.svelte | 56 +++++++++++ .../apps/components/helpers/index.ts | 9 ++ .../components/apps/editor/Component.svelte | 82 +++++++++++++--- .../inputEditor/IconSelectInput.svelte | 98 +++++++++++++++++++ .../inputEditor/StaticInputEditor.svelte | 3 + frontend/src/lib/components/apps/inputType.ts | 2 + frontend/src/lib/components/apps/utils.ts | 12 +++ .../lib/components/common/popup/Popup.svelte | 68 ++++++++----- 11 files changed, 331 insertions(+), 79 deletions(-) create mode 100644 frontend/src/lib/components/apps/components/dataDisplay/AppIcon.svelte create mode 100644 frontend/src/lib/components/apps/components/helpers/index.ts create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/IconSelectInput.svelte diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 292be95784..8b3400f1c3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,7 +8,6 @@ "name": "windmill", "version": "1.64.0", "dependencies": { - "@canutin/svelte-currency-input": "^0.8.0", "@fortawesome/free-brands-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1", "@leeoniya/ufuzzy": "^0.9.1", @@ -19,6 +18,7 @@ "chartjs-plugin-zoom": "^2.0.0", "date-fns": "^2.29.3", "highlight.js": "^11.7.0", + "lucide-svelte": "^0.115.0", "monaco-editor": "0.33.0", "monaco-editor-workers": "0.33.0", "monaco-languageclient": "2.1.0", @@ -48,7 +48,6 @@ "eslint": "^8.28.0", "eslint-config-prettier": "^8.6.0", "eslint-plugin-svelte3": "^4.0.0", - "lucide-svelte": "^0.104.0", "openapi-typescript-codegen": "^0.23.0", "path-browserify": "^1.0.1", "postcss": "^8.4.18", @@ -206,11 +205,6 @@ "node": ">=4" } }, - "node_modules/@canutin/svelte-currency-input": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@canutin/svelte-currency-input/-/svelte-currency-input-0.8.0.tgz", - "integrity": "sha512-u/ywCjAQzBTU1GvoljNgVzA/xV6UjVXsFbe4KISxk3cZJOA3eN35qaGtNMJhWQ0JI+QbFjxv2I2nHbdzmmn1Nw==" - }, "node_modules/@csstools/selector-specificity": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", @@ -3865,10 +3859,9 @@ } }, "node_modules/lucide-svelte": { - "version": "0.104.0", - "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.104.0.tgz", - "integrity": "sha512-PhckIn28E571Kx2gs2SVh5gc0RlDge521AE63ce4c8gRUMYeo9USPUr80bt/26J5+8qce+hw1zRjx/ag2BqBgw==", - "dev": true, + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.115.0.tgz", + "integrity": "sha512-kR7XlwoSVjGX+jwOiHKjTCDMPcTKrsKGyYnJkgW55wyKmWAzfOSESDGuRHcfsRAIQgg133mDNtCm++S8V5rRjg==", "peerDependencies": { "svelte": "^3.49.0" } @@ -7284,11 +7277,6 @@ } } }, - "@canutin/svelte-currency-input": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@canutin/svelte-currency-input/-/svelte-currency-input-0.8.0.tgz", - "integrity": "sha512-u/ywCjAQzBTU1GvoljNgVzA/xV6UjVXsFbe4KISxk3cZJOA3eN35qaGtNMJhWQ0JI+QbFjxv2I2nHbdzmmn1Nw==" - }, "@csstools/selector-specificity": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", @@ -9843,10 +9831,9 @@ } }, "lucide-svelte": { - "version": "0.104.0", - "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.104.0.tgz", - "integrity": "sha512-PhckIn28E571Kx2gs2SVh5gc0RlDge521AE63ce4c8gRUMYeo9USPUr80bt/26J5+8qce+hw1zRjx/ag2BqBgw==", - "dev": true, + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.115.0.tgz", + "integrity": "sha512-kR7XlwoSVjGX+jwOiHKjTCDMPcTKrsKGyYnJkgW55wyKmWAzfOSESDGuRHcfsRAIQgg133mDNtCm++S8V5rRjg==", "requires": {} }, "magic-string": { diff --git a/frontend/package.json b/frontend/package.json index 05526c3db5..ce75ee7391 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -33,7 +33,6 @@ "eslint": "^8.28.0", "eslint-config-prettier": "^8.6.0", "eslint-plugin-svelte3": "^4.0.0", - "lucide-svelte": "^0.104.0", "openapi-typescript-codegen": "^0.23.0", "path-browserify": "^1.0.1", "postcss": "^8.4.18", @@ -71,6 +70,7 @@ "chartjs-plugin-zoom": "^2.0.0", "date-fns": "^2.29.3", "highlight.js": "^11.7.0", + "lucide-svelte": "^0.115.0", "monaco-editor": "0.33.0", "monaco-editor-workers": "0.33.0", "monaco-languageclient": "2.1.0", diff --git a/frontend/src/lib/components/apps/components/AppDivider.svelte b/frontend/src/lib/components/apps/components/AppDivider.svelte index 91984389fc..928de5ea13 100644 --- a/frontend/src/lib/components/apps/components/AppDivider.svelte +++ b/frontend/src/lib/components/apps/components/AppDivider.svelte @@ -1,24 +1,41 @@ - - - - -
-
+
+ +
diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppIcon.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppIcon.svelte new file mode 100644 index 0000000000..9402e8f621 --- /dev/null +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppIcon.svelte @@ -0,0 +1,56 @@ + + + + + + + + + + {#if iconComponent} + + {/if} + + \ No newline at end of file diff --git a/frontend/src/lib/components/apps/components/helpers/index.ts b/frontend/src/lib/components/apps/components/helpers/index.ts new file mode 100644 index 0000000000..9aec864c40 --- /dev/null +++ b/frontend/src/lib/components/apps/components/helpers/index.ts @@ -0,0 +1,9 @@ +export { default as AlignWrapper } from './AlignWrapper.svelte' +export { default as DebouncedInput } from './DebouncedInput.svelte' +export { default as InputDefaultValue } from './InputDefaultValue.svelte' +export { default as InputValue } from './InputValue.svelte' +export { default as MissingConnectionWarning } from './MissingConnectionWarning.svelte' +export { default as NonRunnableComponent } from './NonRunnableComponent.svelte' +export { default as RefreshButton } from './RefreshButton.svelte' +export { default as RunnableComponent } from './RunnableComponent.svelte' +export { default as RunnableWrapper } from './RunnableWrapper.svelte' \ No newline at end of file diff --git a/frontend/src/lib/components/apps/editor/Component.svelte b/frontend/src/lib/components/apps/editor/Component.svelte index 717f3cff18..4a899d0026 100644 --- a/frontend/src/lib/components/apps/editor/Component.svelte +++ b/frontend/src/lib/components/apps/editor/Component.svelte @@ -17,6 +17,7 @@ Code2, SlidersHorizontal, PlusSquare, + Smile, DollarSign, SeparatorHorizontal, SeparatorVertical @@ -28,7 +29,7 @@ } /* How to add a new Svelte Component: - 1. add the the type to the union below + 1. add the type to the union below 2. add the component to the components record 3. add the comoonent to one of the components set (buttons, inputs, display) 4. add the component in the svelte if switch @@ -70,6 +71,7 @@ export type SelectComponent = BaseComponent<'selectcomponent'> export type CheckboxComponent = BaseComponent<'checkboxcomponent'> export type RadioComponent = BaseComponent<'radiocomponent'> + export type IconComponent = BaseComponent<'iconcomponent'> export type HorizontalDividerComponent = BaseComponent<'horizontaldividercomponent'> export type VerticalDividerComponent = BaseComponent<'verticaldividercomponent'> @@ -98,6 +100,7 @@ | FormButtonComponent | VegaLiteComponent | PlotlyComponent + | IconComponent | HorizontalDividerComponent | VerticalDividerComponent ) @@ -108,7 +111,7 @@ { name: string; icon: any; dims: `${number}:${number}-${number}:${number}`; data: AppComponent } > = { displaycomponent: { - name: 'Result', + name: 'Rich Result', icon: Monitor, dims: '2:8-6:8', data: { @@ -896,7 +899,7 @@ } }, dateinputcomponent: { - name: 'Date Input', + name: 'Date', icon: Calendar, dims: '2:1-3:1', data: { @@ -925,6 +928,44 @@ card: false } }, + iconcomponent: { + name: 'Icon', + icon: Smile, + dims: '1:3-1:2', + data: { + softWrap: false, + horizontalAlignment: 'center', + verticalAlignment: 'center', + id: '', + type: 'iconcomponent', + componentInput: undefined, + configuration: { + icon: { + type: 'static', + value: 'Smile', + fieldType: 'icon-select' + }, + color: { + type: 'static', + value: 'currentColor', + fieldType: 'text' + }, + size: { + type: 'static', + value: 24, + fieldType: 'number', + onlyStatic: true + }, + strokeWidth: { + type: 'static', + value: 2, + fieldType: 'number', + onlyStatic: true + } + }, + card: false + } + }, horizontaldividercomponent: { name: 'Divider X', icon: SeparatorHorizontal, @@ -939,14 +980,14 @@ type: 'static', value: 2, fieldType: 'number', - onlyStatic: true, + onlyStatic: true }, color: { type: 'static', value: '#00000060', fieldType: 'text', - onlyStatic: true, - }, + onlyStatic: true + } }, card: false } @@ -965,18 +1006,18 @@ type: 'static', value: 2, fieldType: 'number', - onlyStatic: true, + onlyStatic: true }, color: { type: 'static', value: '#00000060', fieldType: 'text', - onlyStatic: true, - }, + onlyStatic: true + } }, card: false } - }, + } } const inputs: ComponentSet = { @@ -1002,18 +1043,19 @@ const display: ComponentSet = { title: 'Display', components: [ + 'textcomponent', + 'iconcomponent', 'htmlcomponent', + 'tablecomponent', + 'barchartcomponent', + 'piechartcomponent', 'vegalitecomponent', 'plotlycomponent', - 'textcomponent', - 'tablecomponent', - 'piechartcomponent', - 'barchartcomponent', 'scatterchartcomponent', 'timeseriescomponent', 'displaycomponent', 'horizontaldividercomponent', - 'verticaldividercomponent', + 'verticaldividercomponent' ] } @@ -1329,6 +1371,13 @@ "backgroundColor": "orange" } ]` + }, + iconcomponent: { + deno: `export async function main() { + return "smile"; +}`, + python3: `def main(): + return "smile"` } } as const @@ -1375,6 +1424,7 @@ import PlotlyHtml from '../components/dataDisplay/PlotlyHtml.svelte' import { defaultAlignement } from './componentsPanel/componentDefaultProps' import AppRangeInput from '../components/numberInputs/AppRangeInput.svelte' + import AppIcon from '../components/dataDisplay/AppIcon.svelte' import AppCurrencyInput from '../components/numberInputs/AppCurrencyInput.svelte' import AppDivider from '../components/AppDivider.svelte' @@ -1535,6 +1585,8 @@ {:else if component.type === 'rangecomponent'} + {:else if component.type === 'iconcomponent'} + {/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/IconSelectInput.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/IconSelectInput.svelte new file mode 100644 index 0000000000..93a17b2fd1 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/IconSelectInput.svelte @@ -0,0 +1,98 @@ + + + +{#if anchor} + +
+ {#if loading} +
+ +
+ {:else} + {#if filteredItems} + +
+ {#each filteredItems as {label, icon}} + {@const formatedLabel = formatName(label)} + + {:else} +
+ No icons match your search +
+ {/each} +
+ {:else} +
+ Couldn't load options +
+ {/if} + {/if} +
+
+{/if} \ No newline at end of file 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 208186811f..9ee9129132 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte @@ -7,6 +7,7 @@ import JsonEditor from './JsonEditor.svelte' import { getContext } from 'svelte' import type { AppEditorContext } from '$lib/components/apps/types' + import IconSelectInput from './IconSelectInput.svelte' export let componentInput: StaticAppInput | undefined @@ -32,6 +33,8 @@ {/each} + {:else if componentInput.fieldType === 'icon-select'} + {:else if componentInput.fieldType === 'object'} {#if componentInput?.format?.startsWith('resource-')} | AppInputSpec<'array', string[], 'text'> | AppInputSpec<'array', string[], 'textarea'> | AppInputSpec<'array', number[], 'number'> diff --git a/frontend/src/lib/components/apps/utils.ts b/frontend/src/lib/components/apps/utils.ts index c8205d0b7b..b64d470ecf 100644 --- a/frontend/src/lib/components/apps/utils.ts +++ b/frontend/src/lib/components/apps/utils.ts @@ -200,3 +200,15 @@ export function getAllScriptNames(app: App): string[] { return [...names, ...unusedNames, ...backgroundNames] } + +function clearAndUpper(text: string) { + return text.replace(/-/, "").toUpperCase(); +} + +export function toPascalCase(text: string) { + return text.replace(/(^\w|-\w)/g, clearAndUpper); +} + +export function toKebabCase(text: string) { + return text.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); +} diff --git a/frontend/src/lib/components/common/popup/Popup.svelte b/frontend/src/lib/components/common/popup/Popup.svelte index f79c8419f2..53019d8017 100644 --- a/frontend/src/lib/components/common/popup/Popup.svelte +++ b/frontend/src/lib/components/common/popup/Popup.svelte @@ -1,41 +1,40 @@ @@ -139,9 +155,9 @@ aria-expanded={$stateMachine.currentState !== 'closed'} > {#if $stateMachine.currentState !== 'closed'} -
+
- +
{/if}