Further js refactoring

This commit is contained in:
Patrick Jentsch
2024-12-05 14:26:05 +01:00
parent df2bffe0fd
commit c97b2a886e
18 changed files with 110 additions and 68 deletions

View File

@@ -0,0 +1 @@
nopaque.app.endpoints = {};

View File

@@ -1,12 +1,10 @@
nopaque.UsersExtension = class UsersExtension {
nopaque.app.endpoints.Users = class Users {
constructor(app) {
this.app = app;
this.socket = io('/users', {transports: ['websocket'], upgrade: false});
}
init() {}
async get(userId) {
const response = await this.socket.emitWithAck('get', userId);

View File

@@ -0,0 +1 @@
nopaque.app.extensions = {};

View File

@@ -0,0 +1,51 @@
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(`[<a href="/jobs/${jobId}">${job.title}</a>] New status: <span class="job-status-text" data-job-status="${operation.value}"></span>`, '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(`[<a href="/corpora/${corpusId}">${corpus.title}</a>] New status: <span class="job-status-text" data-job-status="${operation.value}"></span>`, 'job');
}
}
}

View File

@@ -1,4 +1,4 @@
nopaque.UIExtension = class UIExtension {
nopaque.app.extensions.UI = class UI {
constructor(app) {
this.app = app;
}

View File

@@ -1,4 +1,4 @@
nopaque.LiveUserRegistryExtension = class LiveUserRegistryExtension extends EventTarget {
nopaque.app.extensions.UserHub = class UserHub extends EventTarget {
#data;
constructor(app) {
@@ -36,35 +36,33 @@ nopaque.LiveUserRegistryExtension = class LiveUserRegistryExtension extends Even
#onPatch(patch) {
// Filter patch to only include operations on users that are initialized
let filterRegExp = new RegExp(`^/users/(${Object.keys(this.#data.users).join('|')})`);
let filteredPatch = patch.filter(operation => filterRegExp.test(operation.path));
const filterRegExp = new RegExp(`^/users/(${Object.keys(this.#data.users).join('|')})`);
const filteredPatch = patch.filter(operation => filterRegExp.test(operation.path));
// Apply patch
jsonpatch.applyPatch(this.#data, filteredPatch);
// Notify event listeners
let event = new CustomEvent('patch', {detail: filteredPatch});
this.dispatchEvent(event);
const patchEventa = new CustomEvent('patch', {detail: filteredPatch});
this.dispatchEvent(patchEventa);
/*
// Notify event listeners. Event type: "patch *"
let event = new CustomEvent('patch *', {detail: filteredPatch});
this.dispatchEvent(event);
const patchEvent = new CustomEvent('patch *', {detail: filteredPatch});
this.dispatchEvent(patchEvent);
// Group patches by user id: {<user-id>: [op, ...], ...}
let patches = {};
let matchRegExp = new RegExp(`^/users/([A-Za-z0-9]+)`);
const patches = {};
const matchRegExp = new RegExp(`^/users/([A-Za-z0-9]+)`);
for (let operation of filteredPatch) {
let [match, userId] = operation.path.match(matchRegExp);
const [match, userId] = operation.path.match(matchRegExp);
if (!(userId in patches)) {patches[userId] = [];}
patches[userId].push(operation);
}
// Notify event listeners. Event type: "patch <user-id>"
for (let [userId, patch] of Object.entries(patches)) {
let event = new CustomEvent(`patch ${userId}`, {detail: patch});
this.dispatchEvent(event);
const userPatchEvent = new CustomEvent(`patch ${userId}`, {detail: patch});
this.dispatchEvent(userPatchEvent);
}
*/
}
}

View File

@@ -0,0 +1 @@
nopaque.app = {};