mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-10 00:05:27 +00:00
fix(frontend): proper each block binding + better app settings reactivity (#5568)
* fix: properly bind to array elements in Svelte each loops
This commit fixes an issue where binding directly to loop variables in Svelte's #each loops doesn't properly update the original array. Instead of binding directly to the loop variable, we now bind to the array elements using index variables.
The pattern used is: - Change: {#each arr as el} -> {#each arr as _, index} - Change: bind:value={el} -> bind:value={arr[index]}
Modified files: - frontend/src/lib/components/ArrayTypeNarrowing.svelte - frontend/src/lib/components/apps/editor/AppInputs.svelte - frontend/src/lib/components/flows/content/FlowModuleWrapper.svelte
* better app settings panel reactivity
---------
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: HugoCasa <hugo@casademont.ch>
This commit is contained in:
committed by
GitHub
co-authored by
Ruben Fiszel
HugoCasa
parent
c8e1f65ac4
commit
a2f2076231
@@ -25,8 +25,8 @@
|
||||
itemsType?.type != 'string'
|
||||
? itemsType?.type
|
||||
: Array.isArray(itemsType?.enum)
|
||||
? 'enum'
|
||||
: 'string'
|
||||
? 'enum'
|
||||
: 'string'
|
||||
|
||||
let schema = {
|
||||
properties: itemsType?.properties || {},
|
||||
@@ -105,16 +105,17 @@
|
||||
<label for="input" class="text-secondary text-xs">
|
||||
Enums
|
||||
<div class="flex flex-col gap-1">
|
||||
{#each itemsType?.enum || [] as e}
|
||||
{#each itemsType?.enum || [] as _, index}
|
||||
<div class="flex flex-row max-w-md gap-1 items-center">
|
||||
<input id="input" type="text" bind:value={e} />
|
||||
<input id="input" type="text" bind:value={itemsType.enum[index]} />
|
||||
<div>
|
||||
<button
|
||||
transition:fade|local={{ duration: 100 }}
|
||||
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover ml-2"
|
||||
on:click={() => {
|
||||
if (itemsType?.enum) {
|
||||
itemsType.enum = (itemsType.enum || []).filter((el) => el !== e)
|
||||
if (itemsType && itemsType.enum) {
|
||||
const enumValue = itemsType.enum[index]
|
||||
itemsType.enum = itemsType.enum.filter((el) => el !== enumValue)
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -106,12 +106,12 @@
|
||||
<label class="block pb-2">
|
||||
<span class="text-primary font-semibold text-sm">Allowed domains</span>
|
||||
<div class="flex flex-col gap-1">
|
||||
{#each value?.['allowed_domains'] ?? [] as domain}
|
||||
{#each value?.['allowed_domains'] ?? [] as domain, idx}
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
class="max-w-96 w-full"
|
||||
type="text"
|
||||
bind:value={domain}
|
||||
bind:value={value['allowed_domains'][idx]}
|
||||
on:keyup={(e) => {
|
||||
if (domain == '') {
|
||||
value['allowed_domains'] = value['allowed_domains']?.filter(
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// Created this utility to avoid circular dependencies between
|
||||
// svelte effects
|
||||
|
||||
import { deepEqual } from 'fast-equals'
|
||||
|
||||
export function createOnObjChange<T extends object>() {
|
||||
let oldValue: T | undefined
|
||||
|
||||
return (value: T | undefined, callback: () => void) => {
|
||||
if (!deepEqual(oldValue, value)) {
|
||||
oldValue = structuredClone(value)
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,11 @@
|
||||
<div>
|
||||
<AppComponentInput bind:component={gridItem.data} {resourceOnly} />
|
||||
<div class="ml-4 mt-4">
|
||||
{#each gridItem.data.actionButtons as actionButton (actionButton.id)}
|
||||
<AppComponentInput bind:component={actionButton.data} {resourceOnly} />
|
||||
{#each gridItem.data.actionButtons as actionButton, actionIndex (actionButton.id)}
|
||||
<AppComponentInput
|
||||
bind:component={gridItem.data.actionButtons[actionIndex].data}
|
||||
{resourceOnly}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@@ -34,8 +37,11 @@
|
||||
<AppComponentInput bind:component={gridItem.data} {resourceOnly} />
|
||||
<div class="ml-4 mt-4">
|
||||
{#if Array.isArray(gridItem.data.actions)}
|
||||
{#each gridItem.data.actions as actionButton (actionButton.id)}
|
||||
<AppComponentInput bind:component={actionButton.data} {resourceOnly} />
|
||||
{#each gridItem.data.actions as actionButton, actionIndex (actionButton.id)}
|
||||
<AppComponentInput
|
||||
bind:component={gridItem.data.actions[actionIndex].data}
|
||||
{resourceOnly}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import type { App, AppViewerContext } from '../types'
|
||||
import { BG_PREFIX, allItems } from '../utils'
|
||||
import { findComponentSettings, findGridItem } from './appUtils'
|
||||
import type { App, AppViewerContext, GridItem } from '../types'
|
||||
import { BG_PREFIX } from '../utils'
|
||||
import { findGridItemWithLocation, allItemsWithLocation } from './appUtils'
|
||||
import PanelSection from './settingsPanel/common/PanelSection.svelte'
|
||||
import ComponentPanel from './settingsPanel/ComponentPanel.svelte'
|
||||
import InputsSpecsEditor from './settingsPanel/InputsSpecsEditor.svelte'
|
||||
import BackgroundScriptSettings from './settingsPanel/script/BackgroundScriptSettings.svelte'
|
||||
import EventHandlerItem from './settingsPanel/EventHandlerItem.svelte'
|
||||
import type { TableAction } from './component'
|
||||
|
||||
const { selectedComponent, app, stateId, runnableComponents } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -20,18 +21,28 @@
|
||||
?.map((x, i) => ({ script: x, index: i }))
|
||||
.find(({ script, index }) => $selectedComponent?.includes(BG_PREFIX + index))
|
||||
|
||||
$: componentSettings = findComponentSettings($app, firstComponent)
|
||||
$: gridItemWithLocation = findGridItemWithLocation($app, firstComponent)
|
||||
$: tableActionSettings = findTableActionSettings($app, firstComponent)
|
||||
$: menuItemsSettings = findMenuItemsSettings($app, firstComponent)
|
||||
|
||||
function findTableActionSettings(app: App, id: string | undefined) {
|
||||
return allItems(app.grid, app.subgrids)
|
||||
.map((x) => {
|
||||
return allItemsWithLocation(app.grid, app.subgrids)
|
||||
.map((itemWithLocation) => {
|
||||
const x = itemWithLocation.item
|
||||
if (x?.data?.type === 'tablecomponent') {
|
||||
if (x?.data?.actionButtons) {
|
||||
const tableAction = x.data.actionButtons.find((x) => x.id === id)
|
||||
if (tableAction) {
|
||||
return { item: { data: tableAction, id: tableAction.id }, parent: x.data.id }
|
||||
const tableActionIdx = x.data.actionButtons.findIndex((x) => x.id === id)
|
||||
if (tableActionIdx > -1) {
|
||||
const tableAction = x.data.actionButtons[tableActionIdx]
|
||||
return {
|
||||
item: { data: tableAction, id: tableAction.id },
|
||||
parent: x.data.id,
|
||||
gridItemLocation: itemWithLocation.location,
|
||||
location: {
|
||||
key: 'actionButtons',
|
||||
index: tableActionIdx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
@@ -42,9 +53,18 @@
|
||||
x?.data?.type === 'aggridinfinitecomponentee'
|
||||
) {
|
||||
if (x?.data?.actions) {
|
||||
const tableAction = x.data.actions.find((x) => x.id === id)
|
||||
if (tableAction) {
|
||||
return { item: { data: tableAction, id: tableAction.id }, parent: x.data.id }
|
||||
const tableActionIdx = x.data.actions.findIndex((x) => x.id === id)
|
||||
if (tableActionIdx > -1) {
|
||||
const tableAction = x.data.actions[tableActionIdx]
|
||||
return {
|
||||
item: { data: tableAction, id: tableAction.id },
|
||||
parent: x.data.id,
|
||||
gridItemLocation: itemWithLocation.location,
|
||||
location: {
|
||||
key: 'actions',
|
||||
index: tableActionIdx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,13 +73,20 @@
|
||||
}
|
||||
|
||||
function findMenuItemsSettings(app: App, id: string | undefined) {
|
||||
return allItems(app.grid, app.subgrids)
|
||||
.map((x) => {
|
||||
return allItemsWithLocation(app.grid, app.subgrids)
|
||||
.map((itemWithLocation) => {
|
||||
const x = itemWithLocation.item
|
||||
if (x?.data?.type === 'menucomponent') {
|
||||
if (x?.data?.menuItems) {
|
||||
const menuItem = x.data.menuItems.find((x) => x.id === id)
|
||||
if (menuItem) {
|
||||
return { item: { data: menuItem, id: menuItem.id }, parent: x.data.id }
|
||||
const menuItemIdx = x.data.menuItems.findIndex((x) => x.id === id)
|
||||
if (menuItemIdx > -1) {
|
||||
const menuItem = x.data.menuItems[menuItemIdx]
|
||||
return {
|
||||
item: { data: menuItem, id: menuItem.id },
|
||||
parent: x.data.id,
|
||||
index: menuItemIdx,
|
||||
gridItemLocation: itemWithLocation.location
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,13 +94,39 @@
|
||||
.find((x) => x)
|
||||
}
|
||||
|
||||
function itemHasActions(
|
||||
item: GridItem | undefined
|
||||
): item is GridItem & { data: { actions: TableAction[] } } {
|
||||
return (
|
||||
item?.data?.type === 'aggridcomponent' ||
|
||||
item?.data?.type === 'aggridcomponentee' ||
|
||||
item?.data?.type === 'dbexplorercomponent' ||
|
||||
item?.data?.type === 'aggridinfinitecomponent' ||
|
||||
item?.data?.type === 'aggridinfinitecomponentee'
|
||||
)
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
{#if componentSettings}
|
||||
{#key componentSettings?.item?.id}
|
||||
{#if gridItemWithLocation}
|
||||
{#key gridItemWithLocation.item.id}
|
||||
<ComponentPanel
|
||||
bind:componentSettings
|
||||
bind:componentSettings={
|
||||
() => gridItemWithLocation,
|
||||
(cs) => {
|
||||
if (gridItemWithLocation?.location.type === 'grid') {
|
||||
$app.grid[gridItemWithLocation.location.gridItemIndex] = cs.item
|
||||
} else if (
|
||||
gridItemWithLocation?.location.type === 'subgrid' &&
|
||||
Array.isArray($app.subgrids?.[gridItemWithLocation.location.subgridKey])
|
||||
) {
|
||||
$app.subgrids[gridItemWithLocation.location.subgridKey][
|
||||
gridItemWithLocation.location.subgridItemIndex
|
||||
] = cs.item
|
||||
}
|
||||
}
|
||||
}
|
||||
onDelete={() => {
|
||||
dispatch('delete')
|
||||
}}
|
||||
@@ -83,30 +136,65 @@
|
||||
{#key tableActionSettings?.item?.data?.id}
|
||||
<ComponentPanel
|
||||
noGrid
|
||||
bind:componentSettings={tableActionSettings}
|
||||
bind:componentSettings={
|
||||
() => tableActionSettings,
|
||||
(cs) => {
|
||||
if (tableActionSettings) {
|
||||
if (tableActionSettings.gridItemLocation.type === 'grid') {
|
||||
const { gridItemIndex } = tableActionSettings.gridItemLocation
|
||||
const { key, index } = tableActionSettings.location
|
||||
if ($app.grid[gridItemIndex]?.data?.[key]) {
|
||||
$app.grid[gridItemIndex].data[key][index] = cs.item.data
|
||||
}
|
||||
} else if (tableActionSettings.gridItemLocation.type === 'subgrid') {
|
||||
const { subgridKey, subgridItemIndex } = tableActionSettings.gridItemLocation
|
||||
const { key, index } = tableActionSettings.location
|
||||
if ($app.subgrids?.[subgridKey]?.[subgridItemIndex]?.data?.[key]) {
|
||||
$app.subgrids[subgridKey][subgridItemIndex].data[key][index] = cs.item.data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
duplicateMoveAllowed={false}
|
||||
onDelete={() => {
|
||||
if (tableActionSettings) {
|
||||
const parent = findGridItem($app, tableActionSettings.parent)
|
||||
if (!parent) return
|
||||
|
||||
const item = findGridItemWithLocation($app, tableActionSettings.parent)
|
||||
if (!item) return
|
||||
const { item: parent, location } = item
|
||||
if (parent.data.type === 'tablecomponent') {
|
||||
parent.data.actionButtons = parent.data.actionButtons.filter(
|
||||
const newActionButtons = parent.data.actionButtons.filter(
|
||||
(x) => x.id !== tableActionSettings?.item.id
|
||||
)
|
||||
if (location.type === 'grid') {
|
||||
const { gridItemIndex } = location
|
||||
if ($app.grid[gridItemIndex]?.data?.type === 'tablecomponent') {
|
||||
$app.grid[gridItemIndex].data.actionButtons = newActionButtons
|
||||
}
|
||||
} else if (location.type === 'subgrid') {
|
||||
const { subgridKey, subgridItemIndex } = location
|
||||
if (
|
||||
$app.subgrids?.[subgridKey]?.[subgridItemIndex]?.data?.type === 'tablecomponent'
|
||||
) {
|
||||
$app.subgrids[subgridKey][subgridItemIndex].data.actionButtons = newActionButtons
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(parent.data.type === 'aggridcomponent' ||
|
||||
parent.data.type === 'aggridcomponentee' ||
|
||||
parent.data.type === 'dbexplorercomponent' ||
|
||||
parent.data.type === 'aggridinfinitecomponent' ||
|
||||
parent.data.type === 'aggridinfinitecomponentee') &&
|
||||
Array.isArray(parent.data.actions)
|
||||
) {
|
||||
parent.data.actions = parent.data.actions.filter(
|
||||
if (itemHasActions(parent) && Array.isArray(parent.data.actions)) {
|
||||
const newActions = parent.data.actions.filter(
|
||||
(x) => x.id !== tableActionSettings?.item.id
|
||||
)
|
||||
if (location.type === 'grid') {
|
||||
const { gridItemIndex } = location
|
||||
if (itemHasActions($app.grid[gridItemIndex])) {
|
||||
$app.grid[gridItemIndex].data.actions = newActions
|
||||
}
|
||||
} else {
|
||||
const { subgridKey, subgridItemIndex } = location
|
||||
if (itemHasActions($app.subgrids?.[subgridKey]?.[subgridItemIndex])) {
|
||||
$app.subgrids[subgridKey][subgridItemIndex].data.actions = newActions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -116,17 +204,44 @@
|
||||
{#key menuItemsSettings?.item?.id}
|
||||
<ComponentPanel
|
||||
noGrid
|
||||
bind:componentSettings={menuItemsSettings}
|
||||
duplicateMoveAllowed={false}
|
||||
bind:componentSettings={
|
||||
() => menuItemsSettings,
|
||||
(cs) => {
|
||||
if (menuItemsSettings) {
|
||||
if (menuItemsSettings.gridItemLocation.type === 'grid') {
|
||||
const { gridItemIndex } = menuItemsSettings.gridItemLocation
|
||||
if ($app.grid[gridItemIndex]?.data?.type === 'menucomponent') {
|
||||
$app.grid[gridItemIndex].data.menuItems[cs.index] = cs.item.data
|
||||
}
|
||||
} else if (menuItemsSettings.gridItemLocation.type === 'subgrid') {
|
||||
const { subgridKey, subgridItemIndex } = menuItemsSettings.gridItemLocation
|
||||
if ($app.subgrids?.[subgridKey]?.[subgridItemIndex]?.data?.type === 'menucomponent') {
|
||||
$app.subgrids[subgridKey][subgridItemIndex].data.menuItems[cs.index] = cs.item.data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onDelete={() => {
|
||||
if (menuItemsSettings) {
|
||||
const parent = findGridItem($app, menuItemsSettings.parent)
|
||||
if (!parent) return
|
||||
|
||||
const item = findGridItemWithLocation($app, menuItemsSettings.parent)
|
||||
if (!item) return
|
||||
const { item: parent, location } = item
|
||||
if (parent.data.type === 'menucomponent') {
|
||||
parent.data.menuItems = parent.data.menuItems.filter(
|
||||
const newItems = parent.data.menuItems.filter(
|
||||
(x) => x.id !== menuItemsSettings?.item.id
|
||||
)
|
||||
if (location.type === 'grid') {
|
||||
const { gridItemIndex } = location
|
||||
if ($app.grid[gridItemIndex]?.data?.type === 'menucomponent') {
|
||||
$app.grid[gridItemIndex].data.menuItems = newItems
|
||||
}
|
||||
} else if (location.type === 'subgrid') {
|
||||
const { subgridKey, subgridItemIndex } = location
|
||||
if ($app.subgrids?.[subgridKey]?.[subgridItemIndex]?.data?.type === 'menucomponent') {
|
||||
$app.subgrids[subgridKey][subgridItemIndex].data.menuItems = newItems
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -135,8 +250,15 @@
|
||||
{:else if hiddenInlineScript}
|
||||
{@const id = BG_PREFIX + hiddenInlineScript.index}
|
||||
{#key id}
|
||||
<BackgroundScriptSettings bind:runnable={hiddenInlineScript.script} {id} />
|
||||
|
||||
<BackgroundScriptSettings
|
||||
bind:runnable={
|
||||
() => hiddenInlineScript.script,
|
||||
(r) => {
|
||||
$app.hiddenInlineScripts[hiddenInlineScript.index] = r
|
||||
}
|
||||
}
|
||||
{id}
|
||||
/>
|
||||
{#if Object.keys(hiddenInlineScript.script.fields ?? {}).length > 0}
|
||||
<div class="mb-8">
|
||||
<PanelSection title={`Inputs`}>
|
||||
@@ -145,7 +267,14 @@
|
||||
displayType
|
||||
{id}
|
||||
shouldCapitalize={false}
|
||||
bind:inputSpecs={hiddenInlineScript.script.fields}
|
||||
bind:inputSpecs={
|
||||
() => hiddenInlineScript.script.fields,
|
||||
(is) => {
|
||||
if ($app.hiddenInlineScripts[hiddenInlineScript.index]) {
|
||||
$app.hiddenInlineScripts[hiddenInlineScript.index].fields = is
|
||||
}
|
||||
}
|
||||
}
|
||||
userInputEnabled={false}
|
||||
recomputeOnInputChanged={hiddenInlineScript.script.recomputeOnInputChanged}
|
||||
showOnDemandOnlyToggle
|
||||
@@ -163,7 +292,14 @@
|
||||
title="on success"
|
||||
tooltip="This event is triggered when the script runs successfully."
|
||||
items={Object.keys($runnableComponents).filter((_id) => _id !== id)}
|
||||
bind:value={hiddenInlineScript.script.recomputeIds}
|
||||
bind:value={
|
||||
() => hiddenInlineScript.script.recomputeIds,
|
||||
(v) => {
|
||||
if ($app.hiddenInlineScripts[hiddenInlineScript.index]) {
|
||||
$app.hiddenInlineScripts[hiddenInlineScript.index].recomputeIds = v
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
</PanelSection>
|
||||
<div class="grow shrink"></div>
|
||||
|
||||
@@ -36,6 +36,91 @@ import { getNextId } from '$lib/components/flows/idUtils'
|
||||
import { enterpriseLicense } from '$lib/stores'
|
||||
import gridHelp from '../svelte-grid/utils/helper'
|
||||
|
||||
type GridItemLocation =
|
||||
| {
|
||||
type: 'grid'
|
||||
gridItemIndex: number
|
||||
}
|
||||
| {
|
||||
type: 'subgrid'
|
||||
subgridItemIndex: number
|
||||
subgridKey: string
|
||||
}
|
||||
interface GridItemWithLocation {
|
||||
location: GridItemLocation
|
||||
item: GridItem
|
||||
parent: string | undefined
|
||||
}
|
||||
|
||||
export function allItemsWithLocation(
|
||||
grid: GridItem[],
|
||||
subgrids: Record<string, GridItem[]> | undefined
|
||||
): GridItemWithLocation[] {
|
||||
const gridItems: GridItemWithLocation[] = grid.map((x, i) => ({
|
||||
location: {
|
||||
type: 'grid',
|
||||
gridItemIndex: i
|
||||
},
|
||||
item: x,
|
||||
parent: undefined
|
||||
}))
|
||||
if (subgrids) {
|
||||
for (const key of Object.keys(subgrids)) {
|
||||
gridItems.push(
|
||||
...subgrids[key].map((x, i) => ({
|
||||
location: {
|
||||
type: 'subgrid' as const,
|
||||
subgridItemIndex: i,
|
||||
subgridKey: key
|
||||
},
|
||||
item: x,
|
||||
parent: key
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
return gridItems
|
||||
}
|
||||
|
||||
export function findGridItemWithLocation(
|
||||
app: App,
|
||||
id: string | undefined
|
||||
): GridItemWithLocation | undefined {
|
||||
if (!id) return undefined
|
||||
if (app?.grid) {
|
||||
const gridItemIndex = app.grid.findIndex((x) => x.data?.id === id)
|
||||
if (gridItemIndex > -1) {
|
||||
return {
|
||||
location: {
|
||||
type: 'grid',
|
||||
gridItemIndex: gridItemIndex
|
||||
},
|
||||
item: app.grid[gridItemIndex],
|
||||
parent: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (app?.subgrids) {
|
||||
for (const key of Object.keys(app.subgrids ?? {})) {
|
||||
const subGridItemIndex = app.subgrids[key].findIndex((x) => x.data?.id === id)
|
||||
if (subGridItemIndex > -1) {
|
||||
return {
|
||||
location: {
|
||||
subgridItemIndex: subGridItemIndex,
|
||||
subgridKey: key,
|
||||
type: 'subgrid'
|
||||
},
|
||||
item: app.subgrids[key][subGridItemIndex],
|
||||
parent: key
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function findComponentSettings(app: App, id: string | undefined) {
|
||||
if (!id) return undefined
|
||||
if (app?.grid) {
|
||||
@@ -772,20 +857,20 @@ export type InitConfig<
|
||||
[Property in keyof T]: T[Property] extends StaticAppInput
|
||||
? T[Property]['value'] | undefined
|
||||
: T[Property] extends { type: 'oneOf' }
|
||||
? {
|
||||
type: 'oneOf'
|
||||
selected: keyof T[Property]['configuration']
|
||||
configuration: {
|
||||
[Choice in keyof T[Property]['configuration']]: {
|
||||
[IT in keyof T[Property]['configuration'][Choice]]: T[Property]['configuration'][Choice][IT] extends StaticAppInput
|
||||
? T[Property]['configuration'][Choice][IT] extends StaticAppInputOnDemand
|
||||
? () => Promise<T[Property]['configuration'][Choice][IT]['value'] | undefined>
|
||||
: T[Property]['configuration'][Choice][IT]['value'] | undefined
|
||||
: undefined
|
||||
? {
|
||||
type: 'oneOf'
|
||||
selected: keyof T[Property]['configuration']
|
||||
configuration: {
|
||||
[Choice in keyof T[Property]['configuration']]: {
|
||||
[IT in keyof T[Property]['configuration'][Choice]]: T[Property]['configuration'][Choice][IT] extends StaticAppInput
|
||||
? T[Property]['configuration'][Choice][IT] extends StaticAppInputOnDemand
|
||||
? () => Promise<T[Property]['configuration'][Choice][IT]['value'] | undefined>
|
||||
: T[Property]['configuration'][Choice][IT]['value'] | undefined
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
: undefined
|
||||
}
|
||||
|
||||
export function initConfig<
|
||||
@@ -827,27 +912,30 @@ export function initConfig<
|
||||
? [
|
||||
key,
|
||||
configuration?.[key]?.type == 'static' ? configuration?.[key]?.['value'] : undefined
|
||||
]
|
||||
]
|
||||
: value.type == 'oneOf'
|
||||
? [
|
||||
key,
|
||||
{
|
||||
selected: value.selected,
|
||||
type: 'oneOf',
|
||||
configuration: Object.fromEntries(
|
||||
Object.entries(value.configuration).map(([choice, config]) => {
|
||||
const conf = initConfig(config, configuration?.[key]?.configuration?.[choice])
|
||||
Object.entries(config).forEach(([innerKey, innerValue]) => {
|
||||
if (innerValue.type === 'static' && !(innerKey in conf)) {
|
||||
conf[innerKey] = innerValue.value
|
||||
}
|
||||
? [
|
||||
key,
|
||||
{
|
||||
selected: value.selected,
|
||||
type: 'oneOf',
|
||||
configuration: Object.fromEntries(
|
||||
Object.entries(value.configuration).map(([choice, config]) => {
|
||||
const conf = initConfig(
|
||||
config,
|
||||
configuration?.[key]?.configuration?.[choice]
|
||||
)
|
||||
Object.entries(config).forEach(([innerKey, innerValue]) => {
|
||||
if (innerValue.type === 'static' && !(innerKey in conf)) {
|
||||
conf[innerKey] = innerValue.value
|
||||
}
|
||||
})
|
||||
return [choice, conf]
|
||||
})
|
||||
return [choice, conf]
|
||||
})
|
||||
)
|
||||
}
|
||||
]
|
||||
: [key, undefined]
|
||||
)
|
||||
}
|
||||
]
|
||||
: [key, undefined]
|
||||
)
|
||||
) as any
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import AlignmentEditor from './AlignmentEditor.svelte'
|
||||
import RunnableInputEditor from './inputEditor/RunnableInputEditor.svelte'
|
||||
import TemplateEditor from '$lib/components/TemplateEditor.svelte'
|
||||
import { ccomponents, components, type AppComponent } from '../component'
|
||||
import { ccomponents, components } from '../component'
|
||||
import CssProperty from '../componentsPanel/CssProperty.svelte'
|
||||
import GridTab from './GridTab.svelte'
|
||||
import { deleteGridItem, isTableAction } from '../appUtils'
|
||||
@@ -45,7 +45,6 @@
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import { createOnObjChange } from '../../components/helpers/onObjChange'
|
||||
|
||||
export let componentSettings: { item: GridItem; parent: string | undefined } | undefined =
|
||||
undefined
|
||||
@@ -141,9 +140,6 @@
|
||||
? ccomponents[componentSettings?.item?.data?.type]?.initialData?.componentInput
|
||||
: undefined
|
||||
|
||||
const onDataChange = createOnObjChange<AppComponent>()
|
||||
$: onDataChange(componentSettings?.item?.data, () => ($app = $app))
|
||||
|
||||
const hasInteraction = componentSettings?.item.data.type
|
||||
? isTriggerable(componentSettings?.item.data.type)
|
||||
: false
|
||||
|
||||
+1
-5
@@ -6,12 +6,11 @@
|
||||
import { getContext } from 'svelte'
|
||||
import ScriptSettingsSection from './shared/ScriptSettingsSection.svelte'
|
||||
import ScriptTransformer from './shared/ScriptTransformer.svelte'
|
||||
import { createOnObjChange } from '$lib/components/apps/components/helpers/onObjChange'
|
||||
|
||||
export let runnable: HiddenRunnable
|
||||
export let id: string
|
||||
|
||||
const { runnableComponents, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { runnableComponents } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
function updateAutoRefresh() {
|
||||
const autoRefresh = runnable.autoRefresh
|
||||
@@ -22,9 +21,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onDataChange = createOnObjChange<HiddenRunnable>()
|
||||
$: onDataChange(runnable, () => ($app = $app))
|
||||
</script>
|
||||
|
||||
<div class={'border-y divide-y '}>
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
{#if $selectedId === `${flowModule?.id}-branch-${branchIndex}`}
|
||||
<FlowBranchOneWrapper
|
||||
{noEditor}
|
||||
bind:branch
|
||||
bind:branch={flowModule.value.branches[branchIndex]}
|
||||
parentModule={flowModule}
|
||||
{previousModule}
|
||||
{enableAi}
|
||||
@@ -254,7 +254,7 @@
|
||||
{:else if flowModule.value.type === 'branchall'}
|
||||
{#each flowModule.value.branches as branch, branchIndex (branchIndex)}
|
||||
{#if $selectedId === `${flowModule?.id}-branch-${branchIndex}`}
|
||||
<FlowBranchAllWrapper {noEditor} bind:branch />
|
||||
<FlowBranchAllWrapper {noEditor} bind:branch={flowModule.value.branches[branchIndex]} />
|
||||
{:else}
|
||||
{#each branch.modules as _, index}
|
||||
<svelte:self
|
||||
|
||||
Reference in New Issue
Block a user