mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 22:24:11 +00:00
Alpha 5 (#1741)
* 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:
+64
-64
@@ -1,89 +1,91 @@
|
||||
import { RefObject, useEffect, useRef } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { IoEllipsisHorizontal } from 'react-icons/io5';
|
||||
import { flexRender, Table } from '@tanstack/react-table';
|
||||
import { OntimeEntry, OntimeEvent, RGBColour, SupportedEntry } from 'ontime-types';
|
||||
import { EntryId, OntimeEntry, RGBColour, SupportedEntry } from 'ontime-types';
|
||||
import { colourToHex, cssOrHexToColour } from 'ontime-utils';
|
||||
|
||||
import IconButton from '../../../../common/components/buttons/IconButton';
|
||||
import type { ExtendedEntry } from '../../../../common/utils/rundownMetadata';
|
||||
import { cx, getAccessibleColour } from '../../../../common/utils/styleUtils';
|
||||
import { AppMode } from '../../../../ontimeConfig';
|
||||
import { useCuesheetTableMenu } from '../cuesheet-table-menu/useCuesheetTableMenu';
|
||||
|
||||
import { observeRow, unobserveRow } from './rowObserver';
|
||||
import { useVisibleRowsStore } from './visibleRowsStore';
|
||||
|
||||
import style from './EventRow.module.scss';
|
||||
|
||||
interface EventRowProps {
|
||||
rowId: string;
|
||||
event: OntimeEvent;
|
||||
id: EntryId;
|
||||
eventIndex: number;
|
||||
colour: string;
|
||||
isFirstAfterGroup: boolean;
|
||||
isLoaded: boolean;
|
||||
isPast: boolean;
|
||||
groupColour: string | undefined;
|
||||
flag: boolean;
|
||||
skip: boolean;
|
||||
parent: EntryId | null;
|
||||
rowIndex: number;
|
||||
isPast?: boolean;
|
||||
selectedRef?: RefObject<HTMLTableRowElement | null>;
|
||||
skip?: boolean;
|
||||
colour?: string;
|
||||
rowBgColour?: string;
|
||||
parentBgColour?: string;
|
||||
table: Table<OntimeEntry>;
|
||||
firstAfterGroup: boolean;
|
||||
table: Table<ExtendedEntry<OntimeEntry>>;
|
||||
}
|
||||
|
||||
export default function EventRow({
|
||||
rowId,
|
||||
event,
|
||||
id,
|
||||
eventIndex,
|
||||
rowIndex,
|
||||
colour,
|
||||
isFirstAfterGroup,
|
||||
isLoaded,
|
||||
isPast,
|
||||
selectedRef,
|
||||
rowBgColour,
|
||||
parentBgColour,
|
||||
groupColour,
|
||||
flag,
|
||||
skip,
|
||||
parent,
|
||||
rowIndex,
|
||||
table,
|
||||
firstAfterGroup,
|
||||
...virtuosoProps
|
||||
}: EventRowProps) {
|
||||
const { cuesheetMode, hideIndexColumn } = table.options.meta?.options ?? {
|
||||
cuesheetMode: AppMode.Edit,
|
||||
hideIndexColumn: false,
|
||||
};
|
||||
|
||||
const ownRef = useRef<HTMLTableRowElement>(null);
|
||||
const isVisible = useVisibleRowsStore((state) => state.visibleRows.has(rowId));
|
||||
const openMenu = useCuesheetTableMenu((store) => store.openMenu);
|
||||
|
||||
// register this row with the intersection observer
|
||||
useEffect(() => {
|
||||
const element = ownRef.current;
|
||||
if (element) {
|
||||
element.id = rowId;
|
||||
observeRow(element);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (element) {
|
||||
unobserveRow(element);
|
||||
}
|
||||
};
|
||||
}, [rowId]);
|
||||
|
||||
const { color, backgroundColor } = getAccessibleColour(event.colour);
|
||||
const { color, backgroundColor } = getAccessibleColour(colour);
|
||||
const tmpColour = cssOrHexToColour(color) as RGBColour; // we know this to be a correct colour
|
||||
const mutedText = colourToHex({ ...tmpColour, alpha: tmpColour.alpha * 0.8 });
|
||||
|
||||
const rowBgColour: string | undefined = useMemo(() => {
|
||||
if (isLoaded) {
|
||||
return '#087A27'; // $active-green
|
||||
} else if (colour) {
|
||||
// the colour is user defined and might be invalid
|
||||
const accessibleBackgroundColor = cssOrHexToColour(getAccessibleColour(colour).backgroundColor);
|
||||
if (accessibleBackgroundColor !== null) {
|
||||
return colourToHex({
|
||||
...accessibleBackgroundColor,
|
||||
alpha: accessibleBackgroundColor.alpha * 0.25,
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}, [colour, isLoaded]);
|
||||
|
||||
return (
|
||||
<tr
|
||||
id={rowId}
|
||||
className={cx([
|
||||
style.eventRow,
|
||||
event.skip && style.skip,
|
||||
firstAfterGroup && style.firstAfterGroup,
|
||||
Boolean(parentBgColour) && style.hasParent,
|
||||
skip && style.skip,
|
||||
isFirstAfterGroup && style.firstAfterGroup,
|
||||
parent && style.hasParent,
|
||||
])}
|
||||
style={{
|
||||
opacity: `${isPast ? '0.2' : '1'}`,
|
||||
'--user-bg': parentBgColour ?? 'transparent',
|
||||
'--user-bg': groupColour ?? 'transparent',
|
||||
}}
|
||||
ref={selectedRef ?? ownRef}
|
||||
data-testid='cuesheet-event'
|
||||
{...virtuosoProps}
|
||||
>
|
||||
{cuesheetMode === AppMode.Edit && (
|
||||
<td className={style.actionColumn} tabIndex={-1} role='cell'>
|
||||
@@ -94,7 +96,7 @@ export default function EventRow({
|
||||
onClick={(e) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
const yPos = 8 + rect.y + rect.height / 2;
|
||||
openMenu({ x: rect.x, y: yPos }, event.id, SupportedEntry.Event, rowIndex, event.parent, event.flag);
|
||||
openMenu({ x: rect.x, y: yPos }, id, SupportedEntry.Event, rowIndex, parent, flag);
|
||||
}}
|
||||
>
|
||||
<IoEllipsisHorizontal />
|
||||
@@ -106,26 +108,24 @@ export default function EventRow({
|
||||
{eventIndex}
|
||||
</td>
|
||||
)}
|
||||
{isVisible
|
||||
? table
|
||||
.getRow(rowId)
|
||||
.getVisibleCells()
|
||||
.map((cell) => {
|
||||
return (
|
||||
<td
|
||||
key={cell.id}
|
||||
style={{
|
||||
width: `calc(var(--col-${cell.column.id}-size) * 1px)`,
|
||||
backgroundColor: rowBgColour,
|
||||
}}
|
||||
tabIndex={-1}
|
||||
role='cell'
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
{table
|
||||
.getRow(rowId)
|
||||
.getVisibleCells()
|
||||
.map((cell) => {
|
||||
return (
|
||||
<td
|
||||
key={cell.id}
|
||||
style={{
|
||||
width: `calc(var(--col-${cell.column.id}-size) * 1px)`,
|
||||
backgroundColor: rowBgColour,
|
||||
}}
|
||||
tabIndex={-1}
|
||||
role='cell'
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user