From 1cefbe263bfec0926a39618da346c83d601267e6 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 8 Nov 2022 10:27:25 +0100 Subject: [PATCH] pass workspace as query arg of every runs link --- backend/windmill-api/src/oauth2.rs | 5 +- .../src/lib/components/FlowMetadata.svelte | 2 +- frontend/src/lib/components/RunChart.svelte | 24 +- .../src/lib/components/TestJobLoader.svelte | 23 +- .../src/lib/components/jobs/JobDetail.svelte | 16 +- .../preview/FlowPreviewStatus.svelte | 2 +- .../[job]/[resume]/[hmac]@none.svelte | 4 +- .../src/routes/flows/run/[...path].svelte | 4 +- frontend/src/routes/run/[...run].svelte | 416 ++++++++++-------- .../src/routes/scripts/run/[...hash].svelte | 4 +- 10 files changed, 283 insertions(+), 217 deletions(-) diff --git a/backend/windmill-api/src/oauth2.rs b/backend/windmill-api/src/oauth2.rs index ecae165b7f..8754a54159 100644 --- a/backend/windmill-api/src/oauth2.rs +++ b/backend/windmill-api/src/oauth2.rs @@ -710,7 +710,10 @@ async fn slack_command( .await?; tx.commit().await?; let url = base_url.0.to_owned(); - return Ok(format!("Job launched. See details at {url}/run/{uuid}")); + return Ok(format!( + "Job launched. See details at {url}/run/{uuid}?workspace={}", + &settings.workspace_id + )); } } diff --git a/frontend/src/lib/components/FlowMetadata.svelte b/frontend/src/lib/components/FlowMetadata.svelte index 0dfa58ac31..ea4a283d63 100644 --- a/frontend/src/lib/components/FlowMetadata.svelte +++ b/frontend/src/lib/components/FlowMetadata.svelte @@ -71,6 +71,6 @@
- run id: {job.id} + run id: {job.id}
diff --git a/frontend/src/lib/components/RunChart.svelte b/frontend/src/lib/components/RunChart.svelte index 95d0cc82ec..a06a976186 100644 --- a/frontend/src/lib/components/RunChart.svelte +++ b/frontend/src/lib/components/RunChart.svelte @@ -16,6 +16,7 @@ } from 'chart.js' import type { CompletedJob } from '$lib/gen' import { createEventDispatcher } from 'svelte' + import { json } from 'svelte-highlight/languages' export let jobs: CompletedJob[] | undefined = [] @@ -43,13 +44,16 @@ // borderColor: 'rgba(99,0,125, .2)', backgroundColor: '#f87171', label: 'Failed', - data: failed?.map((job) => ({ x: job.created_at as any, y: job.duration_ms })) ?? [] + data: + failed?.map((job) => ({ x: job.created_at as any, y: job.duration_ms, id: job.id })) ?? [] }, { // borderColor: 'rgba(99,0,125, .2)', backgroundColor: '#4ade80', label: 'Successful', - data: success?.map((job) => ({ x: job.created_at as any, y: job.duration_ms })) ?? [] + data: + success?.map((job) => ({ x: job.created_at as any, y: job.duration_ms, id: job.id })) ?? + [] } ] } @@ -83,8 +87,24 @@ zoom: zoomOptions, legend: { display: false + }, + tooltip: { + callbacks: { + label: function (context) { + let label = context.dataset.label || 'X' + + if (label) { + label += ': ' + } + if (context.parsed.y !== null) { + label += JSON.stringify(context.parsed) + } + return label + } + } } }, + scales: { x: { grid: { diff --git a/frontend/src/lib/components/TestJobLoader.svelte b/frontend/src/lib/components/TestJobLoader.svelte index d62b9a157a..5cb330397c 100644 --- a/frontend/src/lib/components/TestJobLoader.svelte +++ b/frontend/src/lib/components/TestJobLoader.svelte @@ -11,7 +11,10 @@ export let isLoading = false export let job: Job | undefined = undefined + export let workspaceOverride: string | undefined = undefined + export let notfound = false + $: workspace = workspaceOverride ?? $workspaceStore let intervalId: NodeJS.Timer let syncIteration: number = 0 @@ -27,7 +30,7 @@ intervalId && clearInterval(intervalId) if (isLoading && job) { JobService.cancelQueuedJob({ - workspace: $workspaceStore!, + workspace: workspace!, id: job.id, requestBody: {} }) @@ -35,7 +38,7 @@ isLoading = true const testId = await JobService.runScriptPreview({ - workspace: $workspaceStore!, + workspace: workspace!, requestBody: { path, content: code, @@ -78,7 +81,7 @@ try { if (job && `running` in job) { let previewJobUpdates = await JobService.getJobUpdates({ - workspace: $workspaceStore!, + workspace: workspace!, id, running: job.running, logOffset: job.logs?.length ?? 0 @@ -88,21 +91,29 @@ job.logs = (job.logs ?? '').concat(previewJobUpdates.new_logs) } if ((previewJobUpdates.running ?? false) || (previewJobUpdates.completed ?? false)) { - job = await JobService.getJob({ workspace: $workspaceStore!, id }) + job = await JobService.getJob({ workspace: workspace!, id }) } } else { - job = await JobService.getJob({ workspace: $workspaceStore!, id }) + console.log(workspaceOverride) + console.log(workspace) + + job = await JobService.getJob({ workspace: workspace!, id }) } if (job?.type === 'CompletedJob') { //only CompletedJob has success property isCompleted = true - clearInterval(intervalId) + intervalId && clearInterval(intervalId) if (isLoading) { dispatch('done', job) isLoading = false } } + notfound = false } catch (err) { + intervalId && clearInterval(intervalId) + if (err.status === 404) { + notfound = true + } console.error(err) } return isCompleted diff --git a/frontend/src/lib/components/jobs/JobDetail.svelte b/frontend/src/lib/components/jobs/JobDetail.svelte index f2168639a2..ce3f092495 100644 --- a/frontend/src/lib/components/jobs/JobDetail.svelte +++ b/frontend/src/lib/components/jobs/JobDetail.svelte @@ -89,13 +89,15 @@
{#if job.script_path} - {job.script_path} + {job.script_path} {:else if 'job_kind' in job && job.job_kind == 'preview'} - Preview without path + Preview without path {:else if 'job_kind' in job && job.job_kind == 'dependencies'} - lock deps of {truncateHash(job.script_hash ?? '')} + lock deps of {truncateHash(job.script_hash ?? '')} {:else if 'job_kind' in job && job.job_kind == 'identity'} - no op + no op {/if}
diff --git a/frontend/src/lib/components/preview/FlowPreviewStatus.svelte b/frontend/src/lib/components/preview/FlowPreviewStatus.svelte index 76b2482269..9e18a84de1 100644 --- a/frontend/src/lib/components/preview/FlowPreviewStatus.svelte +++ b/frontend/src/lib/components/preview/FlowPreviewStatus.svelte @@ -20,7 +20,7 @@ Job Id - + {job?.id} diff --git a/frontend/src/routes/approve/[workspace]/[job]/[resume]/[hmac]@none.svelte b/frontend/src/routes/approve/[workspace]/[job]/[resume]/[hmac]@none.svelte index 8c980b37f5..48037b84b6 100644 --- a/frontend/src/routes/approve/[workspace]/[job]/[resume]/[hmac]@none.svelte +++ b/frontend/src/routes/approve/[workspace]/[job]/[resume]/[hmac]@none.svelte @@ -161,7 +161,9 @@
Learn more about Windmill - Flow run details (require auth) + Flow run details (require auth)
{#if job && job.raw_flow}

Flow details

diff --git a/frontend/src/routes/flows/run/[...path].svelte b/frontend/src/routes/flows/run/[...path].svelte index b82e38bfd2..352d2d4478 100644 --- a/frontend/src/routes/flows/run/[...path].svelte +++ b/frontend/src/routes/flows/run/[...path].svelte @@ -54,8 +54,8 @@ requestBody: args, scheduledFor }) - sendUserToast(`Job ${run} started`) - goto('/run/' + run) + sendUserToast(`Job ${run} started`) + goto('/run/' + run + '?workspace=' + $workspaceStore) } $: { diff --git a/frontend/src/routes/run/[...run].svelte b/frontend/src/routes/run/[...run].svelte index 252839aa58..04b5037291 100644 --- a/frontend/src/routes/run/[...run].svelte +++ b/frontend/src/routes/run/[...run].svelte @@ -26,7 +26,7 @@ faFastForward } from '@fortawesome/free-solid-svg-icons' import DisplayResult from '$lib/components/DisplayResult.svelte' - import { userStore, workspaceStore } from '$lib/stores' + import { userStore, usersWorkspaceStore, workspaceStore } from '$lib/stores' import CenteredPage from '$lib/components/CenteredPage.svelte' import FlowStatusViewer from '$lib/components/FlowStatusViewer.svelte' import HighlightCode from '$lib/components/HighlightCode.svelte' @@ -39,8 +39,7 @@ import Tabs from '$lib/components/common/tabs/Tabs.svelte' import Badge from '$lib/components/common/badge/Badge.svelte' - let workspace_id_query: string | undefined = $page.url.searchParams.get('workspace') ?? undefined - let workspace_id: string | undefined + $: workspace_id = $page.url.searchParams.get('workspace') ?? $workspaceStore let job: Job | undefined const iconScale = 1 @@ -83,11 +82,11 @@ } $: { - if ($workspaceStore && $page.params.run && testJobLoader) { - workspace_id = workspace_id_query ?? $workspaceStore + if (workspace_id && $page.params.run && testJobLoader) { getLogs() } } + let notfound = false - -{#if job?.job_kind === 'script' || job?.job_kind === 'flow'} - - - {@const isScript = job?.job_kind === 'script'} - {@const runsHref = `/runs/${job?.script_path}${!isScript ? '?jobKind=flow' : ''}`} - {#if job && 'deleted' in job && !job?.deleted && ($userStore?.is_admin ?? false)} +{#if notfound} + +
+

Job {$page.params.run} not found in {workspace_id}

+

Are you in the right workspace?

+
+ {#each $usersWorkspaceStore?.workspaces ?? [] as workspace} +
+ {/each} +
+ +
+
+
+
+{:else} + + {#if job?.job_kind === 'script' || job?.job_kind === 'flow'} + + + {@const isScript = job?.job_kind === 'script'} + {@const runsHref = `/runs/${job?.script_path}${!isScript ? '?jobKind=flow' : ''}`} + {#if job && 'deleted' in job && !job?.deleted && ($userStore?.is_admin ?? false)} + + + {/if} + + + {@const stem = `/${job?.job_kind}s`} + {@const isScript = job?.job_kind === 'script'} + {@const route = isScript ? job?.script_hash : job?.script_path} + {@const runHref = `${stem}/run/${route}${ + job?.args ? '?args=' + encodeURIComponent(encodeState(job?.args)) : '' + }`} + {@const editHref = `${stem}/edit/${route}${ + isScript + ? `?step=2${job?.args ? `&args=${encodeURIComponent(encodeState(job?.args))}` : ''}` + : `${job?.args ? `?args=${encodeURIComponent(encodeState(job?.args))}` : ''}` + }`} + {@const isRunning = job && 'running' in job && job.running} + {@const viewHref = `${stem}/get/${isScript ? job?.script_hash : job?.script_path}`} + {#if isRunning} + + {/if} - - View runs + {#if canWrite(job?.script_path ?? '', {}, $userStore)} + + {/if} + - {/if} - - - {@const stem = `/${job?.job_kind}s`} - {@const isScript = job?.job_kind === 'script'} - {@const route = isScript ? job?.script_hash : job?.script_path} - {@const runHref = `${stem}/run/${route}${ - job?.args ? '?args=' + encodeURIComponent(encodeState(job?.args)) : '' - }`} - {@const editHref = `${stem}/edit/${route}${ - isScript - ? `?step=2${job?.args ? `&args=${encodeURIComponent(encodeState(job?.args))}` : ''}` - : `${job?.args ? `?args=${encodeURIComponent(encodeState(job?.args))}` : ''}` - }`} - {@const isRunning = job && 'running' in job && job.running} - {@const runsHref = `/runs/${job?.script_path}${!isScript ? '?jobKind=flow' : ''}`} - {@const viewHref = `${stem}/get/${isScript ? job?.script_hash : job?.script_path}`} - {#if isRunning} - - {/if} - - {#if canWrite(job?.script_path ?? '', {}, $userStore)} - - {/if} - - - -{/if} - -

-
- {#if job} - {#if 'success' in job && job.success} - {#if job.is_skipped} - - {:else} - - {/if} - {:else if job && 'success' in job} - - {:else if job && 'running' in job && job.running} - - {:else if job && 'running' in job && job.scheduled_for && forLater(job.scheduled_for)} - - {:else if job && 'running' in job && job.scheduled_for} - - {/if} - {job.script_path ?? (job.job_kind == 'dependencies' ? 'lock dependencies' : 'No path')} - {#if job.script_hash} - {truncateHash(job.script_hash)} - {/if} - {#if job && 'job_kind' in job}{job.job_kind} - {/if} - {/if} -
-

- {#if job && 'deleted' in job && job?.deleted} - +
+
{/if} - - -
-
- - - {#if job?.job_kind == 'flow' || job?.job_kind == 'flowpreview'} -
- -
- { - job = detail - }} - /> -
- {/if} -
-
- - {#if job}{/if} -
-
- - {#if job?.job_kind !== 'flow' && job?.job_kind !== 'flowpreview'} - -
- - Result - Logs - {#if job?.job_kind == 'dependencies'} - Dependencies - {:else if job?.job_kind == 'preview'} - Code - {/if} - - - - {#if job} -
- {#if viewTab == 'logs'} -
- -
- {:else if viewTab == 'code'} - {#if job && 'raw_code' in job && job.raw_code} - - {:else if job} - No code is available + +

+
+ {#if job} + {#if 'success' in job && job.success} + {#if job.is_skipped} + {:else} - + {/if} - {:else if job !== undefined && 'result' in job && job.result !== undefined} - - {:else if job} - No output is available yet + {:else if job && 'success' in job} + + {:else if job && 'running' in job && job.running} + + {:else if job && 'running' in job && job.scheduled_for && forLater(job.scheduled_for)} + + {:else if job && 'running' in job && job.scheduled_for} + {/if} -
- {/if} + {job.script_path ?? (job.job_kind == 'dependencies' ? 'lock dependencies' : 'No path')} + {#if job.script_hash} + {truncateHash(job.script_hash)} + {/if} + {#if job && 'job_kind' in job}{job.job_kind} + {/if} + {/if} +

+ + {#if job && 'deleted' in job && job?.deleted} + + {/if} + + +
+
+ + + {#if job?.job_kind == 'flow' || job?.job_kind == 'flowpreview'} +
+ +
+ { + job = detail + }} + /> +
+ {/if} +
+
+ + {#if job}{/if} +
- {/if} - + + {#if job?.job_kind !== 'flow' && job?.job_kind !== 'flowpreview'} + +
+ + Result + Logs + {#if job?.job_kind == 'dependencies'} + Dependencies + {:else if job?.job_kind == 'preview'} + Code + {/if} + + + + {#if job} +
+ {#if viewTab == 'logs'} +
+ +
+ {:else if viewTab == 'code'} + {#if job && 'raw_code' in job && job.raw_code} + + {:else if job} + No code is available + {:else} + + {/if} + {:else if job !== undefined && 'result' in job && job.result !== undefined} + + {:else if job} + No output is available yet + {/if} +
+ {/if} +
+ {/if} + +{/if} diff --git a/frontend/src/routes/scripts/run/[...hash].svelte b/frontend/src/routes/scripts/run/[...hash].svelte index ec72cd3d82..2a1682935c 100644 --- a/frontend/src/routes/scripts/run/[...hash].svelte +++ b/frontend/src/routes/scripts/run/[...hash].svelte @@ -59,8 +59,8 @@ requestBody: args, scheduledFor }) - sendUserToast(`Job ${run} started`) - goto('/run/' + run) + sendUserToast(`Job ${run} started`) + goto('/run/' + run + '?workspace=' + $workspaceStore) } catch (err) { sendUserToast(`Could not create job: ${err}`, true) }