fix: flow editor design improvements
This commit is contained in:
@@ -319,7 +319,7 @@
|
||||
<div class="flex mt-2">
|
||||
<Button
|
||||
variant="border"
|
||||
color="dark"
|
||||
color="light"
|
||||
size="xs"
|
||||
btnClasses="mt-1"
|
||||
on:click={() => {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
import { ResourceService, VariableService } from '$lib/gen'
|
||||
|
||||
import {
|
||||
faBook,
|
||||
faCube,
|
||||
faDollarSign,
|
||||
faEye,
|
||||
faPlus,
|
||||
faRotate,
|
||||
faRotateLeft
|
||||
@@ -22,7 +22,7 @@
|
||||
import Button from './common/button/Button.svelte'
|
||||
import HighlightCode from './HighlightCode.svelte'
|
||||
import DrawerContent from './common/drawer/DrawerContent.svelte'
|
||||
import { Badge, Drawer } from './common'
|
||||
import { Drawer } from './common'
|
||||
import WorkspaceScriptPicker from './flows/pickers/WorkspaceScriptPicker.svelte'
|
||||
import PickHubScript from './flows/pickers/PickHubScript.svelte'
|
||||
import ToggleHubWorkspace from './ToggleHubWorkspace.svelte'
|
||||
@@ -253,16 +253,17 @@
|
||||
<ResourceEditor bind:this={resourceEditor} on:refresh={resourcePicker.openDrawer} />
|
||||
<VariableEditor bind:this={variableEditor} on:create={variablePicker.openDrawer} />
|
||||
|
||||
<div class="flex justify-between items-center overflow-y-auto w-full p-1">
|
||||
<div class="flex justify-between items-center overflow-y-auto w-full p-0.5">
|
||||
<div class="flex items-center">
|
||||
<Badge color={validCode ? 'green' : 'red'} class="min-w-[60px] mr-3">
|
||||
{validCode ? 'Valid' : 'Invalid'}
|
||||
</Badge>
|
||||
<div class="flex items-center divide-x">
|
||||
<div
|
||||
title={validCode ? 'Main function parsable' : 'Main function not parsable'}
|
||||
class="rounded-full w-2 h-2 mx-2 {validCode ? 'bg-green-300' : 'bg-red-300'}"
|
||||
/>
|
||||
<div class="flex items-center">
|
||||
<Button
|
||||
title="Add context variable"
|
||||
color="light"
|
||||
btnClasses="!font-medium !h-full"
|
||||
btnClasses="!font-medium text-gray-600"
|
||||
on:click={contextualVariablePicker.openDrawer}
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
@@ -275,7 +276,7 @@
|
||||
<Button
|
||||
title="Add variable"
|
||||
color="light"
|
||||
btnClasses="!font-medium !h-full"
|
||||
btnClasses="!font-medium text-gray-600"
|
||||
on:click={variablePicker.openDrawer}
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
@@ -287,7 +288,7 @@
|
||||
|
||||
<Button
|
||||
title="Add resource"
|
||||
btnClasses="!font-medium !h-full"
|
||||
btnClasses="!font-medium text-gray-600"
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
color="light"
|
||||
@@ -300,7 +301,7 @@
|
||||
|
||||
<Button
|
||||
title="Reset Content"
|
||||
btnClasses="!font-medium !h-full"
|
||||
btnClasses="!font-medium text-gray-600"
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
color="light"
|
||||
@@ -312,7 +313,7 @@
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
btnClasses="!font-medium !h-full"
|
||||
btnClasses="!font-medium text-gray-600"
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
color="light"
|
||||
@@ -399,16 +400,16 @@
|
||||
|
||||
{#if SCRIPT_EDITOR_SHOW_EXPLORE_OTHER_SCRIPTS}
|
||||
<Button
|
||||
btnClasses="!font-medium"
|
||||
btnClasses="!font-medium text-gray-600"
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
color="light"
|
||||
on:click={scriptPicker.openDrawer}
|
||||
{iconOnly}
|
||||
startIcon={{ icon: faEye }}
|
||||
startIcon={{ icon: faBook }}
|
||||
title="Explore other scripts"
|
||||
>
|
||||
Explore other scripts
|
||||
Library
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { FlowService, ScheduleService, type Flow, type FlowModule, DraftService } from '$lib/gen'
|
||||
import {
|
||||
FlowService,
|
||||
ScheduleService,
|
||||
type Flow,
|
||||
type FlowModule,
|
||||
DraftService,
|
||||
type PathScript
|
||||
} from '$lib/gen'
|
||||
import { initHistory, redo, undo } from '$lib/history'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { encodeState, formatCron } from '$lib/utils'
|
||||
@@ -24,6 +31,7 @@
|
||||
import { loadHubScripts } from '$lib/scripts'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Awareness from './Awareness.svelte'
|
||||
import { getAllModules } from './flows/previousResults'
|
||||
|
||||
export let initialPath: string = ''
|
||||
export let selectedId: string | undefined
|
||||
@@ -93,10 +101,21 @@
|
||||
loadingDraft = false
|
||||
}
|
||||
|
||||
export function computeUnlockedSteps(flow: Flow) {
|
||||
return Object.fromEntries(
|
||||
getAllModules(flow)
|
||||
.filter((m) => m.value.type == 'script' && m.value.hash == null)
|
||||
.map((m) => [m.id, (m.value as PathScript).path])
|
||||
)
|
||||
}
|
||||
|
||||
async function saveFlow(): Promise<void> {
|
||||
loadingSave = true
|
||||
try {
|
||||
const flow = cleanInputs($flowStore)
|
||||
// console.log('flow', computeUnlockedSteps(flow)) // del
|
||||
// loadingSave = false // del
|
||||
// return
|
||||
const { cron, timezone, args, enabled } = $scheduleStore
|
||||
$dirtyStore = false
|
||||
if (initialPath === '') {
|
||||
|
||||
@@ -9,14 +9,16 @@
|
||||
import type { PropPickerWrapperContext } from './flows/propPicker/PropPickerWrapper.svelte'
|
||||
import { codeToStaticTemplate, getDefaultExpr, isCodeInjection } from './flows/utils'
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
import { Button, ToggleButton, ToggleButtonGroup } from './common'
|
||||
import { faCode } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Button } from './common'
|
||||
import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
|
||||
|
||||
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 } from '$lib/utils'
|
||||
import { Plug } from 'lucide-svelte'
|
||||
import { Code, Plug } from 'lucide-svelte'
|
||||
|
||||
export let schema: Schema
|
||||
export let arg: InputTransform | any
|
||||
@@ -153,7 +155,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
{#if !noDynamicToggle}
|
||||
<div class="flex flex-row gap-x-4 gap-y-1 flex-wrap z-10">
|
||||
<div class="flex flex-row gap-x-6 gap-y-1 flex-wrap z-10 items-center">
|
||||
<div>
|
||||
<ToggleButtonGroup
|
||||
bind:selected={propertyType}
|
||||
@@ -196,24 +198,25 @@
|
||||
>
|
||||
{#if isStaticTemplate(inputCat)}
|
||||
<ToggleButton
|
||||
title={`Write text or surround javascript with \`\$\{\` and \`\}\`. Use \`results\` to connect to another node\'s output.`}
|
||||
tooltip={`Write text or surround javascript with \`\$\{\` and \`\}\`. Use \`results\` to connect to another node\'s output.`}
|
||||
light
|
||||
position="left"
|
||||
value="static"
|
||||
size="xs2"
|
||||
>
|
||||
{'${} '}
|
||||
</ToggleButton>
|
||||
small
|
||||
label={'${}'}
|
||||
/>
|
||||
{:else}
|
||||
<ToggleButton light position="left" value="static" size="xs2">Static</ToggleButton>
|
||||
<ToggleButton small label="Static" position="left" value="static" size="xs2" />
|
||||
{/if}
|
||||
|
||||
<ToggleButton
|
||||
small
|
||||
light
|
||||
title="Javascript expression ('flow_input' or 'results')."
|
||||
tooltip="Javascript expression ('flow_input' or 'results')."
|
||||
position="right"
|
||||
value="javascript"
|
||||
startIcon={{ icon: faCode }}
|
||||
icon={Code}
|
||||
size="xs2"
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
{#if keys.length > 0}
|
||||
{#each keys as argName (argName)}
|
||||
{#if (!filter || filter.includes(argName)) && Object.keys(schema.properties ?? {}).includes(argName)}
|
||||
<div class="z-10 pt-1.5">
|
||||
<div class="z-10 pt-4">
|
||||
<InputTransformForm
|
||||
{previousModuleId}
|
||||
bind:arg={args[argName]}
|
||||
|
||||
@@ -98,11 +98,17 @@
|
||||
>
|
||||
{/if}
|
||||
|
||||
<Button variant="border" size="xs" on:click={() => appConnect?.open?.(resourceType)}>
|
||||
<Button
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs"
|
||||
on:click={() => appConnect?.open?.(resourceType)}
|
||||
>
|
||||
<Icon scale={0.8} data={faPlus} /></Button
|
||||
>
|
||||
<Button
|
||||
variant="border"
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={() => {
|
||||
loadResources(resourceType)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
export let icon: any | undefined = undefined
|
||||
export let disabled: boolean = false
|
||||
export let selectedColor: string = '#3b82f6'
|
||||
export let small: boolean = false
|
||||
|
||||
const { select, selected } = getContext<ToggleButtonContext>('ToggleButtonGroup')
|
||||
</script>
|
||||
@@ -20,7 +21,8 @@
|
||||
<Tab
|
||||
{disabled}
|
||||
class={twMerge(
|
||||
'px-2 py-1 rounded-md transition-all text-xs flex gap-1 flex-row items-center',
|
||||
' rounded-md transition-all text-xs flex gap-1 flex-row items-center',
|
||||
small ? 'px-1 py-0.5' : 'px-2 py-1',
|
||||
$selected === value ? 'bg-white shadow-md text-gray-800' : 'text-gray-600 hover:bg-gray-200',
|
||||
$$props.class
|
||||
)}
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { BadgeColor } from '$lib/components/common'
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import LanguageIcon from '$lib/components/common/languageIcons/LanguageIcon.svelte'
|
||||
import IconedPath from '$lib/components/IconedPath.svelte'
|
||||
import { RawScript, ScriptService, type FlowModule, type PathScript } from '$lib/gen'
|
||||
import { ScriptService, type FlowModule, type PathScript } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { Lock, Unlock } from 'lucide-svelte'
|
||||
|
||||
export let flowModule: FlowModule | undefined = undefined
|
||||
export let title: string | undefined = undefined
|
||||
|
||||
const languageColors: Record<RawScript.language, BadgeColor> = {
|
||||
[RawScript.language.GO]: 'dark-indigo',
|
||||
[RawScript.language.DENO]: 'dark-blue',
|
||||
[RawScript.language.PYTHON3]: 'dark-green',
|
||||
[RawScript.language.BASH]: 'dark-yellow'
|
||||
}
|
||||
|
||||
let latestHash: string | undefined = undefined
|
||||
async function loadLatestHash(value: PathScript) {
|
||||
let script = await ScriptService.getScriptByPath({
|
||||
@@ -33,7 +27,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="overflow-x-auto scrollbar-hidden flex items-center justify-between py-2 px-4 border-b border-gray-300 space-x-2 h-full max-h-12 flex-nowrap"
|
||||
class="overflow-x-auto scrollbar-hidden flex items-center justify-between px-4 py-1 border-b border-gray-100 space-x-2 flex-nowrap"
|
||||
>
|
||||
{#if flowModule}
|
||||
<span class="text-sm w-full mr-4">
|
||||
@@ -41,9 +35,9 @@
|
||||
{#if flowModule.value.type === 'identity'}
|
||||
<span class="font-bold text-xs">Identity (input copied to output)</span>
|
||||
{:else if flowModule?.value.type === 'rawscript'}
|
||||
<Badge color={languageColors[flowModule?.value.language] ?? 'gray'} capitalize>
|
||||
{flowModule?.value.language}
|
||||
</Badge>
|
||||
<div class="w-4 mx-0.5">
|
||||
<LanguageIcon lang={flowModule.value.language} class="w-4 h-4" />
|
||||
</div>
|
||||
<input bind:value={flowModule.summary} placeholder={'Summary'} class="w-full grow" />
|
||||
{:else if flowModule?.value.type === 'script' && 'path' in flowModule.value && flowModule.value.path}
|
||||
<IconedPath path={flowModule.value.path} hash={flowModule.value.hash} class="grow" />
|
||||
@@ -62,25 +56,27 @@
|
||||
>
|
||||
{/if}
|
||||
<Button
|
||||
title="Unlock hash to always use latest deployed version at that path"
|
||||
size="xs"
|
||||
btnClasses="text-gray-600 inline-flex gap-1 items-center"
|
||||
color="light"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
if (flowModule?.value.type == 'script') {
|
||||
flowModule.value.hash = undefined
|
||||
}
|
||||
}}>Unlock hash</Button
|
||||
}}><Unlock size={12} />hash</Button
|
||||
>
|
||||
{:else if latestHash}
|
||||
<Button
|
||||
title="Lock hash to always use this specific version"
|
||||
color="light"
|
||||
size="xs"
|
||||
variant="border"
|
||||
btnClasses="text-gray-600 inline-flex gap-1 items-center"
|
||||
on:click={() => {
|
||||
if (flowModule?.value.type == 'script') {
|
||||
flowModule.value.hash = latestHash
|
||||
}
|
||||
}}>Lock hash</Button
|
||||
}}><Lock size={12} />hash</Button
|
||||
>
|
||||
{/if}
|
||||
<input bind:value={flowModule.summary} placeholder="Summary" class="w-full grow" />
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
{#if module.value.type === 'script' || module.value.type === 'rawscript' || module.value.type == 'flow'}
|
||||
<Popover
|
||||
placement="bottom"
|
||||
class="center-center rounded border p-2
|
||||
class="center-center rounded p-2
|
||||
{moduleRetry
|
||||
? 'bg-blue-100 text-blue-800 border-blue-300 hover:bg-blue-200'
|
||||
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 border-gray-300 hover:bg-gray-100'}"
|
||||
on:click={() => dispatch('toggleRetry')}
|
||||
>
|
||||
@@ -41,10 +41,10 @@
|
||||
</Popover>
|
||||
<Popover
|
||||
placement="bottom"
|
||||
class="center-center rounded border p-2
|
||||
class="center-center rounded p-2
|
||||
{module.cache_ttl != undefined
|
||||
? 'bg-blue-100 text-blue-800 border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 border-gray-300 hover:bg-gray-100'}"
|
||||
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 hover:bg-gray-100'}"
|
||||
on:click={() => dispatch('toggleCache')}
|
||||
>
|
||||
<Database size={14} />
|
||||
@@ -52,10 +52,10 @@
|
||||
</Popover>
|
||||
<Popover
|
||||
placement="bottom"
|
||||
class="center-center rounded border p-2
|
||||
class="center-center rounded p-2
|
||||
{module.stop_after_if
|
||||
? 'bg-blue-100 text-blue-800 border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 border-gray-300 hover:bg-gray-100'}"
|
||||
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 hover:bg-gray-100'}"
|
||||
on:click={() => dispatch('toggleStopAfterIf')}
|
||||
>
|
||||
<Square size={14} />
|
||||
@@ -63,10 +63,10 @@
|
||||
</Popover>
|
||||
<Popover
|
||||
placement="bottom"
|
||||
class="center-center rounded border p-2
|
||||
class="center-center rounded p-2
|
||||
{module.suspend
|
||||
? 'bg-blue-100 text-blue-800 border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 border-gray-300 hover:bg-gray-100'}"
|
||||
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 hover:bg-gray-100'}"
|
||||
on:click={() => dispatch('toggleSuspend')}
|
||||
>
|
||||
<PhoneIncoming size={14} />
|
||||
@@ -74,10 +74,10 @@
|
||||
</Popover>
|
||||
<Popover
|
||||
placement="bottom"
|
||||
class="center-center rounded border p-2
|
||||
class="center-center rounded p-2
|
||||
{module.sleep
|
||||
? 'bg-blue-100 text-blue-800 border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 border-gray-300 hover:bg-gray-100'}"
|
||||
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200'
|
||||
: 'bg-white text-gray-800 hover:bg-gray-100'}"
|
||||
on:click={() => dispatch('toggleSleep')}
|
||||
>
|
||||
<Bed size={14} />
|
||||
@@ -90,7 +90,6 @@
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
on:click={async () => {
|
||||
if (module.value.type == 'script') {
|
||||
const hash = module.value.hash ?? (await getLatestHashForScript(module.value.path))
|
||||
@@ -110,7 +109,6 @@
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
on:click={() => dispatch('fork')}
|
||||
startIcon={{ icon: faCodeBranch }}
|
||||
iconOnly={false}
|
||||
@@ -149,7 +147,7 @@
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
btnClasses="text-gray-600"
|
||||
startIcon={{ icon: faSave }}
|
||||
on:click={() => dispatch('createScriptFromInlineScript')}
|
||||
iconOnly={false}
|
||||
|
||||
Reference in New Issue
Block a user