diff --git a/app/static/js/nopaque/App.js b/app/static/js/nopaque/App.js index 9162640af719ae26b3a97c6d8da56eb0c2c215af..6bad75e8a00dee1bed76278da49f4ce8c7dfd9ff 100644 --- a/app/static/js/nopaque/App.js +++ b/app/static/js/nopaque/App.js @@ -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({ - html: ` - <span>${message}</span> - <button class="btn-flat toast-action white-text" data-action="close"> - <i class="material-icons">close</i> - </button> - `.trim() - }); + toast = M.toast( + { + html: ` + <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);} } } diff --git a/app/static/js/nopaque/JobStatusNotifier.js b/app/static/js/nopaque/JobStatusNotifier.js index 51adf06e4e98088b629d9035261b539435ce84b4..84ccb267838777d2f9bfbd43f1caab6ea3d6df0a 100644 --- a/app/static/js/nopaque/JobStatusNotifier.js +++ b/app/static/js/nopaque/JobStatusNotifier.js @@ -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') diff --git a/app/static/js/nopaque/RessourceDisplays/CorpusDisplay.js b/app/static/js/nopaque/RessourceDisplays/CorpusDisplay.js index 739dde2f0f43feb7c353c681ebf05ba46b8dfeca..fd6fd72f195ad012d227e345b7df234904de1656 100644 --- a/app/static/js/nopaque/RessourceDisplays/CorpusDisplay.js +++ b/app/static/js/nopaque/RessourceDisplays/CorpusDisplay.js @@ -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") + ); } } diff --git a/app/static/js/nopaque/RessourceDisplays/JobDisplay.js b/app/static/js/nopaque/RessourceDisplays/JobDisplay.js index ac1815090b19525ced2a0c90758f689f484dd444..61222693112a218c9b4eb013d509c33dff29262e 100644 --- a/app/static/js/nopaque/RessourceDisplays/JobDisplay.js +++ b/app/static/js/nopaque/RessourceDisplays/JobDisplay.js @@ -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); } } diff --git a/app/static/js/nopaque/RessourceDisplays/RessourceDisplay.js b/app/static/js/nopaque/RessourceDisplays/RessourceDisplay.js index c7aebe75dd417516ee3def4d935cf6f03f52b63c..c8c16be1367ea35d7a8ee4d6a3b7ef9268336479 100644 --- a/app/static/js/nopaque/RessourceDisplays/RessourceDisplay.js +++ b/app/static/js/nopaque/RessourceDisplays/RessourceDisplay.js @@ -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); + } + } } diff --git a/app/static/js/nopaque/RessourceLists/CorpusFileList.js b/app/static/js/nopaque/RessourceLists/CorpusFileList.js index fdd26fcda09e582a1d02b66035eb374eb7466c27..e49ee8fa1bfc3cc3cf478a3081c9236569a11956 100644 --- a/app/static/js/nopaque/RessourceLists/CorpusFileList.js +++ b/app/static/js/nopaque/RessourceLists/CorpusFileList.js @@ -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]*)$`); diff --git a/app/static/js/nopaque/RessourceLists/CorpusList.js b/app/static/js/nopaque/RessourceLists/CorpusList.js index f9c5fead0ca36fdf1a140360d65268fccdd2c591..156623d3ecf35527398b4727e1143f32f7b3b115 100644 --- a/app/static/js/nopaque/RessourceLists/CorpusList.js +++ b/app/static/js/nopaque/RessourceLists/CorpusList.js @@ -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; diff --git a/app/static/js/nopaque/RessourceLists/JobInputList.js b/app/static/js/nopaque/RessourceLists/JobInputList.js index 1a9195523779e693b3c919d5f2c22b153d1b3ab3..4fed368ece6a123fc8b6ee132e1ffb01cac8757b 100644 --- a/app/static/js/nopaque/RessourceLists/JobInputList.js +++ b/app/static/js/nopaque/RessourceLists/JobInputList.js @@ -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`; diff --git a/app/static/js/nopaque/RessourceLists/JobList.js b/app/static/js/nopaque/RessourceLists/JobList.js index 3c21abcb5fcc9676a1964ad31ae7ddbf15d7b639..9dc19ec6c4ac236d28a89b9b8435baab962135be 100644 --- a/app/static/js/nopaque/RessourceLists/JobList.js +++ b/app/static/js/nopaque/RessourceLists/JobList.js @@ -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; diff --git a/app/static/js/nopaque/RessourceLists/JobResultList.js b/app/static/js/nopaque/RessourceLists/JobResultList.js index e741015774962745e846010c0f4dca09f26a2149..0dab71ccece69288887e14b3780b8fd5791e2016 100644 --- a/app/static/js/nopaque/RessourceLists/JobResultList.js +++ b/app/static/js/nopaque/RessourceLists/JobResultList.js @@ -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')) { diff --git a/app/static/js/nopaque/RessourceLists/QueryResultList.js b/app/static/js/nopaque/RessourceLists/QueryResultList.js index c64361b5f61b5bee8fba098fb3678da51ec9ad08..832a482df1082e63bf61b93716293f444dd0d85b 100644 --- a/app/static/js/nopaque/RessourceLists/QueryResultList.js +++ b/app/static/js/nopaque/RessourceLists/QueryResultList.js @@ -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; diff --git a/app/static/js/nopaque/RessourceLists/UserList.js b/app/static/js/nopaque/RessourceLists/UserList.js index 04100d2531f05a8f515f5afd9750b35e571aea34..24b26ad3ab42097cde0cfabc4de8bcaa93857153 100644 --- a/app/static/js/nopaque/RessourceLists/UserList.js +++ b/app/static/js/nopaque/RessourceLists/UserList.js @@ -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 }; } diff --git a/app/templates/admin/edit_user.html.j2 b/app/templates/admin/edit_user.html.j2 index 89a73d035dab74669c23a30411ef2c34addf0e6d..d824c1129ec8569b3ad7e803ebc78159b0caad69 100644 --- a/app/templates/admin/edit_user.html.j2 +++ b/app/templates/admin/edit_user.html.j2 @@ -68,4 +68,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/admin/user.html.j2 b/app/templates/admin/user.html.j2 index 7122e58a62670a15a92d91d899cf31c113353115..3bc9b1d6d3c0b590616a3d34467f2fdc4a4a511d 100644 --- a/app/templates/admin/user.html.j2 +++ b/app/templates/admin/user.html.j2 @@ -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() }} diff --git a/app/templates/admin/users.html.j2 b/app/templates/admin/users.html.j2 index e8ffac293e61a3f78b5ab9c582f37c1a178882b3..8c1e09c192e05fc659b9d146e64b302e57397a57 100644 --- a/app/templates/admin/users.html.j2 +++ b/app/templates/admin/users.html.j2 @@ -35,7 +35,7 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} {% block scripts %} {{ super() }} diff --git a/app/templates/auth/login.html.j2 b/app/templates/auth/login.html.j2 index 58fe45b3584ba892b9920c22150d79c6b64e5beb..aea7138246dbe863a48dd98e247be561106caf29 100644 --- a/app/templates/auth/login.html.j2 +++ b/app/templates/auth/login.html.j2 @@ -52,4 +52,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/auth/register.html.j2 b/app/templates/auth/register.html.j2 index e1c7186f97a77546cf13998813f93f8490e07ad4..99548a1e96d09e19dfc5112ea869484cfefa6bfb 100644 --- a/app/templates/auth/register.html.j2 +++ b/app/templates/auth/register.html.j2 @@ -45,4 +45,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/auth/reset_password.html.j2 b/app/templates/auth/reset_password.html.j2 index 376795e190fd5709ca089727f17113a9cb28f261..4be59edf218f3ec2e5a45197a86dfa2746f530d0 100644 --- a/app/templates/auth/reset_password.html.j2 +++ b/app/templates/auth/reset_password.html.j2 @@ -29,4 +29,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/auth/reset_password_request.html.j2 b/app/templates/auth/reset_password_request.html.j2 index 66d5776dfa0589d22d747a5a62a8ea830df82380..b91cd59b4bf3f5216eee4e004061a724b4a4395c 100644 --- a/app/templates/auth/reset_password_request.html.j2 +++ b/app/templates/auth/reset_password_request.html.j2 @@ -28,4 +28,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/auth/unconfirmed.html.j2 b/app/templates/auth/unconfirmed.html.j2 index 89d643ac237b7798afab7efcd53c93194b14ca5c..db9bf8c4940611ab25e798c58d13a70e219f307e 100644 --- a/app/templates/auth/unconfirmed.html.j2 +++ b/app/templates/auth/unconfirmed.html.j2 @@ -23,4 +23,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/base.html.j2 b/app/templates/base.html.j2 index 7a1c9fa9c6de03a3e9100b6916594b1541c293ca..dbecd35e1e76419baff35b973af85bf4beb9b2bb 100644 --- a/app/templates/base.html.j2 +++ b/app/templates/base.html.j2 @@ -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 %} diff --git a/app/templates/corpora/add_corpus.html.j2 b/app/templates/corpora/add_corpus.html.j2 index a44bb99026c6a33454ddc97ec07871a8b0fc8a8c..9d7f24e4b907a536f36de4acf6347c40e3f4803e 100644 --- a/app/templates/corpora/add_corpus.html.j2 +++ b/app/templates/corpora/add_corpus.html.j2 @@ -38,4 +38,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/corpora/add_corpus_file.html.j2 b/app/templates/corpora/add_corpus_file.html.j2 index da4bb27d007ecc224cd2abf7becd71091ae1a928..fe0320def05463eaa2282f1dffabf10bc035a0aa 100644 --- a/app/templates/corpora/add_corpus_file.html.j2 +++ b/app/templates/corpora/add_corpus_file.html.j2 @@ -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 %} diff --git a/app/templates/corpora/corpus.html.j2 b/app/templates/corpora/corpus.html.j2 index c6c7702fc6fc18c70900a0790117325bd1dc291b..1d455edabc88364d72f990db85b86c8e6bd093ff 100644 --- a/app/templates/corpora/corpus.html.j2 +++ b/app/templates/corpora/corpus.html.j2 @@ -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> diff --git a/app/templates/corpora/corpus_file.html.j2 b/app/templates/corpora/corpus_file.html.j2 index df474606fff6f447e3761bba54d71f82484f0c9b..53ac550ef5e2976f5b47e2b86a6673e7ec5234a8 100644 --- a/app/templates/corpora/corpus_file.html.j2 +++ b/app/templates/corpora/corpus_file.html.j2 @@ -48,4 +48,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/corpora/import_corpus.html.j2 b/app/templates/corpora/import_corpus.html.j2 index 68bfc18670608096ee24a9a7806e74d032d5c26d..d2322fd7bf37bf8db4a24d31e8ef81fa7399622a 100644 --- a/app/templates/corpora/import_corpus.html.j2 +++ b/app/templates/corpora/import_corpus.html.j2 @@ -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 %} diff --git a/app/templates/jobs/job.html.j2 b/app/templates/jobs/job.html.j2 index 344794bdaabfe6661c7c49b5b37cf8ff408a066c..2712b6acd5b0fd72bd0fb228259f259e5b34440f 100644 --- a/app/templates/jobs/job.html.j2 +++ b/app/templates/jobs/job.html.j2 @@ -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> diff --git a/app/templates/main/dashboard.html.j2 b/app/templates/main/dashboard.html.j2 index 1492caf7579e8bdbf62cb75cd8854ac3878e4b95..8872efcaa17fa49b0cc1b424b60d7b7e7804a540 100644 --- a/app/templates/main/dashboard.html.j2 +++ b/app/templates/main/dashboard.html.j2 @@ -119,58 +119,61 @@ <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"> - <div class="modal-content"> - <h4>Select a service</h4> - <p> </p> - <div class="row"> - <div class="col s12 m4"> - <div class="card-panel center-align hoverable"> - <br> - <a href="{{ url_for('services.service', service='file-setup') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);"> - <i class="nopaque-icons service-color darken service-icon" data-service="file-setup"></i> - </a> - <br><br> - <p class="service-color-text darken" data-service="file-setup"><b>File setup</b></p> - <p class="light">Digital copies of text based research data (books, letters, etc.) often comprise various files and formats. nopaque converts and merges those files to facilitate further processing and the application of other services.</p> - <a href="{{ url_for('services.service', service='file-setup') }}" class="waves-effect waves-light btn service-color darken" data-service="file-setup">Create Job</a> - </div> - </div> - <div class="col s12 m4"> - <div class="card-panel center-align hoverable"> - <br> - <a href="{{ url_for('services.service', service='ocr') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);"> - <i class="nopaque-icons service-color darken service-icon" data-service="ocr" style="font-size: 2.5rem;"></i> - </a> - <br><br> - <p class="service-color-text darken" data-service="ocr"><b>Optical Character Recognition</b></p> - <p class="light">nopaque converts your image data – like photos or scans – into text data through a process called OCR. This step enables you to proceed with further computational analysis of your documents.</p> - <a href="{{ url_for('services.service', service='ocr') }}" class="waves-effect waves-light btn service-color darken" data-service="ocr">Create Job</a> - </div> - </div> - <div class="col s12 m4"> - <div class="card-panel center-align hoverable"> - <br> - <a href="{{ url_for('services.service', service='nlp') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);"> - <i class="nopaque-icons service-color darken service-icon" data-service="nlp" style="font-size: 2.5rem;"></i> - </a> - <br><br> - <p class="service-color-text darken" data-service="nlp"><b>Natural Language Processing</b></p> - <p class="light">By means of computational linguistic data processing (tokenization, lemmatization, part-of-speech tagging and named-entity recognition) nopaque extracts additional information from your text.</p> - <a href="{{ url_for('services.service', service='nlp') }}" class="waves-effect waves-light btn service-color darken" data-service="nlp">Create Job</a> - </div> - </div> +{% block modals %} +{{ super() }} +<div id="new-job-modal" class="modal"> + <div class="modal-content"> + <h4>Select a service</h4> + <p> </p> + <div class="row"> + <div class="col s12 m4"> + <div class="card-panel center-align hoverable"> + <br> + <a href="{{ url_for('services.service', service='file-setup') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);"> + <i class="nopaque-icons service-color darken service-icon" data-service="file-setup"></i> + </a> + <br><br> + <p class="service-color-text darken" data-service="file-setup"><b>File setup</b></p> + <p class="light">Digital copies of text based research data (books, letters, etc.) often comprise various files and formats. nopaque converts and merges those files to facilitate further processing and the application of other services.</p> + <a href="{{ url_for('services.service', service='file-setup') }}" class="waves-effect waves-light btn service-color darken" data-service="file-setup">Create Job</a> + </div> + </div> + <div class="col s12 m4"> + <div class="card-panel center-align hoverable"> + <br> + <a href="{{ url_for('services.service', service='ocr') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);"> + <i class="nopaque-icons service-color darken service-icon" data-service="ocr" style="font-size: 2.5rem;"></i> + </a> + <br><br> + <p class="service-color-text darken" data-service="ocr"><b>Optical Character Recognition</b></p> + <p class="light">nopaque converts your image data – like photos or scans – into text data through a process called OCR. This step enables you to proceed with further computational analysis of your documents.</p> + <a href="{{ url_for('services.service', service='ocr') }}" class="waves-effect waves-light btn service-color darken" data-service="ocr">Create Job</a> + </div> + </div> + <div class="col s12 m4"> + <div class="card-panel center-align hoverable"> + <br> + <a href="{{ url_for('services.service', service='nlp') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);"> + <i class="nopaque-icons service-color darken service-icon" data-service="nlp" style="font-size: 2.5rem;"></i> + </a> + <br><br> + <p class="service-color-text darken" data-service="nlp"><b>Natural Language Processing</b></p> + <p class="light">By means of computational linguistic data processing (tokenization, lemmatization, part-of-speech tagging and named-entity recognition) nopaque extracts additional information from your text.</p> + <a href="{{ url_for('services.service', service='nlp') }}" class="waves-effect waves-light btn service-color darken" data-service="nlp">Create Job</a> </div> - </div> - <div class="modal-footer"> - <a href="#!" class="modal-close waves-effect waves-light btn-flat">Close</a> - </div> </div> </div> </div> + <div class="modal-footer"> + <a href="#!" class="modal-close waves-effect waves-light btn-flat">Close</a> + </div> </div> -{% endblock %} +{% endblock modals %} {% block scripts %} {{ super() }} diff --git a/app/templates/main/faq.html.j2 b/app/templates/main/faq.html.j2 index 308534d296179a41038f1b7783813ee23e69afba..86dde843b49ba0e43698b056d0865533cc776ed0 100644 --- a/app/templates/main/faq.html.j2 +++ b/app/templates/main/faq.html.j2 @@ -53,4 +53,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/main/index.html.j2 b/app/templates/main/index.html.j2 index 6165a4b3275cc18c62657712c6581d21fd499b72..94db3551b66afc7e733f2d54f55c513de81f6807 100644 --- a/app/templates/main/index.html.j2 +++ b/app/templates/main/index.html.j2 @@ -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 %} diff --git a/app/templates/main/news.html.j2 b/app/templates/main/news.html.j2 index 8e3cbfd4fd482e73b8e57925a821d63a5fae71a1..568cf70634ad798138f99602495eac431dc4606b 100644 --- a/app/templates/main/news.html.j2 +++ b/app/templates/main/news.html.j2 @@ -48,4 +48,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/main/privacy_policy.html.j2 b/app/templates/main/privacy_policy.html.j2 index 1b7c1c6d6407e4ae5f6fcff1cc92c6cfa2f64080..ff22b10ad8b9b0befa524dc3e5b0bfd14d9e63e4 100644 --- a/app/templates/main/privacy_policy.html.j2 +++ b/app/templates/main/privacy_policy.html.j2 @@ -152,4 +152,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/main/terms_of_use.html.j2 b/app/templates/main/terms_of_use.html.j2 index f84a29417d4dfa1f473293b20efdf5aa7a377d10..baedd0a28530a56d4660c9aae335fbff15eddaf2 100644 --- a/app/templates/main/terms_of_use.html.j2 +++ b/app/templates/main/terms_of_use.html.j2 @@ -109,4 +109,4 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} diff --git a/app/templates/materialize/base.html.j2 b/app/templates/materialize/base.html.j2 index 28b03d45702dea8fd0312c9bdf2f3831ea2fe41a..a7de0e2d14d5ca5a1fc8a8af54a1e2902ea00ff9 100644 --- a/app/templates/materialize/base.html.j2 +++ b/app/templates/materialize/base.html.j2 @@ -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 %} diff --git a/app/templates/services/corpus_analysis.html.j2 b/app/templates/services/corpus_analysis.html.j2 index c3c19568f9315e496c32a46500e2559bbd5aa72e..66d880fe8a9560ef147665703a09e71a7acc0a54 100644 --- a/app/templates/services/corpus_analysis.html.j2 +++ b/app/templates/services/corpus_analysis.html.j2 @@ -88,7 +88,7 @@ </div> </div> </div> -{% endblock %} +{% endblock page_content %} {% block scripts %} {{ super() }} diff --git a/app/templates/services/file_setup.html.j2 b/app/templates/services/file_setup.html.j2 index 65c633f02f5b3c956c38777f85a59884ea50ba90..1c974a9eff2a44e7e8a1e98fb88071e0964d439c 100644 --- a/app/templates/services/file_setup.html.j2 +++ b/app/templates/services/file_setup.html.j2 @@ -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 %} diff --git a/app/templates/services/nlp.html.j2 b/app/templates/services/nlp.html.j2 index de95836fdb71c98bc893d7c5488841558685ebaf..e24d867ccbef07fa5c199364f1ba594fa5ec3da7 100644 --- a/app/templates/services/nlp.html.j2 +++ b/app/templates/services/nlp.html.j2 @@ -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 %} diff --git a/app/templates/services/ocr.html.j2 b/app/templates/services/ocr.html.j2 index 12051b9c0df47e2287ce01efb2060ac136cc3895..7eba0241d4e72001aafcd3312dc111343fc6a936 100644 --- a/app/templates/services/ocr.html.j2 +++ b/app/templates/services/ocr.html.j2 @@ -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 %} diff --git a/app/templates/settings/edit_general_settings.html.j2 b/app/templates/settings/edit_general_settings.html.j2 index 19f487e782529329fe40fc36126a926f146f4e7c..cfae41a695dba32d487a8414bd4f1803fe7a5d48 100644 --- a/app/templates/settings/edit_general_settings.html.j2 +++ b/app/templates/settings/edit_general_settings.html.j2 @@ -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 %}