The settings UI had accumulated three inconsistencies. This addresses all
three without renaming any group or breaking `?settings=` deep links.
Empty states
- Add `Panel.EmptyState` / `Panel.TableEmpty` (title + description + action),
promoting the treatment previously local to the spreadsheet PreviewTable.
- Add missing empty states to Custom fields, Projects, Rundowns and both
Client tables, which previously rendered bare column headers.
- Convert the remaining `TableEmpty` call sites off the generic "No data yet".
- Rename `.empty` to `.loaderBox` in ProjectPanel, where it meant a loader box
rather than an empty state.
Entity forms in modals
- Add `useEntityModal`, replacing six different open/close mechanisms.
- Move the multi-field create/edit forms into `Modal`: automations (wide),
triggers, URL presets, custom fields, custom views, new rundown and project
merge. Single-field row renames stay inline.
- Create and edit now share one surface instead of rendering above the table
and in-place respectively, and the list is no longer interactive underneath.
- Remove the duplicate project create form; the "New" button now routes to the
existing QuickStart modal.
Sidebar
- Add a search box with per-section keywords, so sections are reachable by the
term users have in mind (osc, alias, google sheet, pin...).
- Fix duplicated `manage__sheets` id, which highlighted two entries at once.
Also
- Close button no longer floats over content; drop the 300px padding hack.
- Tables scroll with the panel instead of owning a nested scroll area.
- Derive divider/table/list padding from a card padding custom property.
- Fix an unreachable branch that stopped duplicate custom field labels from
being rejected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UP4knuna8kLe79NAuNDhUJ
* fix: issue where a count-to-end would lead to incorrect expected times
* fix: include add time in overtime when countToEnd
* fix: ui and server use same calculation for expected end
The server serves html/timer-legacy.html and html/login.html from disk
at runtime, relative to the bundled server. The Docker image copies
these files but the electron packaging did not, so the view 404ed in
all desktop distributions.
Additionally, AppImages mount at /tmp/.mount_*, a hidden directory.
Express sendFile refuses paths containing dot-segments by default
(returns 404 without touching disk), so the view failed on Linux even
with the file packaged. Allow dotfiles for this route; the request
path is fixed so no user input is affected.
The Stage Timer and PiP Timer views relied on `align-content: center` to
vertically center the timer digits inside `.timer-container`, which is a
plain block element. Aligning children of a block container via
`align-content` only works in Chromium 123+ (Firefox 125+, Safari 17.4+).
Embedded browsers such as vMix Browser Input (CEF V115) and other older
CEF/Chromium-based production tools ignore the property, so the digits
fall back to the top of the container while every other element renders
correctly.
Make `.timer-container` a real flex column and center with
`justify-content: center`, which is universally supported and matches the
centering approach used elsewhere in the codebase. The removed
`justify-self`/`align-self` were no-ops on a full-width flex item.
Fixes#2126
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014T6ENZ3r6JXZb1fpYw2oNY
Surface {{groupNow.*}} template variables (title, note, colour, times,
custom fields) in the automation template autocomplete so events inside a
group can reference their group. The runtime store already carries
groupNow, so substitution and filters worked already; this makes it
discoverable.
Extend the message-secondary action with an optional text field so an
automation can set the secondary message content, not just its source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZYPZVdZLWowU7DyzGkWyy
Confirmed empirically that it now suppresses nothing under TS 7.0.2:
compiling tsconfig.dts.json directly with this flag set to "6.0",
"7.0", or removed entirely all produce identical (clean) output. It
was a leftover suppression the previous tsdown mode never actually
needed once nothing in the config triggers a deprecation warning.
TypeScript 7 ships as a native Go binary and drastically trims the
package's public JS API surface (no more `main`, and `exports['.']`
now only resolves to lib/version.cjs) since the programmatic compiler
API isn't stable again until 7.1. This broke apps/resolver's tsdown
build, which used rolldown-plugin-dts' tsc-program mode (import ts
from 'typescript'; ts.createProgram(...)) for declaration generation.
Fix by switching that build to isolatedDeclarations, which lets
rolldown-plugin-dts generate .d.ts via its oxc-based path instead of
the TS compiler API entirely. That surfaced two isolatedDeclarations
violations in ontime-types (array/Object.keys initializers lacking
explicit annotations), fixed with explicit `string[]` types matching
their existing inferred type. Also bumped tsdown to pick up its latest
rolldown-plugin-dts, and disabled allowJs in tsconfig.dts.json since
it's incompatible with isolatedDeclarations.
Full workspace typecheck, lint, build, and test suite (1186 tests)
pass under TypeScript 7.0.2.
* feat: create the first event from the cuesheet
* chore: cleanup css
* test: cuesheet beckground edit from empty state
* feat: only show +event button when user is in edit mode and have full write perms
* refactor: allow secondary rundowns
* ui: move dropdown
* feat: follow loaded
* ui: background edit warning
ui: fix disable radio button
* feat(ui): add loaded sufix in the rundown list
* feat(ui): add direct link to background edit from rundown manager
* fix: better fallback
* fix: default to is isCurrentRundown for nav bar colour
* chore: rename navigate to cuesheet
---------
Co-authored-by: alex-arc <ac@omnivox.dk>
Adds timer-legacy.html — a zero-dependency static page that connects
to the Ontime WebSocket and displays the live countdown for browsers
that cannot parse the Vite-built React bundle (Safari < 14, Chrome < 85).
Also adds a synchronous pre-React guard in index.html that redirects
/timer visitors to the legacy page when Promise.any is unavailable,
matching the Vite build target floor of Safari 14 / Chrome 85.
https://claude.ai/code/session_013MfdwdjdDUnr3akpGSGXa4
* feat: update auto cue numbering
* feat: renumber from ui
* refactor: patchEntries is not used
* chore: format
* fix: correct cue at top of group
* fix: handle precision
* refactor dialog
* bump limit for performance time test
* extract type
* add class name to lable
* fix rebase
* refator: extract renumering logic
* chore: comments for getIntegerAndFraction function
* chore: add the for renumber mutation
* fix: fraction match precision
* refactor: small cleanup
* refactor: use more narrow validator
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* refactor: remove unneeded async
* chore: add express Router type to all routes
* refactor: don't use index in react key
* refactor: correctly get error message in excel route
* refactor: avoid exporting muteable values
* refactor: replace traslation hook refetch time with stale time
* refactor: make it the service responsebillety to send refetch keys for asset changes
* chore: only run release action if we have a tag
* chore: typescript 6 is out of beta
* chore: update flaky test
* chore: update pnpm
* chore: update playwright and node types
* chore: migrate tsup to tsdown
* chore: update node to node 22.22.2(LTS)
* chore: fix lockfile
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* fix: prevent add filter from submitting form
* refactor: event clarifies whether automations exist but are disabled
* refactor: improve readability of automation form
* refactor: add affordance for field warnings
* refactor: improve visibility of automation off state
* refactor: apply warning styles to other feature toggles
* Adding playback actions to automations (#2024)
* adding intial automation actions
* cleaning up
* fixing formatting
* ran oxfmt
* switching action names to playback- to match the dropdown strings
* fixing flicker that was caused by scroll arrows gettting unmounted
---------
Co-authored-by: Cameron Slipp <cdslipp@gmail.com>
* chore: upgrade vite
* fix: inconsistentCjsInterop for ReactQR
* chore: e2e tests should use relativve path and get host from playwright config
* refactor: drop qr code dependency
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* chore: migrate eslint to oxlint
* chore: migrate prettier to oxfmt
* chore: migrate typescript
* chore: toThrow should have a expected value
* chore: cast test value as Day
* chore: small title fix
* chore: mocks should be hoisted
* chore: incorrect async useage
* chore: test should be inside description
* chore: test sohuld include an expeced
* chore: oxfmt
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* feat: get server port from app satate or env
optional startup port from env will always override
function for parsing port from env
populate default port in app state
add test for migration
* bump version
* feat: main src in backstage view
* feat: main src in timeline view
* feat: main src in countdown view
* feat: main src in studio view
* feat: hide past events in countdown view
* notes can not be set as main src
* feat: show group title as secondary src
* chore: spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
The logic for deciding whether to show the welcome modal has been moved from `app.ts` to `AppStateService.ts`. The `getShowWelcomeDialog` function now accepts a boolean indicating whether a restore point exists and returns `false` if it does. This keeps the business logic out of the main application file and in the relevant service.
* Fix(automation): Handles undefined values in conditions (#1933)
* Fix(automation): Handles undefined values in conditions
Addresses an issue where conditions with the 'not_equals' operator incorrectly evaluated undefined values. This change ensures that empty string comparisons correctly identify missing values in automation rules.
* Fixes automation "not equals" logic
Simplifies the 'not_equals' condition evaluation in automations by reusing the 'equals' condition, improving code readability and consistency.
Fixes#1932
* Test(automation): Expanding filter condition testing
Expanding test cases to cover various data types and edge case for each operators.
Unexpected behavior have been mark with a TO_DO.
* Fix(automation): Handles default filter case
- Ensures that their is a default scenario.
- Fixing Deepsource issue "No default cases in switch statements JS-0047"
* Test(automation): Remove abstraction in test
* move to test.each
* extract a isEquivalent function
* lowercase contains test
---------
Co-authored-by: Philippe Allard-Rousse <philrousse@gmail.com>
* chore: remove old comment
* chore: smal lclean up of a e2e test
* chore: bump to beta.6
* chore: cleanup imports
* fix integration values com in ms
* allow linkStart and timeStrategy from API
* remove local mac dist
* fix resolver build
* fix docker build
* node version in docker via arg
* add step to setup auth for pnpm
* lint
---------
Co-authored-by: Joel Wetzell <jwetzell@yahoo.com>
* refactor: use correct metadata in op view
* refactor: use correct metadata in backstage view
* remove uneeded test
* fix: correct offset colour
* refactor: use correct metadata in timline view
* refactor: schedule item dont pass the whole event
* chore: lint
* fix: patch in the active rundown id and title
* fix: send a ALL refetch on project patch
* fix: load the last used rundown on project patch and not just the first one
* chore: lint
* chore: clean up and let rundown service send the refetch request
* chore: dont destructure rundown
* feat: add group start time to state
* refactor: calculate expected times when offset mode changes
* feat: show relative data in ui
* fixup! feat: add group start time to state
* fixup! refactor: calculate expected times when offset mode changes
* fixup! feat: show relative data in ui
* try to handle multiday
* show planed/expected rundown end day offset values
* refactor: style tweaks to timers
* refactor: cleanup data use
* day offset
* update tests
* test getExpectedStart multiday
* write start epoch to restore file
* current day in relative mode
* remove todo
* move find day offset to utils
---------
Co-authored-by: arc-alex <ac@omnivox.dk>
* fix error with is linked to loaded metadata
* pass down metadata
* create expected schedule
* expected start in sub info
* for singel subscribtions
* refactor
* add color to single events
* refactor: clean up subscribtion data
* show schedule and secondray data for single events
* improve subscribtion data display
with this changes we allow the client and server to share the same data
shape. even if some of it is useless.
we also get an extra version property in the payload, if we want to save
the transfer cost, we would rather remove it from the sent payload
* refactor: align header columns
* refactor: improve scrollbar visibility
* refactor: center align table elements
* refactor: make param elements stateful
* fix: issue with collapsed elements not loosing value
* fix: prevent search params containing multiple alias references
* fix: the issue where a file disappears if it is both migrated and recovered in the same load operation (#1744)
* refactor: disable group action for elements in groups
* refactor: move context menu items into the event element (#1747)
* feat: sheet import new features for v4 (#1730)
* import milestone
* fixup! import milestone
* test: milestone import
* add entries to group
stop on new group or on group-end type
* fixup! add entries to group
* cleanup
* add event target duration
* link start if undefined
* add skip import type
* extract some to the excel paresing functions
* tweaks to presentation
* move file
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* fix: notify runtimeStore of events bieng groupd
* fix: improve authentication and stage detection in demo
* chore: ship logo with project
* fix: client is referenced by name
* fix: prevent reflow in event editor
* fix: stale render on selected event due to ref mismatch
* Create/Load/Delete multiple rundowns (#1696)
* refactor: restore last loaded rundown
* refactor: initialise rundown in ProjectService
* feat: allow switching rundowns
ensure on coordination between the db object and the working object
server provide list of rundowns
implement switch in the UI
implement delete
implement new rundown button
* fix: render order for floating button
* refactor: appropriate names to service
* refactor: rundown endpoints
* refactor: save last loaded rundown ID
* refactor: rundown management UI
* refactor: emit refetch all on project load
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* feat: recover single event subscription
* fixup! feat: sheet import new features for v4 (#1730)
* fix: prevent dropping a group inside another
* fixup! refactor: move context menu items into the event element (#1747)
* fix: prevent stale references to custom fields
* fix: propagate updates to all rundowns
* refactor: client rundown metadata (#1728)
* generate metadata in the hook
* move test
* ensure there is always a last element
* use for-loop
* update metadata in useEfect
* fully extract metadata generation
* use direct assignment
* cleanup
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* refactor: small imporvement and tests for coerce functions (#1752)
* refactor: small imporvement and tests for coerce functions
add test `coerceString`
add test `coerceBoolean`
add test `coerceColour`
* remove old todo
* fix: consistent quick add behaviour
* refactor: create flat rundown with metadata
* fix: show add buttons on top
* feat: allow editing milestones
* refactor: style tweaks to rundown elements
refactor: milestones are full width
refactor: cuesheet header alignment
fix: editor styling in cuesheet
* refactor: virtualise table
* refactor: improve overscan (#1758)
* bump version to 4.0.0-alpha.5
---------
Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk>
The IntersectionObserver callback in rowObserver.ts was capturing the `addVisibleRow` and `removeVisibleRow` actions from the Zustand store only once, at the time of the observer's creation.
This created a potential for a stale closure bug, where the observer would call outdated action functions if the store's state or actions were ever re-initialized. This would lead to the application's state not being updated correctly, causing the bug where visible rows would not render their content.
This commit fixes the issue by calling `useVisibleRowsStore.getState()` inside the observer callback. This ensures that the latest, freshest versions of the action functions are always used, preventing the stale state bug.
* refactor: runtime types
* refactor: runtimeState functions to use the split type
* refactor: RuntimeService to use the new split data
* refactor: use the split data in the UI
* update comments
* refactor: rename runtime to offset
* fix utils test
* migrate settings
* migrate viewsettings
* migrate url preset
* migrate project data
* migrate custom fields
* migrate automations
* migrate rundown
* lint
* return custom field translation table
* check regex
* new url type
* refactor
* migrate old OSC subscriptions
* migrate old http subscriptions
* update comments
* migrate the whole db
* remove automation logging unlis there is an error
* return a new object
* refactor: copy currup is only used in one place
* make a copy of original migrated file
* refactor: ensure image flder is part of project service init
* add entrys to groups
* small cleanup
* just drop incorrect custom fields in the default data parser
* refactor: split event data and state data
* refactor: calculate the start time insted of until
* cleanup
* send next flag expected start from server
* refactor: render
* fix test
* use same icon
* refactor: group duration
* Optimize (#1711)
* refactor: consolidate block, flag and end loading and expected times
* work on test
* cal end value
* lint
* fix test
* remove todo
Updated DEVELOPMENT.MD to use `turbo run <task>` instead of `turbo <task>` for clarity and consistency when referring to Turborepo tasks that don't have a direct pnpm script alias.
Also, added `dependsOn: ["build"]` to `dist-*` tasks in `turbo.json` to ensure correct build order before packaging.
- italic and bold for rundown metadata entries
- allow deleting groups
- make groups in order
- correct style for milestones
- open playing groups
- style tweaks
* switch to base ui
* ensure all action types is part of the valitation
* update test
* atempt to do it in the base-ui way
* fix fixing
* allow undefide visible on set timer message
* fix set time not showing
* correct time data for aux set automation
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
fix: close modal with button
refactor: small type improvements
refactor: migrate time inputs
refactor: migrate tooltips
refactor: prevent component resizing
* Refactor: Remove GOT dependency, use simplified fetch wrapper
Replaced GOT with a lightweight, functional, fetch-based utility (`appClient.ts`) for handling JSON POST requests in `SheetService.ts`.
- Created `appClient.ts` to encapsulate fetch logic. It mimics GOT's behavior for sending JSON payloads and parsing JSON responses.
- Error handling in `appClient.ts` uses standard `Error` objects with descriptive messages, including status and error body details, instead of custom error types.
- Updated `SheetService.ts` to use the new `appClient.ts`.
- Removed `got` from server dependencies.
* cleanup
* dont throw when we know the error
* rearange logging
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: arc-alex <ac@omnivox.dk>
Decouples the IntersectionObserver from the React component tree to
prevent
unnecessary re-renders of the entire Cuesheet table when row visibility
changes. Restores rootMargin for better UX and memoizes EventRow.
- Introduced `rowObserver.ts` to manage a global IntersectionObserver.
- Observer callback directly updates `useVisibleRowsStore`.
- Configured with `rootMargin: '400px 0px'` and `threshold: 0.01`
to pre-load and retain rows near the viewport, improving UX.
- `EventRow` components use `observeRow`/`unobserveRow` from
`rowObserver.ts`.
- `EventRow` is now wrapped in `React.memo` to prevent re-renders if
props
haven't changed when its parent re-renders.
- Removed observer creation and prop-drilling from `CuesheetBody.tsx`.
This ensures only individual rows re-render content based on visibility
and optimizes row component rendering, improving performance and UX.
* adding block now/next data
* add to ui
* add blockNext
* indicate in UI
* fix test
* restore block start at value
* one loop
* stricter null comparison
* test fails
* dev throw if id cant be found
* fix spelling
* revert client stuff
* rename
* add comment
* change load to use metadata
* update roll to use metadata
* remove filterTimedEvents
* add comment
* atempth to refactor rollUtils
* refactor util functions
* refactor: WS
* refactor refetch
extract refetch keys to package/types
auto invalidata all keys
use refetch keys for project data
no need for constant update of info, just fetch when looking at it
split refetch and query keys
rename types
* refactor viewSettings
* fixup! refactor: WS
* rearange files and make types for api calls
* cleanup viewsettings
* switch exhaustiveCheck
* combine send socket function
* exhaustive check
* rename type to tag
* fixup! fixup! refactor: WS
* remove custom etag solution
* get errors from socket
* lint
* small change
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* Revert "refactor: add version to session endpoint"
This reverts commit cd40a6e55e.
* Revert "Remove public event feature (#1645)"
This reverts commit 08d9e24871.
* Revert "Fix: rearrange playing event (#1640)"
This reverts commit 0649678dca.
* Revert "refactor: style tweaks to edit css modal"
This reverts commit a00ec2d02a.
* Revert "refactor: remove usages of framer-motion"
This reverts commit 54a74ccc2a.
* Revert "Upgrade expressjs (#1633)"
This reverts commit 6f3ab274bd.
* Revert "Refactor: require trigger in all events objects (#1636)"
This reverts commit 90870ecfb6.
* Revert "Fix: Correct boundary condition in applyDelay"
This reverts commit b640e0e181.
* Revert "let vite be the proxy to the dev server (#1630)"
This reverts commit c41fe824cf.
* Revert "refactor: migrate custom fields to transactions"
This reverts commit 62c8319d70.
* Revert "refactor: simplify validations"
This reverts commit b1d23467a2.
* Revert "refactor: create transaction system and apply to adding entry (#1620)"
This reverts commit 9a62daf047.
* Revert "Refactor: better rounding (#1594)"
This reverts commit b9ab1c6fd7.
* Revert "refactor: improve reorder logic"
This reverts commit c1054711b0.
* Revert "chore: simplify URLs"
This reverts commit a4d4f29a37.
* Revert "refactor: order is single source of truth"
This reverts commit 2793aadea0.
* Revert "refactor: refetch targets is enum"
This reverts commit e7cfb7d9d9.
* Revert "refactor: small ux improvements"
This reverts commit 256a851c9b.
* Revert "refactor: remove trivially inferred numEvents"
This reverts commit 4ab9c81cb8.
* Revert "feat: duplicate groups"
This reverts commit 2f13d6c89e.
* Revert "feat: create group from entry selection"
This reverts commit f1f7bad25e.
* Revert "feat: create block from rundown empty"
This reverts commit a8b52a48f7.
* Revert "fix: collapsed blocks dont render children"
This reverts commit cd0999b2ab.
* Revert "refactor: type cleanup and test improvements"
This reverts commit b4c60f3f04.
* Revert "feat: allow dissolving a block"
This reverts commit 5cefad3666.
* Revert "fix: uncontrolled prop on controlled component"
This reverts commit 7a6ecd8c34.
* Revert "refactor: improve return of reorder"
This reverts commit ba96ecfd91.
* Revert "refactor: mutations on batch elements must have IDs"
This reverts commit 7bed3757f2.
* Revert "chore: upgrade dependencies"
This reverts commit e2e755b1d2.
* Revert "refactor: extract utility to merge two arrays"
This reverts commit a77d23109d.
* Revert "refactor: change network mode defaults"
This reverts commit 0eb3b8d382.
* Revert "fix: delete nested events"
This reverts commit 0021185288.
* Revert "fix: add event at end of block"
This reverts commit 94c72ff4f6.
* Revert "refactor: make finder available in exported rundown"
This reverts commit e4c08dc9b2.
* Revert "assert non null and update test (#1604)"
This reverts commit ec74af0d62.
* Revert "Fix project renumber (#1597)"
This reverts commit b6d72dd082.
* Revert "Refactor: WebSocket from flush queue to one patch (#1595)"
This reverts commit 31c311daf0.
* Revert "Refactor: ms for api calls (#1593)"
This reverts commit e9b3cc6090.
* Revert "fix test (#1601)"
This reverts commit 543b04a097.
* Revert "fix: rebase master"
This reverts commit d39b85b6e6.
* Revert "chore: correct test path"
This reverts commit bbe107bb2b.
* Revert "refactor: extract rundown parsing"
This reverts commit c616240db1.
* Revert "chore: improve convention entry <> event"
This reverts commit 166be66ce3.
* Revert "refactor: maintain flat orders"
This reverts commit 4180d0a337.
* Revert "refactor: implement operations on nested events"
This reverts commit 78108e316c.
* Revert "refactor: process events in rundown"
This reverts commit 3bb8b70915.
* Revert "chore: improve convention entry <> event"
This reverts commit 1c4f13a0ed.
* Revert "chore: rename currentBlock > parent"
This reverts commit 3ca0abad53.
* Revert "refactor: fix delay positioning in gaps"
This reverts commit 030c8f897f.
* Revert "refactor(e2e): skip flaky test"
This reverts commit 68175cfa3b.
* Revert "refactor: improve project loading"
This reverts commit fd8f757851.
* Revert "refactor: gather group metadata"
This reverts commit 876d111c61.
* Revert "refactor: swap maintains schedule"
This reverts commit 730cb95c04.
* Revert "chore: rename files"
This reverts commit 3c388d4fb5.
* Revert "refactor: restructure model to contain an object of rundowns"
This reverts commit 2e23718d73.
* Revert "refactor: clearer relationship on rundown elements"
This reverts commit 89ea8c470b.
* Revert "refactor: use strict typing"
This reverts commit 178640bfc4.
* Revert "refactor: remove stop as a possible end action"
This reverts commit 4ed38340e0.
* Revert "refactor: restructure model to contain an object of rundowns"
This reverts commit 69eb9a5eff.
* Revert "chore: remove IDE files"
This reverts commit 351425127a.
* Revert "refactor: remove unused and legacy code"
This reverts commit 95f2ba37cc.
* creat failing test
* find and pass index of eventNow in case it moved
* fix cache invalidate edits should also recalculate timer
* use coluor as test indicator
* fixed empty cue guard
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* upgrade expressjs
* migration
* reenable test
* extend timeout on download test
* fixup! migration
* move empty body test from controller to validator
* enusre not empty
* extract validation function
* fixup! reenable test
* remove thin controllers
* disable e2e test of project file download
The `applyDelay` function had a condition that incorrectly used `rundown.order.length` instead of `rundownMetadata.flatEntryOrder.length` to check if a delay entry was the last in the sequence. `rundown.order` only contains top-level entries, while `flatEntryOrder` contains all entries, including those within blocks, which is the relevant list for this check.
This commit corrects the condition to use `rundownMetadata.flatEntryOrder.length`.
Existing tests in `rundown.dao.test.ts` (specifically the test `removes delays in last position without applying changes`) already cover this scenario and pass with the correction, ensuring the fix behaves as expected.
* fix: generateUniqueFileName
* loadProject should not generate new names
* update comments
* extract and test getProjectNumber
* spell
* finish jsdoc
* use getProjectNumber
* cleanup loadProject
* create a `incrementProjectNumber` function
* spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* creat failing test
* find and pass index of eventNow in case it moved
* fix cache invalidate edits should also recalculate timer
* use coluor as test indicator
* fixed empty cue guard
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* upgrade expressjs
* migration
* reenable test
* extend timeout on download test
* fixup! migration
* move empty body test from controller to validator
* enusre not empty
* extract validation function
* fixup! reenable test
* remove thin controllers
* disable e2e test of project file download
The `applyDelay` function had a condition that incorrectly used `rundown.order.length` instead of `rundownMetadata.flatEntryOrder.length` to check if a delay entry was the last in the sequence. `rundown.order` only contains top-level entries, while `flatEntryOrder` contains all entries, including those within blocks, which is the relevant list for this check.
This commit corrects the condition to use `rundownMetadata.flatEntryOrder.length`.
Existing tests in `rundown.dao.test.ts` (specifically the test `removes delays in last position without applying changes`) already cover this scenario and pass with the correction, ensuring the fix behaves as expected.
* fix: generateUniqueFileName
* loadProject should not generate new names
* update comments
* extract and test getProjectNumber
* spell
* finish jsdoc
* use getProjectNumber
* cleanup loadProject
* create a `incrementProjectNumber` function
* spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* refactor
* separate in and out time
* keep element on screen
* animate on play
* spelling
* explain animation decisions
* guard numbers from url params
* spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* rename safeParseNumber
* use view data
* refactor getOptionsFromParams
* rebalance animation timing
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* inti relative mode
* send imediat update on mode change
* add relative to test
* don't persist offset mode
* add test relative and update calc function
* pass data from ssocket
* add dev guard
* spelling and comments
* show relative in offset overview
* remove comments
* refactor: move totalDelay to _rundown
* update clear naming and comments
* remove old testing values
* crude UI
* add server functionalety
* better event trigger list
* fix default value
* remove log
* add trigger to recalculate whitelist
* use DTO type
* fix rebase
* one callback for delete and submit
* refactor
* add invalid description
* clean up commits
* cleanup
* refactor: find event triggers in `triggerAutomations`
* refactor: switch to flat array for event triggers
* prevent deleting a automation that is in use
* refactor
* refactor: extract EventEditorCustom
* move trigger options to separate file
* move trigger edit down a file level
* cleanup
* spelling
* refactor: ui review proposal
* change default value
* fix delete filter
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* create report service
* write report from runtimeState
* use in UI
* clear report
* update types
* clear all from settings menu
* rearence rightclik menu
* refactor styling
* also report roll events
* ontime/under time is same colour
* refactor reporter
* add target to ontime-refetch
* remove menu
* fectch only on message from server
* memo useGetEventReport
* refactor
* use staleTime
* dont add to menu yet
* implement review
* clear all from menu
* fix merge
* start end show
* combine test for the go button text and action
* add report to menu
* extract csv utility
* report management
* unneeded async
* small refacort of triggerReportEntry
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
refactor: improve empty state
refactor: review schedule design
- fit as many elements as possible
- expose cycle interval as an option
- stabilise rundown reference
- style tweaks
welcome modal is persisted in app state
created endpoints to set the visibility
added UI to support feature
Co-authored-by: Carlos Valente
<34649812+cpvalente@users.noreply.github.com>
* add dayOffset to OntimeEvent
* refactor: isNewLatest
* calculate totalDays
* refactor: getTimeFromPrevious
* add gap as dataset in OntimeEvent
* use in ui
* format overlap is just a simple text formatting, big test is not needed
* add new fields where needed
* update apply delay
* show nex day eaven if there is no gap
* create test
* use buildin day offset in timeline
* remove todo
* consistent naming
* make a calculateDayOffset util for rundownCache
* refactor: checkIsNextDay to use dayOffset
* spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* remove unneeded test
* remove todo
* update test db
* use data-testid
* spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* update comments
* remove null option
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* create db event type
* dont use it yet
* convert to and from database type
* type needed in one place in client
* use flatMap to filter out unknow stuff
* leave revision in save file
* move to utils
* make test
* destructur entry
* simple test
* throw in rundownToDatabaseRundown
* clerify comment
* Refactor: avoid shadowing the rundown variable in rundownCache (#1409)
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* rename to DAO
* add simple edit test
* only the generate function clears the state state
* strict guard for custom fields
* fix small strict issues
* ensure deep copy
* safely set isStale
* todo is done
* small type error
* these functions can work on DAO entries
* only reat rundown as DAO on initial load and the cast immediately and esure all fields are present
* eslint comment
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* fix spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* fix spelling
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* comment not needed
* setIsStale
* remove DAO
* clean up commits
* remove unneeded async/await
* revert test
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* detect `EADDRINUSE` on server start
* @ts-expect-error
* send portError to electron
* use escalateErrorFn
* dont move in docker
* allow errors to be sendt to electron UI
* Log after the new port is found
* Update comment
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* update comment
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* update comment
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* rename to escalate
* extract `serverTryDesiredPort`
* type check server.address()
* request shutdown on `unrecoverable` `escalateError`
* combine network utils
* reject promise
* not unrecoverable by default
* unneeded assignment
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* pass on all event edits
* MakePublic
* trim value in cell
* edit notes
* title
* add key check
* don't log error
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* checkbox
* refactor
* remove log
* fix test
* use row number to test value
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* feat: add lock icon when param `locked=true`
* chore: move `isViewLocked` logic up the component tree
* chore: remove extra container from lock icon
* chore: move fading logic into separate hook
* chore: move locked icon into separate component
* chore: rename variables
* use xlsx
* add existing custom fields to import map
* keep colours of existing custom fields
* use unknown
* fix
* revert
* allow space and upper case
* fix test
* define empty sheet
* remove custom field lowercasing
* don't allow custom field form to submit duplicate field
* remove unused
* update custom field tests
* also keep upper case when editing
* show key in UI
* also kep upper case when creating a new field
* fix test
* allow old forced case keys to stay as is
* allow space
* add extension to import
* supply initial key to CustomFieldForm
* refactor: improve element contrast
* refactor: style and composition
* consistent use of `customFieldLabelToKey`
* fix CopyTag
* remove log
---------
Co-authored-by: arc-alex <ac@omnivox.dk>
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* Revert "refactor: allow messages not starting with http"
This reverts commit 887e5c448e.
* Revert "refactor: allow messages not starting with http"
This reverts commit 6ce275da7a.
* pass full rundown to loadNow
* remove prevBlock from state
* refactor: simplify load logic (#1174)
* send clock to client on block start to avoid it showing -1 in the client
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* chore: escalate stack trace to console
* refactor: event finding in roll
* docs: initial roll specification
* refactor: call to roll
* refactor: normalise index
* refactor: roll into next event
* refactor: hot reload on waiting to roll
* refactor: wait to roll next
* add frozen flag to runtime store
* add middleware for when frozen
* prevent rundown editing when frozen
* add endpoint to router to set frozen state
* add frozen property to rundown placeholder in client
* remove demo and test db JSON
* remove demo-db reference in Dockerfile
* remove preloaded-db folder in server
* cleanup package.json scripts
* remove db.json references from server
* setup detection of TImerPhase changes
* add integration event for transition to warning
* add integration event for transition to danger
---------
Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
* add test for linking start time in excel import
* link ids
* add link to UI
* ensure times with cachedRundown
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* fix: jsdoc comments
* more human casting of string values to boolean
* add coerceColour to get named colors to work
* cue can't pass isKeyOfType event check
* dont mutate value
* alloow cue in eventDef
* lint
* css named or hex formatting
* "sideEffects": false
* test colour hex regex
* roll eventDef back to master
* parse property
* don't export cssColour names
* remove import
* only allow string types to colour
* handle transparent colour
* mix alpha with bg colour
* only allow updating events
* descriptive names
* add test for getAccessibleColour
* readability
* move isColourHex to regex-utils
* simplify and add test
* add `defaultvalue` to `Field` types
* add `defaultValue` to constants; turn into functions for time values
* update constant imports/calls in view components
* use `defaultValue`s in `ParamInput`
* change `Clear` to `Reset`to better reflect actions
* make `defaultValue` optional rather than `undefined`
* update forgotten constants
* add `defaultValue` to boolean input
* change `101010` to `000000`
* add `prefix` property to types
* implement `prefix` for `ParamInput`s
* change `paramField` to `prop`
* add `onEditDrawerClose` to `resetParams`
* `ViewParamsEditor` omits default values
* undo close on reset
* move `useSettings` into `ViewWrapper`
* change `settings` to include `undefined`
-**Run docker image from compose** by running `docker-compose up -d`
Other useful commands
-__List running processes__ by running `docker ps`
-__Kill running process__ by running `docker kill <process-id>`
-**List running processes** by running `docker ps`
-**Kill running process** by running `docker kill <process-id>`
## FORMATTING AND LINTING
Ontime uses [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) for formatting and [oxlint](https://oxc.rs/docs/guide/usage/linter.html) for linting. Look for an [oxc extension](https://oxc.rs/docs/guide/usage/linter/editors) for your editor of choice.
- **Run formatter** by running `pnpm format`
- **Run linter** by running `pnpm lint`
## CONTRIBUTION GUIDELINES
If you want to propose changes to the codebase, please reach out before opening a Pull Request.
For new PRs, please follow the following checklist:
- [ ] You have updated and ran unit locally and they are passing. Unit tests are generally created for all utility functions and business logic
- [ ] You have ran code formatting and linting in all your changes
- [ ] The branch is clean and the commits are meaningfully separated and contain descriptive messages
- [ ] The PR body contains description and motivation for the changes
After this checklist is complete, you can request a review from one of the maintainers to get feedback and approval on the changes. \
<a href="https://hub.docker.com/r/getontime/ontime"><img alt="Get from Dockerhub" src="https://github.com/cpvalente/ontime/blob/master/.github/aux-images/dockerhub.png"/></a>
</div>
<a href="https://www.buymeacoffee.com/cpvalente" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="32"></a>
- Download for <a href="https://github.com/cpvalente/ontime/releases/latest/download/ontime-win64.exe">Windows</a>
- Download for <a href="https://github.com/cpvalente/ontime/releases/latest/download/ontime-macOS-arm64.dmg">macOS (Apple Silicon)</a>
- Download for <a href="https://github.com/cpvalente/ontime/releases/latest/download/ontime-macOS-x64.dmg">macOS (Intel)</a>
- Download AppImage for <a href="https://github.com/cpvalente/ontime/releases/latest/download/ontime-linux-x86_64.AppImage">Linux (Intel / AMD 64-bit)</a>
- Download AppImage for <a href="https://github.com/cpvalente/ontime/releases/latest/download/ontime-linux-arm64.AppImage">Linux (ARM 64-bit, Raspberry Pi 4+)</a>
- Get from <a href="https://hub.docker.com/r/getontime/ontime">Docker hub</a>
- Install from <a href="https://www.npmjs.com/package/@getontime/cli">NPM</a>
- Install from <a href="https://formulae.brew.sh/cask/ontime">Homebrew</a>
## Need help?
We do our best to have most topics covered by the documentation. However, if your question is not covered, you are welcome to [fill in a bug report in an issue](https://github.com/cpvalente/ontime/issues), [ask a question in GitHub discussions](https://github.com/cpvalente/ontime/discussions) or hop in the [discord server](https://discord.com/invite/eje3CSUEXm) for a chat.
## Using Ontime?
Let us know!
Ontime improves from the collaboration with its users. We would like to understand how you use Ontime and appreciate your feedback.
# Ontime
Ontime is an application for creating and managing event running order and timers.
Ontime is a browser-based application that manages event rundowns, scheduling, and cueing.
The user inputs a list of events along with scheduling and event information.
This will then populate a series of screens which are available to be rendered by any device in the Network.
With Ontime, you can plan, track your schedule, manage automation and cross-department show information all in one place.
This makes for a simple and cheap way to distribute over a venue using a network infrastructure instead of video
outputs.
Ontime is made by entertainment and broadcast engineers and used by
- **Multiplatform**: Available as a Cloud service and for Windows, macOS, Linux, or self-hosted via Docker.
- **In any device**: Ontime is available to any device with a browser, eg: tablets, mobile phones, laptops, signage, media servers...
- **Team Collaboration**: Dedicated views for directors, operators, backstage, and signage.
- **Real-Time Updates**: Manage and communicate runtime delays effortlessly.
- **Automatable**: Ontime can be fully or partially controlled by an operator, or run standalone with the system clock
- **Flexible Integrations**: Use one of the APIs provided (OSC, HTTP, Websocket) or the available [Companion module](https://bitfocus.io/connections/getontime-ontime) to integrate into your workflow (vMix, disguise, Qlab, OBS)
... and a lot more ...
### For live environments
Ontime is designed for use in live environments. \
This guides the application into being flexible and efficiently integrating into different workflows.
### For teams
All information added in Ontime is shared with the production team and other software / hardware in your workflow. \
Ontime also improves team collaboration with dedicated views for cuesheets and operators, and for public and production
signage.
### Simple infrastructure
All the data is distributed over the network, making its distribution and infrastructure flexible and cheap. \
With the availability of the docker image, you can also leverage IT infrastructure to make Ontime available online for
your team and clients.
Ontime is made by video engineers and entertainment technicians.
[Read the docs to learn more](https://docs.getontime.no)
## Using Ontime
Once installed and running, Ontime starts a background server that is the heart of all processes.
From the app, you can add / edit your running order and control the timer playback.
### Getting started
Any device with a browser in the same network can choose one of the supported views to render the available data.
This is done by reaching the ontime server at the _default port 4001_ eg: `localhost:4001`
or `192.168.1.3:4001`
<br />
You can then use the menu in the top left corner to select the desired view.
The menu will be initially hidden until there is mouse interaction.
The easiest way to start with Ontime is by leveraging our [Cloud service](https://getontime.no). \
This will give you immediate access to running instances of Ontime which are available to share with anyone with an internet connection.
In the case of unattended machines or automation, it is possible to use different URL to recall
individual views and extend view settings using the URL aliases feature
Alternatively, you can run Ontime locally for free by downloading the latest release for your platform or using the docker image, available at [Docker Hub](https://hub.docker.com/r/getontime/ontime)
We want Ontime to be unique by targeting freelancers instead of roles.
We believe most freelancers work in different fields and we want to give you a tool that you can leverage across your
many environments and workflows.
We are not interested in forcing workflows and have made Ontime so, it is flexible to whichever way you would like to
work.
## Rich APIs for workflow integrations
The app is currently being developed for a broad user base, from broadcast to entertainment and
conference halls.
Taking advantage of the integrations, we currently use Ontime with:
-`disguise`: trigger Ontime from d3's timeline using the **OSC API**, and **render views** using d3's
webmodule
-`OBS`: **render views** using the Browser Module
-`QLab`: trigger Ontime using **OSC API**
-`Companion`: Ontime has a **companion module**. Issue report and feature requests should be done
in the [repository getontime/ontime](https://github.com/bitfocus/companion-module-getontime-ontime)
### Make your own viewer
Ontime broadcasts its data over WebSockets. This allows you to consume its data outside the application.
Writing a new view for the browser can be done with basic knowledge of HTML + CSS + Javascript (or any other language
that can run in the browser).
<br />
See [this repository](https://github.com/cpvalente/ontime-viewer-template-v2) with a small template on
how to get you started and read the docs about
the [Websocket API](https://ontime.gitbook.io/v2/control-and-feedback/ontime-apis#osc-and-websocket-api)
### Headless run️
You can self-host and run Ontime in a docker image.
The docker image along with documentation is [available Docker Hub at getontime/ontime](https://hub.docker.com/r/getontime/ontime)
If you want to run this image in a Raspberry Pi, please see [the docs](https://ontime.gitbook.io/v2/additional-notes/use-in-raspberry-pi)
## Roadmap
### Continued development
Several features are planned in the roadmap, and we continuously adjust this to match how users interact with the app.
<br />
Have an idea? Reach out via [email](mail@getontime.no)
or [open an issue](https://github.com/cpvalente/ontime/issues/new)
### Issues
## Issues
We use Github's issue tracking for bug reporting and feature requests. <br />
We use Github's issue tracking for bug reporting and feature requests. \
Found a bug? [Open an issue](https://github.com/cpvalente/ontime/issues/new).
#### Unsigned App
When installing the app you would see warning screens from the Operating System like:
`Microsoft Defender SmartScreen prevented an unrecognised app from starting. Running this app might put your PC at risk.`
or
`Ontime can't be opened because it is from an unidentified developer`
or in Linux
`Could Not Display "ontime-linux.AppImage`
You can circumvent this by allowing the execution of the app manually.
- In Windows: click more and select "Run Anyway"
- in macOS: the solution in macOS is different across versions, please refer to the [apple documentation](https://support.apple.com/en-gb/guide/mac-help/mh40616/mac)
- In Linux: right-click the AppImage file -> Properties -> Permissions -> select Allow Executing
File as a Program
Long story short: Ontime app is unsigned. </br>Purchasing the certificates for both Mac and Windows
would mean a recurrent expense and is not a priority. This is unlikely to change in future. If you
have tips on how to improve this or would like to sponsor the code signing,
please [open an issue](https://github.com/cpvalente/ontime/issues/new)
#### Safari
There are known issues with Safari versions lower than 13:
- Spacing and text styles might have small inconsistencies
- Table view does not work
There is no plan for any further work on this.
# Contributing
## Contributing
Looking to contribute? All types of help are appreciated, from coding to testing and feature specification.
<br /><br />
If you are a developer and would like to contribute with some code, please open an issue to discuss before opening a
Pull Request.
<br />
If you are a developer and would like to contribute with code, please open an issue to discuss before opening a Pull Request.
Information about the project setup can be found in the [development documentation](./DEVELOPMENT.md)
# Help
## Links
Help is underway! ... and can be found [here](https://ontime.gitbook.io)
This project is licensed under the terms of the GNU GPL v3
## Sponsor
You can help the development of this project or say thank you with a one time donation. \
See [the terms of donations](https://github.com/cpvalente/ontime/blob/master/.github/FUNDING.md).
<p align="center">
<br>
<a href="https://www.buymeacoffee.com/cpvalente" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="200"></a>
Ontime does not exist as a fiscal entity. The sponsorship recipient is the project owner. In this light, contributors are funding the project owner's capacity to work on the project, not the project itself. As a contribution recipient, the code owner reserves the right to redistribute.
## Why sponsor
Ontime is and will remain free, regardless of your decision to contribute.
Regardless, you may choose to provide a monetary contribution:
### Improve user experience
Certain parts of the application user experience are tied to our capacity to pay for services. App signing and Google Sheets integration are good examples of this.
### Cool stuff
We may choose not to implement some features. This could be related to the complexity required, to the skill set, or to the fact that we just feel it doesn't improve the app for a significant percentage of users. In those cases, a feature may be considered "not worth it," regardless of its pertinence.
As a user, you can choose to sponsor a particular feature or donate to the app so that we can create bounties for features.
### Priorities
Monetary contributions are most immediately needed to offset the costs of presenting and distributing Ontime, i.e., hosting, domains, and certificates.
Additional funding will be considered according to the needs at the time.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.