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 122add1e..67c0104b 100644 --- a/web/app/static/js/modules/corpus_analysis/client/Client.js +++ b/web/app/static/js/modules/corpus_analysis/client/Client.js @@ -83,10 +83,6 @@ class Client { connect() { console.info('corpus_analysis_init: Client connecting to session via', 'socket.emit'); - // if (this.displays.init != undefined) { - // this.displays.init.element.M_Modal.open(); - // this.displays.init.setVisibilityByStatus('waiting'); - // } this.socket.emit('corpus_analysis_init', this.corpusId); } @@ -118,12 +114,10 @@ class Client { tmp_last_cpos.push(results.data.matches[dataIndex].c[1]); } nopaque.socket.emit("corpus_analysis_inspect_match", - { - type: resultsType, - data_indexes: dataIndexes, - first_cpos: tmp_first_cpos, - last_cpos: tmp_last_cpos, - }); + {type: resultsType, + data_indexes: dataIndexes, + first_cpos: tmp_first_cpos, + last_cpos: tmp_last_cpos,}); } } 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 145bdaa5..835bebf9 100644 --- a/web/app/static/js/modules/corpus_analysis/client/callbacks.js +++ b/web/app/static/js/modules/corpus_analysis/client/callbacks.js @@ -53,10 +53,26 @@ function getResultsData(args) { } function saveResultsData(args) { - let [payload, client, results, rest] = arguments; - // code to save results data depending on type - console.info('Results data has been saved.'); - client.notifyView('results-data-recieved'); + let [payload, type, client, results, rest] = arguments; + let objectKey = ''; + if (type === 'full-results') { + console.info('Saving full-results data.'); + objectKey = 'fullResultsData'; + } else if (type === 'sub-results') { + console.info('Saving sub-results data.'); + objectKey = 'subResultsData'; + } + results[objectKey].init(); + results[objectKey].matches.push(...payload.matches); + results[objectKey].addData(payload.cpos_lookup, "cpos_lookup"); + results[objectKey].addData(payload.text_lookup, "text_lookup"); + results[objectKey].addData(results.metaData); + results[objectKey].query = results.data.query; + results[objectKey].corpus_type = type; + results[objectKey].match_count = [...payload.matches].length; + results[objectKey].cpos_ranges = payload.cpos_ranges; + console.info('Results data has been saved.', results); + client.notifyView('results-data-recieved', {type: type}); } // export callbacks diff --git a/web/app/static/js/modules/corpus_analysis/client/listeners.js b/web/app/static/js/modules/corpus_analysis/client/listeners.js index 11bfc22b..0edbdde2 100644 --- a/web/app/static/js/modules/corpus_analysis/client/listeners.js +++ b/web/app/static/js/modules/corpus_analysis/client/listeners.js @@ -154,7 +154,8 @@ function recieveResultsData(type, client) { console.info(`corpus_analysis_inspect_match: ${response.code} - ${response.msg}`); console.info(response); // executing the registered callbacks - client.eventListeners[type].executeCallbacks([response.payload]); + client.eventListeners[type].executeCallbacks([response.payload, + response.type]); console.groupEnd(); } else { console.group('Failed to recieve results data.'); 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 6eb5e5c5..db5b0d73 100644 --- a/web/app/static/js/modules/corpus_analysis/view/ResultsView.js +++ b/web/app/static/js/modules/corpus_analysis/view/ResultsView.js @@ -53,6 +53,7 @@ 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; } /** @@ -270,23 +271,21 @@ class ResultsList extends List { // ###### Functions to inspect one match, to show more details ###### // activate inspect buttons if progress is 100 activateInspect() { - if (this.requestQueryProgress === 100) { + if (!this.clientIsBusy) { let inspectBtnElements; - inspectBtnElements = document.getElementsByClassName("inspect"); + inspectBtnElements = document.querySelectorAll('.inspect'); for (let inspectBtn of inspectBtnElements) { - inspectBtn.classList.remove("disabled"); + inspectBtn.classList.toggle('disabled', false); } - } else { - return } } // deactivate inspect buttons deactivateInspect() { let inspectBtnElements; - inspectBtnElements = document.getElementsByClassName("inspect"); + inspectBtnElements = document.querySelectorAll('.inspect'); for (let inspectBtn of inspectBtnElements) { - inspectBtn.classList.add("disabled"); + inspectBtn.classList.toggle('disabled', true); } } @@ -746,7 +745,7 @@ class ResultsList extends List { // # some btn css rules and classes let css = `margin-right: 5px; margin-bottom: 5px;` let classes = `btn-floating btn waves-effect` + - `waves-light grey` + ` waves-light grey` // # add button to trigger more context to every match td inspectBtn = document.createElement("a"); inspectBtn.setAttribute("style", css); @@ -756,7 +755,7 @@ class ResultsList extends List { // # add btn to add matches to sub-results. hidden per default addToSubResultsBtn = document.createElement("a"); addToSubResultsBtn.setAttribute("style", css); - addToSubResultsBtn.setAttribute("class", classes + ` hide add` + addToSubResultsBtn.setAttribute("class", classes + ` add` ); addToSubResultsBtn.innerHTML = 'add'; aCellElement.appendChild(inspectBtn); 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 d3133754..15393a2f 100644 --- a/web/app/static/js/modules/corpus_analysis/view/callbacks.js +++ b/web/app/static/js/modules/corpus_analysis/view/callbacks.js @@ -1,7 +1,22 @@ /** * This file contains all the callbacks triggered by the notificationListener. + * Also general callbacks are defined which are doing some hiding/disabling and + * showing/enabling of common elements when data is being transmitted or not. */ +function disableElementsGeneralCallback(resultsList, detail) { + resultsList.fullResultsCreate.classList.toggle('disabled', true); + resultsList.subResultsCreate.classList.toggle('disabled', true); + resultsList.deactivateInspect(); +} + +function enableElementsGeneralCallback(resultsList, detail) { + resultsList.fullResultsCreate.classList.toggle('disabled'); + resultsList.subResultsCreate.classList.toggle('disabled'); + resultsList.activateInspect(); + +} + function connectingCallback(resultsList, detail) { resultsList.getHTMLElements(['#analysis-init-modal']); resultsList.analysisInitModal = M.Modal.init(resultsList.analysisInitModal, @@ -24,6 +39,7 @@ 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 @@ -39,18 +55,15 @@ function queryDataPreparingCallback(resultsList, detail) { '#query-results-create', '#add-to-sub-results' ]); + // show or enable some things for the user + resultsList.interactionsMenu.classList.toggle('hide', false) + resultsList.queryResultsUserFeedback.classList.toggle('hide', false); + resultsList.queryProgressBar.classList.toggle('hide', false); // set some initial values for the user feedback resultsList.recievedMatchCount.textContent = 0; resultsList.totalMatchCount.textContent = results.data.match_count; resultsList.textLookupTitles.textContent = ''; resultsList.textLookupCount.textContent = 0; - // show or enable some things for the user - resultsList.interactionsMenu.classList.toggle('hide', false) - resultsList.addToSubResults.setAttribute("disabled", ""); - resultsList.queryResultsUserFeedback.classList.toggle('hide', false); - resultsList.queryProgressBar.classList.toggle('hide', false); - // hide ore disable some things for the user - resultsList.queryResultsCreate.classList.toggle('disabled', true); } function queryDataRecievingCallback(resultsList, detail) { @@ -95,17 +108,36 @@ function queryDataRecievedCallback(resultsList, detail) { // hide or disable some things for the user resultsList.queryResultsUserFeedback.classList.toggle('hide'); resultsList.queryProgressBar.classList.toggle('hide'); - // show or enable some things for the user - resultsList.queryResultsCreate.classList.toggle('disabled'); - resultsList.addToSubResults.removeAttribute("disabled"); + // reset bar progress for next query + resultsList.queryProgressBar.firstElementChild.style.width = '0%'; + resultsList.clientIsBusy = false; } function resultsDataRecievingCallback(resultsList, detail) { - // hide or disable elments taht would trigger another cqp data request + resultsList.clientIsBusy = true; } function resultsDataRecievedCallback(resultsList, detail) { - // hide or show the right stuff + resultsList.clientIsBusy = false; + const handleType = (keyPrefix, text) => { + // hides the create element after results have been recieved and reset it + resultsList[`${keyPrefix}Create`].classList.toggle('hide'); + resultsList[`${keyPrefix}Create`].textContent = `Create ${text}`; + resultsList[`${keyPrefix}Create`].insertAdjacentHTML('beforeend', + `build`); + // show and highlight export button + resultsList[`${keyPrefix}Export`].classList.toggle('hide', false); + resultsList[`${keyPrefix}Export`].classList.toggle('pulse', true); + setTimeout(() => { + resultsList[`${keyPrefix}Export`].classList.toggle('pulse', false); + clearTimeout(); + }, 3000) + } + if (detail.type === 'full-results') { + handleType('fullResults', 'Results'); + } else if (detail.type ==='sub-results') { + handleType('subResults', 'Sub-Results'); + } } // export the callbacks @@ -118,4 +150,6 @@ export { queryDataRecievedCallback, resultsDataRecievingCallback, resultsDataRecievedCallback, + disableElementsGeneralCallback, + enableElementsGeneralCallback, }; \ No newline at end of file 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 ff849219..af790ef8 100644 --- a/web/app/static/js/modules/corpus_analysis/view/listeners.js +++ b/web/app/static/js/modules/corpus_analysis/view/listeners.js @@ -16,6 +16,8 @@ import { queryDataRecievedCallback, resultsDataRecievingCallback, resultsDataRecievedCallback, + disableElementsGeneralCallback, + enableElementsGeneralCallback, } from './callbacks.js'; function recieveClientNotification(eventType, resultsList) { @@ -25,7 +27,7 @@ function recieveClientNotification(eventType, resultsList) { case 'connecting': console.info('View recieved notification:', caseIdentifier); connectingCallback(resultsList, event.detail); - // execute callback + // execute callbacks break; case 'connected': console.info('View recieved notification:', caseIdentifier); @@ -33,33 +35,37 @@ function recieveClientNotification(eventType, resultsList) { break; case 'connecting-failed': console.info('View recieved notification:', caseIdentifier); - // execute callback + // execute callbacks connectingFaildeCallback(resultsList, event.detail); break; case 'query-data-prepareing': console.info('View recieved notification:', caseIdentifier); - // execute callback + // execute callbacks + disableElementsGeneralCallback(resultsList, event.detail); queryDataPreparingCallback(resultsList, event.detail); break; case 'query-data-recieving': console.info('View recieved notification:', caseIdentifier); - // execute callback + // execute callbacks queryDataRecievingCallback(resultsList, event.detail); break; case 'query-data-recieved': console.info('View recieved notification:', caseIdentifier); - // execute callback + // execute callbacks queryDataRecievedCallback(resultsList, event.detail); + enableElementsGeneralCallback(resultsList, event.detail); break; case 'results-data-recieving': console.info('View recieved notification:', caseIdentifier); - // execute callback + // execute callbacks + disableElementsGeneralCallback(resultsList, event.detail); resultsDataRecievedCallback(resultsList, event.detail); break; case 'results-data-recieved': console.info('View recieved notification:', caseIdentifier); - // execute callback + // execute callbacks 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 09e7b6fb..c0abaa99 100644 --- a/web/app/templates/corpora/analyse_corpus.html.j2 +++ b/web/app/templates/corpora/analyse_corpus.html.j2 @@ -213,8 +213,11 @@ document.addEventListener("DOMContentLoaded", () => { '#show-meta-data', '#meta-data-modal', '#meta-data-modal-content', - '#query-results-create' - + '#full-results-create', + '#sub-results-create', + '#full-results-export', + '#sub-results-export', + '#download-results-json' ]); /** * Display events: Following event listeners are handleing the @@ -255,19 +258,57 @@ document.addEventListener("DOMContentLoaded", () => { } } }; + resultsList.addToSubResults.on /** * The following event listeners are handeling the data export. + * 1. Create full-results + * 2. Create sub-results + * 3. Download full-results + * 4. Download sub-results */ - resultsList.queryResultsCreate.onclick = () => { - resultsList.queryResultsCreate.querySelector('i').classList.toggle('hide'); - resultsList.queryResultsCreate.innerText = 'Creating...'; - resultsList.queryResultsCreate.insertAdjacentHTML('afterbegin', + resultsList.fullResultsCreate.onclick = () => { + resultsList.fullResultsCreate.querySelector('i').classList.toggle('hide'); + resultsList.fullResultsCreate.innerText = 'Creating...'; + resultsList.fullResultsCreate.insertAdjacentHTML('afterbegin', loadingSpinnerHTML); + let dataIndexes = [...Array(results.data.match_count).keys()]; resultsList.notifyClient('get-results', { resultsType: 'full-results', - dataIndexes: [...Array(results.data.match_count).keys()]}); + dataIndexes: dataIndexes}); + } + resultsList.subResultsCreate.onclick = () => { + let dataIndexes = []; + resultsList.addToSubResultsIdsToShow.forEach((id) => { + dataIndexes.push(id - 1); + }); + resultsList.subResultsCreate.querySelector('i').classList.toggle('hide'); + resultsList.subResultsCreate.innerText = 'Creating...'; + resultsList.subResultsCreate.insertAdjacentHTML('afterbegin', + loadingSpinnerHTML); + resultsList.notifyClient('get-results', { resultsType: 'sub-results', + dataIndexes: dataIndexes}); + } + // Open download modal when full results export button is pressed + resultsList.fullResultsExport.onclick = () => { + exportModal.open(); + // add onclick to download JSON button and download the file + let downloadResultsJSONElement = document.querySelector('#download-results-json') + downloadResultsJSONElement.onclick = () => { + let filename = results.fullResultsData.createDownloadFilename('matches-results'); + results.fullResultsData.addData(results.metaData); + results.fullResultsData.downloadJSONRessource(filename, results.resultsData, + downloadResultsJSONElement)}; + } + // Open download modal when sub results export button is pressed + resultsList.fullResultsExport.onclick = () => { + exportModal.open(); + // add onclick to download JSON button and download the file + let downloadResultsJSONElement = document.querySelector('#download-results-json') + downloadResultsJSONElement.onclick = () => { + let filename = results.subResultsData.createDownloadFilename('matches-results'); + results.subResultsData.addData(results.metaData); + results.subResultsData.downloadJSONRessource(filename, results.resultsData, + downloadResultsJSONElement)}; } - - // enable scroll to Top scrollToTop('.headline', '#menu-scroll-to-top-div'); diff --git a/web/app/templates/interactions/create.html.j2 b/web/app/templates/interactions/create.html.j2 index 7c76be7b..5f6069ce 100644 --- a/web/app/templates/interactions/create.html.j2 +++ b/web/app/templates/interactions/create.html.j2 @@ -6,21 +6,14 @@ results.-->
-
- Sub-Results: - -
+

Add matches to Sub-Results with the + add + button in the list or inspect view. +

-
+
-

matches marked - for Sub-Results:

+

Added matches: