nopaque.app.extensions.Toaster = class Toaster { constructor(app) { this.app = app; } init() { this.app.userHub.addEventListener('patch', (event) => {this.#onPatch(event.detail);}); } #onPatch(patch) { // Handle job updates const jobRegExp = new RegExp(`^/users/([A-Za-z0-9]+)/jobs/([A-Za-z0-9]+)`); const jobPatch = patch.filter((operation) => {return jobRegExp.test(operation.path);}); this.#onJobPatch(jobPatch); // Handle corpus updates const corpusRegExp = new RegExp(`^/users/([A-Za-z0-9]+)/corpora/([A-Za-z0-9]+)`); const corpusPatch = patch.filter((operation) => {return corpusRegExp.test(operation.path);}); this.#onCorpusPatch(corpusPatch); } async #onJobPatch(patch) { // Handle job status updates const jobStatusRegExp = new RegExp(`^/users/([A-Za-z0-9]+)/jobs/([A-Za-z0-9]+)/status$`); const jobStatusPatch = patch.filter((operation) => {return operation.op === 'replace';}); for (let operation of jobStatusPatch) { const [match, userId, jobId] = operation.path.match(jobStatusRegExp); const user = await this.app.userHub.get(userId); const job = user.jobs[jobId]; this.app.ui.flash(`[${job.title}] New status: `, 'job'); } } async #onCorpusPatch(patch) { // Handle job status updates const corpusStatusRegExp = new RegExp(`^/users/([A-Za-z0-9]+)/corpora/([A-Za-z0-9]+)/status$`); const corpusStatusPatch = patch.filter((operation) => {return operation.op === 'replace';}); for (let operation of corpusStatusPatch) { const [match, userId, corpusId] = operation.path.match(corpusStatusRegExp); const user = await this.app.userHub.get(userId); const corpus = user.corpora[corpusId]; this.app.ui.flash(`[${corpus.title}] New status: `, 'job'); } } }