nopaque/app/static/js/App.js

101 lines
3.2 KiB
JavaScript
Raw Normal View History

2021-11-30 15:22:16 +00:00
class App {
constructor() {
this.data = {
promises: {getUser: {}, subscribeUser: {}},
users: {},
};
2021-11-30 15:22:16 +00:00
this.socket = io({transports: ['websocket'], upgrade: false});
2022-09-02 11:07:30 +00:00
this.socket.on('PATCH', (patch) => {this.onPatch(patch);});
2021-11-30 15:22:16 +00:00
}
getUser(userId, backrefs=false, relationships=false) {
if (userId in this.data.promises.getUser) {
return this.data.promises.getUser[userId];
}
this.data.promises.getUser[userId] = new Promise((resolve, reject) => {
this.socket.emit('GET /users/<user_id>', userId, backrefs, relationships, (response) => {
if (response.status !== 200) {
reject(response);
return;
}
this.data.users[userId] = response.body;
resolve(this.data.users[userId]);
});
});
return this.data.promises.getUser[userId];
2021-12-01 13:15:20 +00:00
}
2021-11-30 15:22:16 +00:00
2022-07-04 12:09:17 +00:00
subscribeUser(userId) {
if (userId in this.data.promises.subscribeUser) {
return this.data.promises.subscribeUser[userId];
2021-12-01 13:15:20 +00:00
}
this.data.promises.subscribeUser[userId] = new Promise((resolve, reject) => {
this.socket.emit('SUBSCRIBE /users/<user_id>', userId, (response) => {
if (response.status !== 200) {
2022-07-04 12:09:17 +00:00
reject(response);
return;
2022-07-04 12:09:17 +00:00
}
resolve(response);
2022-07-04 12:09:17 +00:00
});
});
return this.data.promises.subscribeUser[userId];
2021-11-30 15:22:16 +00:00
}
flash(message, category) {
2022-09-02 11:07:30 +00:00
let iconPrefix = '';
2021-11-30 15:22:16 +00:00
switch (category) {
2022-09-02 11:07:30 +00:00
case 'corpus': {
2021-12-01 13:15:20 +00:00
iconPrefix = '<i class="left material-icons">book</i>';
2021-11-30 15:22:16 +00:00
break;
2022-09-02 11:07:30 +00:00
}
case 'error': {
2021-12-01 13:15:20 +00:00
iconPrefix = '<i class="error-color-text left material-icons">error</i>';
2021-11-30 15:22:16 +00:00
break;
2022-09-02 11:07:30 +00:00
}
case 'job': {
iconPrefix = '<i class="left nopaque-icons">J</i>';
2021-11-30 15:22:16 +00:00
break;
2022-09-02 11:07:30 +00:00
}
default: {
2021-12-01 13:15:20 +00:00
iconPrefix = '<i class="left material-icons">notifications</i>';
break;
2022-09-02 11:07:30 +00:00
}
2021-11-30 15:22:16 +00:00
}
2022-09-02 11:07:30 +00:00
let toast = M.toast(
2021-12-01 13:15:20 +00:00
{
html: `
<span>${iconPrefix}${message}</span>
2022-09-02 11:07:30 +00:00
<button class="action-button btn-flat toast-action white-text" data-action="close">
2021-12-01 13:15:20 +00:00
<i class="material-icons">close</i>
</button>
`.trim()
}
);
2022-09-02 11:07:30 +00:00
let toastCloseActionElement = toast.el.querySelector('.action-button[data-action="close"]');
2021-11-30 15:22:16 +00:00
toastCloseActionElement.addEventListener('click', () => {toast.dismiss();});
}
2022-09-02 11:07:30 +00:00
onPatch(patch) {
// Filter Patch to only include operations on users that are initialized
let regExp = new RegExp(`^/users/(${Object.keys(this.data.users).join('|')})`);
let filteredPatch = patch.filter(operation => regExp.test(operation.path));
// Handle job status updates
let subRegExp = new RegExp(`^/users/([A-Za-z0-9]*)/jobs/([A-Za-z0-9]*)/status$`);
let subFilteredPatch = filteredPatch
.filter((operation) => {return operation.op === 'replace';})
.filter((operation) => {return subRegExp.test(operation.path);});
for (let operation of subFilteredPatch) {
let [match, userId, jobId] = operation.path.match(subRegExp);
this.flash(`[<a href="/jobs/${jobId}">${this.data.users[userId].jobs[jobId].title}</a>] New status: <span class="job-status-text" data-job-status="${operation.value}"></span>`, 'job');
}
// Apply Patch
jsonpatch.applyPatch(this.data, filteredPatch);
}
2021-11-30 15:22:16 +00:00
}