mirror of
https://github.com/cpvalente/ontime.git
synced 2026-07-26 10:38:55 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fbbbaa5922 |
@@ -25,12 +25,15 @@ export default function useReactiveTextInput(
|
||||
const isKeyboardSubmitting = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const isFocused = document.activeElement === ref.current;
|
||||
if (isFocused) return;
|
||||
|
||||
if (typeof initialText === 'undefined') {
|
||||
setText('');
|
||||
} else {
|
||||
setText(initialText);
|
||||
}
|
||||
}, [initialText]);
|
||||
}, [initialText, ref]);
|
||||
|
||||
/**
|
||||
* @description Handles Input value change
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { TableVirtuoso, TableVirtuosoHandle } from 'react-virtuoso';
|
||||
import { useTableNav } from '@table-nav/react';
|
||||
import { ColumnDef, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||
import { isOntimeDelay, isOntimeGroup, isOntimeMilestone, OntimeEntry, TimeField } from 'ontime-types';
|
||||
import { ColumnDef, getCoreRowModel, Row, Table, useReactTable } from '@tanstack/react-table';
|
||||
import { EntryId, isOntimeDelay, isOntimeGroup, isOntimeMilestone, OntimeEntry, TimeField } from 'ontime-types';
|
||||
|
||||
import EmptyPage from '../../../common/components/state/EmptyPage';
|
||||
import EmptyTableBody from '../../../common/components/state/EmptyTableBody';
|
||||
@@ -27,6 +27,115 @@ import { useColumnOrder, useColumnSizes, useColumnVisibility } from './useColumn
|
||||
|
||||
import style from './CuesheetTable.module.scss';
|
||||
|
||||
interface VirtuosoContext {
|
||||
table: Table<ExtendedEntry>;
|
||||
rows: Row<ExtendedEntry>[];
|
||||
cursor: EntryId | null;
|
||||
columnSizeVars: Record<string, number | string>;
|
||||
listeners: object;
|
||||
}
|
||||
|
||||
const VirtuosoTable = memo(({ style: injectedStyles, context, ...virtuosoProps }: any) => {
|
||||
const { columnSizeVars, listeners } = context as VirtuosoContext;
|
||||
return (
|
||||
<table
|
||||
className={style.cuesheet}
|
||||
id="cuesheet"
|
||||
style={{ ...injectedStyles, ...columnSizeVars }}
|
||||
{...listeners}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
});
|
||||
VirtuosoTable.displayName = 'VirtuosoTable';
|
||||
|
||||
const VirtuosoTableRow = memo(({ item: _item, context, ...virtuosoProps }: any) => {
|
||||
const { table, rows, cursor } = context as VirtuosoContext;
|
||||
const rowIndex = virtuosoProps['data-index'];
|
||||
const row = rows[rowIndex];
|
||||
if (!row) return null;
|
||||
|
||||
const key = row.original.id;
|
||||
const entry = row.original;
|
||||
const hasCursor = entry.id === cursor;
|
||||
|
||||
if (isOntimeGroup(entry)) {
|
||||
return (
|
||||
<GroupRow
|
||||
key={key}
|
||||
groupId={entry.id}
|
||||
colour={entry.colour}
|
||||
rowId={row.id}
|
||||
rowIndex={row.index}
|
||||
table={table}
|
||||
injectedStyles={virtuosoProps.style}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isOntimeDelay(entry)) {
|
||||
return (
|
||||
<DelayRow
|
||||
key={key}
|
||||
duration={entry.duration}
|
||||
injectedStyles={virtuosoProps.style}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isOntimeMilestone(entry)) {
|
||||
return (
|
||||
<MilestoneRow
|
||||
key={key}
|
||||
entryId={entry.id}
|
||||
isPast={entry.isPast}
|
||||
parentBgColour={entry.groupColour}
|
||||
parentId={entry.parent}
|
||||
colour={entry.colour}
|
||||
rowId={row.id}
|
||||
rowIndex={rowIndex}
|
||||
table={table}
|
||||
injectedStyles={virtuosoProps.style}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EventRow
|
||||
key={row.id}
|
||||
id={entry.id}
|
||||
eventIndex={entry.eventIndex}
|
||||
colour={entry.colour}
|
||||
isFirstAfterGroup={entry.isFirstAfterGroup}
|
||||
isLoaded={entry.isLoaded}
|
||||
isPast={entry.isPast}
|
||||
groupColour={entry.groupColour}
|
||||
flag={entry.flag}
|
||||
skip={entry.skip}
|
||||
parent={entry.parent}
|
||||
rowId={row.id}
|
||||
rowIndex={rowIndex}
|
||||
table={table}
|
||||
injectedStyles={virtuosoProps.style}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
});
|
||||
VirtuosoTableRow.displayName = 'VirtuosoTableRow';
|
||||
|
||||
const VirtuosoTableHead = memo((props: any) => <thead className={style.tableHeader} {...props} />);
|
||||
VirtuosoTableHead.displayName = 'VirtuosoTableHead';
|
||||
|
||||
const VirtuosoEmptyPlaceholder = memo(() => <EmptyTableBody text="No data in rundown" />);
|
||||
VirtuosoEmptyPlaceholder.displayName = 'VirtuosoEmptyPlaceholder';
|
||||
|
||||
interface CuesheetTableProps {
|
||||
columns: ColumnDef<ExtendedEntry>[];
|
||||
cuesheetMode: AppMode;
|
||||
@@ -49,11 +158,14 @@ export default function CuesheetTable({ columns, cuesheetMode, tableRoot = 'cues
|
||||
const virtuosoRef = useRef<TableVirtuosoHandle | null>(null);
|
||||
const { listeners } = useTableNav();
|
||||
|
||||
const dataRef = useRef(data);
|
||||
dataRef.current = data;
|
||||
|
||||
const meta = useMemo(
|
||||
() => ({
|
||||
handleUpdate: (rowIndex: number, accessor: string, payload: string, isCustom = false) => {
|
||||
// check if value is the same
|
||||
const event = data[rowIndex];
|
||||
const event = dataRef.current[rowIndex];
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
@@ -84,7 +196,7 @@ export default function CuesheetTable({ columns, cuesheetMode, tableRoot = 'cues
|
||||
hideIndexColumn,
|
||||
},
|
||||
}),
|
||||
[cuesheetMode, data, hideIndexColumn, hideTableSeconds, showDelayedTimes, updateEntry, updateTimer],
|
||||
[cuesheetMode, hideIndexColumn, hideTableSeconds, showDelayedTimes, updateEntry, updateTimer],
|
||||
);
|
||||
|
||||
const { columnOrder, resetColumnOrder } = useColumnOrder(columns, tableRoot);
|
||||
@@ -171,6 +283,17 @@ export default function CuesheetTable({ columns, cuesheetMode, tableRoot = 'cues
|
||||
const allLeafColumns = table.getAllLeafColumns();
|
||||
const { rows } = table.getRowModel();
|
||||
|
||||
const virtuosoContext = useMemo(
|
||||
() => ({
|
||||
table,
|
||||
rows,
|
||||
cursor,
|
||||
columnSizeVars,
|
||||
listeners,
|
||||
}),
|
||||
[columnSizeVars, cursor, listeners, rows, table],
|
||||
);
|
||||
|
||||
const isLoading = !data || status === 'pending';
|
||||
|
||||
if (isLoading) {
|
||||
@@ -191,99 +314,14 @@ export default function CuesheetTable({ columns, cuesheetMode, tableRoot = 'cues
|
||||
<TableVirtuoso
|
||||
ref={virtuosoRef}
|
||||
data={data}
|
||||
context={virtuosoContext}
|
||||
style={tableRoot === 'editor' ? { paddingLeft: '1rem' } : undefined}
|
||||
increaseViewportBy={{ top: 100, bottom: 200 }}
|
||||
components={{
|
||||
EmptyPlaceholder: () => <EmptyTableBody text='No data in rundown' />,
|
||||
Table: ({ style: injectedStyles, ...virtuosoProps }) => {
|
||||
return (
|
||||
<table
|
||||
className={style.cuesheet}
|
||||
id='cuesheet'
|
||||
style={{ ...injectedStyles, ...columnSizeVars }}
|
||||
{...listeners}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
},
|
||||
TableRow: ({ item: _item, style: injectedStyles, ...virtuosoProps }) => {
|
||||
// eslint-disable-next-line react/destructuring-assignment
|
||||
const rowIndex = virtuosoProps['data-index'];
|
||||
const row = rows[rowIndex];
|
||||
const key = row.original.id;
|
||||
const entry = row.original;
|
||||
const hasCursor = entry.id === cursor;
|
||||
|
||||
if (isOntimeGroup(entry)) {
|
||||
return (
|
||||
<GroupRow
|
||||
key={key}
|
||||
groupId={entry.id}
|
||||
colour={entry.colour}
|
||||
rowId={row.id}
|
||||
rowIndex={row.index}
|
||||
table={table}
|
||||
injectedStyles={injectedStyles}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isOntimeDelay(entry)) {
|
||||
return (
|
||||
<DelayRow
|
||||
key={key}
|
||||
duration={entry.duration}
|
||||
injectedStyles={injectedStyles}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isOntimeMilestone(entry)) {
|
||||
return (
|
||||
<MilestoneRow
|
||||
key={key}
|
||||
entryId={entry.id}
|
||||
isPast={entry.isPast}
|
||||
parentBgColour={entry.groupColour}
|
||||
parentId={entry.parent}
|
||||
colour={entry.colour}
|
||||
rowId={row.id}
|
||||
rowIndex={rowIndex}
|
||||
table={table}
|
||||
injectedStyles={injectedStyles}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EventRow
|
||||
key={row.id}
|
||||
id={entry.id}
|
||||
eventIndex={entry.eventIndex}
|
||||
colour={entry.colour}
|
||||
isFirstAfterGroup={entry.isFirstAfterGroup}
|
||||
isLoaded={entry.isLoaded}
|
||||
isPast={entry.isPast}
|
||||
groupColour={entry.groupColour}
|
||||
flag={entry.flag}
|
||||
skip={entry.skip}
|
||||
parent={entry.parent}
|
||||
rowId={row.id}
|
||||
rowIndex={rowIndex}
|
||||
table={table}
|
||||
injectedStyles={injectedStyles}
|
||||
hasCursor={hasCursor}
|
||||
{...virtuosoProps}
|
||||
/>
|
||||
);
|
||||
},
|
||||
TableHead: (virtuosoProps) => <thead className={style.tableHeader} {...virtuosoProps} />,
|
||||
EmptyPlaceholder: VirtuosoEmptyPlaceholder,
|
||||
Table: VirtuosoTable,
|
||||
TableRow: VirtuosoTableRow,
|
||||
TableHead: VirtuosoTableHead,
|
||||
}}
|
||||
fixedHeaderContent={() => {
|
||||
return table.getHeaderGroups().map((headerGroup) => {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
> ontime@4.3.1 dev /app
|
||||
> turbo run dev
|
||||
|
||||
|
||||
Attention:
|
||||
Turborepo now collects completely anonymous telemetry regarding usage.
|
||||
This information is used to shape the Turborepo roadmap and prioritize features.
|
||||
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
|
||||
https://turborepo.com/docs/telemetry
|
||||
|
||||
turbo 2.5.8
|
||||
|
||||
• Packages in scope: @getontime/cli, @getontime/resolver, ontime-electron, ontime-server, ontime-types, ontime-ui, ontime-utils
|
||||
• Running dev in 7 packages
|
||||
• Remote caching disabled
|
||||
ontime-server:dev: cache bypass, force executing 736e67d68a6b5681
|
||||
ontime-ui:dev: cache bypass, force executing 9eacdb30152cd80e
|
||||
ontime-ui:dev:
|
||||
ontime-ui:dev: > ontime-ui@4.3.1 dev /app/apps/client
|
||||
ontime-ui:dev: > cross-env BROWSER=none vite
|
||||
ontime-ui:dev:
|
||||
ontime-server:dev:
|
||||
ontime-server:dev: > ontime-server@4.3.1 dev /app/apps/server
|
||||
ontime-server:dev: > cross-env NODE_ENV=development tsx watch ./src/index.ts
|
||||
ontime-server:dev:
|
||||
ontime-ui:dev:
|
||||
ontime-ui:dev: VITE v6.3.1 ready in 748 ms
|
||||
ontime-ui:dev:
|
||||
ontime-ui:dev: ➜ Local: http://localhost:3000/
|
||||
ontime-ui:dev: ➜ Network: use --host to expose
|
||||
ontime-server:dev:
|
||||
ontime-server:dev:
|
||||
ontime-server:dev: [96mStarting Ontime version 4.3.1[0m
|
||||
ontime-server:dev: Ontime running in development environment
|
||||
ontime-server:dev: Ontime source directory at /app/apps/server/src/
|
||||
ontime-server:dev: Ontime public directory at /home/jules/.Ontime
|
||||
ontime-server:dev:
|
||||
ontime-server:dev:
|
||||
ontime-server:dev: [96mRequest: Initialise assets...[0m
|
||||
ontime-server:dev: [2m[INFO] SERVER Loaded project demo project.json[0m
|
||||
ontime-server:dev: [2m[INFO] SERVER Switch to rundown: default[0m
|
||||
ontime-server:dev: [2m[INFO] SERVER Initialised Ontime with demo project.json[0m
|
||||
ontime-server:dev:
|
||||
ontime-server:dev:
|
||||
ontime-server:dev: [96mRequest: Start server...[0m
|
||||
ontime-server:dev: [2m[INFO] SERVER Runtime service started[0m
|
||||
ontime-server:dev: [32mLocal: http://localhost:4001/editor[0m
|
||||
ontime-server:dev: [32mNetwork: http://192.168.0.2:4001/editor[0m
|
||||
ontime-server:dev: [2m[INFO] SERVER Ontime is listening on port 4001[0m
|
||||
ontime-server:dev:
|
||||
ontime-server:dev:
|
||||
ontime-server:dev: [96mRequest: Start integrations...[0m
|
||||
ontime-server:dev: [2m[INFO] SERVER Skipping OSC integration[0m
|
||||
ontime-ui:dev: Browserslist: browsers data (caniuse-lite) is 9 months old. Please run:
|
||||
ontime-ui:dev: npx update-browserslist-db@latest
|
||||
ontime-ui:dev: Why you should do it regularly: https://github.com/browserslist/update-db#readme
|
||||
ontime-ui:dev: Browserslist: caniuse-lite is outdated. Please run:
|
||||
ontime-ui:dev: npx update-browserslist-db@latest
|
||||
ontime-ui:dev: Why you should do it regularly: https://github.com/browserslist/update-db#readme
|
||||
ontime-server:dev: [2m[INFO] CLIENT 1 Connections with new: low-fi instrument[0m
|
||||
ontime-ui:dev: Proxy: GET /data/settings
|
||||
ontime-ui:dev: Proxy: GET /user/translations/translations.json
|
||||
ontime-ui:dev: Proxy: GET /data/report
|
||||
ontime-ui:dev: Proxy: GET /data/view-settings
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-ui:dev: Proxy: GET /data/project
|
||||
ontime-ui:dev: Proxy: GET /data/db/all
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-ui:dev: Proxy: GET /data/project
|
||||
ontime-ui:dev: Proxy: GET /data/db/all
|
||||
ontime-server:dev: [2m[INFO] CLIENT 0 Connections with disconnected: low-fi instrument[0m
|
||||
ontime-server:dev: [2m[INFO] CLIENT 1 Connections with new: mellow uplight[0m
|
||||
ontime-ui:dev: Proxy: GET /data/settings
|
||||
ontime-ui:dev: Proxy: GET /user/translations/translations.json
|
||||
ontime-ui:dev: Proxy: GET /data/report
|
||||
ontime-ui:dev: Proxy: GET /data/view-settings
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-ui:dev: Proxy: GET /data/project
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-ui:dev: Proxy: GET /data/project
|
||||
ontime-server:dev: [2m[INFO] CLIENT 0 Connections with disconnected: mellow uplight[0m
|
||||
ontime-server:dev: [2m[INFO] CLIENT 1 Connections with new: nostalgic mix[0m
|
||||
ontime-ui:dev: Proxy: GET /data/settings
|
||||
ontime-ui:dev: Proxy: GET /user/translations/translations.json
|
||||
ontime-ui:dev: Proxy: GET /data/report
|
||||
ontime-ui:dev: Proxy: GET /data/view-settings
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-ui:dev: Proxy: GET /data/project
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-ui:dev: Proxy: GET /data/project
|
||||
ontime-ui:dev: Proxy: GET /data/custom-fields
|
||||
ontime-ui:dev: Proxy: GET /data/rundowns/current
|
||||
ontime-server:dev: [2m[INFO] CLIENT 0 Connections with disconnected: nostalgic mix[0m
|
||||
Reference in New Issue
Block a user