Skip to content

Commit

Permalink
Fix import of session validation results and notes
Browse files Browse the repository at this point in the history
Also improve logging of script execution steps to ease debugging.
  • Loading branch information
tidoust committed Feb 13, 2025
1 parent 94ce7fa commit eed951e
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 59 deletions.
70 changes: 35 additions & 35 deletions tools/appscript/export-to-github.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { fetchProjectFromGitHub, saveSessionMeetings } from '../common/project.m
*/
export default async function () {
// TODO: consider reading only the list of sessions
console.log('Read data from spreadsheet...');
const project = getProject(SpreadsheetApp.getActiveSpreadsheet());
console.log('Read data from spreadsheet... done');

if (!project.metadata.reponame) {
reportError(`No GitHub repository associated with the current document.
Expand All @@ -25,22 +27,17 @@ If not, ask François or Ian to run the required initialization steps.`);
name: repoparts.length > 1 ? repoparts[1] : repoparts[0]
};

let githubProject;
try {
githubProject = await fetchProjectFromGitHub(
console.log('Fetch data from GitHub...');
const githubProject = await fetchProjectFromGitHub(
repo.owner === 'w3c' ? repo.owner : `user/${repo.owner}`,
repo.name,
null
);
}
catch (err) {
reportError(err.toString());
return;
}
console.log('Fetch data from GitHub... done');

const updated = [];
try {
// Check sessions that need an update
console.log('Export updates when needed...');
const updated = [];
for (const session of githubProject.sessions) {
const ssSession = project.sessions.find(s =>
s.number === session.number);
Expand Down Expand Up @@ -79,34 +76,37 @@ If not, ask François or Ian to run the required initialization steps.`);
console.warn(`- updating #${session.number}... done`);
}
}
console.log('Export updates when needed... done');

// Report the list of sessions that were updated
console.log('Report result...');
if (updated.length > 0) {
const list = updated.map(s =>
`${s.title} (<a href="https://github.com/${s.repository}/issues/${s.number}">#${s.number}</a>)`);
const htmlOutput = HtmlService
.createHtmlOutput(`
<p>The following session${list.length > 1 ? 's were' : ' was'} updated:</p>
<ul>
<li>${list.join('</li><li>')}</li>
</ul>
`)
.setWidth(400)
.setHeight(400);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Updated');
}
else {
const htmlOutput = HtmlService
.createHtmlOutput(`
<p>Data seems up-to-date already, nothing to export!</p>`
)
.setWidth(400)
.setHeight(400);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Nothing to update');
}
console.log('Report result... done');
}
catch(err) {
reportError(err.toString());
return;
}

// Report the list of sessions that were updated
if (updated.length > 0) {
const list = updated.map(s =>
`${s.title} (<a href="https://github.com/${s.repository}/issues/${s.number}">#${s.number}</a>)`);
const htmlOutput = HtmlService
.createHtmlOutput(`
<p>The following session${list.length > 1 ? 's were' : ' was'} updated:</p>
<ul>
<li>${list.join('</li><li>')}</li>
</ul>`
)
.setWidth(400)
.setHeight(400);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Updated');
}
else {
const htmlOutput = HtmlService
.createHtmlOutput(`
<p>Data seems up-to-date already, nothing to export!</p>`
)
.setWidth(400)
.setHeight(400);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Nothing to update');
}
}
41 changes: 25 additions & 16 deletions tools/appscript/import-from-github.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import * as YAML from '../../node_modules/yaml/browser/index.js';
* Trigger a GitHub workflow that refreshes the data from GitHub
*/
export default async function () {
console.log('Read data from spreadsheet...');
const project = getProject(SpreadsheetApp.getActiveSpreadsheet());
console.log('Read data from spreadsheet... done');

if (!project.metadata.reponame) {
reportError(`No GitHub repository associated with the current document.
Expand All @@ -26,40 +28,47 @@ If not, ask François or Ian to run the required initialization steps.`);
name: repoparts.length > 1 ? repoparts[1] : repoparts[0]
};

let githubProject;
try {
console.log('Fetch session template from GitHub...');
const yamlTemplateResponse = UrlFetchApp.fetch(
`https://raw.githubusercontent.com/${repo.owner}/${repo.name}/refs/heads/main/.github/ISSUE_TEMPLATE/session.yml`
);
const yamlTemplate = yamlTemplateResponse.getContentText();
const template = YAML.parse(yamlTemplate);
console.log('Fetch session template from GitHub... done');

githubProject = await fetchProjectFromGitHub(
console.log('Fetch data from GitHub...');
const githubProject = await fetchProjectFromGitHub(
repo.owner === 'w3c' ? repo.owner : `user/${repo.owner}`,
repo.name,
template
);
}
catch (err) {
reportError(err.toString());
return;
}
console.log('Fetch data from GitHub... done');

try {
console.log('Refresh spreadsheet data...');
refreshProject(SpreadsheetApp.getActiveSpreadsheet(), githubProject, {
what: 'all'
});
console.log('Refresh spreadsheet data... done');

console.log('Report result...');
const htmlOutput = HtmlService
.createHtmlOutput(`
<p>Spreadsheet updated with data from GitHub:</p>
<ul>
<li><b>${githubProject.rooms.length}</b> rooms</li>
<li><b>${githubProject.days.length}</b> days</li>
<li><b>${githubProject.slots.length}</b> slots</li>
<li><b>${githubProject.sessions.length}</b> sessions</li>
</ul>
`)
.setWidth(300)
.setHeight(400);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Data exported');
console.log('Report result... done');
}
catch(err) {
reportError(err.toString());
return;
}

const htmlOutput = HtmlService
.createHtmlOutput(
'<pre>' + JSON.stringify(githubProject, null, 2) + '</pre>'
)
.setWidth(300)
.setHeight(400);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'GitHub project');
}
35 changes: 27 additions & 8 deletions tools/appscript/project.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ function getValues(sheet) {
function setValues(sheet, values) {
const nbRows = sheet.getLastRow() - 1;
const nbColumns = sheet.getLastColumn();
console.log('rows cols', nbRows, nbColumns);

const headers = sheet
.getRange(1, 1, 1, nbColumns)
Expand All @@ -279,12 +278,12 @@ function setValues(sheet, values) {
}
return value;
});
console.log('headers', headers);
console.log(' - sheet headers', headers);

// Values is an array of indexed objects, while we need a two-dimensional
// array of raw values. Let's convert the values.
const rawValues = values.map((obj, vidx) => headers.map(header => {
if (!obj.hasOwnProperty(header)) {
if (!Object.hasOwn(obj, header)) {
return '';
}
if (obj[header] === true) {
Expand All @@ -293,36 +292,45 @@ function setValues(sheet, values) {
if (obj[header] === false) {
return 'no';
}
if (obj[header] === null) {
if (obj[header] === null || obj[header] === undefined) {
return '';
}
if (header === 'labels' && obj[header]) {
return obj[header].join(', ');
}
if (header === 'author' && obj[header].login) {
return obj[header].login;
}
return obj[header];
}));
console.log('raw values', rawValues);
console.log(' - raw values to set', rawValues);

// Note: we may have more or less rows than in the current sheet
if (nbRows > 0) {
const updateNb = Math.min(nbRows, rawValues.length);
console.log(` - updating ${updateNb}/${rawValues.length} rows...`);
const updateRange = sheet.getRange(
2, 1, updateNb, nbColumns
);
updateRange.setValues(rawValues.slice(0, updateNb));
console.log(` - updating ${updateNb}/${rawValues.length} rows... done`);
if (nbRows > rawValues.length) {
console.log(` - clearing ${nbRows - rawValues.length} rows...`);
const clearRange = sheet.getRange(
rawValues.length + 2, 1,
nbRows - rawValues.length, nbColumns
);
clearRange.clear();
console.log(` - clearing ${nbRows - rawValues.length} rows... done`);
}
}
if (nbRows < rawValues.length) {
console.log(` - adding ${rawValues.length - nbRows} rows...`);
const appendRange = sheet.getRange(
nbRows + 2, 1,
rawValues.length - nbRows, nbColumns);
appendRange.setValues(rawValues.slice(nbRows));
console.log(` - adding ${rawValues.length - nbRows} rows... done`);
}
}

Expand Down Expand Up @@ -365,10 +373,13 @@ export function refreshProject(spreadsheet, project, { what }) {
else if (type === 'sessions') {
idKey = 'number';
}
console.log(type, idKey);
const values = sheets[type].values ?? [];
const seen = [];
for (const obj of project[type]) {
for (let obj of project[type]) {
// Validation notes are nested under a "validation" key in the
// internal representation of a project, but are at the root level
// in the spreadsheet. Let's copy them to the root level as well.
obj = Object.assign({}, obj, obj.validation);
const value = values.find(val => val[idKey] === obj[idKey]);
if (value) {
// Existing item, refresh the data
Expand All @@ -379,33 +390,40 @@ export function refreshProject(spreadsheet, project, { what }) {
}
else {
// New item, add to the end of the list
// (copy validation notes along the way)
values.push(obj);
seen.push(obj);
}
}
const toset = values.filter(value => seen.includes(value));
console.log(type, toset.length);
console.log(`- import ${toset.length} ${type}...`);
setValues(sheets[type].sheet, toset);
console.log(`- import ${toset.length} ${type}... done`);

// Set formula to auto-fill the weekday in the days sheet
// and the slot name in the slots sheet
// TODO: this assumes a position for the columns
if (type === 'days') {
console.log(`- add formula for weekday column again...`);
const range = sheets[type].sheet.getRange('B2:B');
range.setFormulaR1C1(
'=IF(INDIRECT("R[0]C[-1]", false) <> "", CHOOSE(WEEKDAY(INDIRECT("R[0]C[-1]", false)), "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ), "")'
);
console.log(`- add formula for weekday column again... done`);
}
if (type === 'slots') {
console.log(`- add formula for slot name column again...`);
const range = sheets[type].sheet.getRange('C2:C');
range.setFormulaR1C1(
'=IF(INDIRECT("R[0]C[-2]", false) <> "", CONCAT(CONCAT(INDIRECT("R[0]C[-2]", false), "-"), INDIRECT("R[0]C[-1]", false)), "")'
);
console.log(`- add formula for slot name column again... done`);
}

// To make team's life easier, we'll convert session numbers in the first
// column to a link to the session on GitHub
if (type === 'sessions' && toset.length > 0) {
console.log(`- convert session numbers to links...`);
const richValues = toset
.map(session => SpreadsheetApp
.newRichTextValue()
Expand All @@ -416,6 +434,7 @@ export function refreshProject(spreadsheet, project, { what }) {
.map(richValue => [richValue]);
const range = sheets[type].sheet.getRange(2, 1, toset.length, 1);
range.setRichTextValues(richValues);
console.log(`- convert session numbers to links... done`);
}

SpreadsheetApp.flush();
Expand Down

0 comments on commit eed951e

Please sign in to comment.