Skip to content

Commit 64dae52

Browse files
committed
Add ability to export event schedule as an HTML file
New menu action in the Advanced menu do download event data in the spreadsheet either as an HTML page (for the schedule) or as a JSON file (for debugging and for setting up the event initially when the repository/project do not exist yet).
1 parent b6920fe commit 64dae52

File tree

10 files changed

+108
-31
lines changed

10 files changed

+108
-31
lines changed

tools/appscript/add-custom-menu.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default function () {
2222
.addItem('Retrieve latest published schedule (from GitHub)', 'importGrid')
2323
.addItem('Fetch event info, rooms, days, slots (from GitHub)', 'importMetadata')
2424
/*.addItem('Export event info, rooms, days, slots to GitHub', 'exportMetadata')*/
25-
.addItem('Dump event data as JSON', 'exportEventData')
25+
.addItem('Export event to files (HTML, JSON)', 'exportEventToFiles')
2626
)
2727
.addToUi();
2828
}

tools/appscript/export-event-data.mjs

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { getProject } from './lib/project.mjs';
2+
import reportError from './lib/report-error.mjs';
3+
import { fetchMapping } from './lib/w3cid-map.mjs';
4+
import { convertProjectToHTML } from '../common/project2html.mjs';
5+
6+
7+
/**
8+
* Generate the grid for the current spreadsheet
9+
*/
10+
export default function () {
11+
return exportEventToFiles(SpreadsheetApp.getActiveSpreadsheet());
12+
}
13+
14+
15+
/**
16+
* Generate the grid in the provided spreadsheet
17+
*/
18+
async function exportEventToFiles(spreadsheet) {
19+
try {
20+
console.log('Read data from spreadsheet...');
21+
const project = getProject(spreadsheet);
22+
project.w3cIds = await fetchMapping();
23+
if (!project.sheets.sessions.sheet) {
24+
reportError('No sheet found that contains the list of sessions, please import data from GitHub first.');
25+
return;
26+
}
27+
console.log('Read data from spreadsheet... done');
28+
29+
console.log('Convert to HTML...');
30+
const html = await convertProjectToHTML(project);
31+
console.log('Convert to HTML... done');
32+
33+
console.log('Create data URL for the HTML export...');
34+
const htmlBase64 = Utilities.base64Encode(html, Utilities.Charset.UTF_8);
35+
const htmlDataUrl = `data:text/html;charset=UTF8;base64,${htmlBase64}`;
36+
console.log('Create data URL for the HTML export... done');
37+
38+
console.log('Create data URL for the JSON export...');
39+
const jsonBase64 = Utilities.base64Encode(
40+
JSON.stringify(project, null, 2),
41+
Utilities.Charset.UTF_8);
42+
const jsonDataUrl = `data:application/json;charset=UTF8;base64,${jsonBase64}`;
43+
console.log('Create data URL for the JSON export... done');
44+
45+
console.log('Report result...');
46+
const htmlOutput = HtmlService
47+
.createHtmlOutput(`<p>
48+
Event data files prepared.
49+
Click following link(s) to download them:
50+
</p>
51+
<ul>
52+
<li>
53+
<a href="${htmlDataUrl}" download="event.html">
54+
Download event schedule as an HTML file
55+
</a>
56+
</li>
57+
<li>
58+
<a href="${jsonDataUrl}" download="event.json">
59+
Download event data as a JSON file
60+
</a>
61+
</li>
62+
</ul>
63+
`)
64+
.setWidth(300)
65+
.setHeight(400);
66+
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Export event to a file');
67+
console.log('Report result... done');
68+
}
69+
catch(err) {
70+
reportError(err.toString());
71+
return;
72+
}
73+
}

tools/appscript/lib/project.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,7 @@ export function getProject(spreadsheet) {
178178
days: sheets.days.values
179179
.filter(v => !!v.date)
180180
.map(v => {
181-
const name = v.weekday ?
182-
v.weekday + ' (' + v.date + ')' :
183-
v.date;
181+
const name = v.date;
184182
return {
185183
id: v.id,
186184
name,

tools/appscript/main.mjs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/**
2+
* The `add-custom-menu.mjs` script creates the custom menu in the spreadsheet.
3+
* Entries in the custom menu trigger a call to a JavaScript function, but that
4+
* association is done through a string.
5+
*
6+
* This file forces the exposition of these menu functions as global functions.
7+
* That is needed because the rollup bundler does not know anything about
8+
* the AppScript environment, and does not understand the association between
9+
* the custom menu and the functions.
10+
*
11+
* Bundle generation with Rollup must also run with the `--no-treeshake` option
12+
* for the same reason: Rollup would simply drop all code and generate an empty
13+
* bundle otherwise (precisely because, as far as it can tell, nothing calls
14+
* these global functions).
15+
*/
16+
117
import _createOnOpenTrigger from './create-onopen-trigger.mjs';
218
import _addTPACMenu from './add-custom-menu.mjs';
319
import _generateGrid from './generate-grid.mjs';
@@ -8,7 +24,7 @@ import _importGrid from './import-grid.mjs';
824
import _importSessions from './import-sessions.mjs';
925
import _importMetadata from './import-metadata.mjs';
1026
import _exportMetadata from './export-metadata.mjs';
11-
import _exportEventData from './export-event-data.mjs';
27+
import _exportEventToFiles from './export-event-to-files.mjs';
1228

1329
function main() { _createOnOpenTrigger(); }
1430
function addTPACMenu() { _addTPACMenu(); }
@@ -20,4 +36,4 @@ function importGrid() { _importGrid(); }
2036
function importSessions() { _importSessions(); }
2137
function importMetadata() { _importMetadata(); }
2238
function exportMetadata() { _exportMetadata(); }
23-
function exportEventData() { _exportEventData(); }
39+
function exportEventToFiles() { _exportEventToFiles(); }

tools/common/project.mjs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,15 @@ export async function fetchProjectFromGitHub(login, id, sessionTemplate) {
374374
// all sessions will be associated with it.
375375
daysFieldId: days.id,
376376
days: days.options.map(day => {
377+
const metadata = {};
378+
(day.description ?? '')
379+
.split(/\n/)
380+
.map(line => line.trim().replace(/^[*\-] /, '').split(/:\s*/))
381+
.filter(data => data[0] && data[1])
382+
.forEach(data => metadata[data[0].toLowerCase()] = data[1]);
377383
const match =
378384
day.name.match(/(.*) \((\d{4}\-\d{2}\-\d{2})\)$/) ??
379-
[day.name, day.name, day.name];
385+
[day.name, metadata.weekday ?? day.name, day.name];
380386
return {
381387
id: day.id,
382388
name: match[0],
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { parseSessionMeetings, groupSessionMeetings } from '../../common/meetings.mjs';
2-
import { validateGrid } from '../../common/validate.mjs';
3-
import * as YAML from 'yaml';
1+
import { parseSessionMeetings, groupSessionMeetings } from './meetings.mjs';
2+
import { validateGrid } from './validate.mjs';
3+
import * as YAML from '../../node_modules/yaml/browser/index.js';
44

55
const hasMeeting = s => s.atomicMeetings.find(m => m.room && m.day && m.slot);
66

@@ -245,7 +245,7 @@ export async function convertProjectToHTML(project, cliParams) {
245245
for (const table of tables) {
246246
// Columns represent the rooms
247247
writeLine(3, `<section id="d${table.day.date}">
248-
<h3>${table.day.name}</h3>
248+
<h3>${table.day.label ? table.day.label + ' (' + table.day.date + ')' : table.day.name}</h3>
249249
<table>
250250
<thead>
251251
<tr>
@@ -516,7 +516,7 @@ export async function convertProjectToHTML(project, cliParams) {
516516
writeLine(2, '</section>');
517517
}
518518

519-
if (cliParams && !reduce) {
519+
if (cliParams?.cmd && !reduce) {
520520
writeLine(2, `<section id="cli">
521521
<h2>Generation parameters</h2>
522522
<ul>

tools/node/schedule.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { readFile } from 'fs/promises';
2-
import { convertProjectToHTML } from './lib/project2html.mjs';
2+
import { convertProjectToHTML } from '../common/project2html.mjs';
33
import { saveSessionMeetings } from '../common/project.mjs';
44
import { parseMeetingsChanges, applyMeetingsChanges } from './lib/meetings.mjs';
55
import { validateGrid } from '../common/validate.mjs';

tools/node/try-changes.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { validateGrid } from '../common/validate.mjs';
22
import { saveSessionMeetings } from '../common/project.mjs';
3-
import { convertProjectToHTML } from './lib/project2html.mjs';
3+
import { convertProjectToHTML } from '../common/project2html.mjs';
44

55
export default async function (project, options) {
66
if (!project.allowTryMeOut) {

tools/node/view-event.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { convertProjectToHTML } from './lib/project2html.mjs';
1+
import { convertProjectToHTML } from '../common/project2html.mjs';
22
import { convertProjectToJSON } from '../common/project.mjs';
33

44
export default async function (project, options) {

0 commit comments

Comments
 (0)