mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
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
107 lines
3.1 KiB
JavaScript
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}`);
|
|
}
|
|
}
|