diff --git a/frontend/src/lib/components/RunChart.svelte b/frontend/src/lib/components/RunChart.svelte index fe1ac4a536..2d04cde1b8 100644 --- a/frontend/src/lib/components/RunChart.svelte +++ b/frontend/src/lib/components/RunChart.svelte @@ -16,7 +16,6 @@ } from 'chart.js' import type { CompletedJob } from '$lib/gen' import { createEventDispatcher } from 'svelte' - import { json } from 'svelte-highlight/languages' export let jobs: CompletedJob[] | undefined = [] diff --git a/frontend/src/lib/components/TemplateEditor.svelte b/frontend/src/lib/components/TemplateEditor.svelte index b698fa2fda..f570a20a71 100644 --- a/frontend/src/lib/components/TemplateEditor.svelte +++ b/frontend/src/lib/components/TemplateEditor.svelte @@ -359,6 +359,17 @@ languages.setLanguageConfiguration('template', conf) + meditor.defineTheme('myTheme', { + base: 'vs', + inherit: true, + rules: [], + colors: { + 'editorLineNumber.foreground': '#999', + 'editorGutter.background': '#F9FAFB' + } + }) + meditor.setTheme('myTheme') + let divEl: HTMLDivElement | null = null let editor: meditor.IStandaloneCodeEditor let model: meditor.ITextModel @@ -428,7 +439,7 @@ lineNumbers: 'off', fontSize, suggestOnTriggerCharacters: true, - lineDecorationsWidth: 24 + lineDecorationsWidth: 14 }) const stdLib = { content: libStdContent, filePath: 'es5.d.ts' } diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppBarChart.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppBarChart.svelte index 094fce1937..51a99dc6c1 100644 --- a/frontend/src/lib/components/apps/components/dataDisplay/AppBarChart.svelte +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppBarChart.svelte @@ -1,5 +1,5 @@ - + {#if result} - + {#if lineChart} + + {:else} + + {/if} {/if} diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppHtml.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppHtml.svelte new file mode 100644 index 0000000000..5c9390df03 --- /dev/null +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppHtml.svelte @@ -0,0 +1,28 @@ + + + + +
{ + e?.preventDefault() + }} + class="h-full relative w-full overflow-hidden" + > + {@html result ?? 'No html'} +
+
+
diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppPieChart.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppPieChart.svelte index d3f94ff52c..56d916a4fb 100644 --- a/frontend/src/lib/components/apps/components/dataDisplay/AppPieChart.svelte +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppPieChart.svelte @@ -1,5 +1,5 @@ - + {#if result} - + {#if doughnut} + + {:else} + + {/if} {/if} diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppScatterChart.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppScatterChart.svelte new file mode 100644 index 0000000000..d4bb7e09da --- /dev/null +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppScatterChart.svelte @@ -0,0 +1,72 @@ + + + + {#if result} + + {/if} + diff --git a/frontend/src/lib/components/apps/components/dataDisplay/AppTimeseries.svelte b/frontend/src/lib/components/apps/components/dataDisplay/AppTimeseries.svelte new file mode 100644 index 0000000000..b253b6d68a --- /dev/null +++ b/frontend/src/lib/components/apps/components/dataDisplay/AppTimeseries.svelte @@ -0,0 +1,90 @@ + + + + + + {#if result} + + {/if} + diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte index 84c4bf0c74..2ae2f11e34 100644 --- a/frontend/src/lib/components/apps/editor/AppEditor.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte @@ -156,7 +156,7 @@ -
+
@@ -171,7 +171,7 @@
- + {#if $selectedComponent !== undefined} {:else} diff --git a/frontend/src/lib/components/apps/editor/ComponentEditor.svelte b/frontend/src/lib/components/apps/editor/ComponentEditor.svelte index 5e4ee72b31..d6a3cadd30 100644 --- a/frontend/src/lib/components/apps/editor/ComponentEditor.svelte +++ b/frontend/src/lib/components/apps/editor/ComponentEditor.svelte @@ -15,6 +15,9 @@ import DateInputComponent from '../components/dateInputs/AppDateInput.svelte' import ComponentHeader from './ComponentHeader.svelte' import AppForm from '../components/form/AppForm.svelte' + import AppScatterChart from '../components/dataDisplay/AppScatterChart.svelte' + import AppTimeseries from '../components/dataDisplay/AppTimeseries.svelte' + import AppHtml from '../components/dataDisplay/AppHtml.svelte' export let component: AppComponent export let selected: boolean @@ -35,12 +38,18 @@ {/if}
{ + if ($mode === 'preview') { + e?.stopPropagation() + } + }} class={classNames( - 'border cursor-pointer h-full bg-white', + 'border h-full bg-white', selected && $mode !== 'preview' ? 'border-blue-500' : 'border-white', !selected && $mode !== 'preview' && !component.card ? 'border-gray-100' : '', $mode !== 'preview' && !$connectingInput.opened ? 'hover:border-blue-500' : '', component.softWrap ? '' : 'overflow-auto', + $mode != 'preview' ? 'cursor-pointer' : '', 'relative z-auto' )} > @@ -56,6 +65,24 @@ bind:componentInput={component.componentInput} bind:staticOutputs={$staticOutputs[component.id]} /> + {:else if component.type === 'timeseriescomponent'} + + {:else if component.type === 'htmlcomponent'} + + {:else if component.type === 'scatterchartcomponent'} + {:else if component.type === 'piechartcomponent'} = { '4:1-4:1': ['textcomponent'], '2:1-2:1': ['buttoncomponent'], + '2:2-2:2': ['htmlcomponent'], '4:2-4:2': [ 'checkboxcomponent', 'textinputcomponent', @@ -30,7 +31,13 @@ 'dateinputcomponent' ], '3:5-6:5': ['formcomponent'], - '4:12-4:12': ['barchartcomponent', 'piechartcomponent', 'displaycomponent'], + '4:12-4:12': [ + 'timeseriescomponent', + 'barchartcomponent', + 'piechartcomponent', + 'displaycomponent', + 'scatterchartcomponent' + ], '3:10-6:12': ['tablecomponent'] } // Finds the key that is associated with the component type and extracts the dimensions from it diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/data.ts b/frontend/src/lib/components/apps/editor/componentsPanel/data.ts index cd1ccee96c..101f15a29f 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/data.ts +++ b/frontend/src/lib/components/apps/editor/componentsPanel/data.ts @@ -179,6 +179,24 @@ const buttons: ComponentSet = { const display: ComponentSet = { title: 'Display', components: [ + { + softWrap: false, + id: 'htmlcomponent', + type: 'htmlcomponent', + componentInput: { + type: 'static', + fieldType: 'template', + value: ` +
+ Hello \${ctx.username} +
+`, + }, + configuration: {}, + card: false + }, { softWrap: true, horizontalAlignment: 'left', @@ -187,7 +205,7 @@ const display: ComponentSet = { type: 'textcomponent', componentInput: { type: 'static', - fieldType: 'textarea', + fieldType: 'template', value: 'Hello ${ctx.username}', }, configuration: { @@ -260,19 +278,17 @@ const display: ComponentSet = { optionValuesKey: 'chartThemeOptions', value: 'theme1' }, - labels: { + doughnutStyle: { type: 'static', - value: ['First', 'Second', 'Third'], - fieldType: 'array', - subFieldType: 'text', + onlyStatic: true, + fieldType: 'boolean', + value: false } }, componentInput: { type: 'static', - fieldType: 'array', - subFieldType: 'number', - value: [25, 50, 25], - + fieldType: 'object', + value: { data: [25, 50, 25], labels: ['Pie', 'Charts', '<3'] } }, card: true }, @@ -287,20 +303,93 @@ const display: ComponentSet = { optionValuesKey: 'chartThemeOptions', value: 'theme1' }, - labels: { + line: { type: 'static', + onlyStatic: true, + fieldType: 'boolean', + value: false + } - fieldType: 'array', - subFieldType: 'text', - value: ['Lorem ipsum', 'Lorem ipsum', 'Lorem ipsum'] + }, + componentInput: { + type: 'static', + fieldType: 'object', + value: { data: [25, 50, 25], labels: ['Bar', 'Charts', '<3'] } + }, + card: true + }, + { + id: 'scatterchartcomponent', + type: 'scatterchartcomponent', + configuration: {}, + componentInput: { + type: 'static', + fieldType: 'array', + subFieldType: 'object', + value: [{ + label: 'foo', + data: [ + { x: 25, y: 50 }, + { x: 23, y: 23 }, + { x: 12, y: 37 } + ], + backgroundColor: 'rgb(255, 12, 137)' + }, + { + label: 'foobar', + data: [ + { x: 32, y: 32 }, + { x: 25, y: 42 }, + { x: 3, y: 27 } + ], + backgroundColor: 'orange' + }] + }, + card: true + }, + { + id: 'timeseriescomponent', + type: 'timeseriescomponent', + configuration: { + logarithmicScale: { + type: 'static', + onlyStatic: true, + fieldType: 'boolean', + value: false } }, componentInput: { type: 'static', fieldType: 'array', - subFieldType: 'number', - value: [25, 50, 25], - + subFieldType: 'object', + value: [{ + label: 'foo', + data: [{ + x: '2021-11-06 23:39:30', + y: 50 + }, { + x: '2021-11-07 01:00:28', + y: 60 + }, { + x: '2021-11-07 09:00:28', + y: 20 + }], + backgroundColor: 'rgb(255, 12, 137)' + }, + { + label: 'foobar', + data: [{ + x: '2021-11-06 23:39:30', + y: 20 + }, { + x: '2021-11-07 01:00:28', + y: 13 + }, { + x: '2021-11-07 09:00:28', + y: 45 + }], + backgroundColor: 'orange' + }] }, card: true }, @@ -315,7 +404,8 @@ const display: ComponentSet = { }, configuration: {}, card: false - } + }, + ] } diff --git a/frontend/src/lib/components/apps/editor/contextPanel/ContextPanel.svelte b/frontend/src/lib/components/apps/editor/contextPanel/ContextPanel.svelte index a1050fc7cf..6aa18ab0e4 100644 --- a/frontend/src/lib/components/apps/editor/contextPanel/ContextPanel.svelte +++ b/frontend/src/lib/components/apps/editor/contextPanel/ContextPanel.svelte @@ -26,7 +26,7 @@ } function getComponentNameById(componentId: string) { - const component = $app.grid.find((c) => c.data.id === componentId) + const component = $app.grid.find((c) => c?.data?.id === componentId) if (component?.data.type) { return displayData[component?.data.type].name diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte index 51f6c749c5..7a05e2b11c 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte @@ -7,11 +7,13 @@ import { emptySchema } from '$lib/utils' import { createEventDispatcher, getContext } from 'svelte' import { fly } from 'svelte/transition' + import { defaultCode } from '../../editorUtils' import type { AppEditorContext } from '../../types' export let name: string + export let id: string - const { appPath } = getContext('AppEditorContext') + const { appPath, app } = getContext('AppEditorContext') const dispatch = createEventDispatcher() async function inferInlineScriptSchema( @@ -33,8 +35,12 @@ path: string, subkind: 'pgsql' | 'mysql' | undefined = undefined ) { + const componentType = $app.grid.find((c) => c.data.id === id)?.data?.type + const fullPath = `${appPath}/inline-script/${path}` - const content = initialCode(language, Script.kind.SCRIPT, subkind ?? 'flow') + const content = + defaultCode(componentType, language) ?? + initialCode(language, Script.kind.SCRIPT, subkind ?? 'flow') let schema: Schema = emptySchema() diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte index 9233a5525e..5fd43393d5 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte @@ -61,6 +61,7 @@ /> {:else} { if ( diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte index e4446cf222..40a5b17e23 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte @@ -44,16 +44,17 @@
{#if componentInput.value} {#each componentInput.value as value, index (index)} -
+
-
+
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte index 26859fe1b7..a69ba38602 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte @@ -10,7 +10,7 @@ const { onchange } = getContext('AppEditorContext') - $: if (componentInput.fieldType == 'textarea' && componentInput.type == 'static') { + $: if (componentInput.fieldType == 'template' && componentInput.type == 'static') { //@ts-ignore componentInput.type = 'template' componentInput['eval'] = componentInput.value @@ -24,7 +24,7 @@ {#if componentInput.fieldType !== 'any'}
onchange?.()} bind:selected={componentInput.type}> - {#if componentInput.fieldType === 'textarea'} + {#if componentInput.fieldType === 'template'} {brackets}  diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte index a6beaaa0ea..b4c6dd0e71 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte @@ -123,7 +123,7 @@ declare const ${k} = ${JSON.stringify(v)}; {:else if component.componentInput.type === 'template' && component.componentInput !== undefined}
- +
{:else if component.componentInput.type === 'connected' && component.componentInput !== undefined} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte index e59fff5ff0..74a24a86a0 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte @@ -15,9 +15,11 @@ $: code && parseJson() -
- +
+
+ +
+ {#if error != ''} + {error} + {/if}
-{#if error != ''} - {error} -{/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte index d5596a9f54..5b068932e5 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte @@ -103,6 +103,16 @@ acc.push(componentInput.runnable.name) } + if (componentInput.type === 'tablecomponent') { + componentInput.actionButtons.forEach((actionButton) => { + if (actionButton.componentInput?.type === 'runnable') { + if (actionButton.componentInput.runnable?.type === 'runnableByName') { + acc.push(actionButton.componentInput.runnable.name) + } + } + }) + } + return acc }, [] as string[]) diff --git a/frontend/src/lib/components/apps/editorUtils.ts b/frontend/src/lib/components/apps/editorUtils.ts new file mode 100644 index 0000000000..e1be0d2fc9 --- /dev/null +++ b/frontend/src/lib/components/apps/editorUtils.ts @@ -0,0 +1,3 @@ +export function defaultCode(component: string, language: string): string | undefined { + return undefined +} \ No newline at end of file diff --git a/frontend/src/lib/components/apps/inputType.ts b/frontend/src/lib/components/apps/inputType.ts index cb8106fbd2..9e71a09168 100644 --- a/frontend/src/lib/components/apps/inputType.ts +++ b/frontend/src/lib/components/apps/inputType.ts @@ -4,6 +4,7 @@ import type { InlineScript } from './types' export type InputType = | 'text' | 'textarea' + | 'template' | 'number' | 'boolean' | 'select' @@ -91,6 +92,7 @@ type InputConfiguration = { export type AppInput = | AppInputSpec<'text', string> | AppInputSpec<'textarea', string> + | AppInputSpec<'template', string> | AppInputSpec<'number', number> | AppInputSpec<'boolean', boolean> | AppInputSpec<'date', string> diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts index 763c078ca0..3ef9787276 100644 --- a/frontend/src/lib/components/apps/types.ts +++ b/frontend/src/lib/components/apps/types.ts @@ -20,6 +20,8 @@ export type TextInputComponent = BaseComponent<'textinputcomponent'> export type PasswordInputComponent = BaseComponent<'passwordinputcomponent'> export type DateInputComponent = BaseComponent<'dateinputcomponent'> export type NumberInputComponent = BaseComponent<'numberinputcomponent'> +export type HtmlComponent = BaseComponent<'htmlcomponent'> +export type TimeseriesComponent = BaseComponent<'timeseriescomponent'> export type ButtonComponent = BaseComponent<'buttoncomponent'> & { recomputeIds: string[] | undefined } @@ -31,6 +33,7 @@ export type FormComponent = BaseComponent<'formcomponent'> & { export type RunFormComponent = BaseComponent<'runformcomponent'> export type BarChartComponent = BaseComponent<'barchartcomponent'> export type PieChartComponent = BaseComponent<'piechartcomponent'> +export type ScatterChartComponent = BaseComponent<'scatterchartcomponent'> export type TableComponent = BaseComponent<'tablecomponent'> & { actionButtons: (BaseAppComponent & ButtonComponent)[] } @@ -72,11 +75,14 @@ export type AppComponent = BaseAppComponent & | DateInputComponent | NumberInputComponent | BarChartComponent + | TimeseriesComponent + | HtmlComponent | TableComponent | TextComponent | TableComponent | ButtonComponent | PieChartComponent + | ScatterChartComponent | ImageComponent | InputComponent | SelectComponent diff --git a/frontend/src/lib/components/apps/utils.ts b/frontend/src/lib/components/apps/utils.ts index d51ce0e23f..a65578f923 100644 --- a/frontend/src/lib/components/apps/utils.ts +++ b/frontend/src/lib/components/apps/utils.ts @@ -17,7 +17,9 @@ import { Type, Lock, Calendar, - ToggleLeft + ToggleLeft, + GripHorizontal, + Code2 } from 'lucide-svelte' import type { AppInput, InputType, ResultAppInput, StaticAppInput } from './inputType' import type { AppComponent } from './types' @@ -93,9 +95,21 @@ export const displayData: Record