mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-22 08:02:19 +00:00
a689c0b0f1
* runs on svelte 5
* Line component from svelte-chartjs
* Replaced all svelte-chartjs occurrences with custom wrapper
* Fix props mistake
* Fix illegal table structures
* self-closing-tags fix
* aria labels
* Fixed trivial warnings and errors
* @tanstack/svelte-table fix
* upgrade to vite 6
* svelte-kit sync before running svelte-check
* Remove on:clear which is actually on:removeAll and already handled by on:change
* fix worker tags not displaying in Autoscaling
* Try to fix svelte-kit sync not working during CI
* remove warnings
* Fix add flow page crashing
* access worldStore before assignment fix
* fix infinite recursions in App Editor
* Replaced JSON.stringify with proper deepEqual
* component mount api changed (no longer classes)
* fix ci errors
* Fix infinite loops in background runnable panel
* factored effect on deep equal logic in onObjChange
* fix "Add" not working in AgGrid Table
* Replaced legacy component.$set api
* Fix multiselect infinite value reaction
* Fix flow input fields resetting when opening their edit tab
* fix date input resetting when typing year
* Remove !p-0 affecting subgrid dotted borders
* fix missing debounceTemplate causing hundreds of updates
* Fix AgGrid action refreshes and disppearing
* resolve getItems generating random ids every rerun
* fix cannot access items before init
* fix sort lambda arguments being undefined
* Revert "Remove !p-0 affecting subgrid dotted borders"
This reverts commit c62809bb45d682a48376b071680645ed4e1c601b.
* fix input not updating in decision tree editor
* Update frontend/src/lib/components/schema/EditableSchemaWrapper.svelte
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
* Re-added padding affecting subgrid dotted borders (#5479)
* remove !p-0 in preset components
* removed extra padding on accordion tabs subgrid
* Fix non-reactive SchemaForm
* dirty fix for the oneOf bug
* feat: add nu-lang support (#5217)
* feat: add nu (nushell) support
* add worker tests
* deactivate tables and non-any types below top-level
full support will come in V1
for V0 it's better to keep things minimal and simple
* add syntax highlighting
used python's grammar, since nushell isn't supported by monaco nor svelte-highlights
for V1 nu will get it`s own grammar
* add logo
* partially implement plugin support
* change logo + ability to deploy + nsjail draft
* static variables + get_resource + get_variable
* lsp/dev.nu + initial nu lsp (not working yet)
* make it work with nsjail
* nullguard
* Much more flexible signature parsing and better error-messages
* add init script
* rename nulsp to nu
* install nu to dockerfile
* fix merge
* implement Default for MainArgSignature
* stage NU_CACHE_DIR
* improve dockerfiles
* dev.nu for parser-wasm + flake.nix
* update code for windows
* add nushell to flake
* upload Cargo.lock
* make build.sh work on nixos
* build wasm cli parsers
* add docs to README_DEV.md
* add helper script docker/dev.nu
* improve docker/dev.nu
* fix windows
* commit frontend/package(lock).json
* update cargo.lock
* correctly update cargo.lock
* remove lsp
* update flake.nix to include svelte server and nushell
* Revert base.sql to main
* remove PLUGIN_USE_RE
* make CARGO_PATH private
* add nu to cli
* Change flags to build wasm-nu-parser
* remove flake.nix from parser-wasm
* update wasm-build target
* remove unused import
* add cli support for nu
* update github workflows
* wasm-build 0.17 -> 0.19
* update build script
* update cargo.lock
* Fix typographical error
* update Cargo.lock
* update ENV_SETTINGS
* use published nu parser
* update package.lock
* rewrite parser in tree-sitter
* implement parser from scratch
* polishing
* change init script to match new parser
* fix imports
* fix cli build
* fix cli build
* merge
* update wasm
* use MiniPulledJob
* update cli
* change cli wasm schema
* change cli
* update deno.json
* make wasm modules load lazily
* regenerate parsers
* remove leftover
* update cargo.lock
* clean up dnt.ts
* add docs to cli/test.nu
* add schema validation option
* add Nu to try_validate_schema
* reference frontend to new parser version
* feat: unsafe parameters for sql queries (table names, column names) (#5488)
* Make schema validation struct
Schema Validation rules that are constructed from the schema or from the
MainArgSig(TODO).
* Make other validator builder
* Fail dependency job like with lockfile failing for schema validator
* Add last types + tests
* Remove unused dependency
* fix typos
* Migration ID was colliding with another, changed it manually
* Add Oneof + other fixes
* fix: cache for querying scripts correclty handles ScriptMetadata
* Add cache for schema validation from main arg sig
* Prepare sqlx
* Remove default features
* Feature flags
* WIP: unsafe sql params for sql langauges
* Fix down migration table name
* cleanup: put validation logic inside a function
* Refactor to cache the should_validate boolean
Changed the schemavalidators cache to take in an
Option<SchemaValidator>, effectively storing the `should_validate_schema` information.
Also pass the schema when avaialble to construct the schema validator
* Add other job kinds to u8 cache key just in case
* Change sql languages to all get arguments as Values instead of RawValue
* Only cache if not preview
* Add last sql languages and some CI fixes
* Rename after typo on `sanitized`
* Finish rename
* Remove unused import
* Fix wrong test
* Add newly published regex parser version
* Remove default features from cargo.toml
* Change to a cleaner syntax for the interpolated args
* Update republished parser
* fix win build (#5494)
* add sysinfoapi feature flag for winapi dependency
* add ff
* add ff at the right place
* fix(frontend): use stable path for capture tables + nits (#5495)
* add missing capture move on first time deploy (#5496)
* avoid regen client as build step
* perf: cache workspace env variables to avoid one query (#5499)
* perf: optimize number of queries needed for job run (#5504)
* optPerf
* update sqlx
* update sqlx
* fix: improve cancel for flows with many substeps
* feat: list references upon renaming a script or a flow (#5487)
* Refactored flow_workspace_runnables to more generic workspace_runnable_dependencies
* list flows referencing an item upon renaming it
* Refactor with two exclusive columns to avoid breaking FK constraints
* Show apps depending on item upon renaming
* sqlx prepare
* list-disc instead of •
* on delete and on update cascade
* displayPathChangedWarning oneOf check instead noneOf
* combine migrations + add "on update cascade" to flow fk
* unique index on app dependencies to avoid duplicates
* create new workspace_runnable_dependencies instead of renaming old table
* Add "looking for references" loading msg
* Revert "create new workspace_runnable_dependencies instead of renaming old table"
This reverts commit 015c38ca8f.
* flow_workspace_runnables view for backwards compatibility
* Add warning for script imports on rename
* support import dependency tracking in deno
* number of using scripts / flows / apps tooltip
* forgot sqlx prepare
* delete app-related rows in down migration
* Made selection more generic
* RunsBatchActionsDropdown refactor
* started BatchReRunOptionsPane
* fix overflow quirk
* fetch schema
* refactor to group jobs by (kind, path)
* auto select
* computePropertyMap
* InputTransformForm works
* Pickable properties
* remove PropPickerWrapper and make it optional in InputTransformForm
* hide help btn
* available expressions info alert
* extraLib for editor linting
* fix selected group not updating
* nit
* Refactor async logic in script tag
* persist changes in state
* correct typing
* count for each (path, kind) group
* support flows
* use dot operator when possible
* count jobs and fix wrong number
* fix selectedJobs recomputing periodically
* (v0) individual api requests to re-run jobs
* move batchReRunChangedArgs state upwards
* Support static arg
* mistake
* Single confirmation modal + removed unnecessary state
* change confirmation modal color
* use runes in confirmation modal
* listSelectedJobsSchema API endpoint
* refactored batch rerun pane for listSelectedJobsSchema
* eliminated selectedJobs
* batch rerun works backend (v0 same args)
* Static input transforms
* simpler list_selected_jobs_schemas sql query with coalesce
* use latest schema UI + refactor
* run latest version in backend
* add deno_core dependency to windmill-api
* stream jobs from db
* basic js evaluation
* sqlx prepare
* add id path and hash in editor lint
* js works with job object!
* moved deno_core logic to separate function
* openapi yaml mistake
* unnecessary bind
* fix date as string
* Stream re-ran uuids
* handle SSE multiple values at once
* don't select all by default on batch action
* nit ui
* check that schema has property backend
* Better JobGroup query + cache
* handle multi type properties
* Notify user on error
* stupid mistake
* Fix warnings and update svelte-exmarkdown for svelte 5
* regen package-lock to fix crash on vite preview
* batch re-run all filtered jobs
* merge schemas to common type
* more explicit tooltips
* changed sse counter ui
* typos
* fix tutorial first part
* nit mistake
* package lock + elipsis nit
* fix: latest_schema option still checked on the job original schema
* always gotta forget sqlx prepare
* fix flashing loading screen
* fix batch re-run select all filtered
* better tooltip
* fix batch actions btn growing on wide screen
* revert disableBatchActions
* fix selectable step jobs
---------
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Co-authored-by: pyranota <92104930+pyranota@users.noreply.github.com>
Co-authored-by: wendrul <53628737+wendrul@users.noreply.github.com>
Co-authored-by: Alexander Petric <alpetric@users.noreply.github.com>
Co-authored-by: HugoCasa <hugo@casademont.ch>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
632 lines
18 KiB
Svelte
632 lines
18 KiB
Svelte
<script context="module">
|
|
const dynamicTemplateRegexPairs = buildPrefixRegex([
|
|
'flow_input',
|
|
'results',
|
|
'resource',
|
|
'variable'
|
|
])
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
import type { Schema } from '$lib/common'
|
|
import type { InputCat } from '$lib/utils'
|
|
import { createEventDispatcher, getContext } from 'svelte'
|
|
|
|
import ArgInput from './ArgInput.svelte'
|
|
import FieldHeader from './FieldHeader.svelte'
|
|
import DynamicInputHelpBox from './flows/content/DynamicInputHelpBox.svelte'
|
|
import type { PropPickerWrapperContext } from './flows/propPicker/PropPickerWrapper.svelte'
|
|
import { codeToStaticTemplate, getDefaultExpr } from './flows/utils'
|
|
import SimpleEditor from './SimpleEditor.svelte'
|
|
import { Button } from '$lib/components/common'
|
|
import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte'
|
|
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
|
|
import { tick } from 'svelte'
|
|
import { fade } from 'svelte/transition'
|
|
import { buildPrefixRegex } from './flows/previousResults'
|
|
import type VariableEditor from './VariableEditor.svelte'
|
|
import type ItemPicker from './ItemPicker.svelte'
|
|
import type { InputTransform } from '$lib/gen'
|
|
import TemplateEditor from './TemplateEditor.svelte'
|
|
import { setInputCat as computeInputCat, isCodeInjection } from '$lib/utils'
|
|
import { FunctionSquare, InfoIcon } from 'lucide-svelte'
|
|
import { getResourceTypes } from './resourceTypesStore'
|
|
import type { FlowCopilotContext } from './copilot/flow'
|
|
import StepInputGen from './copilot/StepInputGen.svelte'
|
|
import type { PickableProperties } from './flows/previousResults'
|
|
import { twMerge } from 'tailwind-merge'
|
|
import FlowPlugConnect from './FlowPlugConnect.svelte'
|
|
export let schema: Schema | { properties?: Record<string, any>; required?: string[] }
|
|
export let arg: InputTransform | any
|
|
export let argName: string
|
|
export let headerTooltip: string | undefined = undefined
|
|
export let headerTooltipIconClass = ''
|
|
export let HeaderTooltipIcon = InfoIcon
|
|
export let extraLib: string = 'missing extraLib'
|
|
export let inputCheck: boolean = true
|
|
export let previousModuleId: string | undefined
|
|
export let pickForField: string | undefined = undefined
|
|
export let variableEditor: VariableEditor | undefined = undefined
|
|
export let itemPicker: ItemPicker | undefined = undefined
|
|
export let noDynamicToggle = false
|
|
export let argExtra: Record<string, any> = {}
|
|
export let pickableProperties: PickableProperties | undefined = undefined
|
|
export let enableAi = false
|
|
export let hideHelpButton = false
|
|
|
|
let monaco: SimpleEditor | undefined = undefined
|
|
let monacoTemplate: TemplateEditor | undefined = undefined
|
|
let argInput: ArgInput | undefined = undefined
|
|
let focusedPrev = false
|
|
|
|
const dispatch = createEventDispatcher()
|
|
|
|
$: inputCat = computeInputCat(
|
|
schema?.properties?.[argName].type,
|
|
schema?.properties?.[argName].format,
|
|
schema?.properties?.[argName].items?.type,
|
|
schema?.properties?.[argName].enum,
|
|
schema?.properties?.[argName].contentEncoding
|
|
)
|
|
|
|
let propertyType = getPropertyType(arg)
|
|
|
|
const { shouldUpdatePropertyType, exprsToSet } =
|
|
getContext<FlowCopilotContext | undefined>('FlowCopilotContext') || {}
|
|
|
|
const propPickerWrapperContext: PropPickerWrapperContext | undefined =
|
|
getContext<PropPickerWrapperContext>('PropPickerWrapper')
|
|
const { inputMatches, focusProp, propPickerConfig, clearFocus } = propPickerWrapperContext ?? {}
|
|
|
|
function setExpr() {
|
|
const newArg = $exprsToSet?.[argName]
|
|
if (newArg) {
|
|
if (newArg.type === 'javascript') {
|
|
propertyType = 'javascript'
|
|
arg = {
|
|
type: 'javascript',
|
|
expr: newArg.expr
|
|
}
|
|
monaco?.setCode(arg.expr)
|
|
}
|
|
// copilot only sets javascript so static case is not handled
|
|
}
|
|
exprsToSet?.set({
|
|
...$exprsToSet,
|
|
[argName]: undefined
|
|
})
|
|
}
|
|
|
|
$: $exprsToSet?.[argName] && setExpr()
|
|
|
|
function updatePropertyType() {
|
|
propertyType = $shouldUpdatePropertyType?.[argName] || 'static'
|
|
shouldUpdatePropertyType?.set({
|
|
...$shouldUpdatePropertyType,
|
|
[argName]: undefined
|
|
})
|
|
}
|
|
|
|
$: $shouldUpdatePropertyType?.[argName] &&
|
|
arg?.type === $shouldUpdatePropertyType?.[argName] &&
|
|
updatePropertyType()
|
|
|
|
function getPropertyType(arg: InputTransform | any): 'static' | 'javascript' {
|
|
let type: 'static' | 'javascript' = arg?.type ?? 'static'
|
|
|
|
if (
|
|
type == 'javascript' &&
|
|
isStaticTemplate(inputCat) &&
|
|
(arg?.expr?.length === 0 || arg?.expr?.[0] === '`')
|
|
) {
|
|
const newValue = codeToStaticTemplate(arg.expr)
|
|
if (newValue) {
|
|
type = 'static'
|
|
arg.value = newValue
|
|
}
|
|
}
|
|
|
|
return type
|
|
}
|
|
|
|
function setPropertyType(rawValue: string) {
|
|
if (!arg) {
|
|
return
|
|
}
|
|
|
|
if (isCodeInjection(rawValue)) {
|
|
arg.expr = getDefaultExpr(
|
|
argName,
|
|
previousModuleId,
|
|
`\`${rawValue.toString().replaceAll('`', '\\`')}\``
|
|
)
|
|
arg.type = 'javascript'
|
|
propertyType = 'static'
|
|
} else {
|
|
if (arg.type === 'javascript' && propertyType === 'static') {
|
|
arg.type = 'static'
|
|
}
|
|
if (arg.type) {
|
|
propertyType = arg.type
|
|
}
|
|
}
|
|
}
|
|
|
|
let codeInjectionDetected = false
|
|
|
|
function checkCodeInjection(rawValue: string) {
|
|
if (!arg || !rawValue || rawValue.length < 3 || !dynamicTemplateRegexPairs) {
|
|
return undefined
|
|
}
|
|
if (rawValue.trim() !== rawValue) {
|
|
return undefined
|
|
}
|
|
const matches = dynamicTemplateRegexPairs.filter(({ regex }) => regex.test(rawValue))
|
|
if (matches.length > 0) {
|
|
return matches.map((m) => ({ word: m.word, value: rawValue }))
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
async function setJavaScriptExpr(rawValue: string) {
|
|
arg = {
|
|
type: 'javascript',
|
|
expr: rawValue
|
|
}
|
|
propertyType = 'javascript'
|
|
monaco?.setCode('')
|
|
monaco?.insertAtCursor(rawValue)
|
|
await tick()
|
|
monaco?.focus()
|
|
await tick()
|
|
monaco?.setCursorToEnd()
|
|
}
|
|
|
|
function handleKeyUp(e: KeyboardEvent) {
|
|
if (
|
|
e.key === 'Tab' &&
|
|
isStaticTemplate(inputCat) &&
|
|
propertyType == 'static' &&
|
|
!noDynamicToggle &&
|
|
codeInjectionDetected
|
|
) {
|
|
setJavaScriptExpr(arg.value)
|
|
} else {
|
|
stepInputGen?.onKeyUp?.(e)
|
|
}
|
|
}
|
|
|
|
function isStaticTemplate(inputCat: InputCat) {
|
|
return inputCat === 'string' || inputCat === 'sql' || inputCat == 'yaml'
|
|
}
|
|
|
|
function connectProperty(rawValue: string) {
|
|
// Extract path from variable('x') or resource('x') format
|
|
const varMatch = rawValue.match(/^variable\('([^']+)'\)$/)
|
|
const resourceMatch = rawValue.match(/^resource\('([^']+)'\)$/)
|
|
|
|
if (varMatch) {
|
|
arg.type = 'static'
|
|
propertyType = 'static'
|
|
arg.value = '$var:' + varMatch[1]
|
|
monacoTemplate?.setCode(arg.value)
|
|
} else if (resourceMatch) {
|
|
arg.type = 'static'
|
|
propertyType = 'static'
|
|
arg.value = '$res:' + resourceMatch[1]
|
|
monacoTemplate?.setCode(arg.value)
|
|
} else {
|
|
arg.expr = getDefaultExpr(undefined, previousModuleId, rawValue)
|
|
arg.type = 'javascript'
|
|
propertyType = 'javascript'
|
|
monaco?.setCode(arg.expr)
|
|
}
|
|
}
|
|
|
|
function onFocus() {
|
|
focused = true
|
|
if (isStaticTemplate(inputCat)) {
|
|
focusProp?.(argName, 'append', (path) => {
|
|
const toAppend = `\$\{${path}}`
|
|
arg.value = `${arg.value ?? ''}${toAppend}`
|
|
monacoTemplate?.setCode(arg.value)
|
|
setPropertyType(arg.value)
|
|
argInput?.focus()
|
|
return false
|
|
})
|
|
} else {
|
|
focusProp?.(argName, 'insert', (path) => {
|
|
arg.expr = path
|
|
arg.type = 'javascript'
|
|
propertyType = 'javascript'
|
|
monaco?.setCode(arg.expr)
|
|
return true
|
|
})
|
|
}
|
|
}
|
|
|
|
$: updateStaticInput(inputCat, propertyType, arg)
|
|
|
|
function updateStaticInput(
|
|
inputCat: InputCat,
|
|
propertyType: 'static' | 'javascript',
|
|
arg: InputTransform | any
|
|
) {
|
|
if (!isStaticTemplate(inputCat)) {
|
|
return
|
|
}
|
|
if (propertyType == 'static') {
|
|
setPropertyType(arg?.value)
|
|
codeInjectionDetected = checkCodeInjection(arg?.value) != undefined
|
|
} else if (propertyType == 'javascript' && focused && inputMatches) {
|
|
// setPropertyType(arg?.expr)
|
|
$inputMatches = checkCodeInjection(arg?.expr)
|
|
}
|
|
}
|
|
|
|
function setDefaultCode() {
|
|
if (!arg?.value) {
|
|
monacoTemplate?.setCode(schema.properties?.[argName].default)
|
|
}
|
|
}
|
|
|
|
function updateFocused(newFocused: boolean) {
|
|
if (focusedPrev && !newFocused && inputMatches) {
|
|
$inputMatches = undefined
|
|
}
|
|
focusedPrev = focused
|
|
}
|
|
$: updateFocused(focused)
|
|
|
|
$: schema?.properties?.[argName].default && setDefaultCode()
|
|
|
|
let resourceTypes: string[] | undefined = undefined
|
|
|
|
async function loadResourceTypes() {
|
|
resourceTypes = await getResourceTypes()
|
|
}
|
|
|
|
let focused = false
|
|
let stepInputGen: StepInputGen | undefined = undefined
|
|
|
|
loadResourceTypes()
|
|
|
|
$: connecting =
|
|
$propPickerConfig?.propName == argName && $propPickerConfig?.insertionMode == 'connect'
|
|
</script>
|
|
|
|
{#if arg != undefined}
|
|
<div
|
|
class={twMerge(
|
|
'pl-2 pt-2 pb-2 ml-2 relative hover:bg-surface hover:shadow-md transition-all duration-200',
|
|
$propPickerConfig?.propName == argName
|
|
? 'bg-surface border-l-4 border-blue-500 shadow-md rounded-l-md z-50 '
|
|
: 'hover:rounded-md',
|
|
$$props.class
|
|
)}
|
|
>
|
|
<div class="flex flex-row justify-between gap-1 pb-1 px-2">
|
|
<div class="flex flex-wrap grow">
|
|
<FieldHeader
|
|
label={argName}
|
|
simpleTooltip={headerTooltip}
|
|
simpleTooltipIconClass={headerTooltipIconClass}
|
|
SimpleTooltipIcon={HeaderTooltipIcon}
|
|
format={schema?.properties?.[argName].format}
|
|
contentEncoding={schema?.properties?.[argName].contentEncoding}
|
|
required={schema.required?.includes(argName)}
|
|
type={schema.properties?.[argName].type}
|
|
/>
|
|
|
|
{#if isStaticTemplate(inputCat)}
|
|
<div>
|
|
<span
|
|
class="bg-blue-100 text-blue-800 text-sm font-medium mr-2 px-2.5 !py-0.5 rounded ml-2 {propertyType ==
|
|
'static' && arg.type === 'javascript'
|
|
? 'visible'
|
|
: 'invisible'}"
|
|
>
|
|
{'${...}'}
|
|
</span>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{#if !noDynamicToggle}
|
|
<div class="flex flex-row gap-x-2 gap-y-1 flex-wrap z-10 items-center">
|
|
{#if enableAi}
|
|
<StepInputGen
|
|
bind:this={stepInputGen}
|
|
{focused}
|
|
{arg}
|
|
schemaProperty={schema?.properties?.[argName]}
|
|
showPopup={(isStaticTemplate(inputCat) && propertyType == 'static') ||
|
|
propertyType === undefined ||
|
|
propertyType === 'static' ||
|
|
arg?.expr?.length > 0}
|
|
on:showExpr={(e) => {
|
|
setTimeout(() => {
|
|
if (monaco && propertyType === 'javascript') {
|
|
monaco.setSuggestion(e.detail)
|
|
}
|
|
}, 0)
|
|
}}
|
|
on:setExpr={(e) => {
|
|
arg = {
|
|
type: 'javascript',
|
|
expr: e.detail
|
|
}
|
|
propertyType = 'javascript'
|
|
monaco?.setCode('')
|
|
monaco?.insertAtCursor(e.detail)
|
|
}}
|
|
{pickableProperties}
|
|
{argName}
|
|
/>
|
|
{/if}
|
|
<div>
|
|
<ToggleButtonGroup
|
|
selected={propertyType}
|
|
let:item
|
|
on:selected={(e) => {
|
|
if (e.detail == propertyType) return
|
|
const staticTemplate = isStaticTemplate(inputCat)
|
|
if (e.detail === 'javascript') {
|
|
if (arg.expr == undefined) {
|
|
arg.expr = getDefaultExpr(
|
|
argName,
|
|
previousModuleId,
|
|
staticTemplate
|
|
? `\`${arg?.value?.toString().replaceAll('`', '\\`') ?? ''}\``
|
|
: arg.value
|
|
? '(' + JSON.stringify(arg?.value, null, 4) + ')'
|
|
: ''
|
|
)
|
|
}
|
|
if (arg) {
|
|
arg.value = undefined
|
|
arg.type = 'javascript'
|
|
}
|
|
propertyType = 'javascript'
|
|
} else {
|
|
if (staticTemplate) {
|
|
if (arg) {
|
|
arg.value = codeToStaticTemplate(arg.expr)
|
|
arg.expr = undefined
|
|
}
|
|
setPropertyType(arg?.value)
|
|
} else if (inputCat == 'list' || inputCat == 'object') {
|
|
if (arg) {
|
|
try {
|
|
let newExpr = arg.expr
|
|
if (newExpr.startsWith('(') && newExpr.endsWith(')')) {
|
|
newExpr = newExpr.slice(1, -1)
|
|
}
|
|
arg.value = JSON.parse(newExpr)
|
|
} catch (e) {
|
|
arg.value = undefined
|
|
}
|
|
arg.expr = undefined
|
|
arg.type = 'static'
|
|
}
|
|
} else {
|
|
if (arg) {
|
|
arg.type = 'static'
|
|
arg.value = undefined
|
|
arg.expr = undefined
|
|
}
|
|
}
|
|
propertyType = 'static'
|
|
}
|
|
}}
|
|
>
|
|
{#if isStaticTemplate(inputCat)}
|
|
<ToggleButton
|
|
tooltip={`Write text or surround javascript with \`\$\{\` and \`\}\`. Use \`results\` to connect to another node\'s output.`}
|
|
light
|
|
value="static"
|
|
size="xs2"
|
|
label={'${}'}
|
|
{item}
|
|
/>
|
|
{:else}
|
|
<ToggleButton small label="Static" value="static" {item} />
|
|
{/if}
|
|
|
|
{#if codeInjectionDetected && propertyType == 'static'}
|
|
<Button
|
|
size="xs2"
|
|
color="light"
|
|
btnClasses="font-normal text-xs w-fit bg-green-100 text-green-800 hover:bg-green-100 dark:text-green-300 dark:bg-green-700 dark:hover:bg-green-600"
|
|
on:click={() => setJavaScriptExpr(arg.value)}
|
|
>
|
|
<span class="font-normal whitespace-nowrap flex gap-2 items-center"
|
|
><FunctionSquare size={14} /> detected -
|
|
<span class="font-bold">TAB</span>
|
|
</span>
|
|
</Button>
|
|
{:else}
|
|
<ToggleButton
|
|
small
|
|
light
|
|
tooltip="JavaScript expression ('flow_input' or 'results')."
|
|
value="javascript"
|
|
icon={FunctionSquare}
|
|
{item}
|
|
/>
|
|
{/if}
|
|
</ToggleButtonGroup>
|
|
</div>
|
|
|
|
{#if propPickerWrapperContext}
|
|
<FlowPlugConnect
|
|
id="flow-editor-plug"
|
|
{connecting}
|
|
on:click={() => {
|
|
if (
|
|
$propPickerConfig?.propName == argName &&
|
|
$propPickerConfig?.insertionMode == 'connect'
|
|
) {
|
|
clearFocus()
|
|
} else {
|
|
focusProp?.(argName, 'connect', (path) => {
|
|
connectProperty(path)
|
|
dispatch('change', { argName })
|
|
return true
|
|
})
|
|
}
|
|
}}
|
|
/>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="max-w-xs"></div>
|
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
<div class="relative" on:keyup={handleKeyUp}>
|
|
<!-- {#if $propPickerConfig?.propName == argName && $propPickerConfig?.insertionMode == 'connect'}
|
|
<span
|
|
class={'text-white z-50 px-1 text-2xs py-0.5 font-bold rounded-t-sm w-fit absolute top-0 right-0 bg-blue-500'}
|
|
>
|
|
Connect input →
|
|
</span>
|
|
{/if} -->
|
|
<!-- {inputCat}
|
|
{propertyType} -->
|
|
<div class="relative flex flex-row items-top gap-2 justify-between">
|
|
<div class="min-w-0 grow">
|
|
{#if isStaticTemplate(inputCat) && propertyType == 'static' && !noDynamicToggle}
|
|
{#if argName && schema?.properties?.[argName]?.description}
|
|
<div class="text-xs italic pb-1 text-secondary">
|
|
<pre class="font-main">{schema.properties[argName].description}</pre>
|
|
</div>
|
|
{/if}
|
|
<div class="mt-2 min-h-[28px]">
|
|
{#if arg}
|
|
<TemplateEditor
|
|
bind:this={monacoTemplate}
|
|
{extraLib}
|
|
on:focus={onFocus}
|
|
on:blur={() => {
|
|
focused = false
|
|
}}
|
|
bind:code={arg.value}
|
|
fontSize={14}
|
|
on:change={() => {
|
|
dispatch('change', { argName, arg })
|
|
}}
|
|
/>
|
|
{/if}
|
|
</div>
|
|
{:else if (propertyType === undefined || propertyType == 'static') && schema?.properties?.[argName]}
|
|
<ArgInput
|
|
{resourceTypes}
|
|
noMargin
|
|
compact
|
|
bind:this={argInput}
|
|
on:focus={onFocus}
|
|
on:blur={() => {
|
|
focused = false
|
|
}}
|
|
shouldDispatchChanges
|
|
on:change={() => {
|
|
dispatch('change', { argName, arg })
|
|
}}
|
|
label={argName}
|
|
bind:editor={monaco}
|
|
bind:description={schema.properties[argName].description}
|
|
bind:value={arg.value}
|
|
type={schema.properties[argName].type}
|
|
oneOf={schema.properties[argName].oneOf}
|
|
required={schema.required?.includes(argName)}
|
|
bind:pattern={schema.properties[argName].pattern}
|
|
bind:valid={inputCheck}
|
|
defaultValue={schema.properties[argName].default}
|
|
bind:enum_={schema.properties[argName].enum}
|
|
bind:format={schema.properties[argName].format}
|
|
contentEncoding={schema.properties[argName].contentEncoding}
|
|
bind:itemsType={schema.properties[argName].items}
|
|
properties={schema.properties[argName].properties}
|
|
nestedRequired={schema.properties[argName].required}
|
|
displayHeader={false}
|
|
extra={argExtra}
|
|
{variableEditor}
|
|
{itemPicker}
|
|
bind:pickForField
|
|
showSchemaExplorer
|
|
nullable={schema.properties[argName].nullable}
|
|
bind:title={schema.properties[argName].title}
|
|
bind:placeholder={schema.properties[argName].placeholder}
|
|
/>
|
|
{:else if arg.expr != undefined}
|
|
<div class="border mt-2">
|
|
<SimpleEditor
|
|
bind:this={monaco}
|
|
bind:code={arg.expr}
|
|
on:change={() => {
|
|
dispatch('change', { argName, arg })
|
|
}}
|
|
{extraLib}
|
|
lang="javascript"
|
|
shouldBindKey={false}
|
|
on:focus={() => {
|
|
focused = true
|
|
focusProp?.(argName, 'insert', (path) => {
|
|
monaco?.insertAtCursor(path)
|
|
return false
|
|
})
|
|
}}
|
|
on:change={() => {
|
|
dispatch('change', { argName, arg })
|
|
}}
|
|
on:blur={() => {
|
|
focused = false
|
|
}}
|
|
autoHeight
|
|
/>
|
|
</div>
|
|
{#if !hideHelpButton}
|
|
<DynamicInputHelpBox />
|
|
{/if}
|
|
<div class="mb-2"></div>
|
|
{:else}
|
|
Not recognized input type {argName} ({arg.expr}, {propertyType})
|
|
<div class="flex mt-2">
|
|
<Button
|
|
variant="border"
|
|
size="xs"
|
|
on:click={() => {
|
|
arg.expr = ''
|
|
}}>Set expr to empty string</Button
|
|
></div
|
|
>
|
|
{/if}
|
|
</div>
|
|
|
|
{#if $propPickerConfig?.propName == argName}
|
|
<div
|
|
class="text-blue-500 absolute top-2 lg:-right-2.5 -right-1"
|
|
in:fade={{ duration: 200 }}
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="24 24 12 12 24 0" />
|
|
</svg>
|
|
</div>
|
|
{:else}
|
|
<div class="w-0"></div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/if}
|