From 4cbe25a845cbe5b168f87a03d0be001e44e35308 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Fri, 20 Dec 2024 09:36:03 +0100 Subject: [PATCH] refactor: simplify update functions --- apps/client/src/declarations/declaration.d.ts | 16 +++++ .../src/views/cuesheet/CuesheetPage.tsx | 70 +------------------ .../cuesheet/cuesheet-table/CuesheetTable.tsx | 35 +++++++--- .../cuesheet-table-elements/cuesheetCols.tsx | 9 +-- 4 files changed, 47 insertions(+), 83 deletions(-) diff --git a/apps/client/src/declarations/declaration.d.ts b/apps/client/src/declarations/declaration.d.ts index ac4635cc9..e3f681c3a 100644 --- a/apps/client/src/declarations/declaration.d.ts +++ b/apps/client/src/declarations/declaration.d.ts @@ -6,6 +6,9 @@ declare module '*.scss' { type ListenerType = (event: 'string', args: unknown[]) => void; declare global { + /** + * Register the electron properties + */ interface Window { ipcRenderer: { send: (channel: string, args?: string | object) => void; @@ -17,6 +20,19 @@ declare global { } } +/** + * We pass a custom property to the table meta to allow field update + */ +declare module '@tanstack/react-table' { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface TableMeta { + handleUpdate: (rowIndex: number, accessor: string, payload: string, isCustom: boolean) => void; + } +} + +/** + * Allow passing CSS Properties + */ declare module 'react' { interface CSSProperties { [key: `--${string}`]: string | number; diff --git a/apps/client/src/views/cuesheet/CuesheetPage.tsx b/apps/client/src/views/cuesheet/CuesheetPage.tsx index 3025e6769..0f69d5b74 100644 --- a/apps/client/src/views/cuesheet/CuesheetPage.tsx +++ b/apps/client/src/views/cuesheet/CuesheetPage.tsx @@ -3,12 +3,10 @@ import { useSearchParams } from 'react-router-dom'; import { IconButton, Modal, ModalContent, ModalOverlay, useDisclosure } from '@chakra-ui/react'; import { IoApps } from '@react-icons/all-files/io5/IoApps'; import { IoSettingsOutline } from '@react-icons/all-files/io5/IoSettingsOutline'; -import { CustomFieldLabel, isOntimeEvent, OntimeEvent } from 'ontime-types'; import ProductionNavigationMenu from '../../common/components/navigation-menu/ProductionNavigationMenu'; import EmptyPage from '../../common/components/state/EmptyPage'; import ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor'; -import { useEventAction } from '../../common/hooks/useEventAction'; import { useWindowTitle } from '../../common/hooks/useWindowTitle'; import useCustomFields from '../../common/hooks-query/useCustomFields'; import { useFlatRundown } from '../../common/hooks-query/useRundown'; @@ -32,7 +30,6 @@ export default function CuesheetPage() { const { isOpen: isEventEditorOpen, onOpen: onEventEditorOpen, onClose: onEventEditorClose } = useDisclosure(); const [eventId, setEventId] = useState(null); - const { updateCustomField, updateEvent } = useEventAction(); const columns = useMemo(() => makeCuesheetColumns(customFields), [customFields]); useWindowTitle('Cuesheet'); @@ -43,65 +40,6 @@ export default function CuesheetPage() { setSearchParams(searchParams); }, [searchParams, setSearchParams]); - /** - * Handles updating a custom field - */ - const handleUpdateCustom = useCallback( - async (rowIndex: number, accessor: CustomFieldLabel, payload: string) => { - if (!flatRundown || rundownStatus !== 'success') { - return; - } - - if (rowIndex == null || accessor == null || payload == null) { - return; - } - - // check if value is the same - const event = flatRundown[rowIndex]; - if (!event || !isOntimeEvent(event)) { - return; - } - - // skip if there is no value change - const previousValue = event.custom[accessor]; - if (previousValue === payload) { - return; - } - updateCustomField(event.id, accessor, payload); - }, - [flatRundown, rundownStatus, updateCustomField], - ); - - /** - * Handles updating all other string fields - */ - const handleUpdate = useCallback( - async (rowIndex: number, accessor: keyof OntimeEvent, payload: string) => { - if (!flatRundown || rundownStatus !== 'success') { - return; - } - - if (rowIndex == null || accessor == null || payload == null) { - return; - } - - // check if value is the same - const event = flatRundown[rowIndex]; - if (!event || !isOntimeEvent(event)) { - return; - } - - // skip if there is no value change - const previousValue = event[accessor]; - if (previousValue === payload) { - return; - } - - updateEvent({ id: event.id, [accessor]: payload }); - }, - [flatRundown, rundownStatus, updateEvent], - ); - /** * Handles setting the edit modal target and visibility */ @@ -151,13 +89,7 @@ export default function CuesheetPage() { - + diff --git a/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx b/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx index 0a2384a53..f4c24c38e 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx +++ b/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx @@ -4,15 +4,16 @@ import { IoEllipsisHorizontal } from '@react-icons/all-files/io5/IoEllipsisHoriz import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import Color from 'color'; import { - CustomFieldLabel, isOntimeBlock, isOntimeDelay, isOntimeEvent, MaybeString, + OntimeEvent, OntimeRundown, OntimeRundownEntry, } from 'ontime-types'; +import { useEventAction } from '../../../common/hooks/useEventAction'; import useFollowComponent from '../../../common/hooks/useFollowComponent'; import { useSelectedEventId } from '../../../common/hooks/useSocket'; import { getAccessibleColour } from '../../../common/utils/styleUtils'; @@ -31,14 +32,13 @@ import style from './CuesheetTable.module.scss'; interface CuesheetTableProps { data: OntimeRundown; columns: ColumnDef[]; - handleUpdate: (rowIndex: number, accessor: keyof OntimeRundownEntry, payload: string) => void; - handleUpdateCustom: (rowIndex: number, accessor: CustomFieldLabel, payload: string) => void; showModal: (eventId: MaybeString) => void; } export default function CuesheetTable(props: CuesheetTableProps) { - const { data, columns, handleUpdate, handleUpdateCustom, showModal } = props; + const { data, columns, showModal } = props; + const { updateEvent } = useEventAction(); const { selectedEventId } = useSelectedEventId(); const { followSelected, hideDelays, hidePast, hideIndexColumn } = useCuesheetOptions(); const { columnVisibility, columnOrder, columnSizing, resetColumnOrder, setColumnVisibility, setColumnSizing } = @@ -57,13 +57,32 @@ export default function CuesheetTable(props: CuesheetTableProps) { columnVisibility, columnSizing, }, - meta: { - handleUpdate, - handleUpdateCustom, - }, onColumnVisibilityChange: setColumnVisibility, onColumnSizingChange: setColumnSizing, getCoreRowModel: getCoreRowModel(), + meta: { + handleUpdate: async (rowIndex: number, accessor: string, payload: string, isCustom = false) => { + // check if value is the same + const event = data[rowIndex]; + if (!event || !isOntimeEvent(event)) { + return; + } + + // skip if there is no value change + const key = accessor as keyof OntimeEvent; + const previousValue = event[key]; + if (previousValue === payload) { + return; + } + + if (isCustom) { + updateEvent({ id: event.id, custom: { [accessor]: payload } }); + return; + } + + updateEvent({ id: event.id, [accessor]: payload }); + }, + }, }); const setAllVisible = () => { diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetCols.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetCols.tsx index 4b260cee8..d919d6ff6 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetCols.tsx +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetCols.tsx @@ -37,8 +37,7 @@ function MakeDuration({ getValue }: CellContext) { function MakeMultiLineField({ row, column, table }: CellContext) { const update = useCallback( (newValue: string) => { - // @ts-expect-error -- we inject this into react-table - table.options.meta?.handleUpdate(row.index, column.id, newValue); + table.options.meta?.handleUpdate(row.index, column.id, newValue, false); }, // eslint-disable-next-line react-hooks/exhaustive-deps -- we skip table.options.meta since the reference seems unstable [column.id, row.index], @@ -57,8 +56,7 @@ function MakeMultiLineField({ row, column, table }: CellContext) { const update = useCallback( (newValue: string) => { - // @ts-expect-error -- we inject this into react-table - table.options.meta?.handleUpdate(row.index, column.id, newValue); + table.options.meta?.handleUpdate(row.index, column.id, newValue, false); }, // eslint-disable-next-line react-hooks/exhaustive-deps -- we skip table.options.meta since the reference seems unstable [column.id, row.index], @@ -77,8 +75,7 @@ function MakeSingleLineField({ row, column, table }: CellContext) { const update = useCallback( (newValue: string) => { - // @ts-expect-error -- we inject this into react-table - table.options.meta?.handleUpdateCustom(row.index, column.id, newValue); + table.options.meta?.handleUpdate(row.index, column.id, newValue, true); }, // eslint-disable-next-line react-hooks/exhaustive-deps -- we skip table.options.meta since the reference seems unstable [column.id, row.index],