diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 3294d85d95..1c0ac068f3 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -33369,6 +33369,11 @@ components: timezone: description: the schedule's timezone, for a schedule only type: string + cron_version: + description: >- + the schedule's cron version, for a schedule only; v1 numbers + weekdays from 1 = Sunday + type: string TriggersCount: type: object diff --git a/backend/windmill-api/src/runnables.rs b/backend/windmill-api/src/runnables.rs index bd9c569d84..d11d794cc4 100644 --- a/backend/windmill-api/src/runnables.rs +++ b/backend/windmill-api/src/runnables.rs @@ -1130,11 +1130,14 @@ struct AttachedTrigger { path: String, /// `enabled` | `disabled` | `suspended` mode: String, - /// A schedule's cron expression and timezone; absent for every other kind. + /// A schedule's cron expression, timezone and cron version (`v1` numbers + /// weekdays from 1 = Sunday); absent for every other kind. #[serde(skip_serializing_if = "Option::is_none")] schedule: Option, #[serde(skip_serializing_if = "Option::is_none")] timezone: Option, + #[serde(skip_serializing_if = "Option::is_none")] + cron_version: Option, } #[derive(Serialize, Default)] @@ -1194,7 +1197,8 @@ async fn get_runnables_activity( ORDER BY j.created_at DESC" ); - const NO_CRON: &str = "NULL::text AS schedule, NULL::text AS timezone"; + const NO_CRON: &str = + "NULL::text AS schedule, NULL::text AS timezone, NULL::text AS cron_version"; let branch = |table: &str, kind: &str, mode: &str, cron: &str| { format!( "SELECT '{kind}' AS kind, path, script_path, is_flow, {mode} AS mode, {cron} FROM {table} \ @@ -1204,7 +1208,12 @@ async fn get_runnables_activity( let trigger_mode = "mode::text"; let bool_mode = "CASE WHEN enabled THEN 'enabled' ELSE 'disabled' END"; let branches = [ - branch("schedule", "schedule", bool_mode, "schedule, timezone"), + branch( + "schedule", + "schedule", + bool_mode, + "schedule, timezone, cron_version::text", + ), branch("http_trigger", "http", trigger_mode, NO_CRON), branch("websocket_trigger", "websocket", trigger_mode, NO_CRON), branch("kafka_trigger", "kafka", trigger_mode, NO_CRON), diff --git a/frontend/src/lib/components/home/ItemsList.svelte b/frontend/src/lib/components/home/ItemsList.svelte index 8ea43e2973..9e6d37a673 100644 --- a/frontend/src/lib/components/home/ItemsList.svelte +++ b/frontend/src/lib/components/home/ItemsList.svelte @@ -837,6 +837,8 @@ // was on screen so the selection can drop what this reload removes instead of // keeping a dead path. `tick` lets the reloaded rows re-register first. const renderedBefore = homeSelection.renderedKeys + // A row action can add, toggle or remove a trigger, or start a run. + homeActivity.reset() void ownerCountsRes.refetch() await reloadItems() await tick() diff --git a/frontend/src/lib/components/home/RunnableActivityCells.svelte b/frontend/src/lib/components/home/RunnableActivityCells.svelte index d273fdfaeb..58f038efc4 100644 --- a/frontend/src/lib/components/home/RunnableActivityCells.svelte +++ b/frontend/src/lib/components/home/RunnableActivityCells.svelte @@ -2,7 +2,7 @@ import { base } from '$lib/base' import { Tooltip } from '$lib/components/meltComponents' import { triggerDisplayNamesMap, triggerIconMapMono } from '$lib/components/triggers/utils' - import { displayDate } from '$lib/utils' + import { displayDate, formatCron } from '$lib/utils' import { describeSchedule } from '$lib/utils/describeCron' import { twMerge } from 'tailwind-merge' import { getHomeActivity, type ActivityKind } from './homeActivity.svelte' @@ -41,10 +41,26 @@ ) let loneScheduleText = $derived( loneSchedule?.schedule - ? (describeSchedule(loneSchedule.schedule, loneSchedule.timezone) ?? loneSchedule.schedule) + ? (describeLoneSchedule( + loneSchedule.schedule, + loneSchedule.timezone, + loneSchedule.cron_version + ) ?? loneSchedule.schedule) : undefined ) + // `describeCron` reads weekdays the v2 way (0 = Sunday); a v1 cron numbers them + // from 1 = Sunday, so one that names weekdays is shown as the raw expression. + function describeLoneSchedule( + cron: string, + timezone: string | undefined, + cronVersion: string | undefined + ): string | undefined { + const dow = formatCron(cron.trim()).split(/\s+/)[5] + if (cronVersion === 'v1' && dow !== undefined && dow !== '*' && dow !== '?') return undefined + return describeSchedule(cron, timezone) + } + type RunStatus = (typeof runs)[number]['status'] const statusClass: Record = { @@ -111,7 +127,9 @@ {/if} -