improve flow script editor performances
This commit is contained in:
@@ -4,10 +4,21 @@
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
@apply dark:border-gray-600;
|
||||
|
||||
/* Light mode: default border color */
|
||||
.border, .border-t, .border-r, .border-b, .border-l,
|
||||
.border-x, .border-y,
|
||||
.divide-x > :not([hidden]) ~ :not([hidden]),
|
||||
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
||||
border-color: #e5e7eb; /* gray-200 */
|
||||
}
|
||||
|
||||
/* Dark mode: change border color */
|
||||
.dark .border, .dark .border-t, .dark .border-r, .dark .border-b, .dark .border-l,
|
||||
.dark .border-x, .dark .border-y,
|
||||
.dark .divide-x > :not([hidden]) ~ :not([hidden]),
|
||||
.dark .divide-y > :not([hidden]) ~ :not([hidden]) {
|
||||
border-color: #4b5563; /* gray-700 */
|
||||
}
|
||||
|
||||
/* Chrome, Edge, and Safari */
|
||||
@@ -82,6 +93,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
.driver-popover-title {
|
||||
@apply leading-6 !text-primary !text-base;
|
||||
}
|
||||
|
||||
.driver-popover-description {
|
||||
@apply !text-secondary !text-sm;
|
||||
}
|
||||
|
||||
.driver-popover {
|
||||
@apply p-6 !bg-surface !max-w-2xl;
|
||||
}
|
||||
|
||||
.splitpanes--vertical > .splitpanes__pane {
|
||||
transition: none !important;
|
||||
}
|
||||
@@ -165,3 +188,4 @@ svelte-virtual-list-contents > * + * {
|
||||
rgba(0, 0, 192, 0.6) 20px
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,17 +81,3 @@
|
||||
<span> You need to create a new flow before starting the tutorial.</span>
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
|
||||
<style global>
|
||||
.driver-popover-title {
|
||||
@apply leading-6 text-primary text-base;
|
||||
}
|
||||
|
||||
.driver-popover-description {
|
||||
@apply text-secondary text-sm;
|
||||
}
|
||||
|
||||
.driver-popover {
|
||||
@apply p-6 bg-surface max-w-2xl;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
export let path: string
|
||||
export let selected: string | undefined = undefined
|
||||
export let selectInitial: boolean = false
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function loadInitial() {
|
||||
@@ -19,7 +20,9 @@
|
||||
perPage: 1
|
||||
})
|
||||
if (jobs.length > 0) {
|
||||
dispatch('select', { jobId: jobs[0].id, initial: true })
|
||||
if (selectInitial) {
|
||||
dispatch('select', { jobId: jobs[0].id, initial: true })
|
||||
}
|
||||
} else {
|
||||
dispatch('nohistory')
|
||||
}
|
||||
|
||||
@@ -26,12 +26,18 @@
|
||||
|
||||
export let jobId: string | undefined = undefined
|
||||
export let job: Job | undefined = undefined
|
||||
let selectedJobStep: string | undefined = undefined
|
||||
let branchOrIterationN: number = 0
|
||||
let restartBranchNames: [number, string][] = []
|
||||
export let initial: boolean = false
|
||||
|
||||
let selectedJobStepIsTopLevel: boolean | undefined = undefined
|
||||
let selectedJobStepType: 'single' | 'forloop' | 'branchall' = 'single'
|
||||
export let selectedJobStep: string | undefined = undefined
|
||||
export let selectedJobStepIsTopLevel: boolean | undefined = undefined
|
||||
export let selectedJobStepType: 'single' | 'forloop' | 'branchall' = 'single'
|
||||
export let rightColumnSelect: 'timeline' | 'node_status' | 'node_definition' | 'user_states' =
|
||||
'timeline'
|
||||
|
||||
export let branchOrIterationN: number = 0
|
||||
export let scrollTop: number = 0
|
||||
|
||||
let restartBranchNames: [number, string][] = []
|
||||
|
||||
let isRunning: boolean = false
|
||||
let jobProgressReset: () => void
|
||||
@@ -59,7 +65,6 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let renderCount: number = 0
|
||||
let initial: boolean = false
|
||||
let schemaFormWithArgPicker: SchemaFormWithArgPicker | undefined = undefined
|
||||
let currentJobId: string | undefined = undefined
|
||||
|
||||
@@ -210,6 +215,19 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let scrollableDiv: HTMLDivElement | undefined = undefined
|
||||
function handleScroll() {
|
||||
scrollTop = scrollableDiv?.scrollTop ?? 0
|
||||
}
|
||||
|
||||
$: scrollableDiv && onScrollableDivChange()
|
||||
|
||||
function onScrollableDivChange() {
|
||||
if (scrollTop != 0 && scrollableDiv) {
|
||||
scrollableDiv.scrollTop = scrollTop
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
@@ -375,7 +393,11 @@
|
||||
<FlowProgressBar {job} bind:reset={jobProgressReset} />
|
||||
</div>
|
||||
|
||||
<div class="overflow-y-auto grow flex flex-col pt-4">
|
||||
<div
|
||||
bind:this={scrollableDiv}
|
||||
class="overflow-y-auto grow flex flex-col pt-4"
|
||||
on:scroll={(e) => handleScroll()}
|
||||
>
|
||||
<div class="border-b">
|
||||
<SchemaFormWithArgPicker
|
||||
bind:this={schemaFormWithArgPicker}
|
||||
@@ -448,6 +470,7 @@
|
||||
class="absolute top-[22px] right-2 border p-1.5 hover:bg-surface-hover rounded-md center-center"
|
||||
>
|
||||
<FlowHistoryJobPicker
|
||||
selectInitial={jobId == undefined}
|
||||
on:nohistory={() => {
|
||||
loadIndividualStepsStates()
|
||||
}}
|
||||
@@ -499,6 +522,7 @@
|
||||
}
|
||||
}}
|
||||
bind:selectedJobStep
|
||||
bind:rightColumnSelect
|
||||
/>
|
||||
{:else}
|
||||
<div class="italic text-tertiary h-full grow"> Flow status will be displayed here </div>
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
export let hideNodeDefinition = false
|
||||
export let hideJobId = false
|
||||
export let hideDownloadLogs = false
|
||||
|
||||
export let rightColumnSelect: 'timeline' | 'node_status' | 'node_definition' | 'user_states' =
|
||||
'timeline'
|
||||
export let isOwner = false
|
||||
export let wideResults = false
|
||||
|
||||
@@ -77,4 +78,5 @@
|
||||
{workspaceId}
|
||||
{isOwner}
|
||||
{wideResults}
|
||||
bind:rightColumnSelect
|
||||
/>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import FlowPreviewStatus from './preview/FlowPreviewStatus.svelte'
|
||||
import { createEventDispatcher, getContext, tick } from 'svelte'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { Badge, Button, Tab } from './common'
|
||||
import { Badge, Button, Skeleton, Tab } from './common'
|
||||
import DisplayResult from './DisplayResult.svelte'
|
||||
import Tabs from './common/tabs/Tabs.svelte'
|
||||
import { type DurationStatus, type FlowStatusViewerContext, type GraphModuleState } from './graph'
|
||||
@@ -81,6 +81,8 @@
|
||||
export let isForloopSelected = false
|
||||
export let parentRecursiveRefresh: Record<string, (clear, root) => Promise<void>> = {}
|
||||
export let job: Job | undefined = undefined
|
||||
export let rightColumnSelect: 'timeline' | 'node_status' | 'node_definition' | 'user_states' =
|
||||
'timeline'
|
||||
|
||||
let recursiveRefresh: Record<string, (clear, root) => Promise<void>> = {}
|
||||
|
||||
@@ -96,6 +98,8 @@
|
||||
|
||||
$: flowJobIds?.moduleId && onFlowModuleId()
|
||||
|
||||
let selectedId: Writable<string | undefined> = writable(selectedNode)
|
||||
|
||||
function onFlowModuleId() {
|
||||
if (globalRefreshes) {
|
||||
let modId = flowJobIds?.moduleId
|
||||
@@ -793,8 +797,6 @@
|
||||
|
||||
let flowTimeline: FlowTimeline
|
||||
|
||||
let rightColumnSelect: 'timeline' | 'node_status' | 'node_definition' | 'user_states' = 'timeline'
|
||||
|
||||
function loadPreviousIters(lenToAdd: number) {
|
||||
let r = $localDurationStatuses[flowJobIds?.moduleId ?? '']
|
||||
if (r.iteration_from) {
|
||||
@@ -1244,6 +1246,7 @@
|
||||
</div>
|
||||
|
||||
<FlowGraphV2
|
||||
{selectedId}
|
||||
triggerNode={true}
|
||||
download={!hideDownloadInGraph}
|
||||
minHeight={wrapperHeight}
|
||||
@@ -1455,7 +1458,7 @@
|
||||
{/if}
|
||||
{/if}
|
||||
{:else}
|
||||
<Loader2 class="animate-spin" />
|
||||
<Skeleton layout={[[15], 1, [70]]}></Skeleton>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
||||
@@ -2,32 +2,73 @@
|
||||
import { workerTags, workspaceStore } from '$lib/stores'
|
||||
import { WorkerService } from '$lib/gen'
|
||||
|
||||
export let tag: string | undefined
|
||||
export let noLabel: boolean = false
|
||||
export let nullTag: string | undefined = undefined
|
||||
export let disabled = false
|
||||
import Select from './apps/svelte-select/lib/index'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import DarkModeObserver from './DarkModeObserver.svelte'
|
||||
import { SELECT_INPUT_DEFAULT_STYLE } from '$lib/defaults'
|
||||
|
||||
let {
|
||||
tag = $bindable(),
|
||||
noLabel = false,
|
||||
nullTag = undefined,
|
||||
disabled = false
|
||||
} = $props<{
|
||||
tag: string | undefined
|
||||
noLabel?: boolean
|
||||
nullTag?: string | undefined
|
||||
disabled?: boolean
|
||||
}>()
|
||||
|
||||
loadWorkerGroups()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
async function loadWorkerGroups() {
|
||||
if (!$workerTags) {
|
||||
$workerTags = await WorkerService.getCustomTags({ workspace: $workspaceStore })
|
||||
}
|
||||
}
|
||||
let items = $derived([
|
||||
// ...(tag ? ['reset to default'] : [nullTag ? `default: ${nullTag}` : '']),
|
||||
...(tag && tag != '' && !($workerTags ?? []).includes(tag) ? [tag] : []),
|
||||
...($workerTags ?? [])
|
||||
])
|
||||
let darkMode: boolean = $state(false)
|
||||
</script>
|
||||
|
||||
<DarkModeObserver bind:darkMode />
|
||||
|
||||
<div class="flex gap-1 items-center">
|
||||
{#if !noLabel}
|
||||
<div class="text-tertiary text-2xs">tag</div>
|
||||
{/if}
|
||||
<select
|
||||
<Select
|
||||
{disabled}
|
||||
placeholder={nullTag ? `default: ${nullTag}` : 'lang default'}
|
||||
containerStyles={'--height: 30px !important; --input-padding: 0px !important;' + darkMode
|
||||
? SELECT_INPUT_DEFAULT_STYLE.containerStylesDark
|
||||
: SELECT_INPUT_DEFAULT_STYLE.containerStyles}
|
||||
{items}
|
||||
value={tag ? { value: tag, label: tag } : undefined}
|
||||
on:clear={() => {
|
||||
tag = undefined
|
||||
dispatch('change', undefined)
|
||||
}}
|
||||
on:change={(e) => {
|
||||
console.log('change', e.detail)
|
||||
dispatch('change', e.detail.value)
|
||||
}}
|
||||
bind:justValue={tag}
|
||||
/>
|
||||
|
||||
<!-- <select
|
||||
class="min-w-32"
|
||||
placeholder="Tag"
|
||||
bind:value={tag}
|
||||
on:change={(e) => {
|
||||
onchange={(e) => {
|
||||
if (tag == '') {
|
||||
tag = undefined
|
||||
}
|
||||
dispatch('change', tag)
|
||||
}}
|
||||
{disabled}
|
||||
>
|
||||
@@ -42,5 +83,5 @@
|
||||
{#each $workerTags ?? [] as tag (tag)}
|
||||
<option value={tag}>{tag}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</select> -->
|
||||
</div>
|
||||
|
||||
@@ -119,17 +119,3 @@
|
||||
<span> This tutorial can only be run on a new app.</span>
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
|
||||
<style global>
|
||||
.driver-popover-title {
|
||||
@apply leading-6 text-primary text-base;
|
||||
}
|
||||
|
||||
.driver-popover-description {
|
||||
@apply text-secondary text-sm;
|
||||
}
|
||||
|
||||
.driver-popover {
|
||||
@apply p-6 bg-surface max-w-2xl;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<button
|
||||
class={twMerge(
|
||||
'absolute -top-[10px] -right-[10px] rounded-full h-[20px] w-[20px] trash center-center text-primary',
|
||||
'border-[1.5px] border-gray-700 bg-surface duration-150 hover:bg-red-400 hover:text-white hover:border-red-700',
|
||||
'border-[1.5px] border-gray-700 bg-surface duration-0 hover:bg-red-400 hover:text-white hover:border-red-700',
|
||||
'group-hover:opacity-100 opacity-0'
|
||||
)}
|
||||
on:click|preventDefault|stopPropagation={() => {
|
||||
|
||||
@@ -720,69 +720,6 @@
|
||||
|
||||
<style>
|
||||
.svelte-select {
|
||||
/* deprecating camelCase custom props in favour of kebab-case for v5 */
|
||||
--borderRadius: var(--border-radius);
|
||||
--clearSelectColor: var(--clear-select-color);
|
||||
--clearSelectWidth: var(--clear-select-width);
|
||||
--disabledBackground: var(--disabled-background);
|
||||
--disabledBorderColor: var(--disabled-border-color);
|
||||
--disabledColor: var(--disabled-color);
|
||||
--disabledPlaceholderColor: var(--disabled-placeholder-color);
|
||||
--disabledPlaceholderOpacity: var(--disabled-placeholder-opacity);
|
||||
--errorBackground: var(--error-background);
|
||||
--errorBorder: var(--error-border);
|
||||
--groupItemPaddingLeft: var(--group-item-padding-left);
|
||||
--groupTitleColor: var(--group-title-color);
|
||||
--groupTitleFontSize: var(--group-title-font-size);
|
||||
--groupTitleFontWeight: var(--group-title-font-weight);
|
||||
--groupTitlePadding: var(--group-title-padding);
|
||||
--groupTitleTextTransform: var(--group-title-text-transform);
|
||||
--indicatorColor: var(--chevron-color);
|
||||
--indicatorHeight: var(--chevron-height);
|
||||
--indicatorWidth: var(--chevron-width);
|
||||
--inputColor: var(--input-color);
|
||||
--inputLeft: var(--input-left);
|
||||
--inputLetterSpacing: var(--input-letter-spacing);
|
||||
--inputMargin: var(--input-margin);
|
||||
--inputPadding: var(--input-padding);
|
||||
--itemActiveBackground: var(--item-active-background);
|
||||
--itemColor: var(--item-color);
|
||||
--itemFirstBorderRadius: var(--item-first-border-radius);
|
||||
--itemHoverBG: var(--item-hover-bg);
|
||||
--itemHoverColor: var(--item-hover-color);
|
||||
--itemIsActiveBG: var(--item-is-active-bg);
|
||||
--itemIsActiveColor: var(--item-is-active-color);
|
||||
--itemIsNotSelectableColor: var(--item-is-not-selectable-color);
|
||||
--itemPadding: var(--item-padding);
|
||||
--listBackground: var(--list-background);
|
||||
--listBorder: var(--list-border);
|
||||
--listBorderRadius: var(--list-border-radius);
|
||||
--listEmptyColor: var(--list-empty-color);
|
||||
--listEmptyPadding: var(--list-empty-padding);
|
||||
--listEmptyTextAlign: var(--list-empty-text-align);
|
||||
--listMaxHeight: var(--list-max-height);
|
||||
--listPosition: var(--list-position);
|
||||
--listShadow: var(--list-shadow);
|
||||
--listZIndex: var(--list-z-index);
|
||||
--multiItemBG: var(--multi-item-bg);
|
||||
--multiItemBorderRadius: var(--multi-item-border-radius);
|
||||
--multiItemDisabledHoverBg: var(--multi-item-disabled-hover-bg);
|
||||
--multiItemDisabledHoverColor: var(--multi-item-disabled-hover-color);
|
||||
--multiItemHeight: var(--multi-item-height);
|
||||
--multiItemMargin: var(--multi-item-margin);
|
||||
--multiItemPadding: var(--multi-item-padding);
|
||||
--multiSelectInputMargin: var(--multi-select-input-margin);
|
||||
--multiSelectInputPadding: var(--multi-select-input-padding);
|
||||
--multiSelectPadding: var(--multi-select-padding);
|
||||
--placeholderColor: var(--placeholder-color);
|
||||
--placeholderOpacity: var(--placeholder-opacity);
|
||||
--selectedItemPadding: var(--selected-item-padding);
|
||||
--spinnerColor: var(--spinner-color);
|
||||
--spinnerHeight: var(--spinner-height);
|
||||
--spinnerWidth: var(--spinner-width);
|
||||
|
||||
--internal-padding: 0 0 0 16px;
|
||||
|
||||
border: var(--border, 1px solid #d8dbdf);
|
||||
border-radius: var(--border-radius, 6px);
|
||||
min-height: var(--height, 42px);
|
||||
@@ -837,9 +774,9 @@
|
||||
cursor: default;
|
||||
border: none;
|
||||
color: var(--input-color, var(--item-color));
|
||||
padding: var(--input-padding, 0);
|
||||
padding: var(--input-padding, 0) !important;
|
||||
letter-spacing: var(--input-letter-spacing, inherit);
|
||||
margin: var(--input-margin, 0);
|
||||
margin: var(--input-margin, 0) !important;
|
||||
min-width: 10px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type { FlowModule } from '$lib/gen'
|
||||
|
||||
import type { FlowModuleValue } from '$lib/gen'
|
||||
import FlowCardHeader from './FlowCardHeader.svelte'
|
||||
export let title: string | undefined = undefined
|
||||
export let flowModule: FlowModule | undefined = undefined
|
||||
export let summary: string | undefined = undefined
|
||||
export let noEditor: boolean
|
||||
export let flowModuleValue: FlowModuleValue | undefined = undefined
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col h-full">
|
||||
{#if !noEditor}
|
||||
<div>
|
||||
<FlowCardHeader on:reload {title} bind:flowModule>
|
||||
<FlowCardHeader on:setHash on:reload {title} bind:summary {flowModuleValue}>
|
||||
<slot name="header" />
|
||||
</FlowCardHeader>
|
||||
</div>
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
import LanguageIcon from '$lib/components/common/languageIcons/LanguageIcon.svelte'
|
||||
import MetadataGen from '$lib/components/copilot/MetadataGen.svelte'
|
||||
import IconedPath from '$lib/components/IconedPath.svelte'
|
||||
import { ScriptService, type FlowModule, type PathScript } from '$lib/gen'
|
||||
import { ScriptService, type FlowModuleValue, type PathScript } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { Lock, RefreshCw, Unlock } from 'lucide-svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let flowModule: FlowModule | undefined = undefined
|
||||
export let flowModuleValue: FlowModuleValue | undefined = undefined
|
||||
export let title: string | undefined = undefined
|
||||
export let summary: string | undefined = undefined
|
||||
|
||||
let latestHash: string | undefined = undefined
|
||||
async function loadLatestHash(value: PathScript) {
|
||||
@@ -24,45 +25,45 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: $workspaceStore &&
|
||||
flowModule?.value.type === 'script' &&
|
||||
flowModule.value.path &&
|
||||
!flowModule.value.path.startsWith('hub/') &&
|
||||
loadLatestHash(flowModule.value)
|
||||
flowModuleValue?.type === 'script' &&
|
||||
flowModuleValue.path &&
|
||||
!flowModuleValue.path.startsWith('hub/') &&
|
||||
loadLatestHash(flowModuleValue)
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="overflow-x-auto scrollbar-hidden flex items-center justify-between px-4 py-1 flex-nowrap"
|
||||
>
|
||||
{#if flowModule}
|
||||
{#if flowModuleValue}
|
||||
<span class="text-sm w-full mr-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
{#if flowModule.value.type === 'identity'}
|
||||
{#if flowModuleValue.type === 'identity'}
|
||||
<span class="font-bold text-xs">Identity (input copied to output)</span>
|
||||
{:else if flowModule?.value.type === 'rawscript'}
|
||||
{:else if flowModuleValue.type === 'rawscript'}
|
||||
<div class="mx-0.5">
|
||||
<LanguageIcon lang={flowModule.value.language} width={20} height={20} />
|
||||
<LanguageIcon lang={flowModuleValue.language} width={20} height={20} />
|
||||
</div>
|
||||
<MetadataGen
|
||||
bind:content={flowModule.summary}
|
||||
bind:content={summary}
|
||||
promptConfigName="summary"
|
||||
code={flowModule.value.content}
|
||||
code={flowModuleValue.content}
|
||||
class="w-full"
|
||||
elementProps={{
|
||||
placeholder: 'Summary'
|
||||
}}
|
||||
/>
|
||||
{:else if flowModule?.value.type === 'script' && 'path' in flowModule.value && flowModule.value.path}
|
||||
<IconedPath path={flowModule.value.path} hash={flowModule.value.hash} class="grow" />
|
||||
{:else if flowModuleValue.type === 'script' && 'path' in flowModuleValue && flowModuleValue.path}
|
||||
<IconedPath path={flowModuleValue.path} hash={flowModuleValue.hash} class="grow" />
|
||||
|
||||
{#if flowModule.value.hash}
|
||||
{#if latestHash != flowModule.value.hash}
|
||||
{#if flowModuleValue.hash}
|
||||
{#if latestHash != flowModuleValue.hash}
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
if (flowModule?.value.type == 'script') {
|
||||
flowModule.value.hash = latestHash
|
||||
if (flowModuleValue.type == 'script') {
|
||||
dispatch('setHash', latestHash)
|
||||
}
|
||||
dispatch('reload')
|
||||
}}>Update to latest hash</Button
|
||||
@@ -74,8 +75,8 @@
|
||||
btnClasses="text-tertiary inline-flex gap-1 items-center"
|
||||
color="light"
|
||||
on:click={() => {
|
||||
if (flowModule?.value.type == 'script') {
|
||||
flowModule.value.hash = undefined
|
||||
if (flowModuleValue.type == 'script') {
|
||||
dispatch('setHash', undefined)
|
||||
}
|
||||
}}><Unlock size={12} />hash</Button
|
||||
>
|
||||
@@ -87,8 +88,8 @@
|
||||
size="xs"
|
||||
btnClasses="text-tertiary inline-flex gap-1 items-center"
|
||||
on:click={() => {
|
||||
if (flowModule?.value.type == 'script') {
|
||||
flowModule.value.hash = latestHash
|
||||
if (flowModuleValue.type == 'script') {
|
||||
dispatch('setHash', latestHash)
|
||||
}
|
||||
}}><Lock size={12} />hash</Button
|
||||
>
|
||||
@@ -102,10 +103,10 @@
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
<input bind:value={flowModule.summary} placeholder="Summary" class="w-full grow" />
|
||||
{:else if flowModule?.value.type === 'flow'}
|
||||
<input bind:value={summary} placeholder="Summary" class="w-full grow" />
|
||||
{:else if flowModuleValue.type === 'flow'}
|
||||
<Badge color="indigo" capitalize>flow</Badge>
|
||||
<input bind:value={flowModule.summary} placeholder="Summary" class="w-full grow" />
|
||||
<input bind:value={summary} placeholder="Summary" class="w-full grow" />
|
||||
{/if}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
@@ -283,17 +283,31 @@
|
||||
{#if flowModule.value}
|
||||
<div class="h-full" bind:clientWidth={width}>
|
||||
<FlowCard
|
||||
flowModuleValue={flowModule?.value}
|
||||
on:reload={() => {
|
||||
forceReload++
|
||||
reload(flowModule)
|
||||
}}
|
||||
{noEditor}
|
||||
bind:flowModule
|
||||
on:setHash={(e) => {
|
||||
if (flowModule.value.type == 'script') {
|
||||
flowModule.value.hash = e.detail
|
||||
}
|
||||
}}
|
||||
bind:summary={flowModule.summary}
|
||||
>
|
||||
<svelte:fragment slot="header">
|
||||
<FlowModuleHeader
|
||||
{tag}
|
||||
bind:module={flowModule}
|
||||
module={flowModule}
|
||||
on:tagChange={(e) => {
|
||||
console.log('tagChange', e.detail)
|
||||
if (flowModule.value.type == 'script') {
|
||||
flowModule.value.tag_override = e.detail
|
||||
} else if (flowModule.value.type == 'rawscript') {
|
||||
flowModule.value.tag = e.detail
|
||||
}
|
||||
}}
|
||||
on:toggleSuspend={() => selectAdvanced('suspend')}
|
||||
on:toggleSleep={() => selectAdvanced('sleep')}
|
||||
on:toggleMock={() => selectAdvanced('mock')}
|
||||
|
||||
@@ -29,13 +29,11 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let customUi: undefined | FlowBuilderWhitelabelCustomUi = getContext('customUi')
|
||||
|
||||
$: moduleRetry = module.retry?.constant || module.retry?.exponential
|
||||
</script>
|
||||
|
||||
<div class="flex flex-row space-x-1">
|
||||
{#if module.value.type === 'script' || module.value.type === 'rawscript' || module.value.type == 'flow'}
|
||||
{#if moduleRetry}
|
||||
{#if module.retry?.constant || module.retry?.exponential}
|
||||
<Popover
|
||||
placement="bottom"
|
||||
class="center-center rounded p-2 bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200 dark:bg-frost-700 dark:text-frost-100 dark:border-frost-600"
|
||||
@@ -133,7 +131,11 @@
|
||||
</Button>
|
||||
{/if}
|
||||
{#if customUi?.tagEdit != false}
|
||||
<FlowModuleWorkerTagSelect nullTag={tag} bind:tag={module.value.tag_override} />
|
||||
<FlowModuleWorkerTagSelect
|
||||
nullTag={tag}
|
||||
tag={module.value.tag_override}
|
||||
on:change={(e) => dispatch('tagChange', e.detail)}
|
||||
/>
|
||||
{/if}
|
||||
{#if customUi?.scriptFork != false}
|
||||
<Button
|
||||
@@ -146,8 +148,7 @@
|
||||
Fork
|
||||
</Button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if module.value.type === 'flow'}
|
||||
{:else if module.value.type === 'flow'}
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
@@ -175,7 +176,10 @@
|
||||
{/if}
|
||||
<div class="px-0.5"></div>
|
||||
{#if module.value.type === 'rawscript'}
|
||||
<FlowModuleWorkerTagSelect bind:tag={module.value.tag} />
|
||||
<FlowModuleWorkerTagSelect
|
||||
tag={module.value.tag}
|
||||
on:change={(e) => dispatch('tagChange', e.detail)}
|
||||
/>
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import type { FlowEditorContext } from '../types'
|
||||
import { workerTags, workspaceStore } from '$lib/stores'
|
||||
import { WorkerService } from '$lib/gen'
|
||||
import WorkerTagSelect from '$lib/components/WorkerTagSelect.svelte'
|
||||
|
||||
export let tag: string | undefined
|
||||
export let nullTag: string | undefined = undefined
|
||||
let { tag = $bindable(), nullTag = $bindable() } = $props<{
|
||||
tag: string | undefined
|
||||
nullTag?: string | undefined
|
||||
}>()
|
||||
|
||||
const { flowStore, selectedId } = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
loadWorkerGroups()
|
||||
|
||||
async function loadWorkerGroups() {
|
||||
@@ -23,12 +26,12 @@
|
||||
{#if $workerTags?.length > 0}
|
||||
<div class="w-40">
|
||||
{#if $flowStore.tag == undefined}
|
||||
<WorkerTagSelect {nullTag} bind:tag />
|
||||
<WorkerTagSelect {nullTag} bind:tag on:change={(e) => dispatch('change', e.detail)} />
|
||||
{:else}
|
||||
<button
|
||||
title="Worker Group is defined at the flow level"
|
||||
class="w-full text-left items-center font-normal p-1 py-2 border text-xs rounded"
|
||||
on:click={() => ($selectedId = 'settings-worker-group')}
|
||||
onclick={() => ($selectedId = 'settings-worker-group')}
|
||||
>
|
||||
Flow's WG: {$flowStore.tag}
|
||||
</button>
|
||||
|
||||
@@ -32,6 +32,14 @@
|
||||
let jobId: string | undefined = undefined
|
||||
let job: Job | undefined = undefined
|
||||
let preventEscape = false
|
||||
let initial = false
|
||||
let selectedJobStep: string | undefined = undefined
|
||||
let selectedJobStepIsTopLevel: boolean | undefined = undefined
|
||||
let selectedJobStepType: 'single' | 'forloop' | 'branchall' = 'single'
|
||||
let branchOrIterationN: number = 0
|
||||
let scrollTop: number = 0
|
||||
|
||||
let rightColumnSelect: 'timeline' | 'node_status' | 'node_definition' | 'user_states' = 'timeline'
|
||||
|
||||
$: upToDisabled =
|
||||
$selectedId == undefined ||
|
||||
@@ -99,9 +107,16 @@
|
||||
<FlowPreviewContent
|
||||
bind:this={flowPreviewContent}
|
||||
open={previewOpen}
|
||||
bind:scrollTop
|
||||
bind:previewMode
|
||||
bind:job
|
||||
bind:jobId
|
||||
bind:initial
|
||||
bind:selectedJobStep
|
||||
bind:selectedJobStepIsTopLevel
|
||||
bind:selectedJobStepType
|
||||
bind:branchOrIterationN
|
||||
bind:rightColumnSelect
|
||||
on:close={() => {
|
||||
previewOpen = false
|
||||
}}
|
||||
|
||||
@@ -351,7 +351,7 @@
|
||||
{#if deletable}
|
||||
<button
|
||||
class="absolute -top-[10px] -right-[10px] rounded-full h-[20px] w-[20px] trash center-center text-secondary
|
||||
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-150 hover:bg-red-400 hover:text-white
|
||||
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-0 hover:bg-red-400 hover:text-white
|
||||
{hover || selected ? '' : '!hidden'}"
|
||||
title="Delete"
|
||||
on:click|preventDefault|stopPropagation={(event) =>
|
||||
@@ -363,7 +363,7 @@
|
||||
{#if id !== 'preprocessor'}
|
||||
<button
|
||||
class="absolute -top-[10px] right-[60px] rounded-full h-[20px] w-[20px] trash center-center text-secondary
|
||||
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-150 hover:bg-blue-400 hover:text-white
|
||||
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-0 hover:bg-blue-400 hover:text-white
|
||||
{hover ? '' : '!hidden'}"
|
||||
on:click|preventDefault|stopPropagation={(event) => dispatch('move')}
|
||||
title="Move"
|
||||
@@ -388,7 +388,7 @@ outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration
|
||||
</svelte:fragment>
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex items-center justify-center h-full w-full rounded-md p-0.5 border duration-150 ',
|
||||
'flex items-center justify-center h-full w-full rounded-md p-0.5 border duration-0 ',
|
||||
id &&
|
||||
Object.values($flowInputsStore?.[id]?.flowStepWarnings || {})?.some(
|
||||
(x) => x.type === 'error'
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
>
|
||||
{#if deletable}
|
||||
<button
|
||||
class="absolute -left-[28px] z-10 h-[20px] rounded-l rounded-t rounded-s w-[20px] trash center-center text-secondary bg-surface duration-150 hover:bg-blue-400 {editId
|
||||
class="absolute -left-[28px] z-10 h-[20px] rounded-l rounded-t rounded-s w-[20px] trash center-center text-secondary bg-surface duration-0 hover:bg-blue-400 {editId
|
||||
? '!bg-blue-400'
|
||||
: ''} hover:text-white
|
||||
hover:border-blue-700 hover:!visible {hover ? '' : '!hidden'}"
|
||||
|
||||
@@ -69,15 +69,15 @@ shouldUsePortal={true} -->
|
||||
kind === 'failure'
|
||||
? ' failure module '
|
||||
: kind === 'preprocessor'
|
||||
? 'preprocessor step'
|
||||
: kind === 'trigger'
|
||||
? 'trigger'
|
||||
: 'step'
|
||||
? 'preprocessor step'
|
||||
: kind === 'trigger'
|
||||
? 'trigger'
|
||||
: 'step'
|
||||
}`}
|
||||
id={`flow-editor-add-step-${index}`}
|
||||
type="button"
|
||||
class={twMerge(
|
||||
'w-[17.5px] h-[17.5px] flex items-center justify-center outline-[1px] outline dark:outline-gray-500 outline-gray-300 text-secondary bg-surface focus:outline-none hover:bg-surface-hover rounded',
|
||||
'w-[17.5px] h-[17.5px] flex items-center justify-center !outline-[1px] outline dark:outline-gray-500 outline-gray-300 text-secondary bg-surface focus:outline-none hover:bg-surface-hover rounded',
|
||||
$$props.class
|
||||
)}
|
||||
on:pointerdown|preventDefault|stopPropagation={() => {
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
'rounded-full center-center h-[18px] w-[18px]',
|
||||
isConnecting
|
||||
? 'bg-surface text-blue-500'
|
||||
: 'outline-[1px] outline dark:outline-gray-500 outline-gray-300 duration-150 bg-blue-500 hover:bg-blue-700 text-white'
|
||||
: 'outline-[1px] outline dark:outline-gray-500 outline-gray-300 duration-0 bg-blue-500 hover:bg-blue-700 text-white'
|
||||
)}
|
||||
>
|
||||
<Plug size={12} strokeWidth={2} />
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
allowFullScreen
|
||||
contentClasses="overflow-hidden resize rounded-md"
|
||||
contentStyle={`width: calc(${width}px); min-width: calc(${width}px); height: calc(${height}px); min-height: calc(${height}px);`}
|
||||
fullScreenWidthOffset={2 * width}
|
||||
extraProps={{ 'data-prop-picker': true }}
|
||||
closeOnOtherPopoverOpen
|
||||
class="outline-none"
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<button
|
||||
title="Delete branch"
|
||||
class="z-50 absolute -top-[10px] -right-[10px] rounded-full h-[20px] w-[20px] center-center text-primary
|
||||
outline-[1px] outline outline-gray-700 bg-surface duration-150 hover:bg-red-400 hover:text-white
|
||||
outline-[1px] outline outline-gray-700 bg-surface duration-0 hover:bg-red-400 hover:text-white
|
||||
hover:border-red-700"
|
||||
on:click|preventDefault|stopPropagation={() => {
|
||||
data.eventHandlers.deleteBranch(
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<button
|
||||
title="Delete branch"
|
||||
class="z-50 absolute -top-[10px] -right-[10px] rounded-full h-[20px] w-[20px] center-center text-primary
|
||||
border-[1.5px] border-gray-700 bg-surface duration-150 hover:bg-red-400 hover:text-white
|
||||
border-[1.5px] border-gray-700 bg-surface duration-0 hover:bg-red-400 hover:text-white
|
||||
hover:border-red-700"
|
||||
on:click|preventDefault|stopPropagation={() => {
|
||||
data.eventHandlers.deleteBranch(
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
{#if data.module.value.type == 'flow'}
|
||||
<button
|
||||
title="Expand subflow"
|
||||
class="z-50 absolute -top-[10px] right-[25px] rounded-full h-[20px] w-[20px] center-center text-primary bg-surface duration-150 hover:bg-surface-hover"
|
||||
class="z-50 absolute -top-[10px] right-[25px] rounded-full h-[20px] w-[20px] center-center text-primary bg-surface duration-0 hover:bg-surface-hover"
|
||||
on:click|preventDefault|stopPropagation={() => {
|
||||
if (data.module.value.type == 'flow') {
|
||||
data.eventHandlers.expandSubflow(data.module.id, data.module.value.path)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/>
|
||||
<button
|
||||
title="Unexpand subflow"
|
||||
class="z-50 absolute -top-[10px] right-[25px] rounded-full h-[20px] w-[20px] center-center text-primary bg-surface duration-150 hover:bg-surface-hover"
|
||||
class="z-50 absolute -top-[10px] right-[25px] rounded-full h-[20px] w-[20px] center-center text-primary bg-surface duration-0 hover:bg-surface-hover"
|
||||
on:click|preventDefault|stopPropagation={() => {
|
||||
data.eventHandlers.minimizeSubflow(data.subflowId)
|
||||
}}
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
{#if data.simplifiableFlow != undefined}
|
||||
<button
|
||||
class="absolute -top-[10px] -right-[10px] rounded-full h-[20px] w-[20px] trash center-center text-secondary
|
||||
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-150 hover:bg-nord-950 hover:text-white"
|
||||
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-0 hover:bg-nord-950 hover:text-white"
|
||||
on:click|preventDefault|stopPropagation={() =>
|
||||
data?.eventHandlers?.simplifyFlow(!data.simplifiableFlow?.simplifiedFlow)}
|
||||
title={data.simplifiableFlow?.simplifiedFlow
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
export let portal: string | HTMLElement | null = 'body'
|
||||
export let closeOnOtherPopoverOpen: boolean = false
|
||||
export let allowFullScreen: boolean = false
|
||||
export let fullScreenWidthOffset: number = 0
|
||||
export let extraProps: Record<string, any> = {}
|
||||
export let disabled: boolean = false
|
||||
export let documentationLink: string | undefined = undefined
|
||||
@@ -143,9 +142,7 @@
|
||||
)}
|
||||
data-popover
|
||||
{...extraProps}
|
||||
style={fullScreen
|
||||
? `width: calc(90vw - ${fullScreenWidthOffset}px); height: 90vh;`
|
||||
: contentStyle}
|
||||
style={fullScreen ? `width: 90vw; max-width: 800px; height: 90vh;` : contentStyle}
|
||||
>
|
||||
{#if displayArrow}
|
||||
<div use:melt={$arrow}></div>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
>
|
||||
{#each dropdownItems as item}
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150 w-full {item.selected
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-0 w-full {item.selected
|
||||
? 'bg-surface-selected'
|
||||
: 'text-secondary'}"
|
||||
on:click={() => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { driver, type Driver, type DriveStep } from 'driver.js'
|
||||
import 'driver.js/dist/driver.css'
|
||||
import { createEventDispatcher, mount } from 'svelte'
|
||||
import { updateProgress } from '$lib/tutorialUtils'
|
||||
import { ignoredTutorials } from './ignoredTutorials'
|
||||
import SkipTutorials from './SkipTutorials.svelte'
|
||||
import TutorialControls from './TutorialControls.svelte'
|
||||
import TutorialInner from './TutorialInner.svelte'
|
||||
|
||||
export let index: number = 0
|
||||
export let name: string = 'action'
|
||||
@@ -132,12 +132,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:global(.driver-popover) {
|
||||
padding: 32px;
|
||||
}
|
||||
:global(.driver-popover-title) {
|
||||
font-size: 1.2rem !important;
|
||||
line-height: 2 !important;
|
||||
}
|
||||
</style>
|
||||
{#if tutorial}
|
||||
<TutorialInner />
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<script lang="ts">
|
||||
import 'driver.js/dist/driver.css'
|
||||
</script>
|
||||
@@ -146,7 +146,7 @@ export function extToLang(ext: string) {
|
||||
return 'nu'
|
||||
case 'java':
|
||||
return 'java'
|
||||
// for related places search: ADD_NEW_LANG
|
||||
// for related places search: ADD_NEW_LANG
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
@@ -1259,3 +1259,10 @@ export function getOS() {
|
||||
|
||||
return 'Unknown OS' as const
|
||||
}
|
||||
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user