Files
ontime/packages/utils/index.ts
T
Claude 3c2875a956 feat(report): persistent show run history
Turns the reporter from a live-only, single-run curiosity into a
persistent, per-project, per-rundown history of runs.

- Extend OntimeEventReport with a schedule snapshot (scheduledStart,
  scheduledDuration) taken when an event starts, plus playCount. Reports
  are now a record that survives later rundown edits, rather than a live
  join against the current rundown.
- Add a run lifecycle: a run opens on the first event start and closes on
  a full stop, archiving the previous run to history so the next start
  begins fresh.
- Persist runs to a per-project sidecar file (services/report-service),
  patterned on the existing restore-service, so a crash or restart no
  longer loses the whole show's record. Runs are scoped by rundownId for
  multi-rundown projects, cascade-deleted with their rundown or project,
  renamed alongside a project rename, and deliberately not copied when a
  project is duplicated.
- Extract the over/under/on-time variance and run summary maths shared by
  the rundown chip, the report settings panel, and the server into
  ontime-utils (getEventVariance, getRunSummary, countPlannedEvents).
- Extend the report API with run history endpoints (list, get, latest,
  rename, delete) while keeping GET /report's existing shape so Companion
  and HTTP automations are unaffected.
- Replace the settings report table with a run browser: a list of runs
  with a rundown filter, inline rename, delete, and a detail view with
  per-run summary stats and CSV export.
- Add a third, muted state to the rundown event chip: an event with
  nothing in the current run yet previews how it went last time.

Fixes a real bug found while testing the new store: emptyStore() was a
shared object, so its runs array leaked mutations across project loads.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nr3FbLbM8gB8Jm771YgTV
2026-08-08 11:08:28 +00:00

120 lines
3.6 KiB
TypeScript

// runtime utils
export { validatePlayback } from './src/validate-action/validatePlayback.js';
export { isKnownTimerType, validateTimeStrategy } from './src/validate-events/validateEvent.js';
export { calculateDuration, getLinkedTimes, validateTimes } from './src/validate-times/validateTimes.js';
// rundown utils
export { getCueCandidate } from './src/cue-utils/cueUtils.js';
export { generateId } from './src/generate-id/generateId.js';
export {
addToRundown,
getEventWithId,
getFirstEvent,
getFirstEventNormal,
getFirstNormal,
getFirstGroupNormal,
getInsertAfterId,
getLastEvent,
getLastEventNormal,
getLastNormal,
getLastGroupNormal,
getNextGroupNormal,
getNextEvent,
getNextEventNormal,
getNextNormal,
getPreviousEventNormal,
getPreviousNormal,
getPreviousGroupNormal,
resolveInsertParent,
swapEventData,
} from './src/rundown-utils/rundownUtils.js';
export { getFirstRundown } from './src/rundown/rundown.utils.js';
export {
event as eventDef,
group as groupDef,
milestone as milestoneDef,
} from './src/rundown-utils/entryDefinitions.js';
export { createDelay, createEvent, createGroup, createMilestone, makeString } from './src/rundown-utils/entryUtils.js';
// time format utils
export {
dayInMs,
maxDuration,
MILLIS_PER_HOUR,
MILLIS_PER_MINUTE,
MILLIS_PER_SECOND,
millisToSeconds,
secondsInMillis,
} from './src/date-utils/conversionUtils.js';
export { isISO8601, isTimeString } from './src/date-utils/isTimeString.js';
export {
formatFromMillis,
millisToString,
pad,
removeLeadingZero,
removeSeconds,
removeTrailingZero,
} from './src/date-utils/timeFormatting.js';
export { parseUserTime } from './src/date-utils/parseUserTime.js';
export { checkRegex, regex } from './src/regex-utils/checkRegex.js';
export { isColourHex } from './src/regex-utils/isColourHex.js';
export { splitWhitespace } from './src/regex-utils/splitWhitespace.js';
export { customFieldLabelToKey, customKeyFromLabel } from './src/customField-utils/customFieldUtils.js';
// helpers from externals
export { deepmerge } from './src/externals/deepmerge.js';
// array utils
export { deleteAtIndex, insertAtIndex, mergeAtIndex, reorderArray } from './src/common/arrayUtils.js';
// object utils
export { getPropertyFromPath, isObjectEmpty, withoutUndefinedValues, isValueOfEnum } from './src/common/objectUtils.js';
// generic utilities
export { getErrorMessage } from './src/generic/generic.js';
export { obfuscate, unobfuscate } from './src/generic/generic.js';
export { isNumeric } from './src/types/types.js';
// model validation
export { validateEndAction, validateTimerType } from './src/validate-events/validateEvent.js';
// feature business logic
export { getExpectedStart, getExpectedEnd } from './src/date-utils/getExpected.js';
// feature business logic - rundown
export { checkIsNow } from './src/date-utils/checkIsNow.js';
export { checkIsNextDay } from './src/date-utils/checkIsNextDay.js';
export { getTimeFrom } from './src/date-utils/getTimeFrom.js';
export { isNewLatest } from './src/date-utils/isNewLatest.js';
// feature business logic - spreadsheet import
export {
type ImportCustom,
type ImportMap,
type ImportOptions,
defaultImportMap,
isImportMap,
} from './src/feature/spreadsheet-import/spreadsheetImport.js';
export { isPlaybackActive } from './src/playback-utils/playbackstate.js';
// feature business logic - reports
export {
countPlannedEvents,
getEventVariance,
getRunSummary,
type EventVariance,
type VarianceStatus,
} from './src/report-utils/reportUtils.js';
//Colour
export {
colourToHex,
cssOrHexToColour,
hexToColour,
isLightColour,
mixColours,
CssColours,
} from './src/colour/colour.utils.js';