diff --git a/frontend/src/lib/components/assets/AssetGraph/AssetGraphCanvas.svelte b/frontend/src/lib/components/assets/AssetGraph/AssetGraphCanvas.svelte index f21cb5a01f..0b4e5ca385 100644 --- a/frontend/src/lib/components/assets/AssetGraph/AssetGraphCanvas.svelte +++ b/frontend/src/lib/components/assets/AssetGraph/AssetGraphCanvas.svelte @@ -718,6 +718,7 @@ missing: boolean draft: boolean schedule?: string + summary?: string // First target script (drives the per-script create/edit flows). runnable_path?: string // Every target script: a single (kind, ref) — e.g. one schedule — @@ -735,7 +736,8 @@ missing: boolean, draft: boolean, runnable_path?: string, - schedule?: string + schedule?: string, + summary?: string ) { const prev = triggerSourceNodes.get(id) if (!prev) { @@ -746,6 +748,7 @@ missing, draft, schedule, + summary, runnable_path, runnable_paths: runnable_path ? [runnable_path] : [] }) @@ -802,7 +805,8 @@ // disabled `canEdit` (and the resulting click affordance) // on every attached native trigger. t.runnable_path, - t.schedule + t.schedule, + t.summary ) edges.push({ id: `trig-${t.trigger_kind}:${sourceId}->${runnableId}`, @@ -832,6 +836,7 @@ missing: info.missing, draft: info.draft, schedule: info.schedule, + summary: info.summary, runnable_path: info.runnable_path, // data_upload nodes go green once a file is staged for their // target script (see readyDataUploadPaths / page dataUploadArgs). diff --git a/frontend/src/lib/components/assets/AssetGraph/TriggerNode.svelte b/frontend/src/lib/components/assets/AssetGraph/TriggerNode.svelte index 72aeab130b..fc2cbe3904 100644 --- a/frontend/src/lib/components/assets/AssetGraph/TriggerNode.svelte +++ b/frontend/src/lib/components/assets/AssetGraph/TriggerNode.svelte @@ -75,6 +75,8 @@ draft?: boolean // The cron, for a schedule: the node names its cadence instead of "Schedule". schedule?: string + // Shown as the title over the trigger's path, when the trigger has one. + summary?: string runnable_path?: string // Page-supplied dispatcher that opens the matching native // trigger drawer with `script_path` pre-filled. When absent @@ -235,7 +237,7 @@ if (canEdit) return { kindLabel: `${kindName}${data.draft ? ' · draft' : unsaved ? ' · unsaved' : ''}`, - title: data.ref, + title: data.summary || data.ref, tooltip: data.draft ? `Draft ${style.label}: ${data.ref} — created when you save the pipeline. Click to edit.` : `Edit ${style.label} trigger: ${data.ref}`, @@ -263,7 +265,7 @@ } return { kindLabel: `${displayMissing ? style.label : kindName}${displayMissing ? ' · missing' : unsaved ? ' · unsaved' : ''}`, - title: displayMissing ? 'no trigger row' : data.ref, + title: displayMissing ? 'no trigger row' : data.summary || data.ref, tooltip: missingTitle ?? (unsaved ? `Unsaved ${style.label}: ${data.ref}` : `${style.label}: ${data.ref}`), diff --git a/frontend/src/lib/components/assets/AssetGraph/resolveGraph.ts b/frontend/src/lib/components/assets/AssetGraph/resolveGraph.ts index a378f23d2a..1292f53697 100644 --- a/frontend/src/lib/components/assets/AssetGraph/resolveGraph.ts +++ b/frontend/src/lib/components/assets/AssetGraph/resolveGraph.ts @@ -309,7 +309,8 @@ function withTriggerDrafts( runnable_path: d.config.script_path, unsaved: true, draft: true, - ...(d.kind === 'schedule' ? { schedule: d.config.schedule as string } : {}) + ...(d.kind === 'schedule' ? { schedule: d.config.schedule as string } : {}), + ...(d.config.summary ? { summary: d.config.summary as string } : {}) })) ] } diff --git a/frontend/src/lib/components/assets/AssetGraph/types.ts b/frontend/src/lib/components/assets/AssetGraph/types.ts index 1bca932a6d..5a6eda3fc2 100644 --- a/frontend/src/lib/components/assets/AssetGraph/types.ts +++ b/frontend/src/lib/components/assets/AssetGraph/types.ts @@ -214,8 +214,9 @@ export type AssetGraphTrigger = // A pipeline-local `PipelineTriggerDraft`: `path` is the trigger it // will be deployed as, and no row exists yet. draft?: boolean - // A schedule's cron, filled in client-side, for the node's label. + // A schedule's cron and summary, filled in client-side, for the node's labels. schedule?: string + summary?: string } // Macro-library → consumer edge: the consumer calls `macro_names` of diff --git a/frontend/src/routes/(root)/(logged)/pipeline/[folder]/+page.svelte b/frontend/src/routes/(root)/(logged)/pipeline/[folder]/+page.svelte index 6bdec71446..64c8b080a3 100644 --- a/frontend/src/routes/(root)/(logged)/pipeline/[folder]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/pipeline/[folder]/+page.svelte @@ -1381,13 +1381,13 @@ if (refs.length > 0) explicitOnByPath.set(r.path, refs) } const errors = pipelineNodeErrors(g, explicitOnByPath) - const crons = scheduleCrons.current + const schedules = scheduleInfo.current return { ...g, - triggers: crons?.size + triggers: schedules?.size ? g.triggers.map((t) => - t.trigger_kind === 'schedule' && t.path && !t.schedule && crons.has(t.path) - ? { ...t, schedule: crons.get(t.path) } + t.trigger_kind === 'schedule' && t.path && !t.draft && schedules.has(t.path) + ? { ...t, ...schedules.get(t.path) } : t ) : g.triggers, @@ -2467,13 +2467,13 @@ } ) - // Crons of the deployed schedules on the graph, for their nodes' labels. - // Re-read with every graph load, so an edit in the schedule drawer shows. - let scheduleCrons = resource( + // Cron and summary of the deployed schedules on the graph, for their nodes' + // labels. Re-read with every graph load, so an edit in the schedule drawer shows. + let scheduleInfo = resource( [() => $workspaceStore, () => graphRes.current], async ([ws, g]) => { - const crons = new Map() - if (!ws || !g) return crons + const info = new Map() + if (!ws || !g) return info const paths = new Set() for (const t of g.triggers) { if (t.trigger_kind === 'schedule' && t.path && !t.missing) paths.add(t.path) @@ -2482,13 +2482,13 @@ [...paths].map(async (path) => { try { const s = await ScheduleService.getSchedule({ workspace: ws, path }) - crons.set(path, s.schedule) + info.set(path, { schedule: s.schedule, summary: s.summary || undefined }) } catch { // Unreadable schedule: its node keeps the plain "Schedule" label. } }) ) - return crons + return info } )