mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-04 15:08:01 +00:00
refactor: simplify ux for sheet import
This commit is contained in:
committed by
Carlos Valente
parent
9dfc8083f0
commit
becd734ea8
+22
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { CustomFields, Rundown } from 'ontime-types';
|
||||
import { getFirstEventNormal, getLastEventNormal, millisToString } from 'ontime-utils';
|
||||
|
||||
import Button from '../../../../../common/components/buttons/Button';
|
||||
import useRundown from '../../../../../common/hooks-query/useRundown';
|
||||
@@ -43,6 +44,9 @@ export default function ImportReview(props: ImportReviewProps) {
|
||||
onFinished();
|
||||
};
|
||||
|
||||
const { firstEvent } = getFirstEventNormal(rundown.entries, rundown.flatOrder);
|
||||
const { lastEvent } = getLastEventNormal(rundown.entries, rundown.flatOrder);
|
||||
|
||||
return (
|
||||
<Panel.Section>
|
||||
<Panel.Title>
|
||||
@@ -56,6 +60,24 @@ export default function ImportReview(props: ImportReviewProps) {
|
||||
</Button>
|
||||
</Panel.InlineElements>
|
||||
</Panel.Title>
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<b>Title</b> {rundown.title}
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<b>Number of entries</b> {rundown.flatOrder.length}
|
||||
</Panel.ListItem>
|
||||
{firstEvent && (
|
||||
<Panel.ListItem>
|
||||
<b>Start Time</b> {millisToString(firstEvent.timeStart)}
|
||||
</Panel.ListItem>
|
||||
)}
|
||||
{lastEvent && (
|
||||
<Panel.ListItem>
|
||||
<b>End Time</b> {millisToString(lastEvent.timeEnd)}
|
||||
</Panel.ListItem>
|
||||
)}
|
||||
</Panel.ListGroup>
|
||||
<PreviewSpreadsheet rundown={rundown} customFields={customFields} />
|
||||
</Panel.Section>
|
||||
);
|
||||
|
||||
+5
@@ -5,6 +5,7 @@ import { checkRegex, ImportMap } from 'ontime-utils';
|
||||
|
||||
import Button from '../../../../../../common/components/buttons/Button';
|
||||
import IconButton from '../../../../../../common/components/buttons/IconButton';
|
||||
import Info from '../../../../../../common/components/info/Info';
|
||||
import Input from '../../../../../../common/components/input/input/Input';
|
||||
import Select from '../../../../../../common/components/select/Select';
|
||||
import Tooltip from '../../../../../../common/components/tooltip/Tooltip';
|
||||
@@ -136,6 +137,10 @@ export default function ImportMapForm({
|
||||
</Button>
|
||||
</Panel.InlineElements>
|
||||
</Panel.Title>
|
||||
<Info>
|
||||
Match your spreadsheet columns to Ontime fields. <br />
|
||||
You can also add Custom Fields by providing a name for Ontime and the spreadsheet column name.
|
||||
</Info>
|
||||
<Panel.Table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
+2
-6
@@ -18,9 +18,7 @@ function booleanToText(value?: boolean) {
|
||||
return value ? 'Yes' : undefined;
|
||||
}
|
||||
|
||||
export default function PreviewRundown(props: PreviewRundownProps) {
|
||||
const { rundown, customFields } = props;
|
||||
|
||||
export default function PreviewRundown({ rundown, customFields }: PreviewRundownProps) {
|
||||
// we only count Ontime Events which are 1 based in client
|
||||
let eventIndex = 0;
|
||||
|
||||
@@ -59,9 +57,7 @@ export default function PreviewRundown(props: PreviewRundownProps) {
|
||||
const colour = entry.colour ? getAccessibleColour(entry.colour) : {};
|
||||
return (
|
||||
<tr key={entry.id}>
|
||||
<td className={style.center}>
|
||||
<Tag>-</Tag>
|
||||
</td>
|
||||
<td /> {/** Index */}
|
||||
<td className={style.center}>
|
||||
<Tag>{entry.type}</Tag>
|
||||
</td>
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
export const simpleTemplate = [
|
||||
['ⓘ Notes on import', '', '', '', '', '', 'ⓘ How to use'],
|
||||
[
|
||||
'Ontime will import this spreasheet as a rundown in your project',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'1. Make your own copy of the spreadsheet by either File -> Make a copy or File -> Download -> Microsoft Excel',
|
||||
],
|
||||
[
|
||||
'- Each spreadsheet can only contain one rundown',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'2. Delete the table header with the Notes on import and How to use instructions',
|
||||
],
|
||||
[
|
||||
'- You can have as many columns as necessary, Ontime only imports the columns you request',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'3. Remove any columns that are not necessary to your workflow',
|
||||
],
|
||||
[
|
||||
'- The names of the worksheet and columns are given in Ontime on import',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'See documentation for spreadsheet import',
|
||||
'',
|
||||
'https://docs.getontime.no/features/import-spreadsheet/',
|
||||
],
|
||||
[
|
||||
'- Ontime creates an entry for every row on the table with a known Timer Type (see note on column header)',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'See documentation for Google Sheet import',
|
||||
'',
|
||||
'https://docs.getontime.no/features/import-spreadsheet-gsheet/',
|
||||
],
|
||||
['- All fields in a row are optional, Ontime will fill in with default data as needed'],
|
||||
['ⓘ Hover over note tags to see additional help on column data'],
|
||||
[
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'Note ---------------------------------------------',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'Note',
|
||||
'Note --------------------------------------------------------',
|
||||
],
|
||||
['Cue', 'Title', 'Colour', 'Time Start', 'Time End', 'Duration', 'Note', 'Timer Type', 'Video Notes'],
|
||||
[
|
||||
'Demo',
|
||||
'Clear all, or Create New Project to start fresh',
|
||||
'#9d9d9d',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'Moderator - Emma Thompson\n' +
|
||||
'\n' +
|
||||
'Speakers\n' +
|
||||
'- Liam Carter + Sophia Patel\n' +
|
||||
'- Ethan Brooks\n' +
|
||||
'- Lucas Bennett',
|
||||
'milestone',
|
||||
],
|
||||
['', 'Morning Sessions', '#339E4E', '', '', '', '', 'group-start'],
|
||||
[
|
||||
'1',
|
||||
'Pre-show Countdown',
|
||||
'#77C785',
|
||||
'10:00:00',
|
||||
'11:00:00',
|
||||
'',
|
||||
'Music plays, holding slide on screens',
|
||||
'count-down',
|
||||
'Camera + PowerPoint on stream\nPowerPoint on screens',
|
||||
],
|
||||
['Standby', '10:45 - Presenters ready side stage', '#A790F5', '', '', '', '', 'milestone'],
|
||||
['1.1', 'Welcome', '#FFCC78', '', '', '00:10:00', '', 'count-down', 'Cameras on stream\nPowerPoint on screens'],
|
||||
[
|
||||
'1.2',
|
||||
'Session 1',
|
||||
'#77C785',
|
||||
'',
|
||||
'',
|
||||
'00:50:00',
|
||||
'',
|
||||
'count-down',
|
||||
'Camera + PowerPoint on stream\nPowerPoint on screens',
|
||||
],
|
||||
['House', '11:30 - House staff setup lunch in lobby', '#A790F5', '', '', '', '', 'milestone'],
|
||||
['', 'Lunch', '#3E75E8', '', '', '', '', 'group-start'],
|
||||
['2.1', 'Lunch / Countdown to next session', '#779BE7', '12:00:00', '13:00:00', '', '', 'count-down'],
|
||||
['', 'Afternoon Sessions', '#339E4E', '', '', '', '', 'group-start'],
|
||||
['Standby', '12:45 - Presenters ready side stage', '#A790F5', '', '', '', '', 'milestone'],
|
||||
[
|
||||
'3.2',
|
||||
'Session 2',
|
||||
'#77C785',
|
||||
'13:00:00',
|
||||
'',
|
||||
'00:50:00',
|
||||
'',
|
||||
'count-down',
|
||||
'Camera + PPT + Video on stream\n' + 'PowerPoint + Video on screens\n' + '\n' + 'Video file: Session2.mp4',
|
||||
],
|
||||
['3.2', 'Wrap up', '#FFCC78', '', '', '00:10:00', '', 'count-down', 'Holding slide on screens'],
|
||||
['Strike', '14:00 - AV & Room strike', '#A790F5', '', '', '', '', 'milestone'],
|
||||
];
|
||||
@@ -1,12 +1,34 @@
|
||||
import { CustomFields, OntimeEvent, OntimeGroup, SupportedEntry, TimerType } from 'ontime-types';
|
||||
import { ImportMap, MILLIS_PER_MINUTE } from 'ontime-utils';
|
||||
import { ImportMap, MILLIS_PER_MINUTE, millisToString } from 'ontime-utils';
|
||||
|
||||
import { parseExcel } from '../excel.parser.js';
|
||||
|
||||
import { dataFromExcelTemplate } from './mockData.js';
|
||||
import { simpleTemplate } from '../__mocks__/simpleTemplate.js';
|
||||
|
||||
describe('parseExcel()', () => {
|
||||
it('parses the example file', () => {
|
||||
it('parses the simple template file', () => {
|
||||
const result = parseExcel(simpleTemplate, {});
|
||||
|
||||
expect(result.rundown.flatOrder.length).toBe(14);
|
||||
expect(result.rundown.order.length).toBe(4);
|
||||
|
||||
const firstEvent = result.rundown.entries[result.rundown.flatOrder[2]];
|
||||
expect(firstEvent).toMatchObject({
|
||||
type: SupportedEntry.Event,
|
||||
title: 'Pre-show Countdown',
|
||||
});
|
||||
expect(millisToString((firstEvent as OntimeEvent).timeStart)).toBe('10:00:00');
|
||||
|
||||
const lastEvent = result.rundown.entries[result.rundown.flatOrder[12]];
|
||||
expect(lastEvent).toMatchObject({
|
||||
type: SupportedEntry.Event,
|
||||
title: 'Wrap up',
|
||||
});
|
||||
// the excel step does not relate elements yet
|
||||
expect(millisToString((lastEvent as OntimeEvent).timeEnd)).toBe('00:00:00');
|
||||
});
|
||||
it('parses an import map with only custom fields', () => {
|
||||
// partial import map with only custom fields
|
||||
const importMap = {
|
||||
custom: {
|
||||
|
||||
@@ -212,7 +212,7 @@ export const parseExcel = (
|
||||
return;
|
||||
}
|
||||
|
||||
//and fall through to treat it as an event
|
||||
// after group and milestones we only have events remaining
|
||||
const event = {
|
||||
...entry,
|
||||
custom: { ...entryCustomFields },
|
||||
@@ -223,6 +223,7 @@ export const parseExcel = (
|
||||
event.timerType = TimerType.CountDown;
|
||||
}
|
||||
|
||||
// we link all events unless user specifies otherwise
|
||||
if (entry.linkStart === undefined) {
|
||||
event.linkStart = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user