JS codestyle enhancements

This commit is contained in:
Patrick Jentsch 2021-12-01 14:15:20 +01:00
parent 72ba61f369
commit 12ec6be60b
39 changed files with 490 additions and 288 deletions

View File

@ -6,36 +6,46 @@ class App {
this.socket.on('users.patch', patch => this.usersPatchHandler(patch));
}
get users() {return this.data.users;}
get users() {
return this.data.users;
}
addEventListener(type, listener) {
if (!(type in this.eventListeners)) {throw `Unknown event type: ${type}`;}
if (!(type in this.eventListeners)) {
throw `Unknown event type: ${type}`;
}
this.eventListeners[type].push(listener);
}
flash(message, category) {
let toast, toastCloseActionElement;
let iconPrefix;
let toast;
let toastCloseActionElement;
switch (category) {
case "corpus":
message = `<i class="left material-icons">book</i>${message}`;
case 'corpus':
iconPrefix = '<i class="left material-icons">book</i>';
break;
case "error":
message = `<i class="left material-icons error-color-text">error</i>${message}`;
case 'error':
iconPrefix = '<i class="error-color-text left material-icons">error</i>';
break;
case "job":
message = `<i class="left nopaque-icons">J</i>${message}`;
case 'job':
iconPrefix = '<i class="left nopaque-icons">J</i>';
break;
default:
message = `<i class="left material-icons">notifications</i>${message}`;
iconPrefix = '<i class="left material-icons">notifications</i>';
break;
}
toast = M.toast({
toast = M.toast(
{
html: `
<span>${message}</span>
<span>${iconPrefix}${message}</span>
<button class="btn-flat toast-action white-text" data-action="close">
<i class="material-icons">close</i>
</button>
`.trim()
});
}
);
toastCloseActionElement = toast.el.querySelector('.toast-action[data-action="close"]');
toastCloseActionElement.addEventListener('click', () => {toast.dismiss();});
}
@ -55,8 +65,16 @@ class App {
}
usersPatchHandler(patch) {
let re, match, userId, ressourceId, jobId, relationship;
for (let operation of patch.filter(operation => operation.op === 'add')) {
let jobId;
let listener;
let match;
let operation;
let re;
let relationship;
let ressourceId;
let userId;
for (operation of patch.filter(operation => operation.op === 'add')) {
re = new RegExp(`^/users/([A-Za-z0-9]*)/corpora/([A-Za-z0-9]*)/(files)`);
if (re.test(operation.path)) {
[match, userId, ressourceId, relationship] = operation.path.match(re);
@ -75,6 +93,6 @@ class App {
}
}
this.data = jsonpatch.apply_patch(this.data, patch);
for (let listener of this.eventListeners['users.patch']) {listener(patch);}
for (listener of this.eventListeners['users.patch']) {listener(patch);}
}
}

View File

@ -4,7 +4,11 @@ class JobStatusNotifier {
}
usersPatchHandler(patch) {
let re, filteredPatch, match, jobId;
let filteredPatch;
let jobId;
let match;
let re;
re = new RegExp(`^/users/${this.userId}/jobs/([A-Za-z0-9]*)/status$`)
filteredPatch = patch
.filter(operation => operation.op === 'replace')

View File

@ -2,34 +2,45 @@ class CorpusDisplay extends RessourceDisplay {
constructor(displayElement) {
super(displayElement);
this.corpusId = displayElement.dataset.corpusId;
for (let exportCorpusTriggerElement of this.displayElement.querySelectorAll('.export-corpus-trigger')) {
exportCorpusTriggerElement.addEventListener('click', () => this.requestCorpusExport());
}
app.socket.on(`export_corpus_${this.corpusId}`, () => this.downloadCorpus());
}
init(user) {
let corpus;
corpus = user.corpora[this.corpusId];
this.setCreationDate(corpus.creation_date);
this.setDescription(corpus.description);
this.setLastEditedDate(corpus.last_edited_date);
this.setStatus(corpus.status);
this.setTitle(corpus.title);
this.setTokenRatio(corpus.num_tokens, corpus.max_num_tokens);
this.setNumTokens(corpus.num_tokens);
}
patch(patch) {
let re, filteredPatch;
let filteredPatch;
let operation;
let re;
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
for (operation of filteredPatch) {
switch(operation.op) {
case 'replace':
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/last_edited_date$`);
if (re.test(operation.path)) {this.setLastEditedDate(operation.value); break;}
if (re.test(operation.path)) {
this.setLastEditedDate(operation.value);
break;
}
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/num_tokens`);
if (re.test(operation.path)) {
this.numTokens(operation.value);
break;
}
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/status$`);
if (re.test(operation.path)) {this.status$(operation.value); break;}
if (re.test(operation.path)) {
this.status(operation.value);
break;
}
break;
default:
break;
@ -37,55 +48,48 @@ class CorpusDisplay extends RessourceDisplay {
}
}
requestCorpusExport() {
app.socket.emit('export_corpus', app.users[this.userId].corpora[this.corpusId]);
app.flash('Preparing your corpus export...', 'corpus');
for (let exportCorpusTriggerElement of this.displayElement.querySelectorAll('.export-corpus-trigger')) {exportCorpusTriggerElement.classList.toggle('disabled', true);}
}
downloadCorpus() {
let downloadButton;
app.flash('Corpus download is ready!', 'corpus');
for (let exportCorpusTriggerElement of this.displayElement.querySelectorAll('.export-corpus-trigger')) {exportCorpusTriggerElement.classList.toggle('disabled', false);}
// Little trick to call the download view after ziping has finished
downloadButton = document.createElement('a');
downloadButton.href = `/corpora/${app.users[this.userId].corpora[this.corpusId]}/download`;
downloadButton.click();
}
setTitle(title) {
for (let element of this.displayElement.querySelectorAll('.corpus-title')) {this.setElement(element, title);}
this.setElements(this.displayElement.querySelectorAll('.corpus-title'), title);
}
setTokenRatio(numTokens, maxNumTokens) {
for (let element of this.displayElement.querySelectorAll('.corpus-token-ratio')) {this.setElement(element, `${numTokens}/${maxNumTokens}`);}
setNumTokens(numTokens) {
this.setElements(
this.displayElement.querySelectorAll('.corpus-token-ratio'),
`${numTokens}/${app.users[this.userId].corpora[this.corpusId].max_num_tokens}`
);
}
setDescription(description) {
for (let element of this.displayElement.querySelectorAll('.corpus-description')) {this.setElement(element, description);}
this.setElements(this.displayElement.querySelectorAll('.corpus-description'), description);
}
setStatus(status) {
for (let element of this.displayElement.querySelectorAll('.analyse-corpus-trigger')) {
let element;
let elements;
this.setElements(this.displayElement.querySelectorAll('.corpus-status'), status);
elements = this.displayElement.querySelectorAll('.analyse-corpus-trigger')
for (element of elements) {
if (['analysing', 'prepared', 'start analysis'].includes(status)) {
element.classList.remove('disabled');
} else {
element.classList.add('disabled');
}
}
for (let element of this.displayElement.querySelectorAll('.build-corpus-trigger')) {
elements = this.displayElement.querySelectorAll('.build-corpus-trigger');
for (element of elements) {
if (status === 'unprepared' && Object.values(app.users[this.userId].corpora[this.corpusId].files).length > 0) {
element.classList.remove('disabled');
} else {
element.classList.add('disabled');
}
}
for (let element of this.displayElement.querySelectorAll('.corpus-status')) {this.setElement(element, status);}
for (let exportCorpusTriggerElement of this.displayElement.querySelectorAll('.export-corpus-trigger')) {
exportCorpusTriggerElement.classList.toggle('disabled', !['prepared', 'start analysis', 'stop analysis'].includes(status));
elements = this.displayElement.querySelectorAll('.status');
for (element of elements) {
element.dataset.status = status;
}
for (let element of this.displayElement.querySelectorAll('.status')) {element.dataset.status = status;}
for (let element of this.displayElement.querySelectorAll('.status-spinner')) {
elements = this.displayElement.querySelectorAll('.status-spinner');
for (element of elements) {
if (['submitted', 'queued', 'running', 'canceling', 'start analysis', 'stop analysis'].includes(status)) {
element.classList.remove('hide');
} else {
@ -95,14 +99,16 @@ class CorpusDisplay extends RessourceDisplay {
}
setCreationDate(creationDate) {
for (let element of this.displayElement.querySelectorAll('.corpus-creation-date')) {
this.setElement(element, creationDate.toLocaleString("en-US"));
}
this.setElements(
this.displayElement.querySelectorAll('.corpus-creation-date'),
new Date(creationDate).toLocaleString("en-US")
);
}
setLastEditedDate(lastEditedDate) {
for (let element of this.displayElement.querySelectorAll('.corpus-end-date')) {
this.setElement(element, lastEditedDate.toLocaleString("en-US"));
}
this.setElements(
this.displayElement.querySelectorAll('.corpus-end-date'),
new Date(lastEditedDate).toLocaleString("en-US")
);
}
}

View File

@ -5,7 +5,9 @@ class JobDisplay extends RessourceDisplay {
}
init(user) {
let job = user.jobs[this.jobId];
let job;
job = user.jobs[this.jobId];
this.setCreationDate(job.creation_date);
this.setEndDate(job.creation_date);
this.setDescription(job.description);
@ -17,9 +19,13 @@ class JobDisplay extends RessourceDisplay {
}
usersPatchHandler(patch) {
let re = new RegExp(`^/users/${this.userId}/jobs/${this.jobId}`);
let filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
let filteredPatch;
let operation;
let re;
re = new RegExp(`^/users/${this.userId}/jobs/${this.jobId}`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (operation of filteredPatch) {
switch(operation.op) {
case 'replace':
re = new RegExp(`^/users/${this.userId}/jobs/${this.jobId}/end_date$`);
@ -40,26 +46,33 @@ class JobDisplay extends RessourceDisplay {
}
setTitle(title) {
for (let element of this.displayElement.querySelectorAll('.job-title')) {this.setElement(element, title);}
this.setElements(this.displayElement.querySelectorAll('.job-title'), title);
}
setDescription(description) {
for (let element of this.displayElement.querySelectorAll('.job-description')) {this.setElement(element, description);}
this.setElements(this.displayElement.querySelectorAll('.job-description'), description);
}
setStatus(status) {
for (let element of this.displayElement.querySelectorAll('.job-status')) {
this.setElement(element, status);
let element;
let elements;
this.setElements(this.displayElement.querySelectorAll('.job-status'), status);
elements = this.displayElement.querySelectorAll('.status');
for (element of elements) {
element.dataset.status = status;
}
for (let element of this.displayElement.querySelectorAll('.status')) {element.dataset.status = status;}
for (let element of this.displayElement.querySelectorAll('.status-spinner')) {
elements = this.displayElement.querySelectorAll('.status-spinner');
for (element of elements) {
if (['complete', 'failed'].includes(status)) {
element.classList.add('hide');
} else {
element.classList.remove('hide');
}
}
for (let element of this.displayElement.querySelectorAll('.restart-job-trigger')) {
elements = this.displayElement.querySelectorAll('.restart-job-trigger');
for (element of elements) {
if (['complete', 'failed'].includes(status)) {
element.classList.remove('hide');
} else {
@ -69,26 +82,28 @@ class JobDisplay extends RessourceDisplay {
}
setCreationDate(creationDate) {
for (let element of this.displayElement.querySelectorAll('.job-creation-date')) {
this.setElement(element, creationDate.toLocaleString('en-US'));
}
this.setElements(
this.displayElement.querySelectorAll('.job-creation-date'),
new Date(creationDate).toLocaleString('en-US')
);
}
setEndDate(endDate) {
for (let element of this.displayElement.querySelectorAll('.job-end-date')) {
this.setElement(element, endDate.toLocaleString('en-US'));
}
this.setElements(
this.displayElement.querySelectorAll('.job-end-date'),
new Date(endDate).toLocaleString('en-US')
);
}
setService(service) {
for (let element of this.displayElement.querySelectorAll('.job-service')) {this.setElement(element, service);}
this.setElements(this.displayElement.querySelectorAll('.job-service'), service);
}
setServiceArgs(serviceArgs) {
for (let element of this.displayElement.querySelectorAll('.job-service-args')) {this.setElement(element, serviceArgs);}
this.setElements(this.displayElement.querySelectorAll('.job-service-args'), serviceArgs);
}
setServiceVersion(serviceVersion) {
for (let element of this.displayElement.querySelectorAll('.job-service-version')) {this.setElement(element, serviceVersion);}
this.setElements(this.displayElement.querySelectorAll('.job-service-version'), serviceVersion);
}
}

View File

@ -3,7 +3,7 @@ class RessourceDisplay {
this.displayElement = displayElement;
this.userId = this.displayElement.dataset.userId;
app.addEventListener('users.patch', patch => this.usersPatchHandler(patch));
app.getUserById(this.userId).then(user => this.init(user), error => {throw JSON.stringify(error);});
app.getUserById(this.userId).then(user => this.init(user));
}
init(user) {throw 'Not implemented';}
@ -21,4 +21,12 @@ class RessourceDisplay {
break;
}
}
setElements(elements, value) {
let element;
for (element of elements) {
this.setElement(element, value);
}
}
}

View File

@ -9,14 +9,23 @@ class CorpusFileList extends RessourceList {
}
onclick(event) {
let corpusFileElement = event.target.closest('tr[data-id]');
if (corpusFileElement === null) {throw 'Could not locate corpus file element';}
let corpusFileId = corpusFileElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
let action;
let actionButtonElement;
let corpusFileElement;
let corpusFileId;
let deleteModal;
let deleteModalElement;
let tmp;
corpusFileElement = event.target.closest('tr[data-id]');
if (corpusFileElement === null) {return;}
corpusFileId = corpusFileElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
switch (action) {
case 'delete':
let deleteModalHTML = `
tmp = document.createElement('div');
tmp.innerHTML = `
<div class="modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
@ -28,10 +37,16 @@ class CorpusFileList extends RessourceList {
</div>
</div>
`.trim();
let deleteModalParentElement = document.querySelector('#modals');
deleteModalParentElement.insertAdjacentHTML('beforeend', deleteModalHTML);
let deleteModalElement = deleteModalParentElement.lastChild;
let deleteModal = M.Modal.init(deleteModalElement, {onCloseEnd: () => {deleteModal.destroy(); deleteModalElement.remove();}});
deleteModalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
deleteModal = M.Modal.init(
deleteModalElement,
{
onCloseEnd: () => {
deleteModal.destroy();
deleteModalElement.remove();
}
}
);
deleteModal.open();
break;
case 'download':
@ -46,13 +61,22 @@ class CorpusFileList extends RessourceList {
}
usersPatchHandler(patch) {
let re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)`);
let filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
let corpusFileId;
let filteredPatch;
let match;
let operation;
let re;
let valueName;
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (operation of filteredPatch) {
switch(operation.op) {
case 'add':
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {this.add(operation.value);}
if (re.test(operation.path)) {
this.add(operation.value);
}
break;
case 'remove':
re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)$`);

View File

@ -8,14 +8,23 @@ class CorpusList extends RessourceList {
}
onclick(event) {
let corpusElement = event.target.closest('tr[data-id]');
if (corpusElement === null) {throw 'Could not locate corpus element';}
let corpusId = corpusElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
let action;
let actionButtonElement;
let corpusElement;
let corpusId;
let deleteModal;
let deleteModalElement;
let tmp;
corpusElement = event.target.closest('tr[data-id]');
if (corpusElement === null) {return;}
corpusId = corpusElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
switch (action) {
case 'delete':
let deleteModalHTML = `
tmp = document.createElement('div');
tmp.innerHTML = `
<div class="modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
@ -27,10 +36,16 @@ class CorpusList extends RessourceList {
</div>
</div>
`.trim();
let deleteModalParentElement = document.querySelector('#modals');
deleteModalParentElement.insertAdjacentHTML('beforeend', deleteModalHTML);
let deleteModalElement = deleteModalParentElement.lastChild;
let deleteModal = M.Modal.init(deleteModalElement, {onCloseEnd: () => {deleteModal.destroy(); deleteModalElement.remove();}});
deleteModalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
deleteModal = M.Modal.init(
deleteModalElement,
{
onCloseEnd: () => {
deleteModal.destroy();
deleteModalElement.remove();
}
}
);
deleteModal.open();
break;
case 'view':
@ -42,9 +57,16 @@ class CorpusList extends RessourceList {
}
usersPatchHandler(patch) {
let re = new RegExp(`^/users/${this.userId}/corpora/([A-Za-z0-9]*)`);
let filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
let corpusId;
let filteredPatch;
let match;
let operation;
let re;
let valueName;
re = new RegExp(`^/users/${this.userId}/corpora/([A-Za-z0-9]*)`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (operation of filteredPatch) {
switch(operation.op) {
case 'add':
re = new RegExp(`^/users/${this.userId}/corpora/([A-Za-z0-9]*)$`);
@ -53,14 +75,14 @@ class CorpusList extends RessourceList {
case 'remove':
re = new RegExp(`^/users/${this.userId}/corpora/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {
let [match, corpusId] = operation.path.match(re);
[match, corpusId] = operation.path.match(re);
this.remove(corpusId);
}
break;
case 'replace':
re = new RegExp(`^/users/${this.userId}/corpora/([A-Za-z0-9]*)/(status|description|title)$`);
if (re.test(operation.path)) {
let [match, corpusId, valueName] = operation.path.match(re);
[match, corpusId, valueName] = operation.path.match(re);
this.replace(corpusId, valueName, operation.value);
}
break;

View File

@ -9,12 +9,17 @@ class JobInputList extends RessourceList {
}
onclick(event) {
let jobInputElement = event.target.closest('tr[data-id]');
let jobInputElement;
let jobInputId;
let action;
let actionButtonElement;
jobInputElement = event.target.closest('tr[data-id]');
if (jobInputElement === null) {return;}
let jobInputId = jobInputElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
jobInputId = jobInputElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
if (actionButtonElement === null) {return;}
let action = actionButtonElement.dataset.action;
action = actionButtonElement.dataset.action;
switch (action) {
case 'download':
window.location.href = `/jobs/${this.jobId}/inputs/${jobInputId}/download`;

View File

@ -8,14 +8,23 @@ class JobList extends RessourceList {
}
onclick(event) {
let jobElement = event.target.closest('tr[data-id]');
if (jobElement === null) {throw 'Could not locate job element';}
let jobId = jobElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
let action;
let actionButtonElement;
let deleteModal;
let deleteModalElement;
let jobElement;
let jobId;
let tmp;
jobElement = event.target.closest('tr[data-id]');
if (jobElement === null) {return;}
jobId = jobElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
switch (action) {
case 'delete':
let deleteModalHTML = `
tmp = document.createElement('div');
tmp.innerHTML = `
<div class="modal">
<div class="modal-content">
<h4>Confirm job deletion</h4>
@ -27,10 +36,16 @@ class JobList extends RessourceList {
</div>
</div>
`.trim();
let deleteModalParentElement = document.querySelector('#modals');
deleteModalParentElement.insertAdjacentHTML('beforeend', deleteModalHTML);
let deleteModalElement = deleteModalParentElement.lastChild;
let deleteModal = M.Modal.init(deleteModalElement, {onCloseEnd: () => {deleteModal.destroy(); deleteModalElement.remove();}});
deleteModalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
deleteModal = M.Modal.init(
deleteModalElement,
{
onCloseEnd: () => {
deleteModal.destroy();
deleteModalElement.remove();
}
}
);
deleteModal.open();
break;
case 'view':
@ -42,25 +57,34 @@ class JobList extends RessourceList {
}
usersPatchHandler(patch) {
let re = new RegExp(`^/users/${this.userId}/jobs/([A-Za-z0-9]*)`);
let filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
let filteredPatch;
let jobId;
let match;
let operation;
let re;
let valueName;
re = new RegExp(`^/users/${this.userId}/jobs/([A-Za-z0-9]*)`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (operation of filteredPatch) {
switch(operation.op) {
case 'add':
re = new RegExp(`^/users/${this.userId}/jobs/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {this.add(operation.value);}
if (re.test(operation.path)) {
this.add(operation.value);
}
break;
case 'remove':
re = new RegExp(`^/users/${this.userId}/jobs/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {
let [match, jobId] = operation.path.match(re);
[match, jobId] = operation.path.match(re);
this.remove(jobId);
}
break;
case 'replace':
re = new RegExp(`^/users/${this.userId}/jobs/([A-Za-z0-9]*)/(service|status|description|title)$`);
if (re.test(operation.path)) {
let [match, jobId, valueName] = operation.path.match(re);
[match, jobId, valueName] = operation.path.match(re);
this.replace(jobId, valueName, operation.value);
}
break;

View File

@ -9,12 +9,17 @@ class JobResultList extends RessourceList {
}
onclick(event) {
let jobResultElement = event.target.closest('tr[data-id]');
let action;
let actionButtonElement;
let jobResultElement;
let jobResultId;
jobResultElement = event.target.closest('tr[data-id]');
if (jobResultElement === null) {return;}
let jobResultId = jobResultElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
jobResultId = jobResultElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
if (actionButtonElement === null) {return;}
let action = actionButtonElement.dataset.action;
action = actionButtonElement.dataset.action;
switch (action) {
case 'download':
window.location.href = `/jobs/${this.jobId}/results/${jobResultId}`;
@ -25,13 +30,19 @@ class JobResultList extends RessourceList {
}
usersPatchHandler(patch) {
let re = new RegExp(`^/users/${this.userId}/jobs/${this.jobId}/results/([A-Za-z0-9]*)`);
let filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
let filteredPatch;
let operation;
let re;
re = new RegExp(`^/users/${this.userId}/jobs/${this.jobId}/results/([A-Za-z0-9]*)`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (operation of filteredPatch) {
switch(operation.op) {
case 'add':
re = new RegExp(`^/users/${this.userId}/jobs/${this.jobId}/results/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {this.add(operation.value);}
if (re.test(operation.path)) {
this.add(operation.value);
}
break;
default:
break;
@ -41,6 +52,7 @@ class JobResultList extends RessourceList {
preprocessRessource(jobResult) {
let description;
if (jobResult.filename.endsWith('.pdf.zip')) {
description = 'PDF files with text layer';
} else if (jobResult.filename.endsWith('.txt.zip')) {

View File

@ -8,14 +8,23 @@ class QueryResultList extends RessourceList {
}
onclick(event) {
let queryResultElement = event.target.closest('tr[data-id]');
let action;
let actionButtonElement;
let deleteModal;
let deleteModalElement;
let queryResultElement;
let queryResultId;
let tmp;
queryResultElement = event.target.closest('tr[data-id]');
if (queryResultElement === null) {return;}
let queryResultId = queryResultElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
queryResultId = queryResultElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
switch (action) {
case 'delete':
let deleteModalHTML = `
tmp = document.createElement('div');
tmp.innerHTML = `
<div class="modal">
<div class="modal-content">
<h4>Confirm query result deletion</h4>
@ -27,10 +36,16 @@ class QueryResultList extends RessourceList {
</div>
</div>
`.trim();
let deleteModalParentElement = document.querySelector('#modals');
deleteModalParentElement.insertAdjacentHTML('beforeend', deleteModalHTML);
let deleteModalElement = deleteModalParentElement.lastChild;
let deleteModal = M.Modal.init(deleteModalElement, {onCloseEnd: () => {deleteModal.destroy(); deleteModalElement.remove();}});
deleteModalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
deleteModal = M.Modal.init(
deleteModalElement,
{
onCloseEnd: () => {
deleteModal.destroy();
deleteModalElement.remove();
}
}
);
deleteModal.open();
break;
case 'view':
@ -42,25 +57,34 @@ class QueryResultList extends RessourceList {
}
usersPatchHandler(patch) {
let re = new RegExp(`^/users/${this.userId}/query_results/([A-Za-z0-9]*)`);
let filteredPatch = patch.filter(operation => re.test(operation.path));
for (let operation of filteredPatch) {
let filteredPatch;
let match;
let operation;
let queryResultId;
let re;
let valueName;
re = new RegExp(`^/users/${this.userId}/query_results/([A-Za-z0-9]*)`);
filteredPatch = patch.filter(operation => re.test(operation.path));
for (operation of filteredPatch) {
switch(operation.op) {
case 'add':
re = new RegExp(`^/users/${this.userId}/query_results/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {this.add(operation.value);}
if (re.test(operation.path)) {
this.add(operation.value);
}
break;
case 'remove':
re = new RegExp(`^/users/${this.userId}/query_results/([A-Za-z0-9]*)$`);
if (re.test(operation.path)) {
let [match, queryResultId] = operation.path.match(re);
[match, queryResultId] = operation.path.match(re);
this.remove(queryResultId);
}
break;
case 'replace':
re = new RegExp(`^/users/${this.userId}/query_results/([A-Za-z0-9]*)/(corpus_title|description|query|title)$`);
if (re.test(operation.path)) {
let [match, queryResultId, valueName] = operation.path.match(re);
[match, queryResultId, valueName] = operation.path.match(re);
this.replace(queryResultId, valueName, operation.value);
}
break;

View File

@ -8,14 +8,23 @@ class UserList extends RessourceList {
}
onclick(event) {
let userElement = event.target.closest('tr[data-id]');
let action;
let actionButtonElement;
let deleteModal;
let deleteModalElement;
let tmp;
let userElement;
let userId;
userElement = event.target.closest('tr[data-id]');
if (userElement === null) {return;}
let userId = userElement.dataset.id;
let actionButtonElement = event.target.closest('.action-button[data-action]');
let action = (actionButtonElement === null) ? 'view' : actionButtonElement.dataset.action;
userId = userElement.dataset.id;
actionButtonElement = event.target.closest('.action-button[data-action]');
action = (actionButtonElement === null) ? 'view' : actionButtonElement.dataset.action;
switch (action) {
case 'delete':
let deleteModalHTML = `
tmp = document.createElement('div');
tmp.innerHTML = `
<div class="modal">
<div class="modal-content">
<h4>Confirm user deletion</h4>
@ -27,10 +36,16 @@ class UserList extends RessourceList {
</div>
</div>
`.trim();
let deleteModalParentElement = document.querySelector('#modals');
deleteModalParentElement.insertAdjacentHTML('beforeend', deleteModalHTML);
let deleteModalElement = deleteModalParentElement.lastChild;
let deleteModal = M.Modal.init(deleteModalElement, {onCloseEnd: () => {deleteModal.destroy(); deleteModalElement.remove();}});
deleteModalElement = document.querySelector('#modals').appendChild(tmp.firstChild);
deleteModal = M.Modal.init(
deleteModalElement,
{
onCloseEnd: () => {
deleteModal.destroy();
deleteModalElement.remove();
}
}
);
deleteModal.open();
break;
case 'edit':
@ -50,7 +65,7 @@ class UserList extends RessourceList {
id_: user.id,
username: user.username,
email: user.email,
last_seen: user.last_seen.toLocaleString("en-US"),
last_seen: new Date(user.last_seen).toLocaleString("en-US"),
role: user.role.name
};
}

View File

@ -68,4 +68,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -92,9 +92,11 @@
</div>
</div>
</div>
{% endblock page_content %}
<!-- Modals -->
{% block modals %}
{{ super() }}
<div id="delete-user-modal" class="modal">
<div class="modal-content">
<h3>Delete user</h3>
@ -105,8 +107,7 @@
<a href="{{ url_for('.delete_user', user_id=user.id) }}" class="modal-close waves-effect waves-light btn red"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
{% endblock %}
{% endblock modals %}
{% block scripts %}
{{ super() }}

View File

@ -35,7 +35,7 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}
{% block scripts %}
{{ super() }}

View File

@ -52,4 +52,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -45,4 +45,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -29,4 +29,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -28,4 +28,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -23,4 +23,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -32,13 +32,13 @@
{% block main_attribs %} class="background-color"{% endblock main_attribs %}
{% block main %}
{% block page_content %}{% endblock page_content %}
{% block modals %}
<div id="modals">
{% if current_user.is_authenticated %}
{% include "_roadmap.html.j2" %}
{% endif %}
{% block modals %}
{% if current_user.is_authenticated %}
{% include "_roadmap.html.j2" %}
{% endif %}
{% endblock modals %}
</div>
{% endblock modals %}
{% endblock main %}
{% block footer_attribs %} class="page-footer primary-variant-color"{% endblock footer_attribs %}

View File

@ -38,4 +38,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -71,7 +71,11 @@
</div>
</div>
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="progress-modal" class="modal">
<div class="modal-content">
<h4><i class="material-icons prefix">file_upload</i> Uploading file...</h4>
@ -83,4 +87,4 @@
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
</div>
</div>
{% endblock %}
{% endblock modals %}

View File

@ -70,17 +70,6 @@
<a class="btn modal-trigger red waves-effect waves-light" data-target="delete-corpus-modal"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<div id="delete-corpus-modal" class="modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
<p>Do you really want to delete the corpus <span class="corpus-title"></span>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="btn modal-close waves-effect waves-light" href="#!">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('corpora.delete_corpus', corpus_id=corpus.id) }}"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</div>
<div class="col s12" id="corpus-files" data-corpus-id="{{ corpus.hashid }}" data-user-id="{{ corpus.user.hashid }}">
@ -115,6 +104,20 @@
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="delete-corpus-modal" class="modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
<p>Do you really want to delete the corpus <span class="corpus-title"></span>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="btn modal-close waves-effect waves-light" href="#!">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('corpora.delete_corpus', corpus_id=corpus.id) }}"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
{% endblock modals %}
{% block scripts %}
{{ super() }}
<script>

View File

@ -48,4 +48,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -43,7 +43,10 @@
</div>
</div>
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="progress-modal" class="modal">
<div class="modal-content">
<h4><i class="material-icons prefix">file_upload</i> Uploading file...</h4>
@ -55,4 +58,4 @@
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
</div>
</div>
{% endblock %}
{% endblock modals %}

View File

@ -85,30 +85,6 @@
<a class="btn modal-trigger red waves-effect waves-light" data-target="delete-job-modal"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<div id="delete-job-modal" class="modal">
<div class="modal-content">
<h4>Confirm deletion</h4>
<p>Do you really want to delete the job <span class="job-title"></span>? All associated files will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('jobs.delete_job', job_id=job.id) }}"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
{% if current_user.is_administrator() %}
<div id="restart-job-modal" class="modal">
<div class="modal-content">
<h4>Confirm restart</h4>
<p>Do you really want to restart the job <span class="job-title"></span>? All log and result files will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('jobs.restart', job_id=job.id) }}"><i class="material-icons left">restart</i>Restart</a>
</div>
</div>
{% endif %}
</div>
<div class="col s12" id="job-inputs" data-job-id="{{ job.hashid }}" data-user-id="{{ job.user.hashid }}">
@ -165,6 +141,33 @@
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="delete-job-modal" class="modal">
<div class="modal-content">
<h4>Confirm deletion</h4>
<p>Do you really want to delete the job <span class="job-title"></span>? All associated files will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('jobs.delete_job', job_id=job.id) }}"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
{% if current_user.is_administrator() %}
<div id="restart-job-modal" class="modal">
<div class="modal-content">
<h4>Confirm restart</h4>
<p>Do you really want to restart the job <span class="job-title"></span>? All log and result files will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('jobs.restart', job_id=job.id) }}"><i class="material-icons left">restart</i>Restart</a>
</div>
</div>
{% endif %}
{% endblock modals %}
{% block scripts %}
{{ super() }}
<script>

View File

@ -119,8 +119,14 @@
<p><a class="modal-trigger waves-effect waves-light btn" href="#" data-target="new-job-modal"><i class="material-icons left">add</i>New job</a></p>
</div>
</div>
</div>
</div>
</div>
{% endblock page_content %}
<div id="new-job-modal" class="modal">
{% block modals %}
{{ super() }}
<div id="new-job-modal" class="modal">
<div class="modal-content">
<h4>Select a service</h4>
<p>&nbsp;</p>
@ -166,11 +172,8 @@
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-light btn-flat">Close</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock modals %}
{% block scripts %}
{{ super() }}

View File

@ -53,4 +53,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -215,4 +215,4 @@
<img src="{{ url_for('static', filename='images/parallax_lq/05_chapter_book_text_tale.jpg') }}" alt="">
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -48,4 +48,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -152,4 +152,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -109,4 +109,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}

View File

@ -1,7 +1,7 @@
{% block doc %}
<!DOCTYPE html>
<html{% block html_attribs %}{% endblock html_attribs %}>
{% block html %}
{% block html %}
<head>
{% block head %}
<title>{% block title %}{{title|default}}{% endblock title %}</title>
@ -40,6 +40,6 @@
{% endblock scripts %}
{% endblock body %}
</body>
{% endblock html %}
{% endblock html %}
</html>
{% endblock doc %}

View File

@ -88,7 +88,7 @@
</div>
</div>
</div>
{% endblock %}
{% endblock page_content %}
{% block scripts %}
{{ super() }}

View File

@ -65,7 +65,10 @@
</div>
</div>
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="progress-modal" class="modal">
<div class="modal-content">
<h4><i class="material-icons prefix">file_upload</i> Uploading files...</h4>
@ -77,4 +80,4 @@
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
</div>
</div>
{% endblock %}
{% endblock modals %}

View File

@ -107,7 +107,10 @@
</div>
</div>
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="progress-modal" class="modal">
<div class="modal-content">
<h4><i class="material-icons prefix">file_upload</i> Uploading files...</h4>
@ -119,8 +122,7 @@
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
</div>
</div>
{% endblock %}
{% endblock modals %}
{% block scripts %}
{{ super() }}
@ -132,4 +134,4 @@
window.location.href = url.toString();
});
</script>
{% endblock %}
{% endblock scripts %}

View File

@ -134,7 +134,10 @@
</div>
</div>
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
<div id="progress-modal" class="modal">
<div class="modal-content">
<h4><i class="material-icons left">file_upload</i>Uploading files...</h4>
@ -146,8 +149,7 @@
<a href="#!" class="modal-close waves-effect waves-light btn red abort-request">Cancel</a>
</div>
</div>
{% endblock %}
{% endblock modals %}
{% block scripts %}
{{ super() }}
@ -159,4 +161,4 @@
window.location.href = url.toString();
});
</script>
{% endblock %}
{% endblock scripts %}

View File

@ -64,9 +64,10 @@
</div>
</div>
</div>
{% endblock page_content %}
<!-- Modals -->
{% block modals %}
{{ super() }}
<div class="modal" id="delete-account-modal">
<div class="modal-content">
<h4>Confirm deletion</h4>
@ -77,4 +78,4 @@
<a href="{{ url_for('.delete') }}" class="btn red waves-effect waves-light"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
{% endblock page_content %}
{% endblock modals %}