Documentation
¶
Overview ¶
Package timeline builds the unified task-detail timeline consumed by both the TUI and the Web UI. It imports orchestrator only — no api dependency — so web/templates can import it without creating an import cycle with internal/api (which pulls in web/templates for rendering).
The builder takes fully-resolved inputs: the task, its actions, and a list of JobInfo records. Each caller adapts from its own Job shape (api.Job / dispatcher job model) via ConvertAPIJob-style helpers.
Index ¶
- Constants
- func BuildActionLabel(a *orchestrator.Action) string
- func BuildJobLabel(j *JobInfo) string
- func FormatElapsed(t time.Time) string
- func IsProgressAction(a *orchestrator.Action) bool
- func IsStateTransition(a *orchestrator.Action) bool
- func JobDuration(j *JobInfo) string
- type Event
- type EventKind
- type JobInfo
- type StatusGroup
Constants ¶
const ( JobStatusRunning = "running" JobStatusCompleted = "completed" JobStatusFailed = "failed" )
JobStatus mirrors the string values used by api.JobStatus so timeline renderers don't need to import api to discriminate running / completed / failed states. Callers pass these strings through.
Variables ¶
This section is empty.
Functions ¶
func BuildActionLabel ¶
func BuildActionLabel(a *orchestrator.Action) string
BuildActionLabel returns the display label for a timeline action. State transitions: "<type> → <to_status>". Progress actions: "進捗: <message>" (extracted from JSON payload).
func BuildJobLabel ¶
BuildJobLabel returns the display label for a job.
- completed: "[role] <name> ✓ <duration>" (name omitted when empty)
- failed: "[role] <name> ✗ <duration>"
- running: "[role] <elapsed> ago"
- other: "[role] <name><status>"
DisplayName is used when set; otherwise HandlerID is used as fallback. When role is "hook", the "[hook]" prefix is omitted — the handler name alone identifies the hook sufficiently.
func FormatElapsed ¶
FormatElapsed returns a short MM:SS (or HH:MM:SS) elapsed string since t. Matches the TUI helper so that TUI display is unchanged after shared-timeline migration. Exported so the Web UI can compute the initial server-side value for a running job's live-ticking elapsed counter.
func IsProgressAction ¶
func IsProgressAction(a *orchestrator.Action) bool
IsProgressAction reports whether an action is a non-transitioning progress note.
func IsStateTransition ¶
func IsStateTransition(a *orchestrator.Action) bool
IsStateTransition reports whether an action moves the task to a different status.
func JobDuration ¶
JobDuration returns a human-readable duration for a completed/failed job. Returns "?" when the job has no UpdatedAt or UpdatedAt is not after CreatedAt.
Types ¶
type Event ¶
type Event struct {
Time time.Time
HasTime bool
Kind EventKind
Label string
Action *orchestrator.Action
Job *JobInfo
}
Event is a single row in the unified timeline. Exactly one of Action / Job is populated, matching Kind.
func SelectableEvents ¶
func SelectableEvents(groups []StatusGroup) []Event
SelectableEvents returns the flat event list from all groups in order. Used by TUI for cursor clamping and enter-key drilldown.
type JobInfo ¶
type JobInfo struct {
ID string
Role string
HandlerID string
DisplayName string // optional; shown instead of HandlerID when non-empty
Status string // one of JobStatusRunning / Completed / Failed (or other)
ExitCode int
CreatedAt time.Time
UpdatedAt time.Time
}
JobInfo is the minimum job data needed to place a job on the timeline and render its label / status icon / link target. Callers convert from their native job type (api.Job for TUI / Web).
type StatusGroup ¶
StatusGroup groups events under a single task-status visit. Repeated visits to the same status produce distinct groups in order.
func Build ¶
func Build(task *orchestrator.Task, actions []*orchestrator.Action, jobs []*JobInfo) []StatusGroup
Build groups filtered events by the task-status visit in which they occurred. Only state-transition actions and jobs are included. hook_fired actions are intentionally dropped because the associated job carries the same information (success, handler id, duration) plus output.
Each visit to a status creates a new group so repeated visits (e.g. executing → aborted → pending → executing) produce distinct groups in chronological order instead of collapsing same-status events into one.
Each group's EnteredAt records when the task entered that visit:
- initial group: task.CreatedAt
- subsequent groups: the CreatedAt of the transition action that moved into it