mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 00:02:23 +00:00
fix(frontend): fix settings panel (#1323)
* fix(frontend): fix settings panel * fix(frontend): fix settings panel * fix(frontend): fix settings panel
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
import { getContext } from 'svelte'
|
||||
import type { App, AppViewerContext } from '../types'
|
||||
import { allItems } from '../utils'
|
||||
import { findGridItem } from './appUtils'
|
||||
import PanelSection from './settingsPanel/common/PanelSection.svelte'
|
||||
import ComponentPanel from './settingsPanel/ComponentPanel.svelte'
|
||||
import InputsSpecsEditor from './settingsPanel/InputsSpecsEditor.svelte'
|
||||
@@ -26,7 +27,7 @@
|
||||
if (x?.data?.actionButtons) {
|
||||
const tableAction = x.data.actionButtons.find((x) => x.id === id)
|
||||
if (tableAction) {
|
||||
return { item: tableAction, parent: x.data }
|
||||
return { item: { data: tableAction, id: tableAction.id }, parent: x.data.id }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,33 +58,31 @@
|
||||
</script>
|
||||
|
||||
{#if componentSettings}
|
||||
{#key componentSettings.item.id}
|
||||
<ComponentPanel
|
||||
parent={componentSettings.parent}
|
||||
bind:component={componentSettings.item.data}
|
||||
/>
|
||||
{#key componentSettings?.item?.id}
|
||||
<ComponentPanel bind:componentSettings />
|
||||
{/key}
|
||||
{:else if tableActionSettings}
|
||||
{#key tableActionSettings.item.id}
|
||||
{#key tableActionSettings?.item?.data?.id}
|
||||
<ComponentPanel
|
||||
parent={undefined}
|
||||
noGrid
|
||||
rowColumns
|
||||
bind:component={tableActionSettings.item}
|
||||
bind:componentSettings={tableActionSettings}
|
||||
duplicateMoveAllowed={false}
|
||||
onDelete={() => {
|
||||
if (tableActionSettings) {
|
||||
tableActionSettings.parent.actionButtons =
|
||||
tableActionSettings?.parent.actionButtons.filter(
|
||||
(c) => c.id !== tableActionSettings?.item.id
|
||||
const parent = findGridItem($app, tableActionSettings.parent)
|
||||
if (!parent) return
|
||||
|
||||
if (parent.data.type === 'tablecomponent') {
|
||||
parent.data.actionButtons = parent.data.actionButtons.filter(
|
||||
(x) => x.id !== tableActionSettings?.item.id
|
||||
)
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
{#if hiddenInlineScript}
|
||||
{:else if hiddenInlineScript}
|
||||
<div class="min-h-full flex flex-col divide-y">
|
||||
<PanelSection title={`Configuration`}>
|
||||
<div class="flex items-center">
|
||||
|
||||
+11
-2
@@ -13,12 +13,16 @@
|
||||
import InlineScriptEditor from './InlineScriptEditor.svelte'
|
||||
import { computeFields } from './utils'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppViewerContext } from '../../types'
|
||||
|
||||
export let componentInput: AppInput | undefined
|
||||
export let defaultUserInput = false
|
||||
export let id: string
|
||||
export let transformer: boolean
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
async function fork(path: string) {
|
||||
let { content, language, schema } = await getScriptByPath(path)
|
||||
if (componentInput && componentInput.type == 'runnable') {
|
||||
@@ -121,6 +125,7 @@
|
||||
componentInput?.runnable?.type === 'runnableByName'
|
||||
) {
|
||||
componentInput.runnable.inlineScript = e.detail
|
||||
$app = $app
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -139,6 +144,7 @@
|
||||
componentInput.runnable?.type === 'runnableByPath'
|
||||
) {
|
||||
fork(componentInput.runnable.path)
|
||||
$app = $app
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -157,8 +163,10 @@
|
||||
on:click={() => {
|
||||
flowPath = componentInput?.['runnable']?.path
|
||||
drawerFlowViewer.openDrawer()
|
||||
}}>Expand</Button
|
||||
}}
|
||||
>
|
||||
Expand
|
||||
</Button>
|
||||
<Button
|
||||
size="xs"
|
||||
startIcon={{ icon: faPen }}
|
||||
@@ -172,8 +180,9 @@
|
||||
endIcon={{ icon: faExternalLinkAlt }}
|
||||
target="_blank"
|
||||
href="/flows/get/{componentInput?.['runnable']?.path}?workspace_id={$workspaceStore}"
|
||||
>Details page</Button
|
||||
>
|
||||
Details page
|
||||
</Button>
|
||||
</div>
|
||||
<FlowPathViewer path={componentInput.runnable.path} />
|
||||
{:else}
|
||||
|
||||
+4
-3
@@ -20,9 +20,10 @@
|
||||
delete $runnableComponents[`bg_${index}`]
|
||||
}
|
||||
|
||||
$: gridItem = $selectedComponentInEditor
|
||||
? findGridItem($app, $selectedComponentInEditor?.split('_transformer')?.[0])
|
||||
: undefined
|
||||
$: gridItem =
|
||||
$selectedComponentInEditor && !$selectedComponentInEditor.startsWith('bg_')
|
||||
? findGridItem($app, $selectedComponentInEditor?.split('_')?.[0])
|
||||
: undefined
|
||||
|
||||
$: hiddenInlineScript = $app?.hiddenInlineScripts?.findIndex(
|
||||
(k_, index) => `bg_${index}` === $selectedComponentInEditor
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, AppViewerContext, RichConfiguration } from '../../types'
|
||||
import type { AppEditorContext, AppViewerContext, GridItem, RichConfiguration } from '../../types'
|
||||
import PanelSection from './common/PanelSection.svelte'
|
||||
import InputsSpecsEditor from './InputsSpecsEditor.svelte'
|
||||
import TableActions from './TableActions.svelte'
|
||||
@@ -26,10 +26,10 @@
|
||||
import { push } from '$lib/history'
|
||||
import Kbd from '$lib/components/common/kbd/Kbd.svelte'
|
||||
|
||||
export let component: AppComponent
|
||||
export let componentSettings: { item: GridItem; parent: string | undefined } | undefined =
|
||||
undefined
|
||||
export let rowColumns = false
|
||||
export let onDelete: (() => void) | undefined = undefined
|
||||
export let parent: string | undefined
|
||||
export let noGrid = false
|
||||
export let duplicateMoveAllowed = true
|
||||
|
||||
@@ -46,14 +46,16 @@
|
||||
push(history, $app)
|
||||
$selectedComponent = undefined
|
||||
$focusedGrid = undefined
|
||||
if (component && !noGrid) {
|
||||
let ids = deleteGridItem($app, component, parent, false)
|
||||
if (componentSettings?.item && !noGrid) {
|
||||
let ids = deleteGridItem($app, componentSettings?.item.data, componentSettings?.parent, false)
|
||||
for (const key of ids) {
|
||||
delete $runnableComponents[key]
|
||||
}
|
||||
}
|
||||
|
||||
delete $runnableComponents[component.id]
|
||||
if (componentSettings?.item?.data?.id) {
|
||||
delete $runnableComponents[componentSettings?.item?.data?.id]
|
||||
}
|
||||
$app = $app
|
||||
$runnableComponents = $runnableComponents
|
||||
|
||||
@@ -63,8 +65,14 @@
|
||||
let viewCssOptions = false
|
||||
|
||||
$: extraLib =
|
||||
component?.componentInput?.type === 'template' && $worldStore
|
||||
? buildExtraLib($worldStore?.outputsById ?? {}, component?.id, false, $state, false)
|
||||
componentSettings?.item?.data?.componentInput?.type === 'template' && $worldStore
|
||||
? buildExtraLib(
|
||||
$worldStore?.outputsById ?? {},
|
||||
componentSettings?.item?.data?.id,
|
||||
false,
|
||||
$state,
|
||||
false
|
||||
)
|
||||
: undefined
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
@@ -77,16 +85,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
const initialConfiguration = ccomponents[component.type].initialData.configuration
|
||||
const componentInput: RichConfiguration | undefined =
|
||||
ccomponents[component.type].initialData.componentInput
|
||||
const initialConfiguration = componentSettings?.item?.data?.type
|
||||
? ccomponents[componentSettings.item.data.type].initialData.configuration
|
||||
: {}
|
||||
|
||||
$: component && ($app = $app)
|
||||
const componentInput: RichConfiguration | undefined = componentSettings?.item?.data?.type
|
||||
? ccomponents[componentSettings?.item?.data?.type].initialData.componentInput
|
||||
: undefined
|
||||
|
||||
$: componentSettings?.item?.data && ($app = $app)
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={keydown} />
|
||||
|
||||
{#if component}
|
||||
{#if componentSettings?.item?.data}
|
||||
{@const component = componentSettings.item.data}
|
||||
<div class="flex min-h-full flex-col min-w-[150px] w-full divide-y">
|
||||
{#if component.componentInput}
|
||||
<PanelSection title="Data Source">
|
||||
@@ -109,44 +122,50 @@
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
<ComponentInputTypeEditor bind:componentInput={component.componentInput} />
|
||||
{#if componentSettings.item.data.componentInput}
|
||||
<ComponentInputTypeEditor
|
||||
bind:componentInput={componentSettings.item.data.componentInput}
|
||||
/>
|
||||
|
||||
<div class="flex flex-col w-full gap-2 my-2">
|
||||
{#if component.componentInput.type === 'static'}
|
||||
<StaticInputEditor
|
||||
fieldType={componentInput?.fieldType}
|
||||
subFieldType={componentInput?.subFieldType}
|
||||
format={componentInput?.format}
|
||||
bind:componentInput={component.componentInput}
|
||||
noVariablePicker
|
||||
/>
|
||||
{:else if component.componentInput.type === 'template' && component.componentInput !== undefined}
|
||||
<div class="py-1 min-h-[28px] rounded border border-1 border-gray-500">
|
||||
<TemplateEditor
|
||||
bind:this={editor}
|
||||
fontSize={12}
|
||||
bind:code={component.componentInput.eval}
|
||||
{extraLib}
|
||||
<div class="flex flex-col w-full gap-2 my-2">
|
||||
{#if componentSettings.item.data.componentInput.type === 'static'}
|
||||
<StaticInputEditor
|
||||
fieldType={componentInput?.fieldType}
|
||||
subFieldType={componentInput?.subFieldType}
|
||||
format={componentInput?.format}
|
||||
bind:componentInput={componentSettings.item.data.componentInput}
|
||||
noVariablePicker
|
||||
/>
|
||||
</div>
|
||||
{:else if component.componentInput.type === 'connected' && component.componentInput !== undefined}
|
||||
<ConnectedInputEditor bind:componentInput={component.componentInput} />
|
||||
{:else if component.componentInput?.type === 'runnable' && component.componentInput !== undefined}
|
||||
<RunnableInputEditor
|
||||
appComponent={component}
|
||||
bind:appInput={component.componentInput}
|
||||
defaultUserInput={component.type == 'formcomponent' ||
|
||||
component.type == 'formbuttoncomponent'}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if componentSettings.item.data.componentInput.type === 'template' && componentSettings.item.data.componentInput !== undefined}
|
||||
<div class="py-1 min-h-[28px] rounded border border-1 border-gray-500">
|
||||
<TemplateEditor
|
||||
bind:this={editor}
|
||||
fontSize={12}
|
||||
bind:code={componentSettings.item.data.componentInput.eval}
|
||||
{extraLib}
|
||||
/>
|
||||
</div>
|
||||
{:else if componentSettings.item.data.componentInput.type === 'connected' && component.componentInput !== undefined}
|
||||
<ConnectedInputEditor
|
||||
bind:componentInput={componentSettings.item.data.componentInput}
|
||||
/>
|
||||
{:else if componentSettings.item.data.componentInput?.type === 'runnable' && component.componentInput !== undefined}
|
||||
<RunnableInputEditor
|
||||
appComponent={component}
|
||||
bind:appInput={componentSettings.item.data.componentInput}
|
||||
defaultUserInput={component.type == 'formcomponent' ||
|
||||
component.type == 'formbuttoncomponent'}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#key $stateId}
|
||||
{#if component.componentInput?.type === 'runnable'}
|
||||
{#if Object.keys(component.componentInput.fields ?? {}).length > 0}
|
||||
{#if componentSettings.item.data.componentInput?.type === 'runnable'}
|
||||
{#if Object.keys(componentSettings.item.data.componentInput.fields ?? {}).length > 0}
|
||||
<div class="border w-full">
|
||||
<PanelSection
|
||||
title={`Runnable Inputs (${
|
||||
Object.keys(component.componentInput.fields ?? {}).length
|
||||
Object.keys(componentSettings.item.data.componentInput.fields ?? {}).length
|
||||
})`}
|
||||
>
|
||||
<svelte:fragment slot="action">
|
||||
@@ -159,7 +178,7 @@
|
||||
<InputsSpecsEditor
|
||||
id={component.id}
|
||||
shouldCapitalize={false}
|
||||
bind:inputSpecs={component.componentInput.fields}
|
||||
bind:inputSpecs={componentSettings.item.data.componentInput.fields}
|
||||
userInputEnabled={component.type === 'formcomponent' ||
|
||||
component.type === 'formbuttoncomponent'}
|
||||
{rowColumns}
|
||||
@@ -177,23 +196,26 @@
|
||||
{rowColumns}
|
||||
id={component.id}
|
||||
inputSpecsConfiguration={initialConfiguration}
|
||||
bind:inputSpecs={component.configuration}
|
||||
bind:inputSpecs={componentSettings.item.data.configuration}
|
||||
userInputEnabled={false}
|
||||
/>
|
||||
</PanelSection>
|
||||
{/if}
|
||||
|
||||
{#if component.type === 'tabscomponent'}
|
||||
<GridTab bind:tabs={component.tabs} {component} />
|
||||
{:else if component.type === 'verticalsplitpanescomponent' || component.type === 'horizontalsplitpanescomponent'}
|
||||
<GridPane bind:panes={component.panes} {component} />
|
||||
{:else if component.type === 'tablecomponent' && Array.isArray(component.actionButtons)}
|
||||
<TableActions id={component.id} bind:components={component.actionButtons} />
|
||||
{#if componentSettings.item.data.type === 'tabscomponent'}
|
||||
<GridTab bind:tabs={componentSettings.item.data.tabs} {component} />
|
||||
{:else if componentSettings.item.data.type === 'verticalsplitpanescomponent' || componentSettings.item.data.type === 'horizontalsplitpanescomponent'}
|
||||
<GridPane bind:panes={componentSettings.item.data.panes} {component} />
|
||||
{:else if componentSettings.item.data.type === 'tablecomponent' && Array.isArray(componentSettings.item.data.actionButtons)}
|
||||
<TableActions id={component.id} bind:components={componentSettings.item.data.actionButtons} />
|
||||
{/if}
|
||||
|
||||
<AlignmentEditor bind:component />
|
||||
{#if component.type === 'buttoncomponent' || component.type === 'formcomponent' || component.type === 'formbuttoncomponent'}
|
||||
<Recompute bind:recomputeIds={component.recomputeIds} ownId={component.id} />
|
||||
<AlignmentEditor bind:component={componentSettings.item.data} />
|
||||
{#if componentSettings.item.data.type === 'buttoncomponent' || componentSettings.item.data.type === 'formcomponent' || componentSettings.item.data.type === 'formbuttoncomponent'}
|
||||
<Recompute
|
||||
bind:recomputeIds={componentSettings.item.data.recomputeIds}
|
||||
ownId={component.id}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="grow shrink" />
|
||||
@@ -213,13 +235,13 @@
|
||||
{#if viewCssOptions}
|
||||
<div transition:slide|local>
|
||||
{#each Object.keys(ccomponents[component.type].customCss ?? {}) as name}
|
||||
{#if component?.customCss != undefined}
|
||||
{#if componentSettings.item.data?.customCss != undefined}
|
||||
<div class="w-full mb-2">
|
||||
<CssProperty
|
||||
forceStyle={ccomponents[component.type].customCss[name].style != undefined}
|
||||
forceClass={ccomponents[component.type].customCss[name].class != undefined}
|
||||
{name}
|
||||
bind:value={component.customCss[name]}
|
||||
bind:value={componentSettings.item.data.customCss[name]}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
+2
-4
@@ -8,12 +8,10 @@
|
||||
export let appInput: ResultAppInput
|
||||
export let defaultUserInput = false
|
||||
export let appComponent: AppComponent
|
||||
|
||||
$: isRunnableSelected = isScriptByPathDefined(appInput) || isScriptByNameDefined(appInput)
|
||||
</script>
|
||||
|
||||
{#if isRunnableSelected}
|
||||
{#if isScriptByPathDefined(appInput) || isScriptByNameDefined(appInput)}
|
||||
<SelectedRunnable {appComponent} bind:appInput />
|
||||
{:else}
|
||||
{:else if appInput !== undefined}
|
||||
<RunnableSelector id={appComponent.id} {defaultUserInput} bind:appInput />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user