Skip to content

WIP: schedules updates#3405

Draft
tegan-temporal wants to merge 11 commits into
mainfrom
tegan/schedules-update
Draft

WIP: schedules updates#3405
tegan-temporal wants to merge 11 commits into
mainfrom
tegan/schedules-update

Conversation

@tegan-temporal
Copy link
Copy Markdown
Contributor

No description provided.

@tegan-temporal tegan-temporal self-assigned this May 18, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment May 18, 2026 10:39pm

Request Review

Alex-Tideman and others added 11 commits May 18, 2026 15:20
Eliminate 3-layer field destructuring by having store functions accept
ScheduleFormData directly. Move preset into the Zod schema so all form
state flows through SuperForms. Modernize form.svelte to Svelte 5
patterns and simplify page components to thin wrappers.
…olumn layout

Add support for multiple schedule specs (cron, week, month, interval)
with add/remove capability. Introduce new form sections: Schedule Details
(start/end dates, timezone, jitter), Schedule Policies (overlap, catchup,
pause on failure), and a live Schedule Summary sidebar. Replace single
tab-based spec selector with composable spec cards.
Use DatePicker for start/end dates, RadioGroup for end date type,
Combobox with search for timezone, DurationInput for jitter and catchup
window, Select for overlap policy. Add collapsible spec items that show
a compact summary row when collapsed. Fix overlap policy enum mapping
for edit mode and show validation errors above form buttons.
Migrate schedule-view.svelte to Svelte 5 runes ($state, $derived, $effect,
$app/state). Update schedule components to match new designs with
refactored advanced settings, search attributes, and workflow runs.
* refactor: replace PayloadDecoder and MetadataDecoder with unified Payload component

Consolidates two divergent payload display components into a single
`<Payload />` component at `src/lib/components/payload.svelte`.

Previously, `payload-decoder.svelte` (Svelte 5 runes, required a
`children` snippet, always decoded full attribute trees) and
`metadata-decoder.svelte` (Svelte 4 options API with slot syntax,
decoded single payloads to truncated summary strings) served different
display purposes but used inconsistent APIs and decoding paths across
65+ call sites.

The new component unifies both under a single `mode` prop:
- `code-block` (default): renders a CodeBlock with the decoded value,
  replacing all PayloadDecoder + CodeBlock snippet patterns
- `summary`: truncates to 120 chars and renders a Badge, replacing all
  MetadataDecoder usages
- `inline-truncated`: renders the compact .payload pre block used in
  event detail rows
- `children` snippet: escape hatch for callers that need custom
  rendering (schedule input, timeline SVG text elements)

Both old components used a single decoding path internally
(cloneAllPotentialPayloadsWithCodec -> decodePayloadAttributes ->
stringifyWithBigInt). MetadataDecoder previously used a separate
decodeSingleReadablePayloadWithCodec path; the new component uses the
same unified path for consistency.

The component is written in Svelte 5 runes throughout and imports from
$app/state instead of $app/stores, matching the newer direction of the
codebase.

Migrated files:
- src/lib/components/event/event-card.svelte
- src/lib/components/event/event-details-row.svelte (+ moved .payload CSS)
- src/lib/components/event/event-metadata-expanded.svelte
- src/lib/components/event/event-summary-row.svelte
- src/lib/components/lines-and-dots/svg/group-details-text.svelte
- src/lib/components/lines-and-dots/svg/timeline-graph-row.svelte
- src/lib/components/schedule/schedule-form/schedule-input-payload.svelte
- src/lib/components/standalone-activities/activity-input-and-outcome.svelte
- src/lib/components/workflow/client-actions/update-confirmation-modal.svelte
- src/lib/components/workflow/input-and-results-payload.svelte
- src/lib/components/workflow/metadata/metadata-events.svelte
- src/lib/components/workflow/pending-activity/pending-activity-card.svelte
- src/lib/components/workflow/workflow-json-navigator.svelte
- src/lib/pages/standalone-activity-details.svelte
- src/lib/pages/standalone-activity-search-attributes.svelte
- src/lib/pages/workflow-memo.svelte
- src/lib/pages/workflow-metadata.svelte
- src/lib/pages/workflow-search-attributes.svelte

All 1730 tests pass.

* remove unused component, fix css

* refactor: move Payload component into payload/ directory

Moves payload.svelte into src/lib/components/payload/ and adds a
USAGE.md report documenting all 31 call sites grouped by feature area.
Updates all 17 import paths accordingly.

* docs: add Payload component improvement suggestions

* docs: add decode-payload usage report and refactoring recommendations

* refactor(payload): split Payload component into focused mode-specific components

Replace the 14-prop multi-mode payload.svelte with four single-purpose
components: PayloadCodeBlock, PayloadSummary, PayloadDecoder, and
PayloadInline. Each component carries only the props relevant to its
render mode, eliminating dead props at call sites.

Also updates the decode paths to use the renamed decode-payload.ts API
(decodeEventAttributes, parsePayloadAttributes) following the #3302
cleanup.

* fix(payload-summary): use decodeUserMetadata and add onDecode prop

Replace decodeEventAttributes with decodeUserMetadata — the correct
decode path for a single raw Payload (Phase 2 codec only, no attribute
tree walking). Also add onDecode callback prop, called after a
successful decode, consistent with PayloadCodeBlock.

* refactor(payload): extract shared decode logic into decode-payload-value utility

Remove 3-way duplication of getInitialValue/onMount decode logic from
payload-code-block, payload-decoder, and payload-inline by extracting
getInitialPayloadValue and decodePayloadValue into
src/lib/utilities/decode-payload-value.ts.

* fix(payload): replace onMount with \$effect for reactive value updates

Components now re-decode when value or fieldName props change after
mount, fixing the reactivity gap that caused stale decoded content
when parent components updated their payload bindings.

* add workflow with user metadata

* remove unnecessary props from payload code block

* fix summary display

* add improvements

* fix heading levels

* add multi input workflow

* get rid of fieldName prop and fix most of the call sites

* fix remaining type errors

* fix tests

* rm inspect

* rm console.log

* WIP - download external payloads

* add support for downloading externally stored payloads

* add some error handling to downloads

* add support for filename

* fix CR feedback

* remove bad key

* fix export

* remove unused type

* cleanup unused stuff

* fix possibly duplicate key

* add language prop to PayloadCodeBlock

* add copyIconTitle and copySuccessIconTitle to codeblock instance

* refactor(payload): fix reactivity and race condition in payload-summary

Replace $effect+$state async pattern with $derived promise + $effect
cleanup to ensure all reactive deps (value, fallback, prefix,
maxSummaryLength) are tracked synchronously. Use $effect cleanup function
to cancel stale promise callbacks on re-run, preventing race conditions
when value changes rapidly. Remove unused onDecode prop.

* early return if no payloads in decode utils

* add type guards

* support inline external payloads

* fix download error and payload codeblock types

* fix schedule input

* rm console.log

* fix tests and strict mode

* fix spec

* fix typo

* add some optional chaining
spec?.jitter ?? translate('common.none'),
)}
{@render Info(
translate('schedules.overlap-policy'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Argument of type 'string | ScheduleOverlapPolicy' is not assignable to parameter of type 'string | ITimestamp'.

{@render Info(
translate('schedules.exclusion-calendar'),
spec?.excludeCalendar
? (getScheduleSpecLabel({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Type 'ICalendarSpec[]' is not assignable to type 'IStructuredCalendarSpec[]'.

structuredCalendar: spec.excludeCalendar,
}) ?? translate('common.none'))
: translate('common.none'),
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ 'state' is possibly 'null' or 'undefined'.

)}
{#if state.limitedActions}
{@render Info(
translate('schedules.remaining-actions'),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Argument of type 'string | Long' is not assignable to parameter of type 'string | ITimestamp'.


const timezoneComboboxOptions = $derived.by(() => {
const opts = [{ label: 'UTC', value: 'UTC' }];
for (const tz of TimezoneOptions) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Argument of type 'number | undefined' is not assignable to parameter of type 'number'.

<Loading />
{:then { schedule, searchAttributes }}
<ScheduleFormView onConfirm={handleEdit} {schedule} {searchAttributes} />
<ScheduleFormView
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Argument of type 'ISchedule | undefined' is not assignable to parameter of type 'ISchedule'.

<ScheduleFormView onConfirm={handleEdit} {schedule} {searchAttributes} />
<ScheduleFormView
onSubmit={handleEdit(schedule)}
{schedule}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Type 'ISearchAttributes | null | undefined' is not assignable to type 'ISearchAttributes | undefined'.

</h1>
<div class="flex flex-wrap items-center gap-2 text-lg">
<div class="mt-2 flex flex-wrap items-center gap-2">
<WorkflowStatus
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ 'schedule.schedule' is possibly 'undefined'.
  • ⚠️ 'schedule.schedule.state' is possibly 'null' or 'undefined'.

encoding: formData.encoding,
messageType: formData.messageType,
});
} catch (e) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Property 'message' does not exist on type '{}'.

encoding: formData.encoding,
messageType: formData.messageType,
});
} catch (e) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ⚠️ Property 'message' does not exist on type '{}'.

@temporal-cicd
Copy link
Copy Markdown
Contributor

temporal-cicd Bot commented May 18, 2026

Fails
🚫 Please add a meaningful description to the PR.
Warnings
⚠️

📊 Strict Mode: 50 errors in 11 files (5.7% of 881 total)

src/lib/stores/schedules.ts (3)
  • L160:65: Property 'message' does not exist on type '{}'.
  • L230:65: Property 'message' does not exist on type '{}'.
  • L277:65: Property 'message' does not exist on type '{}'.
src/lib/components/schedule/schedule-advanced-settings.svelte (4)
  • L50:8: Argument of type 'string | ScheduleOverlapPolicy' is not assignable to parameter of type 'string | ITimestamp'.
  • L73:14: Type 'ICalendarSpec[]' is not assignable to type 'IStructuredCalendarSpec[]'.
  • L77:11: 'state' is possibly 'null' or 'undefined'.
  • L80:10: Argument of type 'string | Long' is not assignable to parameter of type 'string | ITimestamp'.
src/lib/components/schedule/schedule-recent-runs.svelte (7)
  • L39:45: Argument of type 'IScheduleActionResult[] | null | undefined' is not assignable to parameter of type 'IScheduleActionResult[]'.
  • L49:43: Argument of type 'WorkflowExecutionStatus | null | undefined' is not assignable to parameter of type 'WorkflowStatus | WorkflowExecutionStatus'.
  • L55:12: Type 'string | null | undefined' is not assignable to type 'string'.
  • L55:22: 'run.startWorkflowResult' is possibly 'null' or 'undefined'.
  • L56:12: Type 'string | null | undefined' is not assignable to type 'string'.
  • L56:17: 'run.startWorkflowResult' is possibly 'null' or 'undefined'.
  • L60:11: 'run.startWorkflowResult' is possibly 'null' or 'undefined'.
src/lib/holocene/pill-container/pill-container.svelte (2)
  • L26:38: Argument of type 'null' is not assignable to parameter of type 'string | undefined'.
  • L41:10: Type 'string | null' is not assignable to type 'string'.
src/lib/holocene/pill-container/pill.svelte (3)
  • L30:4: Type 'null' is not assignable to type 'boolean'.
  • L31:4: Type 'null' is not assignable to type '"search" | "link" | "success" | "error" | "action" | "activity" | "add-square" | "add" | "apple" | "archives" | "arrow-down" | "arrow-left" | "arrow-up" | "arrow-right" | "ascending" | ... 140 more ... | "xmark-square"'.
  • L32:4: Type 'null' is not assignable to type 'number'.
src/lib/components/schedule/schedule-workflow-runs.svelte (1)
  • L50:11: Type 'string | undefined' is not assignable to type 'string'.
src/lib/components/schedule/schedule-form/schedule-input-payload.svelte (1)
  • L95:18: Type 'IPayloads | undefined' is not assignable to type 'object | IPayloads | IPayload'.
src/lib/components/schedule/schedule-form/schedule-details-card.svelte (13)
  • L33:37: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
  • L76:15: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L77:16: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L87:15: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L88:16: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L96:16: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L98:15: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L105:15: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L106:16: Element implicitly has an 'any' type because expression of type '0' can't be used to index type '{}'.
  • L146:17: Type 'number | undefined' is not assignable to type 'number'.
  • L172:11: Type 'string | undefined' is not assignable to type 'string'.
  • L175:11: Type 'string | undefined' is not assignable to type 'string'.
  • L176:6: Type 'IPayloads | null | undefined' is not assignable to type 'IPayloads | undefined'.
src/lib/components/schedule/schedule-form/schedule-spec-card.svelte (1)
  • L59:31: Type 'Writable<{ encoding: "json/plain" | "json/protobuf"; name: string; jitter: string; workflowId: string; workflowType: string; taskQueue: string; searchAttributes: { type: "Unspecified" | "Keyword" | ... 5 more ... | "Datetime"; label: string; value?: any; }[]; ... 13 more ...; endAfterOccurrences?: number | undefined...' has no properties in common with type '{ structuredCalendar?: IStructuredCalendarSpec[] | undefined; interval?: IIntervalSpec[] | undefined; }'.
src/lib/pages/schedule-edit.svelte (2)
  • L37:25: Argument of type 'ISchedule | undefined' is not assignable to parameter of type 'ISchedule'.
  • L39:5: Type 'ISearchAttributes | null | undefined' is not assignable to type 'ISearchAttributes | undefined'.
src/lib/pages/schedule-view.svelte (13)
  • L144:18: Property 'message' does not exist on type '{}'.
  • L307:20: 'schedule.schedule' is possibly 'undefined'.
  • L307:20: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L428:12: Type 'IPayloads | null | undefined' is not assignable to type 'IPayloads'.
  • L430:34: Type 'IScheduleSpec | null | undefined' is not assignable to type 'IScheduleSpec'.
  • L438:19: 'schedule.schedule' is possibly 'undefined'.
  • L438:19: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L447:9: 'schedule.schedule' is possibly 'undefined'.
  • L447:9: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L453:11: 'schedule.schedule' is possibly 'undefined'.
  • L453:11: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L462:11: 'schedule.schedule' is possibly 'undefined'.
  • L462:11: 'schedule.schedule.state' is possibly 'null' or 'undefined'.

Generated by 🚫 dangerJS against f6459bf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants