fix(frontend): arginput + apppreview fixes

This commit is contained in:
Ruben Fiszel
2023-03-03 17:34:08 +01:00
parent 70dd6f759c
commit e2c4545240
14 changed files with 208 additions and 117 deletions
@@ -299,6 +299,4 @@
Not recognized input type {argName}
{/if}
</div>
{:else}
<p class="text-sm text-gray-700">Argument at {argName} is undefined</p>
{/if}
@@ -0,0 +1,114 @@
<script lang="ts">
import type { Schema } from '$lib/common'
import { VariableService, type InputTransform } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { allTrue } from '$lib/utils'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { Button } from './common'
import InputTransformForm from './InputTransformForm.svelte'
import ItemPicker from './ItemPicker.svelte'
import VariableEditor from './VariableEditor.svelte'
export let schema: Schema
export let args: Record<string, InputTransform | any> = {}
export let isValid: boolean = true
export let extraLib: string = 'missing extraLib'
export let previousModuleId: string | undefined = undefined
export let filter: string[] | undefined = undefined
export let noDynamicToggle = false
let clazz: string = ''
export { clazz as class }
let inputCheck: { [id: string]: boolean } = {}
$: isValid = allTrue(inputCheck) ?? false
$: if (args == undefined || typeof args !== 'object') {
args = {}
}
function removeExtraKey() {
const nargs = {}
Object.keys(args ?? {}).forEach((key) => {
if (keys.includes(key)) {
nargs[key] = args[key]
}
})
args = nargs
}
let pickForField: string | undefined
let itemPicker: ItemPicker | undefined = undefined
let variableEditor: VariableEditor | undefined = undefined
let keys: string[] = []
$: {
let lkeys = Object.keys(schema?.properties ?? {})
if (schema?.properties && JSON.stringify(lkeys) != JSON.stringify(keys)) {
keys = lkeys
removeExtraKey()
}
}
</script>
<div class="w-full {clazz}">
{#if keys.length > 0}
{#each keys as argName, i (argName)}
{#if (!filter || filter.includes(argName)) && Object.keys(schema.properties ?? {}).includes(argName)}
<div>
<InputTransformForm
{previousModuleId}
bind:arg={args[argName]}
bind:schema
bind:argName
bind:inputCheck={inputCheck[argName]}
bind:extraLib
{variableEditor}
{itemPicker}
bind:pickForField
{noDynamicToggle}
/>
</div>
{/if}
{/each}
{:else}
<div class="text-gray-500 text-sm">No inputs</div>
{/if}
</div>
<ItemPicker
bind:this={itemPicker}
pickCallback={(path, _) => {
if (pickForField) {
args[pickForField].value = '$var:' + path
}
}}
itemName="Variable"
extraField="path"
loadItems={async () =>
(await VariableService.listVariable({ workspace: $workspaceStore ?? '' })).map((x) => ({
name: x.path,
...x
}))}
>
<div
slot="submission"
class="flex flex-row-reverse w-full bg-white border-t border-gray-200 rounded-bl-lg rounded-br-lg"
>
<Button
variant="border"
color="blue"
size="sm"
startIcon={{ icon: faPlus }}
on:click={() => {
variableEditor?.initNew?.()
}}
>
New variable
</Button>
</div>
</ItemPicker>
<VariableEditor bind:this={variableEditor} />
+59 -55
View File
@@ -6,11 +6,9 @@
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import ArgInput from './ArgInput.svelte'
import { Button } from './common'
import InputTransformForm from './InputTransformForm.svelte'
import ItemPicker from './ItemPicker.svelte'
import VariableEditor from './VariableEditor.svelte'
export let inputTransform = false
export let schema: Schema
export let args: Record<string, InputTransform | any> = {}
export let disabledArgs: string[] = []
@@ -18,16 +16,12 @@
export let editableSchema = false
export let isValid: boolean = true
export let extraLib: string = 'missing extraLib'
export let autofocus = false
export let previousModuleId: string | undefined = undefined
export let shouldHideNoInputs: boolean = false
export let compact = false
export let password: string | undefined = undefined
export let noVariablePicker = false
export let filter: string[] | undefined = undefined
export let noDynamicToggle = false
export let flexWrap = false
export let noDelete = false
@@ -42,17 +36,19 @@
}
function removeExtraKey() {
const nargs = {}
Object.keys(args ?? {}).forEach((key) => {
if (!keys.includes(key)) {
delete args[key]
delete inputCheck[key]
if (keys.includes(key)) {
nargs[key] = args[key]
}
})
args = nargs
}
let pickForField: string | undefined
let itemPicker: ItemPicker | undefined = undefined
let variableEditor: VariableEditor | undefined = undefined
let keys: string[] = []
$: {
let lkeys = Object.keys(schema?.properties ?? {})
@@ -68,48 +64,60 @@
<div class="w-full {clazz} {flexWrap ? 'flex flex-row flex-wrap gap-x-6 gap-y-2' : ''}">
{#if keys.length > 0}
{#each keys as argName, i (argName)}
{#if (!filter || filter.includes(argName)) && Object.keys(schema.properties ?? {}).includes(argName)}
{#if Object.keys(schema.properties ?? {}).includes(argName)}
<div>
{#if inputTransform}
<InputTransformForm
{previousModuleId}
bind:arg={args[argName]}
bind:schema
bind:argName
bind:inputCheck={inputCheck[argName]}
bind:extraLib
{variableEditor}
{itemPicker}
bind:pickForField
{noDynamicToggle}
/>
{:else if typeof args == 'object' && schema?.properties[argName]}
<ArgInput
autofocus={i == 0 && autofocus}
label={argName}
bind:description={schema.properties[argName].description}
bind:value={args[argName]}
type={schema.properties[argName].type}
required={schema.required.includes(argName)}
bind:pattern={schema.properties[argName].pattern}
bind:valid={inputCheck[argName]}
defaultValue={schema.properties[argName].default}
bind:enum_={schema.properties[argName].enum}
bind:format={schema.properties[argName].format}
contentEncoding={schema.properties[argName].contentEncoding}
properties={schema.properties[argName].properties}
bind:itemsType={schema.properties[argName].items}
disabled={disabledArgs.includes(argName) || disabled}
{editableSchema}
{compact}
password={argName == password}
{variableEditor}
{itemPicker}
bind:pickForField
bind:extra={schema.properties[argName]}
/>
{:else}
Expected argument to be an object, got {JSON.stringify(args)} instead
{#if typeof args == 'object' && schema?.properties[argName]}
{#if editableSchema}
<ArgInput
autofocus={i == 0 && autofocus}
label={argName}
bind:description={schema.properties[argName].description}
bind:value={args[argName]}
type={schema.properties[argName].type}
required={schema.required.includes(argName)}
bind:pattern={schema.properties[argName].pattern}
bind:valid={inputCheck[argName]}
defaultValue={schema.properties[argName].default}
bind:enum_={schema.properties[argName].enum}
bind:format={schema.properties[argName].format}
contentEncoding={schema.properties[argName].contentEncoding}
properties={schema.properties[argName].properties}
bind:itemsType={schema.properties[argName].items}
disabled={disabledArgs.includes(argName) || disabled}
{editableSchema}
{compact}
password={argName == password}
{variableEditor}
{itemPicker}
bind:pickForField
bind:extra={schema.properties[argName]}
/>
{:else}
<ArgInput
autofocus={i == 0 && autofocus}
label={argName}
description={schema.properties[argName].description}
bind:value={args[argName]}
type={schema.properties[argName].type}
required={schema.required.includes(argName)}
pattern={schema.properties[argName].pattern}
bind:valid={inputCheck[argName]}
defaultValue={schema.properties[argName].default}
enum_={schema.properties[argName].enum}
format={schema.properties[argName].format}
contentEncoding={schema.properties[argName].contentEncoding}
properties={schema.properties[argName].properties}
itemsType={schema.properties[argName].items}
disabled={disabledArgs.includes(argName) || disabled}
{editableSchema}
{compact}
password={argName == password}
{variableEditor}
{itemPicker}
bind:pickForField
extra={schema.properties[argName]}
/>
{/if}
{/if}
</div>
{/if}
@@ -124,11 +132,7 @@
bind:this={itemPicker}
pickCallback={(path, _) => {
if (pickForField) {
if (inputTransform) {
args[pickForField].value = '$var:' + path
} else {
args[pickForField] = '$var:' + path
}
args[pickForField] = '$var:' + path
}
}}
itemName="Variable"
@@ -23,12 +23,26 @@
$: state = $worldStore?.state
$: lastInput && $worldStore && handleConnection()
$: lastInput && lastInput.type == 'template' && $state && (value = getValue(lastInput))
$: lastInput && lastInput.type == 'eval' && $state && (value = evalExpr(lastInput))
let timeout: NodeJS.Timeout | undefined = undefined
const debounce_ms = 50
function debounce(cb: () => void) {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(cb, debounce_ms)
}
$: lastInput && $worldStore && debounce(handleConnection)
$: lastInput &&
lastInput.type == 'template' &&
$state &&
debounce(() => (value = getValue(lastInput)))
$: lastInput &&
lastInput.type == 'eval' &&
$state &&
debounce(() => (value = evalExpr(lastInput)))
function handleConnection() {
// console.log('handle connection', id, lastInput)
if (lastInput.type === 'connected') {
$worldStore?.connect<any>(lastInput, onValueChange)
} else if (lastInput.type === 'static' || lastInput.type == 'template') {
@@ -108,6 +122,7 @@
}
function onValueChange(newValue: any): void {
console.log('newValue', newValue, id)
if (lastInput.type === 'connected' && newValue !== undefined && newValue !== null) {
const { connection } = lastInput
@@ -72,7 +72,7 @@
mounted = true
})
$: mounted && ($worldStore = buildWorld($staticOutputs, undefined, context))
$: mounted && ($worldStore = buildWorld($staticOutputs, $worldStore, context))
$: width = $breakpoint === 'sm' ? 'max-w-[640px]' : 'w-full '
$: lockedClasses = isLocked ? '!max-h-[400px] overflow-hidden pointer-events-none' : ''
</script>
@@ -94,7 +94,6 @@
{#if isLocked}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
transition:fade|local={{ duration: 200, easing: cubicOut }}
on:click={() => (isLocked = false)}
class="absolute inset-0 center-center bg-black/20 z-50 backdrop-blur-[1px] cursor-pointer"
>
@@ -64,6 +64,8 @@
// @ts-ignore
let container
// $: containerHeight = subGrid.map((item) => columnConfiguration.map((c) => item[c[1]].h))
</script>
<div
@@ -36,11 +36,8 @@ export function createNewGridItem(grid: GridItem[], id: string, data: AppCompone
appComponent.id = id
const newComponent = {
fixed: false,
resizable: true,
draggable: true,
customDragger: false,
customResizer: false,
x: 0,
y: 0
}
@@ -60,7 +57,10 @@ export function createNewGridItem(grid: GridItem[], id: string, data: AppCompone
min: { w: 1, h: 1 },
max: { w: column, h: 100 },
w: rec.w,
h: rec.h
h: rec.h,
customDragger: false,
customResizer: false,
fixed: false
}
const position = gridHelp.findSpace(newItem, grid, column) as { x: number; y: number }
newItem[column] = { ...newItem[column], ...position }
@@ -61,7 +61,7 @@
<div
class="overflow-auto min-w-[150px] border-t w-full relative flex flex-col gap-4 px-2 pt-4 pb-2"
>
<div class="relative">
<div class="relative {$connectingInput?.opened ? 'bg-white z-50' : ''}">
<input
bind:value={search}
class="px-2 py-1 border border-gray-300 rounded-sm {search ? 'pr-8' : ''}"
@@ -79,7 +79,7 @@
<InlineScriptEditorDrawer {editor} bind:this={inlineScriptEditorDrawer} bind:inlineScript />
<div class="h-full flex flex-col gap-1" transition:fly|local={{ duration: 50 }}>
<div class="h-full flex flex-col gap-1">
<div class="flex justify-between w-full gap-2 px-2 pt-1 flex-row items-center">
{#if name !== undefined}
<input bind:value={name} placeholder="Inline script name" class="!text-xs !rounded-xs" />
@@ -191,7 +191,7 @@
</Button>
</div>
{#if viewCssOptions}
<div transition:slide>
<div transition:slide|local>
{#each Object.keys(component.customCss ?? {}) as name}
{#if component?.customCss?.[name]}
<div class="w-full mb-2">
+1 -42
View File
@@ -4,13 +4,11 @@ import { inferArgs } from '$lib/infer'
import { emptySchema } from '$lib/utils'
import type { AppComponent } from './editor/component'
import type { App, ComponentCssProperty, ComponentCustomCSS, GridItem } from './types'
import { getRecommendedDimensionsByComponent } from './editor/component'
import { gridColumns } from './gridUtils'
import gridHelp from '@windmill-labs/svelte-grid/src/utils/helper'
import { twMerge } from 'tailwind-merge'
import type { AppInput, InputType, ResultAppInput, StaticAppInput } from './inputType'
import type { Output } from './rx'
import { getNextId } from '../flows/flowStateUtils'
import { createNewGridItem } from './editor/appUtils'
export function allItems(
grid: GridItem[],
@@ -283,45 +281,6 @@ export function insertNewGridItem(
return root
}
// The grid is needed to find a space for the new component
export function createNewGridItem(grid: GridItem[], id: string, data: AppComponent): GridItem {
const appComponent = data
appComponent.id = id
const newComponent = {
fixed: false,
resizable: true,
draggable: true,
customDragger: false,
customResizer: false,
x: 0,
y: 0
}
let newData: AppComponent = JSON.parse(JSON.stringify(appComponent))
const newItem: GridItem = {
data: newData,
id: id
}
gridColumns.forEach((column) => {
const rec = getRecommendedDimensionsByComponent(appComponent.type, column)
newItem[column] = {
...newComponent,
min: { w: 1, h: 1 },
max: { w: column, h: 100 },
w: rec.w,
h: rec.h
}
const position = gridHelp.findSpace(newItem, grid, column) as { x: number; y: number }
newItem[column] = { ...newItem[column], ...position }
})
return newItem
}
function recursiveGetIds(gridItem: GridItem): string[] {
const subGrids = gridItem.data.subGrids ?? []
@@ -9,6 +9,7 @@
import type { PropPickerWrapperContext } from '../propPicker/PropPickerWrapper.svelte'
import { writable } from 'svelte/store'
import Toggle from '../../Toggle.svelte'
import InputTransformSchemaForm from '$lib/components/InputTransformSchemaForm.svelte'
let hideOptional = false
@@ -75,9 +76,8 @@
<Badge large color="indigo">{m.id}</Badge>
</h2>
<SchemaForm
<InputTransformSchemaForm
noDynamicToggle
inputTransform
{filter}
class="mt-2"
schema={$flowStateStore[m.id]?.schema ?? {}}
@@ -28,6 +28,7 @@
import Alert from '$lib/components/common/alert/Alert.svelte'
import FlowModuleSleep from './FlowModuleSleep.svelte'
import FlowPathViewer from './FlowPathViewer.svelte'
import InputTransformSchemaForm from '$lib/components/InputTransformSchemaForm.svelte'
const { selectedId, previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
@@ -225,9 +226,8 @@
pickableProperties={stepPropPicker.pickableProperties}
error={failureModule}
>
<SchemaForm
<InputTransformSchemaForm
schema={$flowStateStore[$selectedId]?.schema ?? {}}
inputTransform={true}
previousModuleId={previousModule?.id}
bind:args={value.input_transforms}
bind:extraLib={stepPropPicker.extraLib}
+1 -1
View File
@@ -46,7 +46,7 @@ declare module '@windmill-labs/svelte-grid' {
default: { item: ItemLayout; dataItem: Item<T> & { data: AppComponent } }
}
export default class Grid<T = {}> extends SvelteComponentTyped<Props<T>, {}, Slots<T>> {}
export default class Grid<T = {}> extends SvelteComponentTyped<Props<T>, {}, Slots<T>> { }
}
declare module '@windmill-labs/svelte-grid/build/helper/index.mjs' {