mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 22:49:18 +00:00
feat: cuesheet sharing
feat: locked presets refactor: simplify locked param refactor: create share links
This commit is contained in:
committed by
Carlos Valente
parent
1695b4dc68
commit
6c6f5c2c0f
@@ -1,12 +1,10 @@
|
||||
import { IoEllipsisHorizontal } from 'react-icons/io5';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
import { flexRender, Table } from '@tanstack/react-table';
|
||||
import { EntryId, OntimeEntry, SupportedEntry } from 'ontime-types';
|
||||
|
||||
import IconButton from '../../../../common/components/buttons/IconButton';
|
||||
import { useCurrentBlockId } from '../../../../common/hooks/useSocket';
|
||||
import { AppMode, sessionKeys } from '../../../../ontimeConfig';
|
||||
import { usePersistedCuesheetOptions } from '../../cuesheet.options';
|
||||
import { AppMode } from '../../../../ontimeConfig';
|
||||
import { useCuesheetTableMenu } from '../cuesheet-table-menu/useCuesheetTableMenu';
|
||||
|
||||
import style from './BlockRow.module.scss';
|
||||
@@ -23,11 +21,11 @@ interface BlockRowProps {
|
||||
export default function BlockRow({ blockId, colour, hidePast, rowId, rowIndex, table }: BlockRowProps) {
|
||||
const { currentBlockId } = useCurrentBlockId();
|
||||
|
||||
const hideIndexColumn = usePersistedCuesheetOptions((state) => state.hideIndexColumn);
|
||||
const [cuesheetMode] = useSessionStorage<AppMode>({
|
||||
key: sessionKeys.cuesheetMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
const { cuesheetMode, hideIndexColumn } = table.options.meta?.options ?? {
|
||||
cuesheetMode: AppMode.Edit,
|
||||
hideIndexColumn: false,
|
||||
};
|
||||
|
||||
const openMenu = useCuesheetTableMenu((store) => store.openMenu);
|
||||
|
||||
if (hidePast && !currentBlockId) {
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetB
|
||||
if (entry.parent) {
|
||||
const rundown = queryClient.getQueryData<Rundown>(RUNDOWN);
|
||||
const parentEntry = rundown?.entries[entry.parent];
|
||||
parentBgColour = (parentEntry as OntimeBlock).colour ?? null;
|
||||
parentBgColour = (parentEntry as OntimeBlock | undefined)?.colour ?? null;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
+3
-7
@@ -1,11 +1,10 @@
|
||||
import { CSSProperties } from 'react';
|
||||
import { horizontalListSortingStrategy, SortableContext } from '@dnd-kit/sortable';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
import { flexRender, HeaderGroup } from '@tanstack/react-table';
|
||||
import { OntimeEntry } from 'ontime-types';
|
||||
|
||||
import { getAccessibleColour } from '../../../../common/utils/styleUtils';
|
||||
import { AppMode, sessionKeys } from '../../../../ontimeConfig';
|
||||
import { AppMode } from '../../../../ontimeConfig';
|
||||
import { usePersistedCuesheetOptions } from '../../cuesheet.options';
|
||||
|
||||
import { SortableCell } from './SortableCell';
|
||||
@@ -14,14 +13,11 @@ import style from '../CuesheetTable.module.scss';
|
||||
|
||||
interface CuesheetHeaderProps {
|
||||
headerGroups: HeaderGroup<OntimeEntry>[];
|
||||
cuesheetMode: AppMode;
|
||||
}
|
||||
|
||||
export default function CuesheetHeader({ headerGroups }: CuesheetHeaderProps) {
|
||||
export default function CuesheetHeader({ headerGroups, cuesheetMode }: CuesheetHeaderProps) {
|
||||
const hideIndexColumn = usePersistedCuesheetOptions((state) => state.hideIndexColumn);
|
||||
const [cuesheetMode] = useSessionStorage<AppMode>({
|
||||
key: sessionKeys.cuesheetMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
|
||||
return (
|
||||
<thead className={style.tableHeader}>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { RefObject, useEffect, useRef } from 'react';
|
||||
import { IoEllipsisHorizontal } from 'react-icons/io5';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
import { flexRender, Table } from '@tanstack/react-table';
|
||||
import { OntimeEntry, OntimeEvent, RGBColour, SupportedEntry } from 'ontime-types';
|
||||
import { colourToHex, cssOrHexToColour } from 'ontime-utils';
|
||||
|
||||
import IconButton from '../../../../common/components/buttons/IconButton';
|
||||
import { cx, getAccessibleColour } from '../../../../common/utils/styleUtils';
|
||||
import { AppMode, sessionKeys } from '../../../../ontimeConfig';
|
||||
import { usePersistedCuesheetOptions } from '../../cuesheet.options';
|
||||
import { AppMode } from '../../../../ontimeConfig';
|
||||
import { useCuesheetTableMenu } from '../cuesheet-table-menu/useCuesheetTableMenu';
|
||||
|
||||
import { observeRow, unobserveRow } from './rowObserver';
|
||||
@@ -43,15 +41,13 @@ export default function EventRow({
|
||||
table,
|
||||
firstAfterBlock,
|
||||
}: EventRowProps) {
|
||||
const hideIndexColumn = usePersistedCuesheetOptions((state) => state.hideIndexColumn);
|
||||
const [cuesheetMode] = useSessionStorage<AppMode>({
|
||||
key: sessionKeys.cuesheetMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
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
|
||||
|
||||
+6
-8
@@ -1,12 +1,10 @@
|
||||
import { IoEllipsisHorizontal } from 'react-icons/io5';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
import { flexRender, Table } from '@tanstack/react-table';
|
||||
import { EntryId, OntimeEntry, SupportedEntry } from 'ontime-types';
|
||||
|
||||
import IconButton from '../../../../common/components/buttons/IconButton';
|
||||
import { cx, enDash } from '../../../../common/utils/styleUtils';
|
||||
import { AppMode, sessionKeys } from '../../../../ontimeConfig';
|
||||
import { usePersistedCuesheetOptions } from '../../cuesheet.options';
|
||||
import { AppMode } from '../../../../ontimeConfig';
|
||||
import { useCuesheetTableMenu } from '../cuesheet-table-menu/useCuesheetTableMenu';
|
||||
|
||||
import style from './MilestoneRow.module.scss';
|
||||
@@ -32,11 +30,11 @@ export default function MilestoneRow({
|
||||
rowIndex,
|
||||
table,
|
||||
}: MilestoneRowProps) {
|
||||
const hideIndexColumn = usePersistedCuesheetOptions((state) => state.hideIndexColumn);
|
||||
const [cuesheetMode] = useSessionStorage<AppMode>({
|
||||
key: sessionKeys.cuesheetMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
const { cuesheetMode, hideIndexColumn } = table.options.meta?.options ?? {
|
||||
cuesheetMode: AppMode.Edit,
|
||||
hideIndexColumn: false,
|
||||
};
|
||||
|
||||
const openMenu = useCuesheetTableMenu((store) => store.openMenu);
|
||||
|
||||
return (
|
||||
|
||||
+94
-66
@@ -1,6 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
import { CellContext, ColumnDef } from '@tanstack/react-table';
|
||||
import { CustomFields, isOntimeDelay, isOntimeEvent, OntimeEntry, TimeStrategy } from 'ontime-types';
|
||||
import { CustomFields, isOntimeDelay, isOntimeEvent, OntimeEntry, TimeStrategy, URLPreset } from 'ontime-types';
|
||||
import { millisToString } from 'ontime-utils';
|
||||
|
||||
import DelayIndicator from '../../../../common/components/delay-indicator/DelayIndicator';
|
||||
@@ -225,85 +225,113 @@ function MakeCustomField({ row, column, table }: CellContext<OntimeEntry, unknow
|
||||
* we cant use the createColumnHelper() because we have custom logic for rendering the cells
|
||||
* This means that the display columns: index and action are added inline by the row components
|
||||
*/
|
||||
export function makeCuesheetColumns(customFields: CustomFields, cuesheetMode: AppMode): ColumnDef<OntimeEntry>[] {
|
||||
export function makeCuesheetColumns(
|
||||
customFields: CustomFields,
|
||||
cuesheetMode: AppMode,
|
||||
preset: URLPreset | undefined,
|
||||
): ColumnDef<OntimeEntry>[] {
|
||||
const columnsDef: ColumnDef<OntimeEntry>[] = [];
|
||||
const modeAllowsWrite = cuesheetMode === AppMode.Edit;
|
||||
const fullRead = preset ? preset.options?.read === 'full' : true;
|
||||
const fullWrite = preset ? preset.options?.write === 'full' : true;
|
||||
const canWriteKeys = preset?.options?.write ? new Set(preset.options.write.split(',')) : new Set<string>();
|
||||
const canReadKeys = preset?.options?.read ? new Set(preset.options.read.split(',')) : new Set<string>();
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'flag',
|
||||
id: 'flag',
|
||||
header: 'Flag',
|
||||
cell: MakeFlagField,
|
||||
size: 45,
|
||||
minSize: 45,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
// helpers to check read/write for a given key
|
||||
const canRead = (key: string) => fullRead || canReadKeys.has(key);
|
||||
const canWrite = (key: string) => modeAllowsWrite && (fullWrite || canWriteKeys.has(key));
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'cue',
|
||||
id: 'cue',
|
||||
header: 'Cue',
|
||||
cell: MakeSingleLineField,
|
||||
size: 75,
|
||||
minSize: 40,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
if (canRead('flag')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'flag',
|
||||
id: 'flag',
|
||||
header: 'Flag',
|
||||
cell: MakeFlagField,
|
||||
size: 45,
|
||||
minSize: 45,
|
||||
meta: { canWrite: canWrite('flag') },
|
||||
});
|
||||
}
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'timeStart',
|
||||
id: 'timeStart',
|
||||
header: 'Start',
|
||||
cell: MakeStart,
|
||||
size: 75,
|
||||
minSize: 75,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
if (canRead('cue')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'cue',
|
||||
id: 'cue',
|
||||
header: 'Cue',
|
||||
cell: MakeSingleLineField,
|
||||
size: 75,
|
||||
minSize: 40,
|
||||
meta: { canWrite: canWrite('cue') },
|
||||
});
|
||||
}
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'timeEnd',
|
||||
id: 'timeEnd',
|
||||
header: 'End',
|
||||
cell: MakeEnd,
|
||||
size: 75,
|
||||
minSize: 75,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
if (canRead('timeStart')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'timeStart',
|
||||
id: 'timeStart',
|
||||
header: 'Start',
|
||||
cell: MakeStart,
|
||||
size: 75,
|
||||
minSize: 75,
|
||||
meta: { canWrite: canWrite('timeStart') },
|
||||
});
|
||||
}
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'duration',
|
||||
id: 'duration',
|
||||
header: 'Duration',
|
||||
cell: MakeDuration,
|
||||
size: 75,
|
||||
minSize: 75,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
if (canRead('timeEnd')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'timeEnd',
|
||||
id: 'timeEnd',
|
||||
header: 'End',
|
||||
cell: MakeEnd,
|
||||
size: 75,
|
||||
minSize: 75,
|
||||
meta: { canWrite: canWrite('timeEnd') },
|
||||
});
|
||||
}
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'title',
|
||||
id: 'title',
|
||||
header: 'Title',
|
||||
cell: MakeSingleLineField,
|
||||
size: 250,
|
||||
minSize: 75,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
if (canRead('duration')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'duration',
|
||||
id: 'duration',
|
||||
header: 'Duration',
|
||||
cell: MakeDuration,
|
||||
size: 75,
|
||||
minSize: 75,
|
||||
meta: { canWrite: canWrite('duration') },
|
||||
});
|
||||
}
|
||||
|
||||
columnsDef.push({
|
||||
accessorKey: 'note',
|
||||
id: 'note',
|
||||
header: 'Note',
|
||||
cell: MakeMultiLineField,
|
||||
size: 250,
|
||||
minSize: 75,
|
||||
meta: { canWrite: modeAllowsWrite },
|
||||
});
|
||||
if (canRead('title')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'title',
|
||||
id: 'title',
|
||||
header: 'Title',
|
||||
cell: MakeSingleLineField,
|
||||
size: 250,
|
||||
minSize: 75,
|
||||
meta: { canWrite: canWrite('title') },
|
||||
});
|
||||
}
|
||||
|
||||
if (canRead('note')) {
|
||||
columnsDef.push({
|
||||
accessorKey: 'note',
|
||||
id: 'note',
|
||||
header: 'Note',
|
||||
cell: MakeMultiLineField,
|
||||
size: 250,
|
||||
minSize: 75,
|
||||
meta: { canWrite: canWrite('note') },
|
||||
});
|
||||
}
|
||||
|
||||
// custom fields at the end
|
||||
const customFieldKeys = Object.keys(customFields);
|
||||
|
||||
for (let i = 0; i < customFieldKeys.length; i++) {
|
||||
const key = customFieldKeys[i];
|
||||
const permissionKey = `custom-${key}`;
|
||||
if (!canRead(permissionKey)) continue;
|
||||
columnsDef.push({
|
||||
accessorKey: key,
|
||||
id: key,
|
||||
@@ -313,7 +341,7 @@ export function makeCuesheetColumns(customFields: CustomFields, cuesheetMode: Ap
|
||||
minSize: 75,
|
||||
meta: {
|
||||
colour: customFields[key].colour,
|
||||
canWrite: true,
|
||||
canWrite: canWrite(permissionKey),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user