mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 14:39:06 +00:00
refactor: react state for cuesheet v editor layout
This commit is contained in:
@@ -59,7 +59,6 @@ export function useRundownWithMetadata(rundownId: Maybe<string>) {
|
|||||||
/**
|
/**
|
||||||
* Provides access to a flat rundown
|
* Provides access to a flat rundown
|
||||||
* built from the order and rundown fields
|
* built from the order and rundown fields
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
export function useFlatRundown(rundownId: Maybe<string>) {
|
export function useFlatRundown(rundownId: Maybe<string>) {
|
||||||
const { data, status } = useRundown(rundownId);
|
const { data, status } = useRundown(rundownId);
|
||||||
@@ -90,7 +89,6 @@ export function useFlatRundownWithMetadata(rundownId: Maybe<string>) {
|
|||||||
* Callers MUST memoize the callback with useCallback to prevent
|
* Callers MUST memoize the callback with useCallback to prevent
|
||||||
* re-filtering on every render.
|
* re-filtering on every render.
|
||||||
*
|
*
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
export function usePartialRundown(rundownId: Maybe<string>, cb: (event: ExtendedEntry<OntimeEntry>) => boolean) {
|
export function usePartialRundown(rundownId: Maybe<string>, cb: (event: ExtendedEntry<OntimeEntry>) => boolean) {
|
||||||
const { data, status } = useFlatRundownWithMetadata(rundownId);
|
const { data, status } = useFlatRundownWithMetadata(rundownId);
|
||||||
@@ -112,10 +110,6 @@ export function useEntry(rundownId: Maybe<string>, entryId: EntryId | null): Ont
|
|||||||
return rundown.entries[entryId] ?? null;
|
return rundown.entries[entryId] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export function useRundownAuxData(rundownId: Maybe<string>) {
|
export function useRundownAuxData(rundownId: Maybe<string>) {
|
||||||
const { data, status } = useRundown(rundownId);
|
const { data, status } = useRundown(rundownId);
|
||||||
const filteredData = useMemo(() => {
|
const filteredData = useMemo(() => {
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ export function MetadataTimes() {
|
|||||||
function GroupTimes() {
|
function GroupTimes() {
|
||||||
const { clock, mode, groupExpectedEnd, actualGroupStart, currentDay, playback, phase } = useGroupTimerOverView();
|
const { clock, mode, groupExpectedEnd, actualGroupStart, currentDay, playback, phase } = useGroupTimerOverView();
|
||||||
const currentGroupId = useCurrentGroupId();
|
const currentGroupId = useCurrentGroupId();
|
||||||
const group = useEntry(currentGroupId) as OntimeGroup | null;
|
const group = useEntry(null, currentGroupId) as OntimeGroup | null;
|
||||||
|
|
||||||
const hasRunningTimer = phase !== TimerPhase.Pending && isPlaybackActive(playback);
|
const hasRunningTimer = phase !== TimerPhase.Pending && isPlaybackActive(playback);
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ function GroupTimes() {
|
|||||||
function FlagTimes() {
|
function FlagTimes() {
|
||||||
const { clock, mode, actualStart, plannedStart, playback, currentDay, phase } = useFlagTimerOverView();
|
const { clock, mode, actualStart, plannedStart, playback, currentDay, phase } = useFlagTimerOverView();
|
||||||
const { id, expectedStart } = useNextFlag();
|
const { id, expectedStart } = useNextFlag();
|
||||||
const entry = useEntry(id) as OntimeEvent | null;
|
const entry = useEntry(null, id) as OntimeEvent | null;
|
||||||
|
|
||||||
const hasRunningTimer = phase !== TimerPhase.Pending && isPlaybackActive(playback);
|
const hasRunningTimer = phase !== TimerPhase.Pending && isPlaybackActive(playback);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import style from './TitleOverview.module.scss';
|
|||||||
export default function TitleOverview() {
|
export default function TitleOverview() {
|
||||||
'use memo';
|
'use memo';
|
||||||
const { data: projectData } = useProjectData();
|
const { data: projectData } = useProjectData();
|
||||||
const { data: rundownData } = useRundownAuxData();
|
const { data: rundownData } = useRundownAuxData(null);
|
||||||
|
|
||||||
if (!projectData.title && !rundownData.title) {
|
if (!projectData.title && !rundownData.title) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function useBackstageData(): ViewData<BackstageData> {
|
|||||||
const isMirrored = useViewOptionsStore((state) => state.mirror);
|
const isMirrored = useViewOptionsStore((state) => state.mirror);
|
||||||
|
|
||||||
// HTTP API data
|
// HTTP API data
|
||||||
const { data: rundownData, status: rundownStatus } = useFlatRundown();
|
const { data: rundownData, status: rundownStatus } = useFlatRundown(null);
|
||||||
const { data: projectData, status: projectDataStatus } = useProjectData();
|
const { data: projectData, status: projectDataStatus } = useProjectData();
|
||||||
const { data: settings, status: settingsStatus } = useSettings();
|
const { data: settings, status: settingsStatus } = useSettings();
|
||||||
const { data: customFields, status: customFieldsStatus } = useCustomFields();
|
const { data: customFields, status: customFieldsStatus } = useCustomFields();
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildre
|
|||||||
[filter],
|
[filter],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: events } = usePartialRundown(filterCallback);
|
const { data: events } = usePartialRundown(null, filterCallback);
|
||||||
|
|
||||||
const [firstIndex, setFirstIndex] = useState(-1);
|
const [firstIndex, setFirstIndex] = useState(-1);
|
||||||
const [numPages, setNumPages] = useState(0);
|
const [numPages, setNumPages] = useState(0);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function useCountdownData(): ViewData<CountdownData> {
|
|||||||
const isMirrored = useViewOptionsStore((state) => state.mirror);
|
const isMirrored = useViewOptionsStore((state) => state.mirror);
|
||||||
|
|
||||||
// HTTP API data
|
// HTTP API data
|
||||||
const { data: rundownData, status: rundownStatus } = useFlatRundownWithMetadata();
|
const { data: rundownData, status: rundownStatus } = useFlatRundownWithMetadata(null);
|
||||||
const { data: projectData, status: projectDataStatus } = useProjectData();
|
const { data: projectData, status: projectDataStatus } = useProjectData();
|
||||||
const { data: settings, status: settingsStatus } = useSettings();
|
const { data: settings, status: settingsStatus } = useSettings();
|
||||||
const { data: customFields, status: customFieldsStatus } = useCustomFields();
|
const { data: customFields, status: customFieldsStatus } = useCustomFields();
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ function CuesheetTableWrapper() {
|
|||||||
cuesheetMode={cuesheetMode}
|
cuesheetMode={cuesheetMode}
|
||||||
tableRoot='cuesheet'
|
tableRoot='cuesheet'
|
||||||
setCuesheetMode={setCuesheetMode}
|
setCuesheetMode={setCuesheetMode}
|
||||||
isCurrentRundown={isLoadedRundown}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</CuesheetDnd>
|
</CuesheetDnd>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useTableNav } from '@table-nav/react';
|
import { useTableNav } from '@table-nav/react';
|
||||||
import { ColumnDef, Table, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
import { ColumnDef, Table, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||||
import { OntimeEntry, SupportedEntry, TimeField, isOntimeDelay, isOntimeGroup, isOntimeMilestone } from 'ontime-types';
|
import { OntimeEntry, SupportedEntry, TimeField, isOntimeDelay, isOntimeGroup, isOntimeMilestone } from 'ontime-types';
|
||||||
import { ComponentProps, ReactNode, memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
import { ComponentProps, memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
ContextProp,
|
ContextProp,
|
||||||
ItemProps,
|
ItemProps,
|
||||||
@@ -40,25 +40,17 @@ type CuesheetTableBaseProps = {
|
|||||||
type EditorCuesheetTableProps = CuesheetTableBaseProps & {
|
type EditorCuesheetTableProps = CuesheetTableBaseProps & {
|
||||||
tableRoot: 'editor';
|
tableRoot: 'editor';
|
||||||
setCuesheetMode?: undefined;
|
setCuesheetMode?: undefined;
|
||||||
isCurrentRundown?: undefined;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type ViewCuesheetTableProps = CuesheetTableBaseProps & {
|
type ViewCuesheetTableProps = CuesheetTableBaseProps & {
|
||||||
tableRoot: 'cuesheet';
|
tableRoot: 'cuesheet';
|
||||||
setCuesheetMode: (mode: AppMode) => void;
|
setCuesheetMode: (mode: AppMode) => void;
|
||||||
isCurrentRundown?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type CuesheetTableProps = EditorCuesheetTableProps | ViewCuesheetTableProps;
|
type CuesheetTableProps = EditorCuesheetTableProps | ViewCuesheetTableProps;
|
||||||
|
|
||||||
export default function CuesheetTable({
|
export default function CuesheetTable({ columns, cuesheetMode, tableRoot, setCuesheetMode }: CuesheetTableProps) {
|
||||||
columns,
|
const { flatRundown, status, loadedEventId } = useContextRundownTable();
|
||||||
cuesheetMode,
|
|
||||||
tableRoot,
|
|
||||||
setCuesheetMode,
|
|
||||||
isCurrentRundown,
|
|
||||||
}: CuesheetTableProps) {
|
|
||||||
const { flatRundown, status, selectedEventId } = source;
|
|
||||||
const { updateEntry, updateTimer, addEntry } = useEntryActionsContext();
|
const { updateEntry, updateTimer, addEntry } = useEntryActionsContext();
|
||||||
const canCreateEntries = useCuesheetPermissions((state) => state.canCreateEntries) && cuesheetMode === AppMode.Edit;
|
const canCreateEntries = useCuesheetPermissions((state) => state.canCreateEntries) && cuesheetMode === AppMode.Edit;
|
||||||
|
|
||||||
@@ -238,16 +230,9 @@ export default function CuesheetTable({
|
|||||||
handleResetResizing={resetColumnResizing}
|
handleResetResizing={resetColumnResizing}
|
||||||
handleResetReordering={resetColumnOrder}
|
handleResetReordering={resetColumnOrder}
|
||||||
handleClearToggles={setAllVisible}
|
handleClearToggles={setAllVisible}
|
||||||
modeControls={
|
appMode={cuesheetMode}
|
||||||
tableRoot === 'cuesheet'
|
tableRoot={tableRoot}
|
||||||
? {
|
setCuesheetMode={setCuesheetMode}
|
||||||
cuesheetMode,
|
|
||||||
setCuesheetMode,
|
|
||||||
isCurrentRundown,
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
showShare={tableRoot === 'cuesheet'}
|
|
||||||
/>
|
/>
|
||||||
<TableVirtuoso
|
<TableVirtuoso
|
||||||
ref={virtuosoRef}
|
ref={virtuosoRef}
|
||||||
|
|||||||
+21
-26
@@ -10,6 +10,7 @@ import Button from '../../../../common/components/buttons/Button';
|
|||||||
import Checkbox from '../../../../common/components/checkbox/Checkbox';
|
import Checkbox from '../../../../common/components/checkbox/Checkbox';
|
||||||
import * as Editor from '../../../../common/components/editor-utils/EditorUtils';
|
import * as Editor from '../../../../common/components/editor-utils/EditorUtils';
|
||||||
import PopoverContents from '../../../../common/components/popover/Popover';
|
import PopoverContents from '../../../../common/components/popover/Popover';
|
||||||
|
import { useRundownSelectionContext } from '../../../../common/context/RundownSelectionContext';
|
||||||
import type { ExtendedEntry } from '../../../../common/utils/rundownMetadata';
|
import type { ExtendedEntry } from '../../../../common/utils/rundownMetadata';
|
||||||
import { AppMode } from '../../../../ontimeConfig';
|
import { AppMode } from '../../../../ontimeConfig';
|
||||||
import { useCuesheetPermissions } from '../../useTablePermissions';
|
import { useCuesheetPermissions } from '../../useTablePermissions';
|
||||||
@@ -31,20 +32,15 @@ type TableHeaderOptionValues = Pick<
|
|||||||
'hideTableSeconds' | 'hideIndexColumn' | 'showDelayedTimes' | 'hideDelays'
|
'hideTableSeconds' | 'hideIndexColumn' | 'showDelayedTimes' | 'hideDelays'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type TableModeControls = {
|
|
||||||
cuesheetMode: AppMode;
|
|
||||||
setCuesheetMode: (mode: AppMode) => void;
|
|
||||||
isCurrentRundown?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface CuesheetTableHeaderToolbarProps {
|
interface CuesheetTableHeaderToolbarProps {
|
||||||
columns: Column<ExtendedEntry, unknown>[];
|
columns: Column<ExtendedEntry, unknown>[];
|
||||||
optionsStore: TableHeaderOptionsStore;
|
optionsStore: TableHeaderOptionsStore;
|
||||||
handleResetResizing: () => void;
|
handleResetResizing: () => void;
|
||||||
handleResetReordering: () => void;
|
handleResetReordering: () => void;
|
||||||
handleClearToggles: () => void;
|
handleClearToggles: () => void;
|
||||||
modeControls?: TableModeControls;
|
setCuesheetMode?: (mode: AppMode) => void;
|
||||||
showShare?: boolean;
|
appMode: AppMode;
|
||||||
|
tableRoot: 'editor' | 'cuesheet';
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CuesheetTableHeaderToolbar({
|
export default function CuesheetTableHeaderToolbar({
|
||||||
@@ -53,22 +49,22 @@ export default function CuesheetTableHeaderToolbar({
|
|||||||
handleResetResizing,
|
handleResetResizing,
|
||||||
handleResetReordering,
|
handleResetReordering,
|
||||||
handleClearToggles,
|
handleClearToggles,
|
||||||
modeControls,
|
setCuesheetMode,
|
||||||
showShare = false,
|
tableRoot,
|
||||||
|
appMode,
|
||||||
}: CuesheetTableHeaderToolbarProps) {
|
}: CuesheetTableHeaderToolbarProps) {
|
||||||
const canChangeMode = useCuesheetPermissions((state) => state.canChangeMode);
|
const canChangeMode = useCuesheetPermissions((state) => state.canChangeMode) && tableRoot === 'cuesheet';
|
||||||
const canShare = useCuesheetPermissions((state) => state.canShare);
|
const canShare = useCuesheetPermissions((state) => state.canShare) && tableRoot === 'cuesheet';
|
||||||
|
const { isLoadedRundown } = useRundownSelectionContext();
|
||||||
|
|
||||||
const toggleCuesheetMode = (mode: AppMode[]) => {
|
const toggleCuesheetMode = (mode: AppMode[]) => {
|
||||||
const newValue = mode.at(0);
|
const newValue = mode.at(0);
|
||||||
if (!newValue || !modeControls) return;
|
if (!newValue || !setCuesheetMode) return;
|
||||||
modeControls.setCuesheetMode(newValue);
|
setCuesheetMode(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isBackground = !(modeControls?.isCurrentRundown ?? true);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Toolbar.Root className={style.tableSettings} data-background-rundown={isBackground}>
|
<Toolbar.Root className={style.tableSettings} data-background-rundown={!isLoadedRundown}>
|
||||||
<ViewSettings optionsStore={optionsStore} />
|
<ViewSettings optionsStore={optionsStore} />
|
||||||
<ColumnSettings
|
<ColumnSettings
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@@ -76,15 +72,14 @@ export default function CuesheetTableHeaderToolbar({
|
|||||||
handleResetReordering={handleResetReordering}
|
handleResetReordering={handleResetReordering}
|
||||||
handleClearToggles={handleClearToggles}
|
handleClearToggles={handleClearToggles}
|
||||||
/>
|
/>
|
||||||
{modeControls && canChangeMode && (
|
<div className={style.apart}>
|
||||||
<div className={style.apart}>
|
<RundownSelect appMode={appMode} />
|
||||||
{/* {insertElement} */}
|
{canChangeMode && (
|
||||||
<RundownSelect cuesheetMode={modeControls.cuesheetMode} />
|
|
||||||
<ToggleGroup
|
<ToggleGroup
|
||||||
value={[modeControls.cuesheetMode]}
|
value={[appMode]}
|
||||||
onValueChange={toggleCuesheetMode}
|
onValueChange={toggleCuesheetMode}
|
||||||
className={style.group}
|
className={style.group}
|
||||||
disabled={!modeControls.isCurrentRundown}
|
disabled={!isLoadedRundown}
|
||||||
>
|
>
|
||||||
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>
|
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>
|
||||||
Run
|
Run
|
||||||
@@ -93,10 +88,10 @@ export default function CuesheetTableHeaderToolbar({
|
|||||||
Edit
|
Edit
|
||||||
</Toolbar.Button>
|
</Toolbar.Button>
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
{showShare && canShare && (
|
{canShare && (
|
||||||
<>
|
<>
|
||||||
<Editor.Separator orientation='vertical' />
|
<Editor.Separator orientation='vertical' />
|
||||||
<CuesheetShareModal />
|
<CuesheetShareModal />
|
||||||
|
|||||||
+3
-3
@@ -7,10 +7,10 @@ import styles from './RundownSelect.module.scss';
|
|||||||
const FOLLOW = '___null___';
|
const FOLLOW = '___null___';
|
||||||
|
|
||||||
interface RundownSelectProps {
|
interface RundownSelectProps {
|
||||||
cuesheetMode: AppMode;
|
appMode: AppMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RundownSelect({ cuesheetMode }: RundownSelectProps) {
|
export function RundownSelect({ appMode }: RundownSelectProps) {
|
||||||
'use memo';
|
'use memo';
|
||||||
const { selectRundownId, rundowns, loadedRundownId, selectedRundownId } = useRundownSelectionContext();
|
const { selectRundownId, rundowns, loadedRundownId, selectedRundownId } = useRundownSelectionContext();
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export function RundownSelect({ cuesheetMode }: RundownSelectProps) {
|
|||||||
if (value === FOLLOW) selectRundownId(null);
|
if (value === FOLLOW) selectRundownId(null);
|
||||||
else selectRundownId(value);
|
else selectRundownId(value);
|
||||||
}}
|
}}
|
||||||
disabled={cuesheetMode === AppMode.Run}
|
disabled={appMode === AppMode.Run}
|
||||||
fluid
|
fluid
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export interface TimelineData {
|
|||||||
|
|
||||||
export function useTimelineData(): ViewData<TimelineData> {
|
export function useTimelineData(): ViewData<TimelineData> {
|
||||||
// HTTP API data
|
// HTTP API data
|
||||||
const { data: rundownData, status: rundownStatus } = useFlatRundownWithMetadata();
|
const { data: rundownData, status: rundownStatus } = useFlatRundownWithMetadata(null);
|
||||||
const { data: projectData, status: projectDataStatus } = useProjectData();
|
const { data: projectData, status: projectDataStatus } = useProjectData();
|
||||||
const { data: settings, status: settingsStatus } = useSettings();
|
const { data: settings, status: settingsStatus } = useSettings();
|
||||||
const { data: customFields, status: customFieldsStatus } = useCustomFields();
|
const { data: customFields, status: customFieldsStatus } = useCustomFields();
|
||||||
|
|||||||
Reference in New Issue
Block a user