From 9ae74cc9deb49633b2a2138409d1da3b669bc2d7 Mon Sep 17 00:00:00 2001 From: Stephan Porada Date: Wed, 9 Sep 2020 14:35:00 +0200 Subject: [PATCH] Fix enable/disable toggle of buttons etc. with new client.isBusy field. --- .../modules/corpus_analysis/client/Client.js | 9 +- .../corpus_analysis/client/callbacks.js | 7 ++ .../corpus_analysis/view/ResultsView.js | 95 +++++++++---------- .../modules/corpus_analysis/view/callbacks.js | 26 ++--- .../modules/corpus_analysis/view/listeners.js | 9 +- .../templates/corpora/analyse_corpus.html.j2 | 24 ++--- 6 files changed, 80 insertions(+), 90 deletions(-) diff --git a/web/app/static/js/modules/corpus_analysis/client/Client.js b/web/app/static/js/modules/corpus_analysis/client/Client.js index 262c8f48..5e2c626c 100644 --- a/web/app/static/js/modules/corpus_analysis/client/Client.js +++ b/web/app/static/js/modules/corpus_analysis/client/Client.js @@ -17,8 +17,7 @@ class Client { this.requestQueryProgress = 0; this.socket = socket; this.eventListeners = {}; - this.connected = false; - + this.isBusy = false; /** * Disables all console logging. * This is global. So every other log message in every other Class or @@ -72,8 +71,10 @@ class Client { */ notifyView(caseIdentifier, detailObject={}) { detailObject.caseIdentifier = caseIdentifier; + detailObject.client = this; const event = new CustomEvent('notify-view', { detail: detailObject }); - console.info('Client dispatching Notification:', caseIdentifier); + console.info('Client dispatching Notification with detail object in details:', + detailObject); document.dispatchEvent(event); } @@ -89,6 +90,7 @@ class Client { // Gets the meta data of the current corpus. getMetaData() { + this.isBusy = true; console.info('corpus_analysis_meta_data: Client getting meta data via', 'socket.emit.'); this.socket.emit('corpus_analysis_meta_data', this.corpusId); @@ -99,6 +101,7 @@ class Client { * back. */ query(queryStr) { + this.isBusy = true; console.info('corpus_analysis_query: Client sending query via', 'socket.emit for the query', queryStr); this.socket.emit('corpus_analysis_query', queryStr); diff --git a/web/app/static/js/modules/corpus_analysis/client/callbacks.js b/web/app/static/js/modules/corpus_analysis/client/callbacks.js index 64bb24d4..c936d4e7 100644 --- a/web/app/static/js/modules/corpus_analysis/client/callbacks.js +++ b/web/app/static/js/modules/corpus_analysis/client/callbacks.js @@ -6,6 +6,7 @@ function saveMetaData() { let [payload, client, results, rest] = arguments; results.metaData.init(payload) console.info('Metada saved:', results); + client.isBusy = false; } /** @@ -24,6 +25,9 @@ function prepareQueryData() { client.notifyView('query-data-prepareing', { results: results }); } +/** + * This callbacks saves the incoming query data chunks into the model results. + */ function saveQueryData(args) { let [payload, client, results, rest] = arguments; // get data matches length before new chun kdata is being inserted @@ -42,12 +46,14 @@ function saveQueryData(args) { dataLength: dataLength }); console.info('Query data chunk saved', results.data); if (client.requestQueryProgress === 100) { + client.isBusy = false; client.notifyView('query-data-recieved'); } } function getResultsData(args) { let [resultsType, dataIndexes, client, results, rest] = arguments; + client.isBusy = true; client.notifyView('results-data-recieving'); client.getResultsData(resultsType, dataIndexes, results); } @@ -76,6 +82,7 @@ function saveResultsData(args) { results[objectKey].match_count = [...payload.matches].length; results[objectKey].cpos_ranges = payload.cpos_ranges; console.info('Results data has been saved.', results); + client.isBusy = false; client.notifyView('results-data-recieved', {type: type, results: results}); } diff --git a/web/app/static/js/modules/corpus_analysis/view/ResultsView.js b/web/app/static/js/modules/corpus_analysis/view/ResultsView.js index 2fe6ba1b..2803cb2f 100644 --- a/web/app/static/js/modules/corpus_analysis/view/ResultsView.js +++ b/web/app/static/js/modules/corpus_analysis/view/ResultsView.js @@ -54,7 +54,6 @@ class ResultsList extends List { this.addToSubResultsIdsToShow = new Set(); // If check button is pressed its corresponding data_index is saved in this set. The set is shown to the user. // notification listeners listening for client notifications (or other in the future?) this.notificationListeners = {}; - this.clientIsBusy = false; } /** @@ -267,19 +266,26 @@ class ResultsList extends List { } // ###### Functions to inspect one match, to show more details ###### - // activate inspect buttons if progress is 100 - activateInspect() { - if (!this.clientIsBusy) { - let inspectBtnElements; - inspectBtnElements = document.querySelectorAll('.inspect'); - for (let inspectBtn of inspectBtnElements) { - inspectBtn.classList.toggle('disabled', false); - } + // Activate inspect buttons depending on the Client status + toggleInspectButtons(client) { + if (!client.isBusy) { + this.activateInspectButtons(); + } else if (client.isBusy) { + this.deactivateInspectButtons(); } } - // deactivate inspect buttons - deactivateInspect() { + // Activate inspect buttons. Should be private if this is supported. + activateInspectButtons() { + let inspectBtnElements; + inspectBtnElements = document.querySelectorAll('.inspect'); + for (let inspectBtn of inspectBtnElements) { + inspectBtn.classList.toggle('disabled', false); + } + } + + // Deactivate inspect buttons. Should be private if this is supported. + deactivateInspectButtons() { let inspectBtnElements; inspectBtnElements = document.querySelectorAll('.inspect'); for (let inspectBtn of inspectBtnElements) { @@ -535,56 +541,41 @@ class ResultsList extends List { // Event function that changes the shown hits per page. // Just alters the resultsList.page property - changeHitsPerPage() { - try { - if (event.type === "change") { - nopaque.flash("Updated matches per page.", "corpus") - } - } catch (e) { - - } finally { - this.page = this.displayOptionsFormResultsPerPage.value; - this.update(); - } - this.activateInspect(); + changeHitsPerPage(client, results) { + this.page = this.displayOptionsFormResultsPerPage.value; + this.update(); + this.changeContext(); + this.toggleInspectButtons(client); if (this.displayOptionsFormExpertMode.checked) { - this.expertModeOn("query-display"); + this.expertModeOn('query-display', results); } } // Event function triggered on context select change // also if pagination is clicked changeContext() { - try { - if (event.type === "change") { - nopaque.flash("Updated context per match!", "corpus"); - } - } catch (e) { - - } finally { - let newContextValue = this.displayOptionsFormResultContext.value; - let lc = document.querySelectorAll(".left-context"); - let rc = document.querySelectorAll(".right-context"); - for (let element of lc) { - let arrayLc = Array.from(element.childNodes); - for (let element of arrayLc.reverse().slice(newContextValue)) { - element.classList.add("hide"); - } - for (let element of arrayLc.slice(0, newContextValue)) { - element.classList.remove("hide"); - } - } - for (let element of rc) { - let arrayRc = Array.from(element.childNodes); - for (let element of arrayRc.slice(newContextValue)) { - element.classList.add("hide"); - } - for (let element of arrayRc.slice(0, newContextValue)) { - element.classList.remove("hide"); - } - } + let newContextValue = this.displayOptionsFormResultContext.value; + let lc = document.querySelectorAll(".left-context"); + let rc = document.querySelectorAll(".right-context"); + for (let element of lc) { + let arrayLc = Array.from(element.childNodes); + for (let element of arrayLc.reverse().slice(newContextValue)) { + element.classList.add("hide"); + } + for (let element of arrayLc.slice(0, newContextValue)) { + element.classList.remove("hide"); } } + for (let element of rc) { + let arrayRc = Array.from(element.childNodes); + for (let element of arrayRc.slice(newContextValue)) { + element.classList.add("hide"); + } + for (let element of arrayRc.slice(0, newContextValue)) { + element.classList.remove("hide"); + } + } + } // ###### Expert view event functions ###### // function to create a tooltip for the current hovered token diff --git a/web/app/static/js/modules/corpus_analysis/view/callbacks.js b/web/app/static/js/modules/corpus_analysis/view/callbacks.js index d9c85926..4a6e0f87 100644 --- a/web/app/static/js/modules/corpus_analysis/view/callbacks.js +++ b/web/app/static/js/modules/corpus_analysis/view/callbacks.js @@ -5,23 +5,21 @@ */ function disableElementsGeneralCallback(resultsList, detail) { - if (detail.type === 'full-results') { - resultsList.fullResultsCreate.classList.toggle('hide', false); - resultsList.fullResultsExport.classList.toggle('hide', true); - } else if (detail.type === 'sub-results') { - resultsList.subResultsCreate.classList.toggle('hide', false); - resultsList.subResultsExport.classList.toggle('hide', true); - } else { + if (detail.client.isBusy) { resultsList.fullResultsCreate.classList.toggle('disabled', true); resultsList.subResultsCreate.classList.toggle('disabled', true); + resultsList.toggleInspectButtons(detail.client); } - resultsList.deactivateInspect(); } function enableElementsGeneralCallback(resultsList, detail) { - resultsList.fullResultsCreate.classList.toggle('disabled'); - resultsList.subResultsCreate.classList.toggle('disabled'); - resultsList.activateInspect(); + if (!detail.client.isBusy) { + resultsList.fullResultsCreate.classList.toggle('disabled', false); + if (resultsList.addToSubResultsIdsToShow.size > 0) { + resultsList.subResultsCreate.classList.toggle('disabled', false); + } + resultsList.toggleInspectButtons(detail.client); + } } function connectingCallback(resultsList, detail) { @@ -46,7 +44,6 @@ function connectingFaildeCallback(resultsList, detail) { } function queryDataPreparingCallback(resultsList, detail) { - resultsList.clientIsBusy = true; // remove all items from resultsList, like from the query issued before resultsList.clear() // get needed HTML Elements @@ -106,7 +103,7 @@ function queryDataRecievingCallback(resultsList, detail) { resultsList.textLookupTitles.textContent = `${titles.join(', ')}`; // updating table on finished item creation callback via createResultRowElement resultsList.update(); - resultsList.changeHitsPerPage(); + resultsList.changeHitsPerPage(client, results); resultsList.changeContext(); //activate expertMode of switch is checked if (resultsList.displayOptionsFormExpertMode.checked) { @@ -128,15 +125,12 @@ function queryDataRecievedCallback(resultsList, detail) { resultsList.queryProgressBar.classList.toggle('hide'); // reset bar progress for next query resultsList.queryProgressBar.firstElementChild.style.width = '0%'; - resultsList.clientIsBusy = false; } function resultsDataRecievingCallback(resultsList, detail) { - resultsList.clientIsBusy = true; } function resultsDataRecievedCallback(resultsList, detail) { - resultsList.clientIsBusy = false; // create strings for create buttons depending on type const handleType = (keyPrefix, text) => { // hides the create element after results have been recieved and reset it diff --git a/web/app/static/js/modules/corpus_analysis/view/listeners.js b/web/app/static/js/modules/corpus_analysis/view/listeners.js index 469bcaf2..ee3612fd 100644 --- a/web/app/static/js/modules/corpus_analysis/view/listeners.js +++ b/web/app/static/js/modules/corpus_analysis/view/listeners.js @@ -40,11 +40,6 @@ function recieveClientNotification(eventType, resultsList) { break; case 'query-data-prepareing': console.info('View recieved notification:', caseIdentifier); - // some extra hiding and showing (this should be done less confusing) - resultsList.fullResultsExport.classList.toggle('hide', true); - resultsList.subResultsExport.classList.toggle('hide', true); - resultsList.fullResultsCreate.classList.toggle('hide', false); - resultsList.subResultsCreate.classList.toggle('hide', false); // execute callbacks disableElementsGeneralCallback(resultsList, event.detail); queryDataPreparingCallback(resultsList, event.detail); @@ -66,14 +61,14 @@ function recieveClientNotification(eventType, resultsList) { console.info('View recieved notification:', caseIdentifier); // execute callbacks disableElementsGeneralCallback(resultsList, event.detail); - resultsDataRecievedCallback(resultsList, event.detail); + resultsDataRecievingCallback(resultsList, event.detail); break; case 'results-data-recieved': console.info('View recieved notification:', caseIdentifier); // execute callbacks console.info(event.detail); - enableElementsGeneralCallback(resultsList, event.detail); resultsDataRecievedCallback(resultsList, event.detail); + enableElementsGeneralCallback(resultsList, event.detail); break; default: console.error('Recieved unkown notification case identifier from Client'); diff --git a/web/app/templates/corpora/analyse_corpus.html.j2 b/web/app/templates/corpora/analyse_corpus.html.j2 index eaa3688c..2aa52a16 100644 --- a/web/app/templates/corpora/analyse_corpus.html.j2 +++ b/web/app/templates/corpora/analyse_corpus.html.j2 @@ -257,7 +257,7 @@ document.addEventListener("DOMContentLoaded", () => { resultsList.expertModeOff('query-display'); } // Activates inspect buttons on new page if client is not busy. - resultsList.activateInspect(); + resultsList.toggleInspectButtons(client); }); } @@ -291,10 +291,10 @@ document.addEventListener("DOMContentLoaded", () => { * Following event listeners handle the change of Context size per match and * the number of matches shown per page. */ - resultsList.displayOptionsFormResultsPerPage.onchange = () => { - resultsList.changeHitsPerPage(); + resultsList.displayOptionsFormResultsPerPage.onchange = (event) => { + resultsList.changeHitsPerPage(client, results); }; - resultsList.displayOptionsFormResultContext.onchange = () => { + resultsList.displayOptionsFormResultContext.onchange = (event) => { resultsList.changeContext(); }; @@ -332,7 +332,7 @@ document.addEventListener("DOMContentLoaded", () => { * 5. Download single inspect-results */ // 1. Add events for full-results create - resultsList.fullResultsCreate.onclick = () => { + resultsList.fullResultsCreate.onclick = (event) => { resultsList.fullResultsCreate.querySelector('i').classList.toggle('hide'); resultsList.fullResultsCreate.innerText = 'Creating...'; resultsList.fullResultsCreate.insertAdjacentHTML('afterbegin', @@ -342,7 +342,7 @@ document.addEventListener("DOMContentLoaded", () => { dataIndexes: dataIndexes}); } // 2. Add events for sub-results create - resultsList.subResultsCreate.onclick = () => { + resultsList.subResultsCreate.onclick = (event) => { let dataIndexes = []; resultsList.addToSubResultsIdsToShow.forEach((id) => { dataIndexes.push(id - 1); @@ -357,10 +357,10 @@ document.addEventListener("DOMContentLoaded", () => { // Before the download events are added the needed modal is initialized. resultsList.queryResultsDownloadModal = M.Modal.init(resultsList.queryResultsDownloadModal); // 3. Open download modal when full results export button is pressed - resultsList.fullResultsExport.onclick = () => { + resultsList.fullResultsExport.onclick = (event) => { resultsList.queryResultsDownloadModal.open(); // add onclick to download JSON button and download the file - resultsList.downloadResultsJson.onclick = () => { + resultsList.downloadResultsJson.onclick = (event) => { let filename = results.fullResultsData.createDownloadFilename('full-results'); results.fullResultsData.addData(results.metaData); results.fullResultsData.downloadJSONRessource(filename, @@ -368,10 +368,10 @@ document.addEventListener("DOMContentLoaded", () => { resultsList.downloadResultsJson)}; } // 4. Open download modal when sub results export button is pressed - resultsList.subResultsExport.onclick = () => { + resultsList.subResultsExport.onclick = (event) => { resultsList.queryResultsDownloadModal.open(); // add onclick to download JSON button and download the file - resultsList.downloadResultsJson.onclick = () => { + resultsList.downloadResultsJson.onclick = (event) => { let filename = results.subResultsData.createDownloadFilename('sub-results'); results.subResultsData.addData(results.metaData); results.subResultsData.downloadJSONRessource(filename, @@ -379,10 +379,10 @@ document.addEventListener("DOMContentLoaded", () => { resultsList.downloadResultsJson)}; } // 5. Open download modal when inspect-results-export button is pressed - resultsList.inspectResultsExport.onclick = () => { + resultsList.inspectResultsExport.onclick = (event) => { resultsList.queryResultsDownloadModal.open(); // add onclick to download JSON button and download the file - resultsList.downloadResultsJson.onclick = () => { + resultsList.downloadResultsJson.onclick = (event) => { let filename = results.subResultsData.createDownloadFilename('inspect-results'); results.subResultsData.addData(results.metaData); results.subResultsData.downloadJSONRessource(filename,