V2 rundown manager (#237)

* refactor: migrate eventlist > rundown
This commit is contained in:
Carlos Valente
2022-10-30 21:07:18 +01:00
committed by GitHub
parent a3f14182a4
commit c03ed07762
55 changed files with 487 additions and 489 deletions
@@ -27,7 +27,7 @@ export default function PlaybackTimer(props: PlaybackTimerProps) {
const finish = stringFromMillis(timerData.expectedFinish, true);
const isRolling = playback === 'roll';
const isWaiting = timerData.secondaryTimer !== null && timerData.secondaryTimer > 0 && timerData.current === null;
const disableButtons = selectedId == null || isRolling;
const disableButtons = selectedId === null || isRolling;
const isOvertime = timerData.current !== null && timerData.current < 0;
return (
+2 -2
View File
@@ -9,7 +9,7 @@ import MenuBar from '../menu/MenuBar';
import styles from './Editor.module.scss';
const EventList = lazy(() => import('features/editors/list/EventListExport'));
const Rundown = lazy(() => import('features/rundown/RundownExport'));
const TimerControl = lazy(() => import('features/control/playback/TimerControlExport'));
const MessageControl = lazy(() => import('features/control/message/MessageControlExport'));
const Info = lazy(() => import('features/info/InfoExport'));
@@ -51,7 +51,7 @@ export default function Editor() {
/>
</ErrorBoundary>
</Box>
<EventList />
<Rundown />
<MessageControl />
<TimerControl />
<Info />
@@ -14,14 +14,14 @@ import { stringFromMillis } from 'common/utils/time';
import { calculateDuration, validateEntry } from 'common/utils/timesManager';
import { useAtom } from 'jotai';
import useEventsList from '../../common/hooks-query/useEventsList';
import useRundown from '../../common/hooks-query/useRundown';
import style from './EventEditor.module.scss';
import CopyTag from '../../common/components/osc-tag/CopyTag';
export default function EventEditor() {
const [openId] = useAtom(editorEventId);
const { data } = useEventsList();
const { data } = useRundown();
const { emitWarning, emitError } = useContext(LoggingContext);
const { updateEvent } = useEventAction();
const [event, setEvent] = useState(null);
+2 -2
View File
@@ -6,7 +6,7 @@ import { FiMinimize } from '@react-icons/all-files/fi/FiMinimize';
import { FiSave } from '@react-icons/all-files/fi/FiSave';
import { FiUpload } from '@react-icons/all-files/fi/FiUpload';
import { IoSettingsOutline } from '@react-icons/all-files/io5/IoSettingsOutline';
import { downloadEvents } from 'common/api/ontimeApi';
import { downloadRundown } from 'common/api/ontimeApi';
import QuitIconBtn from '../../common/components/buttons/QuitIconBtn';
import TooltipActionBtn from '../../common/components/buttons/TooltipActionBtn';
@@ -136,7 +136,7 @@ export default function MenuBar(props: MenuBarProps) {
<TooltipActionBtn
{...buttonStyle}
icon={<FiSave />}
clickHandler={downloadEvents}
clickHandler={downloadRundown}
tooltip='Export event list'
aria-label=''
/>
@@ -18,14 +18,14 @@ import { CursorContext } from 'common/context/CursorContext';
import { useEventAction } from '../../common/hooks/useEventAction';
import style from './EventListMenu.module.scss';
import style from './RundownMenu.module.scss';
const menuStyle = {
color: '#000000',
backgroundColor: 'rgba(255,255,255,1)',
};
const EventListMenu = () => {
const RundownMenu = () => {
const { isCursorLocked, toggleCursorLocked } = useContext(CursorContext);
const { addEvent, deleteAllEvents } = useEventAction();
@@ -91,4 +91,4 @@ const EventListMenu = () => {
);
};
export default memo(EventListMenu);
export default memo(RundownMenu);
@@ -9,20 +9,20 @@ import {
import Empty from 'common/components/state/Empty';
import { CursorContext } from 'common/context/CursorContext';
import { useEventAction } from 'common/hooks/useEventAction';
import { useEventListProvider } from 'common/hooks/useSocketProvider';
import { useRundownProvider } from 'common/hooks/useSocketProvider';
import { duplicateEvent } from 'common/utils/eventsManager';
import { useAtomValue } from 'jotai';
import PropTypes from 'prop-types';
import useSubscription from '../../../common/hooks/useSubscription';
import QuickAddBlock from '../quick-add-block/QuickAddBlock';
import useSubscription from '../../common/hooks/useSubscription';
import EventListItem from './EventListItem';
import QuickAddBlock from './quick-add-block/QuickAddBlock';
import RundownEntry from './RundownEntry';
import style from './List.module.scss';
import style from './Rundown.module.scss';
export default function EventList(props) {
const { events } = props;
export default function Rundown(props) {
const { entries } = props;
const { cursor, moveCursorUp, moveCursorDown, moveCursorTo, isCursorLocked } =
useContext(CursorContext);
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
@@ -30,7 +30,7 @@ export default function EventList(props) {
const { addEvent, reorderEvent } = useEventAction();
const cursorRef = createRef();
const showQuickEntry = useAtomValue(showQuickEntryAtom);
const data = useEventListProvider();
const data = useRundownProvider();
const [selectedId] = useSubscription('selected-id', null);
const [nextId] = useSubscription('next-id', null);
@@ -39,8 +39,8 @@ export default function EventList(props) {
if (cursor === -1) {
addEvent({ type: type });
} else {
const previousEvent = events?.[cursor];
const nextEvent = events?.[cursor + 1];
const previousEvent = entries?.[cursor];
const nextEvent = entries?.[cursor + 1];
// prevent adding two non-event blocks consecutively
const isPreviousDifferent = previousEvent?.type !== type;
@@ -64,7 +64,7 @@ export default function EventList(props) {
}
}
},
[addEvent, defaultPublic, events, startTimeIsLastEnd],
[addEvent, defaultPublic, entries, startTimeIsLastEnd],
);
// Handle keyboard shortcuts
@@ -77,7 +77,7 @@ export default function EventList(props) {
if (e.altKey && (!e.ctrlKey || !e.shiftKey)) {
// Arrow down
if (e.keyCode === 40) {
if (cursor < events.length - 1) moveCursorDown();
if (cursor < entries.length - 1) moveCursorDown();
}
// Arrow up
if (e.keyCode === 38) {
@@ -103,21 +103,21 @@ export default function EventList(props) {
}
}
},
[cursor, events.length, insertAtCursor, moveCursorDown, moveCursorUp],
[cursor, entries.length, insertAtCursor, moveCursorDown, moveCursorUp],
);
useEffect(() => {
// attach the event listener
document.addEventListener('keydown', handleKeyPress);
if (cursor > events.length - 1) moveCursorTo(events.length - 1);
if (events.length > 0 && cursor === -1) moveCursorTo(0);
if (cursor > entries.length - 1) moveCursorTo(entries.length - 1);
if (entries.length > 0 && cursor === -1) moveCursorTo(0);
// remove the event listener
return () => {
document.removeEventListener('keydown', handleKeyPress);
};
}, [handleKeyPress, cursor, events, moveCursorTo]);
}, [handleKeyPress, cursor, entries, moveCursorTo]);
// when cursor moves, view should follow
useEffect(() => {
@@ -138,7 +138,7 @@ export default function EventList(props) {
// move cursor
let gotoIndex = -1;
let found = false;
for (const e of events) {
for (const e of entries) {
gotoIndex++;
if (e.id === data.selectedEventId) {
found = true;
@@ -166,10 +166,10 @@ export default function EventList(props) {
[reorderEvent],
);
if (events.length < 1) {
if (entries.length < 1) {
return (
<div className={style.alignCenter}>
<Empty text='No Events' style={{ marginTop: '7vh' }} />
<Empty text='No data yet' style={{ marginTop: '7vh' }} />
<Button
onClick={() => insertAtCursor('event', cursor)}
variant='solid'
@@ -192,7 +192,7 @@ export default function EventList(props) {
<Droppable droppableId='eventlist'>
{(provided) => (
<div className={style.list} {...provided.droppableProps} ref={provided.innerRef}>
{events.map((e, index) => {
{entries.map((e, index) => {
if (index === 0) {
cumulativeDelay = 0;
eventIndex = -1;
@@ -207,7 +207,7 @@ export default function EventList(props) {
thisEnd = e.timeEnd;
previousEventId = e.id;
}
const isLast = index === events.length - 1;
const isLast = index === entries.length - 1;
return (
<div
key={e.id}
@@ -218,7 +218,7 @@ export default function EventList(props) {
ref={cursor === index ? cursorRef : undefined}
className={cursor === index ? style.cursor : ''}
>
<EventListItem
<RundownEntry
type={e.type}
index={index}
eventIndex={eventIndex}
@@ -251,6 +251,6 @@ export default function EventList(props) {
);
}
EventList.propTypes = {
events: PropTypes.array,
Rundown.propTypes = {
entries: PropTypes.array,
};
@@ -1,5 +1,5 @@
@use '../../../theme/main' as *;
@use '../../../theme/mixins' as *;
@use '../../theme/main' as *;
@use '../../theme/mixins' as *;
.eventContainer {
margin-top: 1em;
@@ -6,16 +6,17 @@ import {
} from 'common/atoms/LocalEventSettings';
import { LoggingContext } from 'common/context/LoggingContext';
import { useEventAction } from 'common/hooks/useEventAction';
import { OntimeEvent, OntimeEventEntry } from 'common/models/EventTypes';
import { OntimeEvent, OntimeRundownEntry } from 'common/models/EventTypes';
import { Playstate } from 'common/models/OntimeTypes';
import { duplicateEvent } from 'common/utils/eventsManager';
import { calculateDuration } from 'common/utils/timesManager';
import { useAtom, useAtomValue } from 'jotai';
import { CursorContext } from '../../../common/context/CursorContext';
import BlockBlock from '../block-block/BlockBlock';
import DelayBlock from '../delay-block/DelayBlock';
import EventBlock from '../event-block/EventBlock';
import { CursorContext } from '../../common/context/CursorContext';
import BlockBlock from './block-block/BlockBlock';
import DelayBlock from './delay-block/DelayBlock';
import EventBlock from './event-block/EventBlock';
export type EventItemActions =
'set-cursor'
@@ -26,10 +27,10 @@ export type EventItemActions =
| 'clone'
| 'update'
interface EventListItemProps {
interface RundownEntryProps {
index: number;
eventIndex: number;
data: OntimeEventEntry;
data: OntimeRundownEntry;
selected: boolean;
next: boolean;
delay: number;
@@ -37,7 +38,7 @@ interface EventListItemProps {
playback: Playstate;
}
export default function EventListItem(props: EventListItemProps) {
export default function RundownEntry(props: RundownEntryProps) {
const { index, eventIndex, data, selected, next, delay, previousEnd, playback } = props;
const { emitError } = useContext(LoggingContext);
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
@@ -4,20 +4,20 @@ import ErrorBoundary from 'common/components/errorBoundary/ErrorBoundary';
import { CursorProvider } from 'common/context/CursorContext';
import { handleLinks } from 'common/utils/linkUtils';
import EventListWrapper from './EventListWrapper';
import RundownWrapper from './RundownWrapper';
import style from '../Editor.module.scss';
import style from '../editors/Editor.module.scss';
export default function EventListExport() {
export default function RundownExport() {
return (
<CursorProvider>
<Box className={style.editor} data-testid="panel-event-list">
<Box className={style.editor} data-testid='panel-rundown'>
<FiArrowUpRight
className={style.corner}
onClick={(event) => handleLinks(event, 'eventlist')}
onClick={(event) => handleLinks(event, 'rundown')}
/>
<ErrorBoundary>
<EventListWrapper />
<RundownWrapper />
</ErrorBoundary>
</Box>
</CursorProvider>
@@ -1,17 +1,17 @@
import { useContext, useEffect } from 'react';
import Empty from 'common/components/state/Empty';
import { LoggingContext } from 'common/context/LoggingContext';
import EventListMenu from 'features/menu/EventListMenu';
import RundownMenu from 'features/menu/RundownMenu';
import useEventsList from '../../../common/hooks-query/useEventsList';
import useRundown from '../../common/hooks-query/useRundown';
import EventList from './EventList';
import Rundown from './Rundown';
import styles from '../Editor.module.scss';
import styles from '../editors/Editor.module.scss';
export default function EventListWrapper() {
export default function RundownWrapper() {
const { emitError } = useContext(LoggingContext);
const { data, status, isError } = useEventsList();
const { data, status, isError } = useRundown();
useEffect(() => {
if (isError) {
@@ -21,10 +21,10 @@ export default function EventListWrapper() {
return (
<>
<EventListMenu />
<RundownMenu />
<div className={styles.content}>
{status === 'success' && data ? (
<EventList events={data} />
<Rundown entries={data} />
) : (
<Empty text='Connecting to server' />
)}
@@ -20,7 +20,7 @@ import { useAtom } from 'jotai';
import { useEventProvider } from '../../../common/hooks/useSocketProvider';
import { Playstate } from '../../../common/models/OntimeTypes';
import { tooltipDelayMid } from '../../../ontimeConfig';
import { EventItemActions } from '../list/EventListItem';
import { EventItemActions } from '../RundownEntry';
import EventBlockActionMenu from './composite/EventBlockActionMenu';
import EventBlockTimers from './composite/EventBlockTimers';
+2 -2
View File
@@ -4,7 +4,7 @@ import { requestPatchEvent } from '../../common/api/eventsApi';
import { TableSettingsContext } from '../../common/context/TableSettingsContext';
import useMutateEvents from '../../common/hooks/useMutateEvents';
import { useCuesheetProvider } from '../../common/hooks/useSocketProvider';
import useEventsList from '../../common/hooks-query/useEventsList';
import useRundown from '../../common/hooks-query/useRundown';
import useUserFields from '../../common/hooks-query/useUserFields';
import OntimeTable from './OntimeTable';
@@ -14,7 +14,7 @@ import { makeCSV, makeTable } from './utils';
import style from './Table.module.scss';
export default function TableWrapper() {
const { data: events } = useEventsList();
const { data: events } = useRundown();
const { data: userFields } = useUserFields();
const mutation = useMutateEvents(requestPatchEvent);
const { theme } = useContext(TableSettingsContext);
+2 -2
View File
@@ -5,12 +5,12 @@ import { useSocket } from '../../common/context/socketContext';
import { useMessageControlProvider } from '../../common/hooks/useSocketProvider';
import useSubscription from '../../common/hooks/useSubscription';
import useEvent from '../../common/hooks-query/useEvent';
import useEventsList from '../../common/hooks-query/useEventsList';
import useRundown from '../../common/hooks-query/useRundown';
import useViewSettings from '../../common/hooks-query/useViewSettings';
const withSocket = (Component) => {
return (props) => {
const { data: eventsData } = useEventsList();
const { data: eventsData } = useRundown();
const { data: genData } = useEvent();
const { data: viewSettings } = useViewSettings();
const { data: messages } = useMessageControlProvider();