mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 22:49:18 +00:00
refactor: improve editor and cuesheet headers
- consistent behaviour for app mode - improve navigation
This commit is contained in:
committed by
Carlos Valente
parent
79bcc179ba
commit
6facd6a666
@@ -35,9 +35,9 @@ import {
|
||||
import { type EventOptions, useEntryActions } from '../../common/hooks/useEntryAction';
|
||||
import useFollowComponent from '../../common/hooks/useFollowComponent';
|
||||
import { useRundownEditor } from '../../common/hooks/useSocket';
|
||||
import { AppMode, useAppMode } from '../../common/stores/appModeStore';
|
||||
import { useEntryCopy } from '../../common/stores/entryCopyStore';
|
||||
import { cloneEvent } from '../../common/utils/clone';
|
||||
import { AppMode, sessionKeys } from '../../ontimeConfig';
|
||||
|
||||
import QuickAddBlock from './quick-add-block/QuickAddBlock';
|
||||
import BlockEnd from './rundown-block/BlockEnd';
|
||||
@@ -70,12 +70,15 @@ export default function Rundown({ data }: RundownProps) {
|
||||
const { entryCopyId, setEntryCopyId } = useEntryCopy();
|
||||
|
||||
// cursor
|
||||
const { mode: appMode } = useAppMode();
|
||||
const [editorMode] = useSessionStorage<AppMode>({
|
||||
key: sessionKeys.editorMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
const { clearSelectedEvents, setSelectedEvents, cursor } = useEventSelection();
|
||||
|
||||
const cursorRef = useRef<HTMLDivElement | null>(null);
|
||||
const scrollRef = useRef<HTMLDivElement | null>(null);
|
||||
useFollowComponent({ followRef: cursorRef, scrollRef, doFollow: appMode === AppMode.Run });
|
||||
useFollowComponent({ followRef: cursorRef, scrollRef, doFollow: editorMode === AppMode.Run });
|
||||
|
||||
// DND KIT
|
||||
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }));
|
||||
@@ -283,12 +286,12 @@ export default function Rundown({ data }: RundownProps) {
|
||||
|
||||
// in run mode, we follow selection
|
||||
useEffect(() => {
|
||||
if (appMode !== AppMode.Run || !featureData?.selectedEventId) {
|
||||
if (editorMode !== AppMode.Run || !featureData?.selectedEventId) {
|
||||
return;
|
||||
}
|
||||
const index = order.findIndex((id) => id === featureData.selectedEventId);
|
||||
setSelectedEvents({ id: featureData.selectedEventId, selectMode: 'click', index });
|
||||
}, [appMode, featureData.selectedEventId, order, setSelectedEvents]);
|
||||
}, [editorMode, featureData.selectedEventId, order, setSelectedEvents]);
|
||||
|
||||
/**
|
||||
* On drag end, we reorder the events
|
||||
@@ -359,7 +362,7 @@ export default function Rundown({ data }: RundownProps) {
|
||||
}
|
||||
|
||||
// 1. gather presentation options
|
||||
const isEditMode = appMode === AppMode.Edit;
|
||||
const isEditMode = editorMode === AppMode.Edit;
|
||||
|
||||
// 2. initialise rundown metadata
|
||||
const { metadata, process } = makeRundownMetadata(featureData?.selectedEventId);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { memo } from 'react';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
|
||||
import { ContextMenu } from '../../common/components/context-menu/ContextMenu';
|
||||
import { Corner } from '../../common/components/editor-utils/EditorUtils';
|
||||
@@ -6,9 +7,9 @@ import ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary'
|
||||
import ViewNavigationMenu from '../../common/components/navigation-menu/ViewNavigationMenu';
|
||||
import ProtectRoute from '../../common/components/protect-route/ProtectRoute';
|
||||
import { useIsSmallDevice } from '../../common/hooks/useIsSmallDevice';
|
||||
import { useAppMode } from '../../common/stores/appModeStore';
|
||||
import { handleLinks } from '../../common/utils/linkUtils';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import { AppMode, sessionKeys } from '../../ontimeConfig';
|
||||
|
||||
import RundownEntryEditor from './entry-editor/RundownEntryEditor';
|
||||
import FinderPlacement from './placements/FinderPlacement';
|
||||
@@ -20,7 +21,10 @@ export default memo(RundownExport);
|
||||
|
||||
function RundownExport() {
|
||||
const isExtracted = window.location.pathname.includes('/rundown');
|
||||
const appMode = useAppMode((state) => state.mode);
|
||||
const [editorMode] = useSessionStorage({
|
||||
key: sessionKeys.editorMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
const isSmallDevice = useIsSmallDevice();
|
||||
|
||||
if (isSmallDevice && isExtracted) {
|
||||
@@ -45,7 +49,7 @@ function RundownExport() {
|
||||
);
|
||||
}
|
||||
|
||||
const hideSideBar = isExtracted && appMode === 'run';
|
||||
const hideSideBar = isExtracted && editorMode === 'run';
|
||||
|
||||
return (
|
||||
<ProtectRoute permission='editor'>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { memo, useRef } from 'react';
|
||||
import { IoAdd } from 'react-icons/io5';
|
||||
import { Toolbar } from '@base-ui-components/react/toolbar';
|
||||
import { MaybeString, SupportedEntry } from 'ontime-types';
|
||||
|
||||
import Button from '../../../common/components/buttons/Button';
|
||||
@@ -64,21 +65,23 @@ function QuickAddBlock({ previousEventId, parentBlock, backgroundColor }: QuickA
|
||||
const blockColour = backgroundColor === '' ? '#9d9d9d' : backgroundColor;
|
||||
|
||||
return (
|
||||
<div className={style.quickAdd} style={blockColour ? { '--user-bg': blockColour } : {}}>
|
||||
<Button onClick={addEvent} size='small' variant='subtle-white'>
|
||||
<Toolbar.Root className={style.quickAdd} style={blockColour ? { '--user-bg': blockColour } : {}}>
|
||||
<Toolbar.Button render={<Button size='small' variant='subtle-white' />} onClick={addEvent}>
|
||||
<IoAdd />
|
||||
Event
|
||||
</Button>
|
||||
<Button onClick={addDelay} size='small' variant='subtle-white'>
|
||||
</Toolbar.Button>
|
||||
|
||||
<Toolbar.Button render={<Button size='small' variant='subtle-white' />} onClick={addDelay}>
|
||||
<IoAdd />
|
||||
Delay
|
||||
</Button>
|
||||
</Toolbar.Button>
|
||||
|
||||
{parentBlock === null && (
|
||||
<Button onClick={addBlock} size='small' variant='subtle-white'>
|
||||
<Toolbar.Button render={<Button size='small' variant='subtle-white' />} onClick={addBlock}>
|
||||
<IoAdd />
|
||||
Block
|
||||
</Button>
|
||||
</Toolbar.Button>
|
||||
)}
|
||||
</div>
|
||||
</Toolbar.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** styles should match CuesheetTableSettings.module.scss */
|
||||
.group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -19,7 +20,8 @@
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.button {
|
||||
/** styles should match CuesheetTableSettings.module.scss */
|
||||
.radioButton {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -34,6 +36,7 @@
|
||||
|
||||
&:focus-visible {
|
||||
background: transparent;
|
||||
outline: 1px solid $blue-500;
|
||||
}
|
||||
|
||||
&:hover:not(:disabled):not(:active) {
|
||||
|
||||
@@ -2,11 +2,12 @@ import { memo } from 'react';
|
||||
import { Toggle } from '@base-ui-components/react/toggle';
|
||||
import { ToggleGroup } from '@base-ui-components/react/toggle-group';
|
||||
import { Toolbar } from '@base-ui-components/react/toolbar';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
import { OffsetMode } from 'ontime-types';
|
||||
|
||||
import * as Editor from '../../../common/components/editor-utils/EditorUtils';
|
||||
import { setOffsetMode, useOffsetMode } from '../../../common/hooks/useSocket';
|
||||
import { AppMode, useAppMode } from '../../../common/stores/appModeStore';
|
||||
import { AppMode, sessionKeys } from '../../../ontimeConfig';
|
||||
|
||||
import RundownMenu from './RundownMenu';
|
||||
|
||||
@@ -14,8 +15,7 @@ import style from './RundownHeader.module.scss';
|
||||
|
||||
export default memo(RundownHeader);
|
||||
function RundownHeader() {
|
||||
const appMode = useAppMode((state) => state.mode);
|
||||
const setAppMode = useAppMode((state) => state.setMode);
|
||||
const [editorMode, setEditorMode] = useSessionStorage({ key: sessionKeys.editorMode, defaultValue: AppMode.Edit });
|
||||
|
||||
const { offsetMode } = useOffsetMode();
|
||||
|
||||
@@ -23,7 +23,7 @@ function RundownHeader() {
|
||||
// we need to stop user from deselecting a mode
|
||||
const newValue = mode.at(0);
|
||||
if (!newValue) return;
|
||||
setAppMode(newValue);
|
||||
setEditorMode(newValue);
|
||||
};
|
||||
|
||||
const toggleOffsetMode = (mode: OffsetMode[]) => {
|
||||
@@ -35,11 +35,11 @@ function RundownHeader() {
|
||||
|
||||
return (
|
||||
<Toolbar.Root className={style.header}>
|
||||
<ToggleGroup value={[appMode]} onValueChange={toggleAppMode} className={style.group}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.button}>
|
||||
<ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>
|
||||
Run
|
||||
</Toolbar.Button>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.radioButton}>
|
||||
Edit
|
||||
</Toolbar.Button>
|
||||
</ToggleGroup>
|
||||
@@ -47,10 +47,10 @@ function RundownHeader() {
|
||||
<Editor.Separator className={style.separator} />
|
||||
|
||||
<ToggleGroup value={[offsetMode]} onValueChange={toggleOffsetMode} className={style.group}>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.radioButton}>
|
||||
Absolute
|
||||
</Toolbar.Button>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.radioButton}>
|
||||
Relative
|
||||
</Toolbar.Button>
|
||||
</ToggleGroup>
|
||||
|
||||
@@ -2,18 +2,21 @@ import { memo } from 'react';
|
||||
import { Toggle } from '@base-ui-components/react/toggle';
|
||||
import { ToggleGroup } from '@base-ui-components/react/toggle-group';
|
||||
import { Toolbar } from '@base-ui-components/react/toolbar';
|
||||
import { useSessionStorage } from '@mantine/hooks';
|
||||
import { OffsetMode } from 'ontime-types';
|
||||
|
||||
import * as Editor from '../../../common/components/editor-utils/EditorUtils';
|
||||
import { setOffsetMode, useOffsetMode } from '../../../common/hooks/useSocket';
|
||||
import { AppMode, useAppMode } from '../../../common/stores/appModeStore';
|
||||
import { AppMode, sessionKeys } from '../../../ontimeConfig';
|
||||
|
||||
import style from './RundownHeader.module.scss';
|
||||
|
||||
export default memo(RundownHeader);
|
||||
function RundownHeader() {
|
||||
const appMode = useAppMode((state) => state.mode);
|
||||
const setAppMode = useAppMode((state) => state.setMode);
|
||||
const [editorMode, setEditorMode] = useSessionStorage<AppMode>({
|
||||
key: sessionKeys.editorMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
|
||||
const { offsetMode } = useOffsetMode();
|
||||
|
||||
@@ -21,7 +24,7 @@ function RundownHeader() {
|
||||
// we need to stop user from deselecting a mode
|
||||
const newValue = mode.at(0);
|
||||
if (!newValue) return;
|
||||
setAppMode(newValue);
|
||||
setEditorMode(newValue);
|
||||
};
|
||||
|
||||
const toggleOffsetMode = (mode: OffsetMode[]) => {
|
||||
@@ -33,7 +36,7 @@ function RundownHeader() {
|
||||
|
||||
return (
|
||||
<Toolbar.Root className={style.header}>
|
||||
<ToggleGroup value={[appMode]} onValueChange={toggleAppMode} className={style.group}>
|
||||
<ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.button}>
|
||||
Run
|
||||
</Toolbar.Button>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { memo, useCallback } from 'react';
|
||||
import { IoTrash } from 'react-icons/io5';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { Toolbar } from '@base-ui-components/react/toolbar';
|
||||
import { useDisclosure, useSessionStorage } from '@mantine/hooks';
|
||||
|
||||
import Button from '../../../common/components/buttons/Button';
|
||||
import Dialog from '../../../common/components/dialog/Dialog';
|
||||
import { useEntryActions } from '../../../common/hooks/useEntryAction';
|
||||
import { AppMode, useAppMode } from '../../../common/stores/appModeStore';
|
||||
import { AppMode, sessionKeys } from '../../../ontimeConfig';
|
||||
import { useEventSelection } from '../useEventSelection';
|
||||
|
||||
import style from './RundownHeader.module.scss';
|
||||
@@ -15,7 +16,10 @@ function RundownMenu() {
|
||||
const [isOpen, handlers] = useDisclosure();
|
||||
|
||||
const clearSelectedEvents = useEventSelection((state) => state.clearSelectedEvents);
|
||||
const appMode = useAppMode((state) => state.mode);
|
||||
const [editorMode] = useSessionStorage({
|
||||
key: sessionKeys.cuesheetMode,
|
||||
defaultValue: AppMode.Edit,
|
||||
});
|
||||
const { deleteAllEntries } = useEntryActions();
|
||||
|
||||
const deleteAll = useCallback(() => {
|
||||
@@ -26,15 +30,15 @@ function RundownMenu() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant='subtle-destructive'
|
||||
<Toolbar.Button
|
||||
render={<Button variant='subtle-destructive' />}
|
||||
onClick={handlers.open}
|
||||
disabled={editorMode === AppMode.Run}
|
||||
className={style.apart}
|
||||
onClick={() => handlers.open()}
|
||||
disabled={appMode === AppMode.Run}
|
||||
>
|
||||
<IoTrash />
|
||||
Clear all
|
||||
</Button>
|
||||
</Toolbar.Button>
|
||||
<Dialog
|
||||
isOpen={isOpen}
|
||||
onClose={handlers.close}
|
||||
@@ -48,7 +52,7 @@ function RundownMenu() {
|
||||
}
|
||||
footerElements={
|
||||
<>
|
||||
<Button size='large' onClick={handlers.close}>
|
||||
<Button variant='ghosted-white' size='large' onClick={handlers.close}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant='destructive' size='large' onClick={deleteAll}>
|
||||
|
||||
Reference in New Issue
Block a user