Flow fix property picker (#326)

* Fix property picker

* Fix property picker
This commit is contained in:
Faton Ramadani
2022-08-04 00:28:46 +02:00
committed by GitHub
parent 72a6004380
commit 486387d0ec
5 changed files with 61 additions and 120 deletions
+2 -3
View File
@@ -41,7 +41,6 @@
| { type?: 'string' | 'number' | 'bytes'; contentEncoding?: 'base64' }
| undefined = undefined
export let displayHeader = true
export let numberAsString = false
let seeEditable: boolean = enum_ != undefined || pattern != undefined
const dispatch = createEventDispatcher()
@@ -188,7 +187,7 @@
</div>
</div>
<div class="flex space-x-1">
{#if inputCat == 'number' && !numberAsString}
{#if inputCat == 'number'}
<input
{disabled}
type="number"
@@ -303,7 +302,7 @@
? format.substring('resource-'.length)
: undefined}
/>
{:else if inputCat == 'string' || (inputCat == 'number' && numberAsString)}
{:else if inputCat == 'string'}
<textarea
on:focus={() => dispatch('focus')}
on:blur={() => dispatch('blur')}
@@ -10,8 +10,7 @@
import FieldHeader from './FieldHeader.svelte'
import DynamicInputHelpBox from './flows/DynamicInputHelpBox.svelte'
import { codeToStaticTemplate } from './flows/flowStore'
import { getCodeInjectionExpr, getDefaultExpr, isCodeInjection } from './flows/utils'
import ClickablePropertyPicker from './propertyPicker/ClickablePropertyPicker.svelte'
import { getDefaultExpr, isCodeInjection } from './flows/utils'
import OverlayPropertyPicker from './propertyPicker/OverlayPropertyPicker.svelte'
import Toggle from './Toggle.svelte'
@@ -39,21 +38,18 @@
return type
}
function setPropertyType(id: string, rawValue: string, isRaw: boolean) {
function setPropertyType(rawValue: string) {
if (!arg) {
return
}
if (isCodeInjection(rawValue)) {
arg.expr = getCodeInjectionExpr(rawValue, isRaw)
arg.expr = getDefaultExpr(i!, argName, `\`${rawValue}\``)
arg.type = 'javascript'
propertyType = 'static'
} else {
if (arg.type === 'javascript' && propertyType === 'static') {
arg.type = 'static'
if (inputCats[id] == 'number') {
arg.value = Number(arg.value)
}
}
if (arg.type) {
propertyType = arg.type
@@ -62,12 +58,12 @@
}
function isStaticTemplate(inputCat: InputCat) {
return inputCat === 'string' || inputCat === 'number' || inputCat === 'sql'
return inputCat === 'string' || inputCat === 'sql'
}
function focusProp(argName: string) {
function focusProp(argName: string, monacoEditor: boolean = false) {
Object.keys(overlays).forEach((k) => {
if (k == argName) {
if (k == argName && (isStaticTemplate(inputCats[argName]) || monacoEditor)) {
overlays[k].focus()
} else {
overlays[k].unfocus()
@@ -75,15 +71,13 @@
})
}
function onPropertyLink(argName: string, rawValue: string) {
function connectProperty(argName: string, rawValue: string) {
if (isStaticTemplate(inputCats[argName])) {
arg.value = `\$\{${rawValue}}`
setPropertyType(argName, arg.value, false)
setPropertyType(arg.value)
} else {
arg.expr = getDefaultExpr(i ?? -1, undefined, rawValue)
arg.type = 'javascript'
propertyType = 'javascript'
}
@@ -125,8 +119,9 @@
arg.expr = getDefaultExpr(
i ?? -1,
argName,
staticTemplate ? `\`${arg.value ?? ''}\`` : undefined
staticTemplate ? `\`${arg.value ?? ''}\`` : arg.value
)
arg.value = undefined
propertyType = 'javascript'
} else {
@@ -144,16 +139,21 @@
{#if propertyType === undefined || !checked}
<OverlayPropertyPicker
bind:this={overlays[argName]}
{pickableProperties}
disabled={!isStaticTemplate(inputCats[argName])}
on:select={(event) => {
const toAppend = `\$\{${event.detail}}`
arg.value = `${arg.value ?? ''}${toAppend}`
if (monacos[argName]) {
monacos[argName].setCode(arg.value)
bind:this={overlays[argName]}
on:select={({ detail }) => {
if (detail.pickerVariation === 'connect') {
connectProperty(argName, detail.propPath)
} else {
const toAppend = `\$\{${detail.propPath}}`
arg.value = `${arg.value ?? ''}${toAppend}`
if (monacos[argName]) {
monacos[argName].setCode(arg.value)
}
if (isStaticTemplate(inputCats[argName])) {
setPropertyType(arg.value)
}
}
setPropertyType(argName, arg.value, false)
}}
>
<ArgInput
@@ -173,24 +173,20 @@
bind:itemsType={schema.properties[argName].items}
displayHeader={false}
bind:inputCat={inputCats[argName]}
numberAsString={true}
on:input={(e) => {
if (isStaticTemplate(inputCats[argName])) {
setPropertyType(argName, e.detail.rawValue, e.detail.isRaw)
setPropertyType(e.detail.rawValue)
}
}}
>
<div slot="actions">
<ClickablePropertyPicker
bind:pickableProperties
on:select={(event) => onPropertyLink(argName, event.detail)}
>
<div on:click={() => overlays[argName]?.focus('connect')}>
<Tooltip placement="bottom" content="Input connect">
<Button color="blue" size="sm" class="h-8">
<Icon data={faChain} />
</Button>
</Tooltip>
</ClickablePropertyPicker>
</div>
</div>
</ArgInput>
</OverlayPropertyPicker>
@@ -200,13 +196,13 @@
bind:this={overlays[argName]}
{pickableProperties}
on:select={(event) => {
monacos[argName].insertAtCursor(event.detail)
monacos[argName].insertAtCursor(event.detail.propPath)
}}
>
<div class="border rounded p-2 mt-2 border-gray-300">
<Editor
bind:this={monacos[argName]}
on:focus={() => focusProp(argName)}
on:focus={() => focusProp(argName, true)}
bind:code={arg.expr}
lang="javascript"
class="few-lines-editor"
+1 -10
View File
@@ -153,17 +153,8 @@ export function isCodeInjection(expr: string | undefined): boolean {
return false
}
export function getCodeInjectionExpr(code: string, isRaw: boolean): string {
let expr = `\`${code}\``
if (isRaw) {
expr = `JSON.parse(${expr})`
}
return `import { previous_result, flow_input, step, variable, resource, params } from 'windmill'
${expr}`
}
export function getDefaultExpr(i: number, key: string = 'myfield', previousExpr?: string) {
console.log(key, previousExpr)
const expr = previousExpr ?? `previous_result.${key}`
return `import { previous_result, flow_input, step, variable, resource, params } from 'windmill@${i}'
@@ -1,52 +0,0 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { createPopperActions } from 'svelte-popperjs'
import PropPicker from './PropPicker.svelte'
const [popperRef, popperContent] = createPopperActions({
placement: 'bottom-end',
strategy: 'fixed'
})
export let pickableProperties: Object | undefined
export let disabled = false
let isOpen = false
function toggle() {
isOpen = !isOpen
}
const dispatch = createEventDispatcher()
</script>
{#if !disabled}
<div class="w-full">
<div use:popperRef on:click={toggle}>
<slot />
</div>
{#if isOpen}
<div class="content" use:popperContent>
<PropPicker
bind:pickableProperties
on:select={(event) => {
isOpen = false
dispatch('select', event.detail)
}}
/>
</div>
{/if}
</div>
{:else}
<slot />
{/if}
<style>
.content {
@apply drop-shadow-xl;
@apply w-full;
@apply max-w-4xl;
@apply px-6;
@apply z-50;
}
</style>
@@ -9,17 +9,22 @@
})
export let pickableProperties: Object | undefined
export let disabled = false
let isOpen = false
let isFocused = false
let timeout: NodeJS.Timeout
type PickerVariation = 'append' | 'connect'
let pickerVariation: PickerVariation = 'append'
export function unfocus() {
isFocused = false
close()
}
export function focus() {
export function focus(newPickerVariation?: PickerVariation) {
if (newPickerVariation) {
pickerVariation = newPickerVariation
}
isFocused = true
open()
}
@@ -31,40 +36,42 @@
}
}
function close() {
if (pickerVariation === 'append') {
timeout = setTimeout(() => (isOpen = false), 50)
}
}
function closePropertyPicker() {
timeout = setTimeout(() => (isOpen = false), 50)
}
const dispatch = createEventDispatcher()
</script>
{#if !disabled}
<div class="w-full">
<div use:popperRef on:mouseleave={close}>
<slot />
</div>
{#if isOpen}
<div class="content" use:popperContent on:mouseenter={open} on:mouseleave={close}>
<PropPicker
bind:pickableProperties
on:select={(event) => {
isOpen = false
dispatch('select', event.detail)
}}
/>
</div>
{/if}
<div class="w-full">
<div use:popperRef on:mouseleave={close}>
<slot />
</div>
{:else}
<slot />
{/if}
{#if isOpen}
<div class="content" use:popperContent on:mouseenter={open} on:mouseleave={closePropertyPicker}>
<PropPicker
bind:pickableProperties
on:select={(event) => {
dispatch('select', { propPath: event.detail, pickerVariation })
isOpen = false
pickerVariation = 'append'
}}
/>
</div>
{/if}
</div>
<style>
.content {
@apply drop-shadow-xl;
@apply w-full;
@apply max-w-4xl;
@apply px-6;
@apply z-50;
}