diff --git a/apps/client/src/common/components/import-preview/PreviewColumn.module.scss b/apps/client/src/common/components/import-preview/PreviewColumn.module.scss
index 7fa0f6da7..12e1952e4 100644
--- a/apps/client/src/common/components/import-preview/PreviewColumn.module.scss
+++ b/apps/client/src/common/components/import-preview/PreviewColumn.module.scss
@@ -10,6 +10,7 @@
grid-template-columns: auto 1fr;
grid-template-rows: repeat(6, auto);
gap: 1px;
+ font-size: calc(1rem - 2px);
}
.field {
diff --git a/apps/client/src/common/components/import-preview/PreviewRundown.tsx b/apps/client/src/common/components/import-preview/PreviewRundown.tsx
new file mode 100644
index 000000000..a2e6d5cfd
--- /dev/null
+++ b/apps/client/src/common/components/import-preview/PreviewRundown.tsx
@@ -0,0 +1,92 @@
+import { isOntimeEvent, OntimeRundown } from 'ontime-types';
+import { millisToString } from 'ontime-utils';
+
+import { getAccessibleColour } from '../../utils/styleUtils';
+
+import style from './PreviewTable.module.scss';
+
+interface PreviewRundownProps {
+ rundown: OntimeRundown;
+}
+
+function booleanToText(value?: boolean) {
+ return value ? 'Yes' : '';
+}
+
+export default function PreviewRundown({ rundown }: PreviewRundownProps) {
+ return (
+
+
+
+
+
+ | # |
+ Type |
+ Cue |
+ Title |
+ Subtitle |
+ Presenter |
+ Note |
+ Time Start |
+ Time End |
+ Duration |
+ Is Public |
+ Skip |
+ Colour |
+ Timer Type |
+ End Action |
+ user0 |
+ user1 |
+ user2 |
+ user3 |
+ user4 |
+ user5 |
+ user6 |
+ user7 |
+ user8 |
+ user9 |
+
+
+
+ {rundown.map((event, index) => {
+ const key = event.id;
+ if (isOntimeEvent(event)) {
+ const colour = event.colour ? getAccessibleColour(event.colour) : {};
+ return (
+
+ | {index + 1} |
+ Event |
+ {event.cue} |
+ {event.title} |
+ {event.subtitle} |
+ {event.presenter} |
+ {event.note} |
+ {millisToString(event.timeStart)} |
+ {millisToString(event.timeEnd)} |
+ {millisToString(event.duration)} |
+ {booleanToText(event.isPublic)} |
+ {booleanToText(event.skip)} |
+ {event.colour} |
+ {event.timerType} |
+ {event.endAction} |
+ {event.user0} |
+ {event.user1} |
+ {event.user2} |
+ {event.user3} |
+ {event.user4} |
+ {event.user5} |
+ {event.user6} |
+ {event.user7} |
+ {event.user8} |
+ {event.user9} |
+
+ );
+ }
+ return null;
+ })}
+
+
+
+
+ );
+}
diff --git a/apps/client/src/common/components/import-preview/PreviewTable.module.scss b/apps/client/src/common/components/import-preview/PreviewTable.module.scss
new file mode 100644
index 000000000..b4564e007
--- /dev/null
+++ b/apps/client/src/common/components/import-preview/PreviewTable.module.scss
@@ -0,0 +1,34 @@
+@use "../../../theme/_ontimeColours" as *;
+
+.container {
+ max-width: 100%;
+ max-height: 40vh;
+}
+
+.scrollContainer {
+ overflow-x: scroll;
+}
+
+.rundownPreview {
+ font-size: calc(1rem - 2px);
+}
+
+.header,
+.body {
+ th {
+ font-weight: 400;
+ height: unset;
+ line-height: calc(1rem - 2px);
+ text-align: left;
+ }
+}
+
+.header {
+ background-color: $gray-100;
+}
+
+.body {
+ tr:nth-child(even) {
+ background-color: $gray-50;
+ }
+}
\ No newline at end of file
diff --git a/apps/client/src/features/modals/upload-modal/UploadModal.tsx b/apps/client/src/features/modals/upload-modal/UploadModal.tsx
index f9ed44440..0477ff85b 100644
--- a/apps/client/src/features/modals/upload-modal/UploadModal.tsx
+++ b/apps/client/src/features/modals/upload-modal/UploadModal.tsx
@@ -16,20 +16,426 @@ import { IoClose } from '@react-icons/all-files/io5/IoClose';
import { IoDocumentTextOutline } from '@react-icons/all-files/io5/IoDocumentTextOutline';
import { IoWarningOutline } from '@react-icons/all-files/io5/IoWarningOutline';
import { useQueryClient } from '@tanstack/react-query';
+import { OntimeRundown } from 'ontime-types';
import { RUNDOWN_TABLE } from '../../../common/api/apiConstants';
import { postPreviewExcel, uploadData } from '../../../common/api/ontimeApi';
+import PreviewProjectData from '../../../common/components/import-preview/PreviewProjectData';
+import PreviewRundown from '../../../common/components/import-preview/PreviewRundown';
+import PreviewUserField from '../../../common/components/import-preview/PreviewUserFields';
+import { projectDataPlaceholder } from '../../../common/models/ProjectData';
+import { userFieldsPlaceholder } from '../../../common/models/UserFields';
import { useEmitLog } from '../../../common/stores/logger';
import ModalSplitInput from '../ModalSplitInput';
import { validateFile } from './utils';
import style from './UploadModal.module.scss';
-import PreviewProjectData from '../../../common/components/import-preview/PreviewProjectData';
-import { projectDataPlaceholder } from '../../../common/models/ProjectData';
-import CollapsableInfo from '../../info/CollapsableInfo';
-import PreviewUserField from '../../../common/components/import-preview/PreviewUserFields';
-import { userFieldsPlaceholder } from '../../../common/models/UserFields';
+
+const rundownDemo: OntimeRundown = [
+ {
+ title: 'Albania',
+ subtitle: 'Sekret',
+ presenter: 'Ronela Hajati',
+ note: 'SF1.01',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 36000000,
+ timeEnd: 37200000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '32d31',
+ cue: '1',
+ },
+ {
+ title: 'Latvia',
+ subtitle: 'Eat Your Salad',
+ presenter: 'Citi Zeni',
+ note: 'SF1.02',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 37500000,
+ timeEnd: 38700000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '21cd2',
+ cue: '2',
+ },
+ {
+ title: 'Lithuania',
+ subtitle: 'Sentimentai',
+ presenter: 'Monika Liu',
+ note: 'SF1.03',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 39000000,
+ timeEnd: 40200000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '0b371',
+ cue: '3',
+ },
+ {
+ title: 'Switzerland',
+ subtitle: 'Boys Do Cry',
+ presenter: 'Marius Bear',
+ note: 'SF1.04',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 40500000,
+ timeEnd: 41700000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '3cd28',
+ cue: '4',
+ },
+ {
+ title: 'Slovenia',
+ subtitle: 'Disko',
+ presenter: 'LPS',
+ note: 'SF1.05',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 42000000,
+ timeEnd: 43200000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: 'e457f',
+ cue: '5',
+ },
+ {
+ title: 'Lunch break',
+ type: 'block',
+ id: '01e85',
+ },
+ {
+ title: 'Ukraine',
+ subtitle: 'Stefania',
+ presenter: 'Kalush Orchestra',
+ note: 'SF1.06',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 47100000,
+ timeEnd: 48300000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '1c420',
+ cue: '6',
+ },
+ {
+ title: 'Bulgaria',
+ subtitle: 'Intention',
+ presenter: 'Intelligent Music Project',
+ note: 'SF1.07',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 48600000,
+ timeEnd: 49800000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: 'b7737',
+ cue: '7',
+ },
+ {
+ title: 'Netherlands',
+ subtitle: 'De Diepte',
+ presenter: 'S10',
+ note: 'SF1.08',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 50100000,
+ timeEnd: 51300000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: 'd3a80',
+ cue: '8',
+ },
+ {
+ title: 'Moldova',
+ subtitle: 'Trenuletul',
+ presenter: 'Zdob si Zdub',
+ note: 'SF1.09',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 51600000,
+ timeEnd: 52800000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '8276c',
+ cue: '9',
+ },
+ {
+ title: 'Portugal',
+ subtitle: 'Saudade Saudade',
+ presenter: 'Maro',
+ note: 'SF1.10',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 53100000,
+ timeEnd: 54300000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '2340b',
+ cue: '10',
+ },
+ {
+ title: 'Afternoon break',
+ type: 'block',
+ id: 'cb90b',
+ },
+ {
+ title: 'Croatia',
+ subtitle: 'Guilty Pleasure',
+ presenter: 'Mia Dimsic',
+ note: 'SF1.11',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 56100000,
+ timeEnd: 57300000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '503c4',
+ cue: '11',
+ },
+ {
+ title: 'Denmark',
+ subtitle: 'The Show',
+ presenter: 'Reddi',
+ note: 'SF1.12',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 57600000,
+ timeEnd: 58800000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: '5e965',
+ cue: '12',
+ },
+ {
+ title: 'Austria',
+ subtitle: 'Halo',
+ presenter: 'LUM!X & Pia Maria',
+ note: 'SF1.13',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 59100000,
+ timeEnd: 60300000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: 'bab4a',
+ cue: '13',
+ },
+ {
+ title: 'Greece',
+ subtitle: 'Die Together',
+ presenter: 'Amanda Tenfjord',
+ note: 'SF1.14',
+ endAction: 'none',
+ timerType: 'count-down',
+ timeStart: 60600000,
+ timeEnd: 61800000,
+ duration: 1200000,
+ isPublic: true,
+ skip: false,
+ colour: '',
+ user0: '',
+ user1: '',
+ user2: '',
+ user3: '',
+ user4: '',
+ user5: '',
+ user6: '',
+ user7: '',
+ user8: '',
+ user9: '',
+ type: 'event',
+ revision: 0,
+ id: 'd3eb1',
+ cue: '14',
+ },
+];
interface UploadModalProps {
onClose: () => void;
@@ -161,6 +567,7 @@ export default function UploadModal({ onClose, isOpen }: UploadModalProps) {
+