diff --git a/web/app/static/js/nopaque/lists/CorpusFileList.js b/web/app/static/js/nopaque/lists/CorpusFileList.js index afd2a42cb133173d5136c3cf968d05acca15870c..478be52ef0bfde2eed7ca134a512208ff2a3c2d4 100644 --- a/web/app/static/js/nopaque/lists/CorpusFileList.js +++ b/web/app/static/js/nopaque/lists/CorpusFileList.js @@ -40,7 +40,7 @@ class CorpusFileList extends RessourceList { window.location.href = this.corpus.files[corpusFileId].download_url; break; case 'view': - window.location.href = this.corpus.files[corpusFileId].url; + if (corpusFileId !== '-1') {window.location.href = this.corpus.files[corpusFileId].url;} break; default: console.error(`Unknown action: "${action}"`); @@ -49,7 +49,7 @@ class CorpusFileList extends RessourceList { } patch(patch) { - let id, match, re; + let id, match, re, valueName; for (let operation of patch) { switch(operation.op) { case 'add': @@ -65,6 +65,14 @@ class CorpusFileList extends RessourceList { this.remove(id); } break; + case 'replace': + // Matches the only paths that should be handled here: /corpora/{corpusId}/{status || description || title} + re = new RegExp('^/corpora/' + this.corpus.id + '/files/(\\d+)/(author|filename|publishing_year|title)$'); + if (re.test(operation.path)) { + [match, id, valueName] = operation.path.match(re); + this.replace(id, valueName, operation.value); + } + break; default: break; } @@ -72,7 +80,7 @@ class CorpusFileList extends RessourceList { } preprocessRessource(corpusFile) { - return {id: corpusFile.id, author: corpusFile.author, filename: corpusFile.filename, 'publishing-year': corpusFile.publishing_year, title: corpusFile.title}; + return {id: corpusFile.id, author: corpusFile.author, filename: corpusFile.filename, publishing_year: corpusFile.publishing_year, title: corpusFile.title}; } } CorpusFileList.options = { @@ -80,12 +88,12 @@ CorpusFileList.options = { <td><span class="filename"></span></td> <td><span class="author"></span></td> <td><span class="title"></span></td> - <td><span class="publishing-year"></span></td> + <td><span class="publishing_year"></span></td> <td class="right-align"> <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a> <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="download" data-position="top" data-tooltip="View"><i class="material-icons">file_download</i></a> <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a> </td> </tr>`, - valueNames: [{data: ['id']}, 'author', 'filename', 'publishing-year', 'title'] + valueNames: [{data: ['id']}, 'author', 'filename', 'publishing_year', 'title'] }; diff --git a/web/app/static/js/nopaque/lists/CorpusList.js b/web/app/static/js/nopaque/lists/CorpusList.js index e9fd392cb0a815c9665c5dd61b01d8e10b585de6..a343341130ad8f83ccff99b30475fd78a63ae871 100644 --- a/web/app/static/js/nopaque/lists/CorpusList.js +++ b/web/app/static/js/nopaque/lists/CorpusList.js @@ -36,7 +36,7 @@ class CorpusList extends RessourceList { deleteModal.open(); break; case 'view': - window.location.href = this.corpora[corpusId].url; + if (corpusId !== '-1') {window.location.href = this.corpora[corpusId].url;} break; default: console.error(`Unknown action: ${action}`); diff --git a/web/app/static/js/nopaque/lists/JobList.js b/web/app/static/js/nopaque/lists/JobList.js index 52d308250d9eb2ec9a18ab8daee3ab54ca4da53d..b4cd84fffb3b120baf74c92232e302c785367445 100644 --- a/web/app/static/js/nopaque/lists/JobList.js +++ b/web/app/static/js/nopaque/lists/JobList.js @@ -30,7 +30,7 @@ class JobList extends RessourceList { deleteModal.open(); break; case 'view': - window.location.href = this.user.data.jobs[jobId].url; + if (jobId !== '-1') {window.location.href = this.user.data.jobs[jobId].url;} break; default: console.error(`Unknown action: "${action}"`); @@ -57,7 +57,7 @@ class JobList extends RessourceList { break; case 'replace': // Matches the only paths that should be handled here: /jobs/{jobId}/{service || status || description || title} - re = /^\/jobs\/(\d+)\/(status|description|title)$/; + re = /^\/jobs\/(\d+)\/(service|status|description|title)$/; if (re.test(operation.path)) { [match, id, valueName] = operation.path.match(re); this.replace(id, valueName, operation.value); diff --git a/web/app/static/js/nopaque/lists/QueryResultList.js b/web/app/static/js/nopaque/lists/QueryResultList.js index c8cf0771f6e7c08dd57e901df2bad8e51b6b49f8..98f3e7fbc22bd7f29208279397dc86a19ea599a1 100644 --- a/web/app/static/js/nopaque/lists/QueryResultList.js +++ b/web/app/static/js/nopaque/lists/QueryResultList.js @@ -2,6 +2,79 @@ class QueryResultList extends RessourceList { constructor(listElement, options = {}) { super(listElement, {...QueryResultList.options, ...options}); this.user.eventListeners.queryResult.addEventListener((eventType, payload) => this.eventHandler(eventType, payload)); + listElement.addEventListener('click', event => this.onclick(event)); + } + + onclick(event) { + let ressourceElement = event.target.closest('tr'); + if (ressourceElement === null) {return;} + let queryResultId = ressourceElement.dataset.id; + let actionButtonElement = event.target.closest('.action-button'); + let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action; + switch (action) { + case 'delete': + let deleteModalHTML = `<div class="modal"> + <div class="modal-content"> + <h4>Confirm query result deletion</h4> + <p>Do you really want to delete the query result <b>${this.user.data.query_results[queryResultId].title}</b>? It 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="${this.user.data.query_results[queryResultId].url}/delete"><i class="material-icons left">delete</i>Delete</a> + </div> + </div>`; + let deleteModalParentElement = document.querySelector('main'); + deleteModalParentElement.insertAdjacentHTML('beforeend', deleteModalHTML); + let deleteModalElement = deleteModalParentElement.lastChild; + let deleteModal = M.Modal.init(deleteModalElement, {onCloseEnd: () => {deleteModal.destroy(); deleteModalElement.remove();}}); + deleteModal.open(); + break; + case 'view': + if (queryResultId !== '-1') {window.location.href = this.user.data.query_results[queryResultId].url;} + break; + default: + console.error(`Unknown action: "${action}"`); + break; + } + } + + patch(patch) { + let id, match, re, valueName; + for (let operation of patch) { + switch(operation.op) { + case 'add': + // Matches the only paths that should be handled here: /jobs/{jobId} + re = /^\/query_results\/(\d+)$/; + if (re.test(operation.path)) {this.add(operation.value);} + break; + case 'remove': + // See case add ;) + re = /^\/query_results\/(\d+)$/; + if (re.test(operation.path)) { + [match, id] = operation.path.match(re); + this.remove(id); + } + break; + case 'replace': + // Matches the only paths that should be handled here: /jobs/{jobId}/{service || status || description || title} + re = /^\/query_results\/(\d+)\/(corpus_title|description|query|title)$/; + if (re.test(operation.path)) { + [match, id, valueName] = operation.path.match(re); + this.replace(id, valueName, operation.value); + } + break; + default: + break; + } + } + } + + preprocessRessource(queryResult) { + return {id: queryResult.id, + corpus_title: queryResult.corpus_title, + description: queryResult.description, + query: queryResult.query, + title: queryResult.title}; } } QueryResultList.options = { @@ -11,7 +84,6 @@ QueryResultList.options = { <td class="right-align"> <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a> <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a> - <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="analyse" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a> </td> </tr>`, valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title'] diff --git a/web/app/static/js/nopaque/lists/RessourceList.js b/web/app/static/js/nopaque/lists/RessourceList.js index 3aabfc9d7d319b04232f892aadaaa4533e3d5fdc..ec5afa695dd0d4c0d0645af037cb5cd19afd0b91 100644 --- a/web/app/static/js/nopaque/lists/RessourceList.js +++ b/web/app/static/js/nopaque/lists/RessourceList.js @@ -34,8 +34,8 @@ class RessourceList { </div> </div> <div class="col s9 m6 xl5"> - <span class="card-title">Preparing data...</span> - <p>No ressource available (yet).</p> + <span class="card-title">Waiting for data...</span> + <p>This list is not initialized yet.</p> </div> </td> </tr>`; @@ -59,6 +59,13 @@ class RessourceList { this.list.clear(); this.add(Object.values(ressources)); this.list.sort('id', {order: 'desc'}); + let emptyListElementHTML = `<tr class="show-if-only-child" data-id="-1"> + <td colspan="100%"> + <span class="card-title"><i class="left material-icons" style="font-size: inherit;">file_download</i>Nothing here...</span> + <p>No ressource available.</p> + </td> + </tr>`; + this.list.list.insertAdjacentHTML('afterbegin', emptyListElementHTML); } patch(patch) { diff --git a/web/app/static/js/nopaque/main.js b/web/app/static/js/nopaque/main.js index 1bf3561c7c348c4cac82882ded27e836c3a8a094..c8f886bec370470c5f5d9906e3599ba059ab5547 100644 --- a/web/app/static/js/nopaque/main.js +++ b/web/app/static/js/nopaque/main.js @@ -42,41 +42,32 @@ class User { init(data) { this.data = data; - if (Object.keys(this.data.corpora).length > 0) { - //for (listener of this.eventListeners.corporaInit) {listener(this.data.corpora);} - for (let [corpusId, eventListeners] of Object.entries(this.eventListeners.corpus)) { - if (corpusId === '*') { - for (let eventListener of eventListeners) {eventListener('init', this.data.corpora);} - } else { - if (corpusId in this.data.corpora) { - for (let eventListener of eventListeners) {eventListener('init', this.data.corpora[corpusId]);} - } + for (let [corpusId, eventListeners] of Object.entries(this.eventListeners.corpus)) { + if (corpusId === '*') { + for (let eventListener of eventListeners) {eventListener('init', this.data.corpora);} + } else { + if (corpusId in this.data.corpora) { + for (let eventListener of eventListeners) {eventListener('init', this.data.corpora[corpusId]);} } } } - if (Object.keys(this.data.jobs).length > 0) { - //for (listener of this.eventListeners.jobsInit) {listener(this.data.jobs);} - for (let [jobId, eventListeners] of Object.entries(this.eventListeners.job)) { - if (jobId === '*') { - for (let eventListener of eventListeners) {eventListener('init', this.data.jobs);} - } else { - if (jobId in this.data.jobs) { - for (let eventListener of eventListeners) {eventListener('init', this.data.jobs[jobId]);} - } + for (let [jobId, eventListeners] of Object.entries(this.eventListeners.job)) { + if (jobId === '*') { + for (let eventListener of eventListeners) {eventListener('init', this.data.jobs);} + } else { + if (jobId in this.data.jobs) { + for (let eventListener of eventListeners) {eventListener('init', this.data.jobs[jobId]);} } } } - if (Object.keys(this.data.query_results).length > 0) { - //for (listener of this.eventListeners.queryResultsInit) {listener(this.data.query_results);} - for (let [queryResultId, eventListeners] of Object.entries(this.eventListeners.queryResult)) { - if (queryResultId === '*') { - for (let eventListener of eventListeners) {eventListener('init', this.data.query_results);} - } else { - if (queryResultId in this.data.query_results) { - for (let eventListener of eventListeners) {eventListener('init', this.data.query_results[queryResultId]);} - } + for (let [queryResultId, eventListeners] of Object.entries(this.eventListeners.queryResult)) { + if (queryResultId === '*') { + for (let eventListener of eventListeners) {eventListener('init', this.data.query_results);} + } else { + if (queryResultId in this.data.query_results) { + for (let eventListener of eventListeners) {eventListener('init', this.data.query_results[queryResultId]);} } } }