diff --git a/frontend/src/lib/components/apps/CreateApp.svelte b/frontend/src/lib/components/apps/CreateApp.svelte index 927bbf95fa..3a4d5e9f44 100644 --- a/frontend/src/lib/components/apps/CreateApp.svelte +++ b/frontend/src/lib/components/apps/CreateApp.svelte @@ -23,7 +23,8 @@ async function createApp() { const appJson: App = { grid: [], - title: 'New app' + title: 'New app', + unusedInlineScripts: [] } const policy = { diff --git a/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte b/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte index fd535c02d1..684e0e8ff2 100644 --- a/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte +++ b/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte @@ -1,5 +1,6 @@ diff --git a/frontend/src/lib/components/apps/components/table/AppTable.svelte b/frontend/src/lib/components/apps/components/table/AppTable.svelte index 3c0e8a7188..c62eb41f7a 100644 --- a/frontend/src/lib/components/apps/components/table/AppTable.svelte +++ b/frontend/src/lib/components/apps/components/table/AppTable.svelte @@ -32,12 +32,12 @@ let page = 1 const options = writable>({ - data: result, + data: [], columns: [], ...tableOptions }) - const table = createSvelteTable(options) + let table = createSvelteTable(options) const { worldStore, staticOutputs: staticOutputsStore } = getContext('AppEditorContext') @@ -91,12 +91,18 @@ $: outputs = $worldStore?.outputsById[id] as { selectedRow: Output } + + function rerender() { + table = createSvelteTable(options) + } + + $: result && rerender() - +
@@ -129,7 +135,7 @@ {/each} - {#each $table.getRowModel().rows as row, rowIndex} + {#each $table.getRowModel().rows as row, rowIndex (row.id)} toggleRow(row, rowIndex)} > - {#each row.getVisibleCells() as cell} + {#each row.getVisibleCells() as cell, index (index)} 0} - {#each actionButtons as props} + {#each actionButtons as props, actionIndex (actionIndex)} {#if !$userStore?.operator} @@ -77,7 +83,7 @@ {/if} {#if previewing} - + {:else} @@ -85,10 +91,10 @@ - -
+ +
{#if $appStore.grid} -
+
{/if} @@ -99,7 +105,7 @@ {/if}
- + diff --git a/frontend/src/lib/components/apps/editor/AppPreview.svelte b/frontend/src/lib/components/apps/editor/AppPreview.svelte index 0666778ee0..646783ac29 100644 --- a/frontend/src/lib/components/apps/editor/AppPreview.svelte +++ b/frontend/src/lib/components/apps/editor/AppPreview.svelte @@ -1,7 +1,7 @@ @@ -55,7 +75,6 @@ rowHeight={64} cols={columnConfiguration} fastStart={true} - throttleUpdate={50} on:pointerup={({ detail }) => { if (!$connectingInput.opened) { $selectedComponent = detail.id @@ -73,7 +92,7 @@ deleteComponent(gridComponent.data)} + on:delete={() => removeGridElement(gridComponent.data)} on:lock={() => { gridComponent = toggleFixed(gridComponent) }} diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte new file mode 100644 index 0000000000..fce564c8c4 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte @@ -0,0 +1,80 @@ + + +
+ Please choose a language: +
+ {#each Object.values(Script.language) as lang} + { + createInlineScriptByLanguage(lang, name) + }} + /> + {/each} + + { + createInlineScriptByLanguage(Script.language.DENO, name, 'pgsql') + }} + /> + { + createInlineScriptByLanguage(Script.language.DENO, name, 'mysql') + }} + /> +
+
diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte index 8269bd78fa..8287b28e01 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte @@ -1,15 +1,11 @@ -{#if componentInput.runnable && componentInput.runnable.type === 'runnableByName' && componentInput.runnable.inlineScript} - -{/if} + -{#if shouldDisplay} - {#if componentInput?.runnable?.type === 'runnableByName' && componentInput?.runnable?.inlineScript} -
-
- {#if componentInput?.runnable?.name !== undefined} - - {/if} -
- {#if validCode} - - - - {:else} - - - - {/if} - - -
-
- - {#if componentInput?.runnable?.type === 'runnableByName' && componentInput?.runnable?.inlineScript} -
- { - if ( - componentInput?.runnable?.type === 'runnableByName' && - componentInput?.runnable?.inlineScript - ) { - let schema = await inferInlineScriptSchema( - componentInput?.runnable?.inlineScript?.language, - componentInput.runnable.inlineScript.content, - componentInput.runnable.inlineScript.schema - ) - - componentInput.runnable.inlineScript.schema = schema - - componentInput = componentInput - } - }} - /> -
+
+
+ {#if name !== undefined} + + {/if} +
+ {#if validCode} + + + + {:else} + + + {/if} -
- {:else} -
- Please choose a language: -
- {#each Object.values(Script.language) as lang} - { - createInlineScriptByLanguage(lang, name) - }} - /> - {/each} - { - createInlineScriptByLanguage(Script.language.DENO, name, 'pgsql') - }} - /> - { - createInlineScriptByLanguage(Script.language.DENO, name, 'mysql') - }} - /> -
+
- {/if} -{/if} +
+ +
+ { + if (inlineScript) { + let schema = await inferInlineScriptSchema( + inlineScript?.language, + inlineScript.content, + inlineScript.schema + ) + inlineScript.schema = schema + inlineScript = inlineScript + } + }} + /> +
+
diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte new file mode 100644 index 0000000000..a25a0439ef --- /dev/null +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte @@ -0,0 +1,67 @@ + + +{#if componentInput?.runnable?.type === 'runnableByName' && componentInput?.runnable?.name !== undefined} + {#if componentInput.runnable.inlineScript} + { + componentInput = clearResultAppInput(componentInput) + }} + /> + {:else} + { + if (componentInput?.runnable?.type === 'runnableByName') { + componentInput.runnable.inlineScript = e.detail + } + }} + /> + {/if} +{:else if componentInput?.runnable?.type === 'runnableByPath' && componentInput?.runnable?.path} +
+
+ +
+
+ +
+
+{/if} diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte index b0ca39d442..e03e860d76 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte @@ -4,6 +4,7 @@ import SplitPanesWrapper from '$lib/components/splitPanes/SplitPanesWrapper.svelte' import { Pane } from 'svelte-splitpanes' import InlineScriptsPanelList from './InlineScriptsPanelList.svelte' + import InlineScriptEditorPanel from './InlineScriptEditorPanel.svelte' import InlineScriptEditor from './InlineScriptEditor.svelte' const { app } = getContext('AppEditorContext') @@ -18,8 +19,30 @@ {#each $app.grid as gridComponent, index (index)} {#if gridComponent.data.id === selectedScriptComponentId} - + + {/if} + + {#if gridComponent.data.type === 'tablecomponent'} + {#each gridComponent.data.actionButtons as actionButton, index (index)} + {#if actionButton.id === selectedScriptComponentId} + + {/if} + {/each} {/if} {/each} + {#if Array.isArray($app.unusedInlineScripts)} + {#each $app.unusedInlineScripts as unusedInlineScript, index (index)} + {#if unusedInlineScript.name === selectedScriptComponentId} + { + // remove the script from the array at the index + $app.unusedInlineScripts.splice(index, 1) + $app.unusedInlineScripts = [...$app.unusedInlineScripts] + }} + /> + {/if} + {/each} + {/if} diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte index 3bfebb84ad..856abb4d85 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte @@ -3,19 +3,36 @@ import { classNames } from '$lib/utils' import { getContext } from 'svelte' import type { AppInput } from '../../inputType' - import type { AppEditorContext } from '../../types' + import type { AppComponent, AppEditorContext } from '../../types' import PanelSection from '../settingsPanel/common/PanelSection.svelte' export let selectedScriptComponentId: string | undefined = undefined - const { app } = getContext('AppEditorContext') + const { app, selectedComponent } = getContext('AppEditorContext') - function selectInlineScript(id: string) { - selectedScriptComponentId = id + function selectInlineScript(id: string, subId?: string) { + selectedScriptComponentId = subId ? subId : id + $selectedComponent = id } - $: componentInlineScripts = $app.grid.reduce((acc, gridComponent) => { - const componentInput: AppInput = gridComponent.data.componentInput + $: runnablesByName = $app.grid.reduce((acc, gridComponent) => { + const component: AppComponent = gridComponent.data + + if (component.type === 'tablecomponent') { + component.actionButtons.forEach((actionButton) => { + if (actionButton.componentInput?.type === 'runnable') { + if (actionButton.componentInput.runnable?.type === 'runnableByName') { + acc.push({ + name: actionButton.componentInput.runnable.name, + id: gridComponent.id, + subId: actionButton.id + }) + } + } + }) + } + + const componentInput = component.componentInput if (componentInput?.type === 'runnable') { if (componentInput.runnable?.type === 'runnableByName') { @@ -27,13 +44,81 @@ } return acc }, []) + + $: runnablesByPath = $app.grid.reduce((acc, gridComponent) => { + const componentInput: AppInput = gridComponent.data.componentInput + + if (componentInput?.type === 'runnable') { + if (componentInput.runnable?.type === 'runnableByPath') { + acc.push({ + name: componentInput.runnable.path, + id: gridComponent.id + }) + } + } + return acc + }, []) + + // When seleced component changes, update selectedScriptComponentId + $: { + if (selectedComponent) { + selectedScriptComponentId = $selectedComponent + } + } - +
- {#if componentInlineScripts.length > 0} + {#if runnablesByName.length > 0}
- {#each componentInlineScripts as { name, id }, index (index)} + {#each runnablesByName as { name, id, subId }, index (index)} + +
selectInlineScript(id, subId)} + > + {name} +
+ {id} + {#if subId} + {subId} + {/if} +
+
+ {/each} +
+ {:else} +
No inline scripts
+ {/if} + + {#if Array.isArray($app.unusedInlineScripts) && $app.unusedInlineScripts.length > 0} +
+ {#each $app.unusedInlineScripts as unusedInlineScript, index (index)} + +
selectInlineScript(unusedInlineScript.name)} + > + {unusedInlineScript.name} + Unused +
+ {/each} +
+ {/if} +
+
+ + +
+ {#if runnablesByPath.length > 0} +
+ {#each runnablesByPath as { name, id }, index (index)}
+
No inline scripts
+
Add inline scripts to your app
+
+{:else if filteredItems.length === 0} {:else}
    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 ef5c8e0bb4..525a38fc2f 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte @@ -40,13 +40,19 @@ } } - function pickInlineScript(name: string, inlineScript: InlineScript) { - if (appInput.type === 'runnable') { + function pickInlineScript(name: string) { + const unusedInlineScriptIndex = $app.unusedInlineScripts?.findIndex( + (script) => script.name === name + ) + const unusedInlineScript = $app.unusedInlineScripts?.[unusedInlineScriptIndex] + if (appInput.type === 'runnable' && unusedInlineScript?.inlineScript) { appInput.runnable = { type: 'runnableByName', name, - inlineScript + inlineScript: unusedInlineScript.inlineScript } + + $app.unusedInlineScripts.splice(unusedInlineScriptIndex, 1) } } @@ -67,7 +73,10 @@ return acc }, [] as string[]) - while (names.includes(newScriptPath)) { + const unusedNames = Object.keys($app.unusedInlineScripts ?? {}) + + // Find a name that is not used by any other inline script + while (names.includes(newScriptPath) || unusedNames.includes(newScriptPath)) { newScriptPath = `inline_script_${++index}` } @@ -117,7 +126,12 @@
    {#if tab == 'inlinescripts'} - pickInlineScript('', e.detail)} /> + pickInlineScript(e.detail)} + inlineScripts={$app.unusedInlineScripts + ? $app.unusedInlineScripts.map((uis) => uis.name) + : []} + /> {:else if tab == 'workspacescripts'} pickScript(e.detail)} /> {:else if tab == 'workspaceflows'} diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts index e01837df35..5ad45b6d54 100644 --- a/frontend/src/lib/components/apps/types.ts +++ b/frontend/src/lib/components/apps/types.ts @@ -113,6 +113,10 @@ export type InlineScript = { export type App = { grid: GridItem[] title: string + unusedInlineScripts: Array<{ + name: string + inlineScript: InlineScript + }> } export type ConnectingInput = { diff --git a/frontend/src/lib/components/apps/utils.ts b/frontend/src/lib/components/apps/utils.ts index e3101bad83..ce603baf97 100644 --- a/frontend/src/lib/components/apps/utils.ts +++ b/frontend/src/lib/components/apps/utils.ts @@ -17,7 +17,7 @@ import { Calendar, ToggleLeft } from 'lucide-svelte' -import type { AppInput, AppInputs, InputType } from './inputType' +import type { AppInput, AppInputs, InputType, ResultAppInput } from './inputType' import type { AppComponent } from './types' export async function loadSchema( @@ -194,3 +194,9 @@ export function isScriptByPathDefined(appInput: AppInput | undefined): boolean { return false } + +export function clearResultAppInput(appInput: ResultAppInput): ResultAppInput { + appInput.runnable = undefined + appInput.fields = {} + return appInput +} diff --git a/frontend/src/routes/apps/get/[...path].svelte b/frontend/src/routes/apps/get/[...path].svelte index 00b69a94cc..4f77b3a241 100644 --- a/frontend/src/routes/apps/get/[...path].svelte +++ b/frontend/src/routes/apps/get/[...path].svelte @@ -9,6 +9,7 @@ @@ -41,7 +45,7 @@
    - +
    {/if}