* 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>
This commit is contained in:
Carlos Valente
2025-09-03 15:50:20 +02:00
committed by GitHub
parent 3c41b40c5f
commit ae15f3cdc5
102 changed files with 2950 additions and 2104 deletions
+30 -58
View File
@@ -29,7 +29,7 @@ import { customFieldLabelToKey, insertAtIndex } from 'ontime-utils';
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
import type { AssignedMap, CustomFieldsMetadata, RundownMetadata } from './rundown.types.js';
import type { RundownMetadata } from './rundown.types.js';
import {
applyPatchToEntry,
cloneGroup,
@@ -67,15 +67,6 @@ let rundownMetadata: RundownMetadata = {
flags: [],
};
const customFieldsMetadata: CustomFieldsMetadata = {
/**
* Keep track of which custom fields are used.
* This will be handy for when we delete custom fields
* since we can clear the custom fields from every event where they are used
*/
assigned: {},
};
/**
* The custom fields that are used in the project
* Not unique to the loaded rundown
@@ -89,7 +80,6 @@ export const getEntryWithId = (entryId: EntryId): OntimeEntry | undefined => cac
type Transaction = {
customFields: CustomFields;
customFieldsMetadata: Readonly<CustomFieldsMetadata>;
rundown: Rundown;
rundownMetadata: Readonly<RundownMetadata>;
@@ -136,13 +126,11 @@ export function createTransaction(options: TransactionOptions): Transaction {
const processedData = processRundown(rundown, projectCustomFields);
// update the cache values
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- we are not interested in the iteration data
const { previousEvent, latestEvent, previousEntry, entries, order, assignedCustomFields, ...metadata } =
processedData;
const { previousEvent, latestEvent, previousEntry, entries, order, ...metadata } = processedData;
cachedRundown.entries = entries;
cachedRundown.order = order;
cachedRundown.flatOrder = metadata.flatEntryOrder;
customFieldsMetadata.assigned = assignedCustomFields;
rundownMetadata = metadata;
}
}
@@ -167,7 +155,6 @@ export function createTransaction(options: TransactionOptions): Transaction {
return {
customFields,
customFieldsMetadata,
rundown,
rundownMetadata,
commit,
@@ -564,6 +551,15 @@ export const rundownMutation = {
ungroup,
};
/**
* Exposes a way to update a rundown which is not active
*/
export function updateBackgroundRundown(rundownId: string, rundown: Rundown) {
setImmediate(async () => {
await getDataProvider().setRundown(rundownId, rundown);
});
}
/**
* Adds a new custom field to the object and returns it
*/
@@ -603,51 +599,29 @@ function customFieldRemove(customFields: CustomFields, key: CustomFieldKey) {
}
/**
* Renames a custom field key in all the rundown entries that use it
* Iterates through all entries of a rundown and renames a custom field
*/
function customFieldRenameUsages(
rundown: Rundown,
assigned: AssignedMap,
oldKey: CustomFieldKey,
newKey: CustomFieldKey,
) {
const usages = assigned[oldKey];
// iterate through all the entries that use the custom field
for (let i = 0; i < usages.length; i++) {
const entryId = usages[i];
const entry = rundown.entries[entryId] as OntimeEvent;
// copy the data a new key and delete the old key
entry.custom[newKey] = entry.custom[oldKey];
delete entry.custom[oldKey];
}
// update assignment
assigned[newKey] = [...assigned[oldKey]];
delete assigned[oldKey];
function customFieldRenameUsages(rundown: Rundown, oldKey: CustomFieldKey, newKey: CustomFieldKey) {
Object.keys(rundown.entries).forEach((entryId) => {
const entry = rundown.entries[entryId];
if ('custom' in entry && entry.custom[oldKey]) {
// copy the data a new key and delete the old key
entry.custom[newKey] = entry.custom[oldKey];
delete entry.custom[oldKey];
}
});
}
/**
* Deletes data for a custom field from all the entries that use it
* Iterates through all entries of a rundown and removes data associated with a custom field
*/
function customFieldRemoveUsages(rundown: Rundown, assigned: AssignedMap, key: CustomFieldKey) {
const usages = assigned[key];
if (!usages) {
return;
}
// iterate through all the entries that use the custom field
for (let i = 0; i < usages.length; i++) {
const entryId = usages[i];
const entry = rundown.entries[entryId] as OntimeEvent;
// delete the custom field entry
delete entry.custom[key];
}
// update assignment
delete assigned[key];
function customFieldRemoveUsages(rundown: Rundown, key: CustomFieldKey) {
Object.keys(rundown.entries).forEach((entryId) => {
const entry = rundown.entries[entryId];
if ('custom' in entry && entry.custom[key]) {
delete entry.custom[key];
}
});
}
export const customFieldMutation = {
@@ -672,13 +646,11 @@ export function init(initialRundown: Readonly<Rundown>, initialCustomFields: Rea
projectCustomFields = customFields;
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- we are not interested in the iteration data
const { previousEvent, latestEvent, previousEntry, entries, order, assignedCustomFields, ...metadata } =
processedData;
const { previousEvent, latestEvent, previousEntry, entries, order, ...metadata } = processedData;
cachedRundown.entries = entries;
cachedRundown.order = order;
cachedRundown.flatOrder = metadata.flatEntryOrder;
cachedRundown.revision = rundown.revision;
customFieldsMetadata.assigned = assignedCustomFields;
rundownMetadata = metadata;
// defer writing to the database