refactor: show menu only if enabled

This commit is contained in:
Carlos Valente
2025-02-17 15:34:00 +01:00
committed by Carlos Valente
parent 4cc138e3c0
commit 2c8b6180d7
4 changed files with 90 additions and 65 deletions
@@ -55,6 +55,17 @@ export const useEventAction = () => {
defaultEndAction, defaultEndAction,
} = useEditorSettings(); } = useEditorSettings();
const getEventById = useCallback(
(eventId: string) => {
const cachedRundown = queryClient.getQueryData<RundownCached>(RUNDOWN);
if (!cachedRundown?.rundown) {
return;
}
return cachedRundown.rundown[eventId];
},
[queryClient],
);
/** /**
* Calls mutation to add new event * Calls mutation to add new event
* @private * @private
@@ -615,6 +626,7 @@ export const useEventAction = () => {
batchUpdateEvents, batchUpdateEvents,
deleteEvent, deleteEvent,
deleteAllEvents, deleteAllEvents,
getEventById,
reorderEvent, reorderEvent,
swapEvents, swapEvents,
updateEvent, updateEvent,
@@ -1,5 +1,4 @@
import { useRef } from 'react'; import { useRef } from 'react';
import { Menu } from '@chakra-ui/react';
import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
import Color from 'color'; import Color from 'color';
import { import {
@@ -23,7 +22,6 @@ import BlockRow from './cuesheet-table-elements/BlockRow';
import CuesheetHeader from './cuesheet-table-elements/CuesheetHeader'; import CuesheetHeader from './cuesheet-table-elements/CuesheetHeader';
import DelayRow from './cuesheet-table-elements/DelayRow'; import DelayRow from './cuesheet-table-elements/DelayRow';
import EventRow from './cuesheet-table-elements/EventRow'; import EventRow from './cuesheet-table-elements/EventRow';
import CuesheetTableMenu from './cuesheet-table-menu/CuesheetTableMenu';
import CuesheetTableSettings from './cuesheet-table-settings/CuesheetTableSettings'; import CuesheetTableSettings from './cuesheet-table-settings/CuesheetTableSettings';
import useColumnManager from './useColumnManager'; import useColumnManager from './useColumnManager';
@@ -165,24 +163,25 @@ export default function CuesheetTable(props: CuesheetTableProps) {
} }
return ( return (
<Menu key={key} variant='ontime-on-dark' size='sm' isLazy> <EventRow
<EventRow key={key}
eventIndex={eventIndex} eventId={entry.id}
isPast={isPast} eventIndex={eventIndex}
selectedRef={isSelected ? selectedRef : undefined} rowIndex={index}
skip={entry.skip} isPast={isPast}
colour={entry.colour} selectedRef={isSelected ? selectedRef : undefined}
> skip={entry.skip}
{row.getVisibleCells().map((cell) => { colour={entry.colour}
return ( showModal={showModal}
<td key={cell.id} style={{ width: cell.column.getSize(), backgroundColor: rowBgColour }}> >
{flexRender(cell.column.columnDef.cell, cell.getContext())} {row.getVisibleCells().map((cell) => {
</td> return (
); <td key={cell.id} style={{ width: cell.column.getSize(), backgroundColor: rowBgColour }}>
})} {flexRender(cell.column.columnDef.cell, cell.getContext())}
</EventRow> </td>
<CuesheetTableMenu event={entry} entryIndex={index} showModal={showModal} /> );
</Menu> })}
</EventRow>
); );
} }
@@ -1,23 +1,27 @@
import { memo, MutableRefObject, PropsWithChildren, useLayoutEffect, useRef, useState } from 'react'; import { memo, MutableRefObject, PropsWithChildren, useLayoutEffect, useRef, useState } from 'react';
import { IconButton, MenuButton } from '@chakra-ui/react'; import { IconButton, Menu, MenuButton } from '@chakra-ui/react';
import { IoEllipsisHorizontal } from '@react-icons/all-files/io5/IoEllipsisHorizontal'; import { IoEllipsisHorizontal } from '@react-icons/all-files/io5/IoEllipsisHorizontal';
import Color from 'color'; import Color from 'color';
import { cx, getAccessibleColour } from '../../../../common/utils/styleUtils'; import { cx, getAccessibleColour } from '../../../../common/utils/styleUtils';
import { useCuesheetOptions } from '../../cuesheet.options'; import { useCuesheetOptions } from '../../cuesheet.options';
import CuesheetTableMenu from '../cuesheet-table-menu/CuesheetTableMenu';
import style from '../CuesheetTable.module.scss'; import style from '../CuesheetTable.module.scss';
interface EventRowProps { interface EventRowProps {
eventId: string;
eventIndex: number; eventIndex: number;
rowIndex: number;
isPast?: boolean; isPast?: boolean;
selectedRef?: MutableRefObject<HTMLTableRowElement | null>; selectedRef?: MutableRefObject<HTMLTableRowElement | null>;
skip?: boolean; skip?: boolean;
colour?: string; colour?: string;
showModal: (eventId: string) => void;
} }
function EventRow(props: PropsWithChildren<EventRowProps>) { function EventRow(props: PropsWithChildren<EventRowProps>) {
const { children, eventIndex, isPast, selectedRef, skip, colour } = props; const { children, eventId, eventIndex, rowIndex, isPast, selectedRef, skip, colour, showModal } = props;
const { hideIndexColumn, showActionMenu } = useCuesheetOptions(); const { hideIndexColumn, showActionMenu } = useCuesheetOptions();
const ownRef = useRef<HTMLTableRowElement>(null); const ownRef = useRef<HTMLTableRowElement>(null);
const [isVisible, setIsVisible] = useState(false); const [isVisible, setIsVisible] = useState(false);
@@ -60,13 +64,16 @@ function EventRow(props: PropsWithChildren<EventRowProps>) {
> >
{showActionMenu && ( {showActionMenu && (
<td className={style.actionColumn}> <td className={style.actionColumn}>
<MenuButton <Menu variant='ontime-on-dark' size='sm' isLazy>
as={IconButton} <MenuButton
size='sm' as={IconButton}
aria-label='Options' size='sm'
icon={<IoEllipsisHorizontal />} aria-label='Options'
variant='ontime-subtle' icon={<IoEllipsisHorizontal />}
/> variant='ontime-subtle'
/>
<CuesheetTableMenu eventId={eventId} entryIndex={rowIndex} showModal={showModal} />
</Menu>
</td> </td>
)} )}
{!hideIndexColumn && ( {!hideIndexColumn && (
@@ -1,63 +1,70 @@
import { MenuDivider, MenuItem, MenuList } from '@chakra-ui/react'; import { MenuDivider, MenuItem, MenuList, Portal } from '@chakra-ui/react';
import { IoAdd } from '@react-icons/all-files/io5/IoAdd'; import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
import { IoArrowDown } from '@react-icons/all-files/io5/IoArrowDown'; import { IoArrowDown } from '@react-icons/all-files/io5/IoArrowDown';
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp'; import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp';
import { IoDuplicateOutline } from '@react-icons/all-files/io5/IoDuplicateOutline'; import { IoDuplicateOutline } from '@react-icons/all-files/io5/IoDuplicateOutline';
import { IoOptions } from '@react-icons/all-files/io5/IoOptions'; import { IoOptions } from '@react-icons/all-files/io5/IoOptions';
import { IoTrash } from '@react-icons/all-files/io5/IoTrash'; import { IoTrash } from '@react-icons/all-files/io5/IoTrash';
import { OntimeEvent, SupportedEvent } from 'ontime-types'; import { isOntimeEvent, SupportedEvent } from 'ontime-types';
import { useEventAction } from '../../../../common/hooks/useEventAction'; import { useEventAction } from '../../../../common/hooks/useEventAction';
import { cloneEvent } from '../../../../common/utils/eventsManager'; import { cloneEvent } from '../../../../common/utils/eventsManager';
interface CuesheetTableMenuProps { interface CuesheetTableMenuProps {
event: OntimeEvent; eventId: string;
entryIndex: number; entryIndex: number;
showModal: (entryId: string) => void; showModal: (entryId: string) => void;
} }
export default function CuesheetTableMenu(props: CuesheetTableMenuProps) { export default function CuesheetTableMenu(props: CuesheetTableMenuProps) {
const { event, entryIndex, showModal } = props; const { eventId, entryIndex, showModal } = props;
const { addEvent, reorderEvent, deleteEvent } = useEventAction(); const { addEvent, getEventById, reorderEvent, deleteEvent } = useEventAction();
const handleCloneEvent = () => { const handleCloneEvent = () => {
const newEvent = cloneEvent(event); const currentEvent = getEventById(eventId);
if (!currentEvent || !isOntimeEvent(currentEvent)) {
return;
}
const newEvent = cloneEvent(currentEvent);
try { try {
addEvent(newEvent, { after: event.id }); addEvent(newEvent, { after: eventId });
} catch (_error) { } catch (_error) {
// we do not handle errors here // we do not handle errors here
} }
}; };
return ( return (
<MenuList> <Portal>
<MenuItem icon={<IoOptions />} onClick={() => showModal(event.id)}> <MenuList>
Edit ... <MenuItem icon={<IoOptions />} onClick={() => showModal(eventId)}>
</MenuItem> Edit ...
<MenuDivider /> </MenuItem>
<MenuItem icon={<IoAdd />} onClick={() => addEvent({ type: SupportedEvent.Event }, { before: event.id })}> <MenuDivider />
Add event above <MenuItem icon={<IoAdd />} onClick={() => addEvent({ type: SupportedEvent.Event }, { before: eventId })}>
</MenuItem> Add event above
<MenuItem icon={<IoAdd />} onClick={() => addEvent({ type: SupportedEvent.Event }, { after: event.id })}> </MenuItem>
Add event below <MenuItem icon={<IoAdd />} onClick={() => addEvent({ type: SupportedEvent.Event }, { after: eventId })}>
</MenuItem> Add event below
<MenuItem icon={<IoDuplicateOutline />} onClick={handleCloneEvent}> </MenuItem>
Clone event <MenuItem icon={<IoDuplicateOutline />} onClick={handleCloneEvent}>
</MenuItem> Clone event
<MenuDivider /> </MenuItem>
<MenuItem <MenuDivider />
isDisabled={entryIndex < 1} <MenuItem
icon={<IoArrowUp />} isDisabled={entryIndex < 1}
onClick={() => reorderEvent(event.id, entryIndex, entryIndex - 1)} icon={<IoArrowUp />}
> onClick={() => reorderEvent(eventId, entryIndex, entryIndex - 1)}
Move up >
</MenuItem> Move up
<MenuItem icon={<IoArrowDown />} onClick={() => reorderEvent(event.id, entryIndex, entryIndex + 1)}> </MenuItem>
Move down <MenuItem icon={<IoArrowDown />} onClick={() => reorderEvent(eventId, entryIndex, entryIndex + 1)}>
</MenuItem> Move down
<MenuItem icon={<IoTrash />} onClick={() => deleteEvent([event.id])}> </MenuItem>
Delete <MenuItem icon={<IoTrash />} onClick={() => deleteEvent([eventId])}>
</MenuItem> Delete
</MenuList> </MenuItem>
</MenuList>
</Portal>
); );
} }