fix: renaming app + improve flow rendering

This commit is contained in:
Ruben Fiszel
2023-06-02 11:51:47 +02:00
parent 45641cbbab
commit f7e23acfdc
6 changed files with 181 additions and 155 deletions
+2 -2
View File
@@ -602,7 +602,7 @@ async fn update_app(
if let Some(nvalue) = &ns.value {
let app_id = sqlx::query_scalar!(
"SELECT id FROM app WHERE path = $1 AND workspace_id = $2",
path,
npath,
w_id
)
.fetch_one(&mut tx)
@@ -623,7 +623,7 @@ async fn update_app(
sqlx::query!(
"UPDATE app SET versions = array_append(versions, $1) WHERE path = $2 AND workspace_id = $3",
v_id,
path,
npath,
w_id
)
.execute(&mut tx)
@@ -37,6 +37,7 @@
let localFlowModuleStates: Record<string, GraphModuleState> = {}
export let retry_status: Record<string, number> = {}
export let suspend_status: number | undefined = undefined
export let render = true
export let is_owner = false
@@ -152,7 +153,7 @@
$: jobId && updateJobId()
$: isListJob = flowJobIds && Array.isArray(flowJobIds?.flowJobs)
$: isListJob = flowJobIds != undefined && Array.isArray(flowJobIds?.flowJobs)
onDestroy(() => {
timeout && clearTimeout(timeout)
@@ -162,7 +163,7 @@
is_owner = isOwner(path, $userStore!, workspaceId ?? $workspaceStore!)
}
let selected: 'graph' | 'sequence' = 'graph'
$: selected = isListJob ? 'sequence' : 'graph'
let payload: string = '"a test payload in json"'
@@ -209,10 +210,12 @@
<h3 class="text-md leading-6 font-bold text-gray-900 border-b pb-2">Flow result</h3>
{/if}
{#if isListJob}
<div class="w-full h-full border border-gray-600 bg-white p-1">
<DisplayResult result={jobResults} />
</div>
{:else}
{#if render}
<div class="w-full h-full border border-gray-600 bg-white p-1">
<DisplayResult result={jobResults} />
</div>
{/if}
{:else if render}
<div class={innerModules.length > 0 ? 'border border-gray-400 shadow p-2' : ''}>
<FlowPreviewStatus {job} />
{#if `result` in job}
@@ -291,48 +294,51 @@
{/if}
</div>
{/if}
{#if innerModules.length > 0 && !isListJob}
<Tabs bind:selected>
<Tab value="graph"><span class="font-semibold text-md">Graph</span></Tab>
<Tab value="sequence"><span class="font-semibold">Details</span></Tab>
</Tabs>
{#if render}
{#if innerModules.length > 0 && !isListJob}
<Tabs bind:selected>
<Tab value="graph"><span class="font-semibold text-md">Graph</span></Tab>
<Tab value="sequence"><span class="font-semibold">Details</span></Tab>
</Tabs>
{/if}
{/if}
<div class={selected == 'graph' && !isListJob ? 'hidden' : ''}>
<div class={selected == 'graph' ? 'hidden' : ''}>
{#if isListJob}
<h3 class="text-md leading-6 font-bold text-gray-600 border-b mb-4">
Embedded flows: ({flowJobIds?.flowJobs.length} items)
</h3>
{#each flowJobIds?.flowJobs ?? [] as loopJobId, j}
<Button
variant={forloop_selected === loopJobId ? 'contained' : 'border'}
color={jobFailures[j] === true
? 'red'
: forloop_selected === loopJobId
? 'dark'
: 'light'}
btnClasses="w-full flex justify-start"
on:click={() => {
if (forloop_selected == loopJobId) {
forloop_selected = ''
} else {
forloop_selected = loopJobId
}
}}
>
<span class="truncate">
#{j + 1}: {loopJobId}
</span>
{#if render}
<Button
variant={forloop_selected === loopJobId ? 'contained' : 'border'}
color={jobFailures[j] === true
? 'red'
: forloop_selected === loopJobId
? 'dark'
: 'light'}
btnClasses="w-full flex justify-start"
on:click={() => {
if (forloop_selected == loopJobId) {
forloop_selected = ''
} else {
forloop_selected = loopJobId
}
}}
>
<span class="truncate">
#{j + 1}: {loopJobId}
</span>
<Icon
class="ml-2"
data={forloop_selected == loopJobId ? faChevronUp : faChevronDown}
scale={0.8}
/>
</Button>
<Icon
class="ml-2"
data={forloop_selected == loopJobId ? faChevronUp : faChevronDown}
scale={0.8}
/>
</Button>
{/if}
<div class="border p-6" class:hidden={forloop_selected != loopJobId}>
<svelte:self
render={forloop_selected == loopJobId && selected == 'sequence' && render}
{workspaceId}
bind:suspend_status
bind:retry_status
@@ -386,29 +392,32 @@
</h3>
{#each innerModules as mod, i}
<div class="line w-8 h-10" />
<h3 class="text-gray-500 mb-2 w-full">
{#if job?.raw_flow?.modules && i < job?.raw_flow?.modules.length}
Step
<span class="font-medium text-gray-900">
{i + 1}
</span>
out of
<span class="font-medium text-gray-900">{job?.raw_flow?.modules.length}</span>
{#if job.raw_flow?.modules[i]?.summary}
: <span class="font-medium text-gray-900">
{job.raw_flow?.modules[i]?.summary ?? ''}
{#if render}
<div class="line w-8 h-10" />
<h3 class="text-gray-500 mb-2 w-full">
{#if job?.raw_flow?.modules && i < job?.raw_flow?.modules.length}
Step
<span class="font-medium text-gray-900">
{i + 1}
</span>
out of
<span class="font-medium text-gray-900">{job?.raw_flow?.modules.length}</span>
{#if job.raw_flow?.modules[i]?.summary}
: <span class="font-medium text-gray-900">
{job.raw_flow?.modules[i]?.summary ?? ''}
</span>
{/if}
{:else}
<h3>Failure module</h3>
{/if}
{:else}
<h3>Failure module</h3>
{/if}
</h3>
<div class="line w-8 h-10" />
</h3>
<div class="line w-8 h-10" />
{/if}
<li class="w-full border border-gray-600 p-6 space-y-2 bg-blue-50/50">
{#if [FlowStatusModule.type.IN_PROGRESS, FlowStatusModule.type.SUCCESS, FlowStatusModule.type.FAILURE].includes(mod.type)}
{#if job.raw_flow?.modules[i]?.value.type == 'flow'}
<svelte:self
render={selected == 'sequence' && render}
{workspaceId}
jobId={mod.job}
bind:suspend_status
@@ -417,6 +426,7 @@
/>
{:else}
<svelte:self
render={selected == 'sequence' && render}
{workspaceId}
bind:suspend_status
bind:retry_status
@@ -444,102 +454,105 @@
{/if}
</div>
</div>
{#if job.raw_flow && !isListJob}
<div class="{selected != 'graph' ? 'hidden' : ''} mt-4">
<div class="grid grid-cols-3 border border-gray-300">
<div class="col-span-2 bg-gray-50">
<div class="flex flex-col">
{#each Object.values(retry_status) as count}
<span class="text-sm">
Retry in progress, # of failed attempts: {count}
</span>
{/each}
{#if suspend_status}
<span class="text-sm">
Flow suspended, waiting for {pluralize(suspend_status, 'approval')}
</span>
{/if}
</div>
<FlowGraph
success={isSuccess(job?.['success'])}
flowModuleStates={localFlowModuleStates}
on:select={(e) => {
if (typeof e.detail == 'string') {
if (e.detail == 'Input') {
selectedNode = 'start'
} else if (e.detail == 'Result') {
selectedNode = 'end'
} else {
selectedNode = e.detail
}
} else {
selectedNode = e.detail.id
}
}}
modules={job.raw_flow?.modules ?? []}
failureModule={job.raw_flow?.failure_module}
/>
</div>
<div class="border-l border-gray-400 pt-1 overflow-hidden">
{#if selectedNode}
{@const node = localFlowModuleStates[selectedNode]}
{#if selectedNode == 'end'}
<FlowJobResult
filename={job.id}
loading={job['running']}
noBorder
col
result={job['result']}
logs={job.logs ?? ''}
/>
{:else if selectedNode == 'start'}
{#if job.args}
<div class="p-2">
<JobArgs args={job.args} />
</div>
{:else}
<p class="p-2">No arguments</p>
{#if render}
{#if job.raw_flow && !isListJob}
<div class="{selected != 'graph' ? 'hidden' : ''} mt-4">
<div class="grid grid-cols-3 border border-gray-300">
<div class="col-span-2 bg-gray-50">
<div class="flex flex-col">
{#each Object.values(retry_status) as count}
<span class="text-sm">
Retry in progress, # of failed attempts: {count}
</span>
{/each}
{#if suspend_status}
<span class="text-sm">
Flow suspended, waiting for {pluralize(suspend_status, 'approval')}
</span>
{/if}
{:else if node}
<div class="px-2 flex gap-2 min-w-0">
<ModuleStatus type={node.type} scheduled_for={node['scheduled_for']} />
{#if node.job_id}
<div class="truncate"
><div class=" text-gray-900 whitespace-nowrap truncate">
<span class="font-bold">Job Id</span>
<a
rel="noreferrer"
target="_blank"
href="/run/{node.job_id ?? ''}?workspace={job?.workspace_id}"
>
{truncateRev(node.job_id ?? '', 10) ?? ''}
</a>
</div>
</div>
{/if}
</div>
<div class="px-1 border-b border-black">
<JobArgs args={node.args} />
</div>
</div>
<FlowJobResult
loading={job['running'] == true}
noBorder
col
result={node.result}
logs={node.logs ?? ''}
/>
{:else}
<p class="p-2 text-gray-600 italic"
>The execution of this node has no information attached to it. The job likely did
not run yet</p
>
{/if}
{:else}<p class="p-2 text-gray-600 italic">Select a node to see its details here</p>{/if}
<FlowGraph
success={isSuccess(job?.['success'])}
flowModuleStates={localFlowModuleStates}
on:select={(e) => {
if (typeof e.detail == 'string') {
if (e.detail == 'Input') {
selectedNode = 'start'
} else if (e.detail == 'Result') {
selectedNode = 'end'
} else {
selectedNode = e.detail
}
} else {
selectedNode = e.detail.id
}
}}
modules={job.raw_flow?.modules ?? []}
failureModule={job.raw_flow?.failure_module}
/>
</div>
<div class="border-l border-gray-400 pt-1 overflow-hidden">
{#if selectedNode}
{@const node = localFlowModuleStates[selectedNode]}
{#if selectedNode == 'end'}
<FlowJobResult
filename={job.id}
loading={job['running']}
noBorder
col
result={job['result']}
logs={job.logs ?? ''}
/>
{:else if selectedNode == 'start'}
{#if job.args}
<div class="p-2">
<JobArgs args={job.args} />
</div>
{:else}
<p class="p-2">No arguments</p>
{/if}
{:else if node}
<div class="px-2 flex gap-2 min-w-0">
<ModuleStatus type={node.type} scheduled_for={node['scheduled_for']} />
{#if node.job_id}
<div class="truncate"
><div class=" text-gray-900 whitespace-nowrap truncate">
<span class="font-bold">Job Id</span>
<a
rel="noreferrer"
target="_blank"
href="/run/{node.job_id ?? ''}?workspace={job?.workspace_id}"
>
{truncateRev(node.job_id ?? '', 10) ?? ''}
</a>
</div>
</div>
{/if}
</div>
<div class="px-1 border-b border-black">
<JobArgs args={node.args} />
</div>
<FlowJobResult
loading={job['running'] == true}
noBorder
col
result={node.result}
logs={node.logs ?? ''}
/>
{:else}
<p class="p-2 text-gray-600 italic"
>The execution of this node has no information attached to it. The job likely did
not run yet</p
>
{/if}
{:else}<p class="p-2 text-gray-600 italic">Select a node to see its details here</p
>{/if}
</div>
</div>
</div>
</div>
{/if}
{/if}
{:else}
Job loading...
@@ -67,6 +67,7 @@
function handleAddOrEditArgument(modalProperty: ModalSchemaProperty): void {
// If editing the arg's name, oldName containing the old argument name must be provided
argError = ''
modalProperty.name = modalProperty.name.trim()
if (modalProperty.name.length === 0) {
argError = 'Arguments need to have a name'
} else if (Object.keys(schema.properties).includes(modalProperty.name) && !editing) {
@@ -206,20 +206,26 @@
}
}
async function updateApp(path: string) {
async function updateApp(npath: string) {
await computeTriggerables()
await AppService.updateApp({
workspace: $workspaceStore!,
path,
path: appPath,
requestBody: {
value: $app!,
summary: $summary,
policy
policy,
path: npath
}
})
$dirtyStore = false
closeSaveDrawer()
sendUserToast('App deployed successfully')
if (appPath !== npath) {
await goto(`/apps/edit/${npath}?nodraft=true`)
window.location.reload()
}
}
let secretUrl: string | undefined = undefined
@@ -15,7 +15,7 @@
export let trigger: boolean
export let insertable: boolean
export let insertableEnd = false
// export let annotation: string | undefined = undefined
export let annotation: string | undefined = undefined
export let branchable: boolean = false
export let bgColor: string = ''
export let modules: FlowModule[]
@@ -87,6 +87,12 @@
</div>
{/if}
{#if annotation && annotation != ''}
<div class="absolute z-10 left-0 -top-5 center-center text-gray-600">
{annotation}
</div>
{/if}
<div class={moving == mod.id ? 'opacity-50' : ''}>
{#if mod.value.type === 'forloopflow'}
<FlowModuleSchemaItem
@@ -250,7 +250,7 @@
insertableEnd,
branchable,
bgColor: getStateColor(flowModuleStates?.[mod.id]?.type),
// annotation,
annotation,
modules,
moving
},