mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2025-06-15 10:30:40 +00:00
Update javascript app structure
This commit is contained in:
@ -1,10 +1,9 @@
|
||||
nopaque.App = class App {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
|
||||
this.socket = io({transports: ['websocket'], upgrade: false});
|
||||
|
||||
this.ui = new nopaque.UIExtension(this);
|
||||
this.liveUserRegistry = new nopaque.LiveUserRegistryExtension(this);
|
||||
this.users = new nopaque.UsersExtension(this);
|
||||
}
|
||||
|
||||
@ -29,5 +28,7 @@ nopaque.App = class App {
|
||||
|
||||
init() {
|
||||
this.ui.init();
|
||||
this.liveUserRegistry.init();
|
||||
this.users.init();
|
||||
}
|
||||
};
|
||||
|
@ -1,53 +0,0 @@
|
||||
nopaque.UsersExtension = class UsersExtension {
|
||||
#data;
|
||||
#promises;
|
||||
|
||||
constructor(app) {
|
||||
this.app = app;
|
||||
|
||||
this.#data = {};
|
||||
this.app.data.users = this.#data;
|
||||
|
||||
this.#promises = {
|
||||
get: {},
|
||||
subscribe: {}
|
||||
};
|
||||
}
|
||||
|
||||
async #get(userId) {
|
||||
const response = await this.app.socket.emitWithAck('users.get', userId);
|
||||
|
||||
if (response.status != 200) {
|
||||
throw new Error(`[${response.status}] ${response.statusText}`);
|
||||
}
|
||||
|
||||
this.#data[userId] = response.body;
|
||||
return this.#data[userId];
|
||||
}
|
||||
|
||||
get(userId) {
|
||||
if (userId in this.#promises.get) {
|
||||
return this.#promises.get[userId];
|
||||
}
|
||||
|
||||
this.#promises.get[userId] = this.#get(userId);
|
||||
return this.#promises.get[userId];
|
||||
}
|
||||
|
||||
async #subscribe(userId) {
|
||||
const response = await this.app.socket.emitWithAck('users.subscribe', userId);
|
||||
|
||||
if (response.status != 200) {
|
||||
throw new Error(`[${response.status}] ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(userId) {
|
||||
if (userId in this.#promises.subscribe) {
|
||||
return this.#promises.subscribe[userId];
|
||||
}
|
||||
|
||||
this.#promises.subscribe[userId] = this.#subscribe(userId);
|
||||
return this.#promises.subscribe[userId];
|
||||
}
|
||||
}
|
70
app/static/js/app/user-live-registry.js
Normal file
70
app/static/js/app/user-live-registry.js
Normal file
@ -0,0 +1,70 @@
|
||||
nopaque.LiveUserRegistryExtension = class LiveUserRegistryExtension extends EventTarget {
|
||||
#data;
|
||||
|
||||
constructor(app) {
|
||||
super();
|
||||
|
||||
this.app = app;
|
||||
|
||||
this.#data = {
|
||||
users: {},
|
||||
promises: {}
|
||||
};
|
||||
}
|
||||
|
||||
init() {
|
||||
this.app.users.socket.on('patch', (patch) => {this.#onPatch(patch)});
|
||||
}
|
||||
|
||||
add(userId) {
|
||||
if (!(userId in this.#data.promises)) {
|
||||
this.#data.promises[userId] = this.#add(userId);
|
||||
}
|
||||
|
||||
return this.#data.promises[userId];
|
||||
}
|
||||
|
||||
async #add(userId) {
|
||||
await this.app.users.subscribe(userId);
|
||||
this.#data.users[userId] = await this.app.users.get(userId);
|
||||
}
|
||||
|
||||
async get(userId) {
|
||||
await this.add(userId);
|
||||
return this.#data.users[userId];
|
||||
}
|
||||
|
||||
#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));
|
||||
|
||||
// Apply patch
|
||||
jsonpatch.applyPatch(this.#data, filteredPatch);
|
||||
|
||||
// Notify event listeners
|
||||
let event = new CustomEvent('patch', {detail: filteredPatch});
|
||||
this.dispatchEvent(event);
|
||||
|
||||
/*
|
||||
// Notify event listeners. Event type: "patch *"
|
||||
let event = new CustomEvent('patch *', {detail: filteredPatch});
|
||||
this.dispatchEvent(event);
|
||||
|
||||
// Group patches by user id: {<user-id>: [op, ...], ...}
|
||||
let patches = {};
|
||||
let matchRegExp = new RegExp(`^/users/([A-Za-z0-9]+)`);
|
||||
for (let operation of filteredPatch) {
|
||||
let [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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
43
app/static/js/app/users.js
Normal file
43
app/static/js/app/users.js
Normal file
@ -0,0 +1,43 @@
|
||||
nopaque.UsersExtension = class UsersExtension {
|
||||
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);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`[${response.status}] ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.body;
|
||||
}
|
||||
|
||||
async subscribe(userId) {
|
||||
const response = await this.socket.emitWithAck('subscribe', userId);
|
||||
|
||||
if (response.status != 200) {
|
||||
throw new Error(`[${response.status}] ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
|
||||
async unsubscribe(userId) {
|
||||
const response = await this.socket.emitWithAck('unsubscribe', userId);
|
||||
|
||||
if (response.status != 200) {
|
||||
throw new Error(`[${response.status}] ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(userId) {
|
||||
const response = await this.socket.emitWithAck('delete', userId);
|
||||
|
||||
if (response.status != 202) {
|
||||
throw new Error(`[${response.status}] ${response.statusText}`);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,19 +5,14 @@ nopaque.resource_displays.ResourceDisplay = class ResourceDisplay {
|
||||
this.displayElement = displayElement;
|
||||
this.userId = this.displayElement.dataset.userId;
|
||||
this.isInitialized = false;
|
||||
if (this.userId) {
|
||||
app.users.subscribe(this.userId)
|
||||
.then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
});
|
||||
app.users.get(this.userId)
|
||||
.then((user) => {
|
||||
this.init(user);
|
||||
this.isInitialized = true;
|
||||
});
|
||||
}
|
||||
if (this.userId === undefined) {return;}
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.init(user);
|
||||
this.isInitialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
init(user) {throw 'Not implemented';}
|
||||
|
@ -14,12 +14,11 @@ nopaque.resource_lists.CorpusFileList = class CorpusFileList extends nopaque.res
|
||||
this.hasPermissionView = listContainerElement.dataset?.hasPermissionView == 'true' || false;
|
||||
this.hasPermissionManageFiles = listContainerElement.dataset?.hasPermissionManageFiles == 'true' || false;
|
||||
if (this.userId === undefined || this.corpusId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
// TODO: Make this better understandable
|
||||
this.add(Object.values(user.corpora[this.corpusId].files || user.followed_corpora[this.corpusId].files));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -12,15 +12,16 @@ nopaque.resource_lists.CorpusFollowerList = class CorpusFollowerList extends nop
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
this.corpusId = listContainerElement.dataset.corpusId;
|
||||
if (this.userId === undefined || this.corpusId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
// TODO: Check if the following is better
|
||||
// let corpusFollowerAssociations = Object.values(user.corpora[this.corpusId].corpus_follower_associations);
|
||||
// let filteredList = corpusFollowerAssociations.filter(association => association.follower.id != currentUserId);
|
||||
// this.add(filteredList);
|
||||
|
||||
// TODO: Make this better understandable
|
||||
this.add(Object.values(user.corpora[this.corpusId].corpus_follower_associations));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -11,12 +11,10 @@ nopaque.resource_lists.CorpusList = class CorpusList extends nopaque.resource_li
|
||||
this.selectedItemIds = new Set();
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
if (this.userId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.add(this.aggregateData(user));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -8,8 +8,10 @@ nopaque.resource_lists.JobInputList = class JobInputList extends nopaque.resourc
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
this.jobId = listContainerElement.dataset.jobId;
|
||||
if (this.userId === undefined || this.jobId === undefined) {return;}
|
||||
app.users.subscribe(this.userId);
|
||||
app.users.get(this.userId).then((user) => {
|
||||
// app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
// if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
// });
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.add(Object.values(user.jobs[this.jobId].inputs));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -12,12 +12,10 @@ nopaque.resource_lists.JobList = class JobList extends nopaque.resource_lists.Re
|
||||
this.selectedItemIds = new Set();
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
if (this.userId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.add(Object.values(user.jobs));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -8,12 +8,10 @@ nopaque.resource_lists.JobResultList = class JobResultList extends nopaque.resou
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
this.jobId = listContainerElement.dataset.jobId;
|
||||
if (this.userId === undefined || this.jobId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.add(Object.values(user.jobs[this.jobId].results));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -8,12 +8,10 @@ nopaque.resource_lists.SpaCyNLPPipelineModelList = class SpaCyNLPPipelineModelLi
|
||||
this.isInitialized = false;
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
if (this.userId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.add(Object.values(user.spacy_nlp_pipeline_models));
|
||||
this.isInitialized = true;
|
||||
});
|
||||
|
@ -8,21 +8,11 @@ nopaque.resource_lists.TesseractOCRPipelineModelList = class TesseractOCRPipelin
|
||||
this.isInitialized = false;
|
||||
this.userId = listContainerElement.dataset.userId;
|
||||
if (this.userId === undefined) {return;}
|
||||
app.users.subscribe(this.userId).then((response) => {
|
||||
app.socket.on('users.patch', (patch) => {
|
||||
if (this.isInitialized) {this.onPatch(patch);}
|
||||
});
|
||||
app.liveUserRegistry.addEventListener('patch', (event) => {
|
||||
if (this.isInitialized) {this.onPatch(event.detail);}
|
||||
});
|
||||
app.users.get(this.userId).then((user) => {
|
||||
app.liveUserRegistry.get(this.userId).then((user) => {
|
||||
this.add(Object.values(user.tesseract_ocr_pipeline_models));
|
||||
for (let uncheckedCheckbox of this.listjs.list.querySelectorAll('input[data-checked="True"]')) {
|
||||
uncheckedCheckbox.setAttribute('checked', '');
|
||||
}
|
||||
if (user.role.name !== ('Administrator' || 'Contributor')) {
|
||||
for (let switchElement of this.listjs.list.querySelectorAll('.is_public')) {
|
||||
switchElement.setAttribute('disabled', '');
|
||||
}
|
||||
}
|
||||
this.isInitialized = true;
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user