angular/aio/scripts/generate-events/apps-script-extension/persister.js
George Kalpakas c9241fdeb0 build(docs-infra): introduce new process for generating data for the events page (#45588)
This commit introduces a new process for generating data for the AIO
[events page](https://angular.io/events), which streamlines the process
and minimizes duplication and manual work. For more details, see
`aio/scripts/generate-events/README.md`.

PR Close #45588
2022-09-12 12:25:44 -07:00

107 lines
3.1 KiB
JavaScript

/**
* Helper function to be invoked by a manually set-up, time-based trigger in order to update the
* data on Firebase.
*/
function updateEventsOnFirebase() {
const persister = new Persister();
persister.updateDb();
}
/**
* Helper class to encapsulate logic about persisting events changes in the spreadsheet to the
* database (currently Firebase Realtime Database).
*/
class Persister {
/**
* Update the database with the latest data from edited sheets.
*
* If no sheets have been edited, this is a no-op.
*/
updateDb() {
this._log('Updating database...');
// Get the data for each edited sheet.
const data = this._getDataForEditedSheets();
// If no sheets have been edited, there is nothing to do.
if (data.length === 0) {
this._log('No sheets edited. Exiting...');
return;
}
// Update the database.
const partialEvents = data.reduce((acc, dataForSheet) => {
acc[dataForSheet.year] = dataForSheet.events;
return acc;
}, {});
const res = UrlFetchApp.fetch(`${DB_BASE_URL}/events.json?print=silent`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`,
'Content-type': 'application/json',
},
payload: JSON.stringify(partialEvents),
});
this._log(`Database updated: ${res.getResponseCode()} - ${res.getContentText()}`);
}
_getDataForEditedSheets() {
// Get edited sheets that need processing.
const editedSheets = Property.editedSheets.get() || [];
this._log(`Edited sheets (${editedSheets.length}): ${editedSheets.join(', ') || '-'}`);
// Delete the corresponding property, indicating that no processing is pending.
Property.editedSheets.delete();
// Get the events data for edited sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
return editedSheets.map(name => this._getDataForSheet(ss.getSheetByName(name)));
}
_getDataForSheet(sheet) {
const year = TEAM_ALLOCATION_SHEET_NAME_RE.exec(sheet.getName())[1];
// Get event dates per cell index.
// Dates display value is expected to be in the format `M/D`. For example: `5/15`
const startDatesRange = sheet.getRange('1:1');
const startDates = startDatesRange.
getDisplayValues()[0].
map((x, i) => ({
index: i,
value: x,
})).
filter(x => x.value !== '').
map(x => ({
index: x.index,
date: `${year}-${x.value.split('/').map(p => p.padStart(2, '0')).join('-')}`,
}));
// Get other event info (name, url) per cell index and merge with dates.
const namesRange = sheet.getRange('2:2');
const events = namesRange.
getRichTextValues()[0].
map((x, i) => ({
index: i,
value: {
text: x.getText(),
url: x.getLinkUrl() || undefined,
},
})).
filter(x => !/^(?:total)?$/i.test(x.value.text)).
map(x => ({
name: x.value.text,
linkUrl: x.value.url,
date: {
start: (startDates.find(y => y.index === x.index) || {}).date,
},
}));
return {year, events};
}
_log(msg) {
Logger.log(`[Persister] ${msg}`);
}
}