mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 00:06:14 +00:00
fix: improve conditional wrapper and prevent more app errors
This commit is contained in:
@@ -24,7 +24,6 @@
|
||||
})
|
||||
|
||||
function onFocus() {
|
||||
console.log('onFocus', id, selectedConditionIndex)
|
||||
$focusedGrid = {
|
||||
parentComponentId: id,
|
||||
subGridIndex: selectedConditionIndex
|
||||
|
||||
@@ -202,7 +202,8 @@
|
||||
color="light"
|
||||
variant="contained"
|
||||
disabled={selectedIndex === 0}
|
||||
on:click={() => {
|
||||
on:click={(e) => {
|
||||
e.preventDefault()
|
||||
directionClicked = 'left'
|
||||
runStep(selectedIndex - 1)
|
||||
}}
|
||||
@@ -222,7 +223,8 @@
|
||||
color="dark"
|
||||
variant="contained"
|
||||
disabled={lastStep}
|
||||
on:click={() => {
|
||||
on:click={(e) => {
|
||||
e.preventDefault()
|
||||
directionClicked = 'right'
|
||||
runStep(selectedIndex + 1)
|
||||
}}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let currentNodeId: string = ''
|
||||
let currentNodeId: string = $worldStore.outputsById[id]?.currentNodeId?.peak() ?? 'a'
|
||||
|
||||
$worldStore.outputsById[id]?.currentNodeId?.subscribe(
|
||||
{
|
||||
|
||||
@@ -368,6 +368,14 @@ export function insertNewGridItem(
|
||||
: undefined
|
||||
|
||||
if (key && app.subgrids[key] === undefined) {
|
||||
let parent = findGridItemById(app.grid, app.subgrids, key)?.data
|
||||
let subgrids = parent?.numberOfSubgrids
|
||||
if (subgrids === undefined) {
|
||||
throw Error(`Invalid subgrid selected, the parent has no subgrids: ${key}, parent: ${JSON.stringify(parent)}`)
|
||||
}
|
||||
if (focusedGrid?.subGridIndex && (focusedGrid?.subGridIndex < 0 || focusedGrid?.subGridIndex >= subgrids)) {
|
||||
throw Error(`Invalid subgrid selected: ${key}, max subgrids: ${subgrids}`)
|
||||
}
|
||||
// If ever the subgrid is undefined, we want to make sure it is defined
|
||||
app.subgrids[key] = []
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import type { AppViewerContext } from '../../types'
|
||||
import Section from '$lib/components/Section.svelte'
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import { findGridItem } from '../appUtils'
|
||||
import { deleteGridItem, findGridItem, findGridItemParentGrid } from '../appUtils'
|
||||
import { pluralize } from '$lib/utils'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { Trash } from 'lucide-svelte'
|
||||
@@ -21,8 +21,13 @@
|
||||
.map((x) => {
|
||||
const parentId = x.split('-')[0]
|
||||
const parent = findGridItem($app, parentId)
|
||||
|
||||
if (parent === undefined) {
|
||||
const subgrid = x.replace(`${parentId}-`, '')
|
||||
if (subgrid == '-1') {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Invalid subgrid index -1 '
|
||||
}
|
||||
} else if (parent === undefined) {
|
||||
return {
|
||||
subGridId: x,
|
||||
error: 'Parent not found'
|
||||
@@ -57,7 +62,7 @@
|
||||
There are {pluralize(unintitializedComponents.length, 'uninitialized component')} in the app.
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 border rounded-md overflow-hidden">
|
||||
<div class="grid grid-cols-4 border rounded-md overflow-hidden">
|
||||
<!-- Header -->
|
||||
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
|
||||
>Component Id</div
|
||||
@@ -68,9 +73,15 @@
|
||||
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
|
||||
>Status</div
|
||||
>
|
||||
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
|
||||
>Action</div>
|
||||
|
||||
<!-- Iterate over uninitializedComponents to display each component in the grid -->
|
||||
{#each unintitializedComponents as c}
|
||||
{@const item = findGridItem($app, c)}
|
||||
{#if !item}
|
||||
<div>Item {c} not found</div>
|
||||
{:else}
|
||||
<!-- Component Id -->
|
||||
<div class="text-xs flex items-center px-2 py-2">
|
||||
<Badge>
|
||||
@@ -80,13 +91,32 @@
|
||||
|
||||
<div class="text-xs flex items-center px-2 py-2">
|
||||
<Badge color="blue">
|
||||
{findGridItem($app, c)?.data?.type || 'Unknown'}
|
||||
{item?.data?.type || 'Unknown'}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div class="text-xs flex items-center px-2 py-2">
|
||||
<Badge color="red">Uninitialized</Badge>
|
||||
</div>
|
||||
<div class="text-xs flex items-center px-2 py-2">
|
||||
|
||||
<Button
|
||||
color="light"
|
||||
startIcon={{
|
||||
icon: Trash
|
||||
}}
|
||||
size="xs2"
|
||||
on:click={() => {
|
||||
let parent = findGridItemParentGrid($app, c)
|
||||
deleteGridItem($app, item.data, parent)
|
||||
$app = $app
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,7 +170,7 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
Remove subgrid
|
||||
Remove
|
||||
</Button>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -17,11 +17,16 @@
|
||||
export let component: AppComponent
|
||||
let dragDisabled = true
|
||||
|
||||
let items = conditions.map((condition, index) => {
|
||||
let items = conditions.slice(0, -1).map((condition, index) => {
|
||||
return { value: condition, id: generateRandomString(), originalIndex: index }
|
||||
})
|
||||
|
||||
$: conditions = items.map((item) => item.value)
|
||||
$: conditions = items.map((item) => item.value).concat([{
|
||||
type: 'evalv2',
|
||||
expr: 'true',
|
||||
fieldType: 'boolean',
|
||||
connections: []
|
||||
}])
|
||||
|
||||
const { app, runnableComponents, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -83,6 +88,7 @@
|
||||
delete $runnableComponents[key]
|
||||
}
|
||||
}
|
||||
|
||||
$runnableComponents = $runnableComponents
|
||||
for (let i = index; i < items.length - 1; i++) {
|
||||
$app!.subgrids![`${component.id}-${i}`] = $app!.subgrids![`${component.id}-${i + 1}`]
|
||||
@@ -91,14 +97,14 @@
|
||||
// Remove the corresponding item from the items array
|
||||
const nitems = items.filter((item) => item.originalIndex !== index)
|
||||
|
||||
component.numberOfSubgrids = nitems.length
|
||||
component.numberOfSubgrids = nitems.length + 1
|
||||
// Update the originalIndex of the remaining items
|
||||
nitems.forEach((item, i) => {
|
||||
item.originalIndex = i
|
||||
})
|
||||
items = nitems
|
||||
|
||||
delete $app!.subgrids![`${component.id}-${items.length}`]
|
||||
delete $app!.subgrids![`${component.id}-${items.length + 1}`]
|
||||
$app = $app
|
||||
}
|
||||
|
||||
@@ -111,6 +117,7 @@
|
||||
|
||||
$app.subgrids[`${component.id}-${numberOfConditions}`] =
|
||||
$app.subgrids[`${component.id}-${numberOfConditions - 1}`]
|
||||
|
||||
$app.subgrids[`${component.id}-${numberOfConditions - 1}`] = []
|
||||
|
||||
const newCondition: AppInputSpec<'boolean', boolean> = {
|
||||
@@ -143,54 +150,63 @@
|
||||
use:dndzone={{
|
||||
items: items,
|
||||
flipDurationMs: 200,
|
||||
dropTargetStyle: {}
|
||||
dropTargetStyle: {},
|
||||
dragDisabled
|
||||
}}
|
||||
on:consider={handleConsider}
|
||||
on:finalize={handleFinalize}
|
||||
>
|
||||
{#each items as item, index (item.id)}
|
||||
{#if index < items.length - 1}
|
||||
{@const condition = item.value}
|
||||
<div class="w-full flex flex-row gap-2 items-center relative">
|
||||
<div class={twMerge('grow border p-3 my-2 rounded-md bg-surface')}>
|
||||
<InputsSpecEditor
|
||||
key={`Condition ${index + 1}`}
|
||||
bind:componentInput={item.value}
|
||||
id={component.id}
|
||||
userInputEnabled={false}
|
||||
shouldCapitalize={true}
|
||||
resourceOnly={false}
|
||||
fieldType={condition?.['fieldType']}
|
||||
subFieldType={condition?.['subFieldType']}
|
||||
format={condition?.['format']}
|
||||
selectOptions={condition?.['selectOptions']}
|
||||
tooltip={condition?.['tooltip']}
|
||||
fileUpload={condition?.['fileUpload']}
|
||||
placeholder={condition?.['placeholder']}
|
||||
customTitle={condition?.['customTitle']}
|
||||
displayType={false}
|
||||
/>
|
||||
{@const condition = item.value}
|
||||
<div class="w-full flex flex-row gap-2 items-center relative">
|
||||
<div class={twMerge('grow border p-3 my-2 rounded-md bg-surface relative')}>
|
||||
{#if dragDisabled}
|
||||
<InputsSpecEditor
|
||||
key={`Condition ${index + 1}`}
|
||||
bind:componentInput={item.value}
|
||||
id={component.id}
|
||||
userInputEnabled={false}
|
||||
shouldCapitalize={true}
|
||||
resourceOnly={false}
|
||||
fieldType={condition?.['fieldType']}
|
||||
subFieldType={condition?.['subFieldType']}
|
||||
format={condition?.['format']}
|
||||
selectOptions={condition?.['selectOptions']}
|
||||
tooltip={condition?.['tooltip']}
|
||||
fileUpload={condition?.['fileUpload']}
|
||||
placeholder={condition?.['placeholder']}
|
||||
customTitle={condition?.['customTitle']}
|
||||
displayType={false}
|
||||
/>
|
||||
{:else}
|
||||
<pre><code>{condition?.['expr']}</code></pre>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center gap-2">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div on:click={() => deleteSubgrid(index)}>
|
||||
<X size={16} />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center gap-2">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div on:click={() => deleteSubgrid(index)}>
|
||||
<X size={16} />
|
||||
</div>
|
||||
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<div
|
||||
tabindex={dragDisabled ? 0 : -1}
|
||||
class="w-4 h-4"
|
||||
on:mousedown={startDrag}
|
||||
on:touchstart={startDrag}
|
||||
on:keydown={handleKeyDown}
|
||||
>
|
||||
<GripVertical size={16} />
|
||||
</div>
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
tabindex={dragDisabled ? 0 : -1}
|
||||
class="w-4 h-4"
|
||||
on:mousedown={startDrag}
|
||||
on:touchstart={startDrag}
|
||||
on:keydown={handleKeyDown}
|
||||
aria-label="drag-handle"
|
||||
style={dragDisabled ? 'cursor: grab' : 'cursor: grabbing'}
|
||||
>
|
||||
<GripVertical size={16} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
</section>
|
||||
<div class="border rounded-md p-3 mb-2">
|
||||
|
||||
Reference in New Issue
Block a user