mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 16:05:42 +00:00
feat(flow): Add helper to add expression to arrays (#6629)
* Implement array expression helper for number arrays in JS mode - Add showArrayExprPicker state to manage helper UI - Add shouldShowArrayHelper() to check conditions (JS mode + number array) - Add 'Add item' button that shows picker UI when clicked - Implement picker row with disabled input, FlowPlugConnect, and Cancel button - Connect callback sets array expression [property] and updates Monaco editor - Include helpful text and proper cleanup on cancel/connect * Enhance array expression helper to append items to existing arrays - Check if current expr is already an array expression [...] - If it is, append new item to existing content: [existing, newItem] - If not or empty, create new array with single item: [newItem] - Update helper text to reflect append behavior - Maintains backward compatibility with non-array expressions * Add S3 resource array helper for JavaScript mode - Add shouldShowS3ArrayHelper() function to detect S3 resource arrays - Show direct FlowPlugConnect for S3 arrays instead of Add item button - Apply same append logic: add to existing array or create new one - Include helpful text explaining S3 resource connection - Support both s3_object and s3object resourceType variants * Add S3 resource catalog helper for static mode arrays - Add shouldShowS3ArrayStaticHelper() to detect S3 arrays in static mode - Show 'Add an object from the catalog' button below static S3 array inputs - Button switches to JavaScript mode and immediately activates connect mode - Sets initial empty array [] then replaces with [selectedPath] when connected - Includes helpful text explaining the mode switch and connection * Fix reactivity issue when switching from static to JS mode - Make button click handler async and await tick() before activating connect mode - Add Monaco editor update after setting expression in connect callback - Use tick().then() to ensure Monaco is available before calling setCode() - This ensures the SimpleEditor displays the new array expression immediately * Add plug icon to 'Add object from an expression' button - Import Plug icon from lucide-svelte - Add startIcon with Plug to the S3 array static helper button - Makes the button visually consistent with other connection-related UI elements * Unify S3 resource button style across static and JS modes - Replace 'Add S3 resource:' text + FlowPlugConnect with consistent Button style - Use same variant, color, size, and plug icon as static mode button - Maintain same functionality but with unified visual appearance - Both S3 helpers now use identical button styling * Consolidate and clean up array expression helpers - Extract appendPathToArrayExpr() to eliminate duplicate array building logic - Add switchToJsAndConnect() helper for consistent mode switching flow - Add emitChange() and updateEditor() utilities for consistent updates - Add safety reset of showArrayExprPicker when switching away from JS mode - Reduce code duplication across number and S3 array helpers - Improve maintainability and consistency * Remove number array helper functionality - Remove shouldShowArrayHelper() function for number arrays - Remove showArrayExprPicker state variable and related UI - Remove number array 'Add item' button and picker interface - Keep only S3 resource array helpers (static and JS modes) - Clean up unused safety reset logic for array picker * Create reusable S3ArrayHelperButton component - Extract S3 array helper button into dedicated component - Add consistent styling with Plug icon and configurable label - Replace both static and JavaScript mode button implementations - Reduce code duplication and improve maintainability - Component dispatches click event for parent handling * cleaning * Hide S3ArrayHelperButton when in connect mode - Add connecting prop to S3ArrayHelperButton component - Hide button when connecting is true to avoid UI clutter - Pass connecting state from InputTransformForm to both button instances - Improves UX by removing unnecessary button when plug is already active * cleaning * cleaning
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import FlowPlugConnect from './FlowPlugConnect.svelte'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import S3ArrayHelperButton from './S3ArrayHelperButton.svelte'
|
||||
|
||||
interface Props {
|
||||
schema: Schema | { properties?: Record<string, any>; required?: string[] }
|
||||
@@ -241,6 +242,51 @@
|
||||
return inputCat === 'string' || inputCat === 'sql' || inputCat == 'yaml'
|
||||
}
|
||||
|
||||
function appendPathToArrayExpr(currentExpr: string | undefined, path: string) {
|
||||
const trimmedExpr = currentExpr?.trim() || ''
|
||||
|
||||
let newExpr = trimmedExpr
|
||||
if (trimmedExpr.startsWith('[') && trimmedExpr.endsWith(']')) {
|
||||
// Parse existing array and append new item
|
||||
const innerContent = trimmedExpr.slice(1, -1).trim()
|
||||
if (innerContent) {
|
||||
newExpr = `[${innerContent}, ${path}]`
|
||||
} else {
|
||||
newExpr = `[${path}]`
|
||||
}
|
||||
} else {
|
||||
// Create new array with single item
|
||||
newExpr = `[${path}]`
|
||||
}
|
||||
arg.expr = newExpr
|
||||
arg.type = 'javascript'
|
||||
|
||||
// Update Monaco editor after setting the expression
|
||||
tick().then(() => {
|
||||
monaco?.setCode(newExpr)
|
||||
})
|
||||
|
||||
// Dispatch change
|
||||
dispatch('change', { argName, arg })
|
||||
}
|
||||
|
||||
async function switchToJsAndConnect(onPath: (path: string) => void) {
|
||||
// Switch to JavaScript mode
|
||||
propertyType = 'javascript'
|
||||
arg.type = 'javascript'
|
||||
arg.expr = arg.expr || '[]'
|
||||
arg.value = undefined
|
||||
|
||||
// Wait for the component to re-render and Monaco to be available
|
||||
await tick()
|
||||
|
||||
// Activate connect mode
|
||||
focusProp?.(argName, 'connect', (path) => {
|
||||
onPath(path)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
function connectProperty(rawValue: string) {
|
||||
// Extract path from variable('x') or resource('x') format
|
||||
const varMatch = variableMatch(rawValue)
|
||||
@@ -416,6 +462,10 @@
|
||||
let connecting = $derived(
|
||||
$propPickerConfig?.propName == argName && $propPickerConfig?.insertionMode == 'connect'
|
||||
)
|
||||
let shouldShowS3ArrayHelper = $derived(
|
||||
inputCat === 'list' &&
|
||||
['s3object', 's3_object'].includes(schema?.properties?.[argName]?.items?.resourceType)
|
||||
)
|
||||
</script>
|
||||
|
||||
{#if arg != undefined && !hidden}
|
||||
@@ -492,6 +542,7 @@
|
||||
on:selected={(e) => {
|
||||
if (e.detail == propertyType) return
|
||||
const staticTemplate = isStaticTemplate(inputCat)
|
||||
|
||||
if (e.detail === 'javascript') {
|
||||
if (arg.expr == undefined) {
|
||||
arg.expr = getDefaultExpr(
|
||||
@@ -683,6 +734,14 @@
|
||||
bind:title={schema.properties[argName].title}
|
||||
bind:placeholder={schema.properties[argName].placeholder}
|
||||
/>
|
||||
|
||||
{#if shouldShowS3ArrayHelper}
|
||||
<S3ArrayHelperButton
|
||||
{connecting}
|
||||
onClick={() =>
|
||||
switchToJsAndConnect((path) => appendPathToArrayExpr(arg.expr, path))}
|
||||
/>
|
||||
{/if}
|
||||
{:else if arg.expr != undefined}
|
||||
<div class="border mt-2">
|
||||
<SimpleEditor
|
||||
@@ -712,6 +771,18 @@
|
||||
{#if !hideHelpButton}
|
||||
<DynamicInputHelpBox />
|
||||
{/if}
|
||||
|
||||
{#if shouldShowS3ArrayHelper}
|
||||
<S3ArrayHelperButton
|
||||
{connecting}
|
||||
onClick={() =>
|
||||
focusProp?.(argName, 'connect', (path) => {
|
||||
appendPathToArrayExpr(arg.expr, path)
|
||||
return true
|
||||
})}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="mb-2"></div>
|
||||
{:else}
|
||||
Not recognized input type {argName} ({arg.expr}, {propertyType})
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/common'
|
||||
import { Plug } from 'lucide-svelte'
|
||||
|
||||
interface Props {
|
||||
label?: string
|
||||
onClick: () => void
|
||||
connecting?: boolean
|
||||
}
|
||||
|
||||
let { label = 'Add object from an expression', onClick, connecting = false }: Props = $props()
|
||||
</script>
|
||||
|
||||
{#if !connecting}
|
||||
<div class="mt-2 mb-2">
|
||||
<Button variant="border" color="light" size="xs" startIcon={{ icon: Plug }} onclick={onClick}>
|
||||
{label}
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user