From 12586bb13dbe201a3099283e845007c0d9eae21b Mon Sep 17 00:00:00 2001 From: Stephan Porada Date: Mon, 6 Apr 2020 12:32:29 +0200 Subject: [PATCH] First feature complete rebuilt of analysis interface --- app/corpora/pj_events.py | 7 +- app/static/js/nopaque.pj_analyse_corpus.js | 108 +++++++++++------- .../corpora/pj_analyse_corpus.html.j2 | 38 +++++- 3 files changed, 104 insertions(+), 49 deletions(-) diff --git a/app/corpora/pj_events.py b/app/corpora/pj_events.py index 66e9cd56..b4b10d77 100644 --- a/app/corpora/pj_events.py +++ b/app/corpora/pj_events.py @@ -96,7 +96,7 @@ def pj_corpus_analysis_query(query): @socketio.on('pj_corpus_analysis_inspect_match') @socketio_login_required def pj_corpus_analysis_inspect_match(payload): - logger.warning(payload) + payload = payload["payload"] client = pj_corpus_analysis_clients.get(request.sid) if client is None: socketio.emit('query', '[424]: Failed Dependency', @@ -106,8 +106,9 @@ def pj_corpus_analysis_inspect_match(payload): corpus = client.corpora.get('CORPUS') s = corpus.attributes.structural.get('s') match_context = s.export(payload['first_cpos'], payload['last_cpos'], - context=3, expand_lists=True) - socketio.emit('pj_corpus_analysis_inspect_match', + context=3, expand_lists=False) + match_context['cpos_ranges'] = True + socketio.emit('pj_match_context', {'payload': match_context}, room=request.sid) diff --git a/app/static/js/nopaque.pj_analyse_corpus.js b/app/static/js/nopaque.pj_analyse_corpus.js index 370b4317..85517acd 100644 --- a/app/static/js/nopaque.pj_analyse_corpus.js +++ b/app/static/js/nopaque.pj_analyse_corpus.js @@ -86,58 +86,80 @@ function inspect(dataIndex) { // This function should be in the AnalysisClient class as a method. console.log("Inspect!"); console.log(results.resultsJSON.matches[dataIndex].c); + contextResultsElement = document.getElementById("context-results"); + contextResultsElement.innerHTML = ""; // clear it from old inspects contextModal.open(); nopaque.socket.emit("pj_corpus_analysis_inspect_match", - {payload: {first_cpos: results.resultsJSON.matches[dataIndex].c[0], - last_cpos: results.resultsJSON.matches[dataIndex].c[1]}}); + {payload: { + first_cpos: results.resultsJSON.matches[dataIndex].c[0], + last_cpos: results.resultsJSON.matches[dataIndex].c[1] + } + }); } -function showMatchContext(payload) { +function showMatchContext(response) { + let contextData = response.payload let contextResultsElement; - let sentenceElement + let contextModalLoading; + let contextModalReady; + let expertModeSwitchElement + let partElement let token; let tokenElement; console.log("###### match_context ######"); - console.log("Incoming data:", payload); + console.log("Incoming data:", contextData); + expertModeSwitchElement = document.getElementById("display-options-form-expert_mode"); contextResultsElement = document.getElementById("context-results"); - contextResultsElement.innerHTML = "

 

"; - document.getElementById("context-modal-loading").classList.add("hide"); - document.getElementById("context-modal-ready").classList.remove("hide"); + contextModalLoading = document.getElementById("context-modal-loading"); + contextModalLoading.classList.add("hide"); + contextModalReady = document.getElementById("context-modal-ready"); + contextModalReady.classList.remove("hide"); - for (let [key, value] of Object.entries(payload['context_s_cpos'])) { - sentenceElement = document.createElement("p"); - for (let cpos of value) { - token = payload["cpos_lookup"][cpos]; - tokenElement = document.createElement("span"); - tokenElement.classList.add("token"); - if (payload["match_cpos_list"].includes(cpos)) { - tokenElement.classList.add("bold"); - tokenElement.classList.add("light-green"); - } - tokenElement.dataset.cpos = cpos; - tokenElement.innerText = token["word"]; - var expertModeSwitchElement = document.getElementById("expert-mode-switch"); - if (expertModeSwitchElement.checked) { - expertModeOn([tokenElement], payload); - } - sentenceElement.append(tokenElement); - sentenceElement.append(document.createTextNode(" ")); - } - contextResultsElement.append(sentenceElement); + if (contextData.cpos_ranges == true) { + // python range like function from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Sequence_generator_(range) + const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step)); + lc = range(contextData.match.lc[0], contextData.match.lc[1], 1) + c = range(contextData.match.c[0], contextData.match.c[1], 1) + rc = range(contextData.match.rc[0], contextData.match.rc[1], 1) + } else { + lc = contextData.match.lc; + c = contextData.match.c; + rc = contextData.match.rc; + } + + partElement = document.createElement("p"); + for (let cpos of lc) { + token = contextData["cpos_lookup"][cpos]; + partElement.insertAdjacentHTML("beforeend", `${token["word"]} `); + contextResultsElement.append(partElement); + } + for (let cpos of c) { + token = contextData["cpos_lookup"][cpos]; + partElement.insertAdjacentHTML("beforeend", `${token["word"]} `); + contextResultsElement.append(partElement); + } + for (let cpos of rc) { + token = contextData["cpos_lookup"][cpos]; + partElement.insertAdjacentHTML("beforeend", `${token["word"]} `); + contextResultsElement.append(partElement); + } + if (expertModeSwitchElement.checked) { + let tokenElements = partElement.getElementsByClassName("token"); + expertModeOn(tokenElements, contextData); } } // ###### Display options changing live how the matches are being displayed ###### // Event function that changes the shown hits per page. -// Just alters the resultList.page property +// Just alters the resultsList.page property function changeHitsPerPage(event) { try { - resultList.page = event.target.value; - resultList.update(); + resultsList.page = event.target.value; + resultsList.update(); nopaque.flash("Updated matches per page.") } catch (e) { - console.log("resultList has no results right now. Live update of items per page is useless for now."); + console.log("resultsList has no results right now. Live update of items per page is useless for now."); } } @@ -190,7 +212,7 @@ function eventHandlerCheck(event) { console.log("pagination used!"); console.log(expertModeSwitchElement.checked); if (expertModeSwitchElement.checked) { - expertModeOn(event.currentTarget.tokenElements, result); + expertModeOn(event.currentTarget.tokenElements, resultsJSON); } else if (!expertModeSwitchElement.checked) { event.preventDefault(); console.log("prevented! Destroy"); @@ -199,19 +221,21 @@ function eventHandlerCheck(event) { } // function to apply extra information and animation to every token -function expertModeOn(tokenElements, result_lookup) { +function expertModeOn(tokenElements, results) { let token; console.log("expertModeOn!"); + console.log(results); + console.log("hier:", tokenElements); for (let tokenElement of tokenElements) { tokenElement.classList.add("chip"); tokenElement.classList.add("hoverable"); tokenElement.classList.add("expert-view"); - token = result_lookup["cpos_lookup"][tokenElement.dataset.cpos]; + token = results["cpos_lookup"][tokenElement.dataset.cpos]; tokenElement.addEventListener("mouseover", function(event) { console.log("Mouseover!"); console.log(event.target); - token = result_lookup["cpos_lookup"][event.target.dataset.cpos]; + token = results["cpos_lookup"][event.target.dataset.cpos]; addToolTipToTokenElement(event.target, token); }); } @@ -235,16 +259,12 @@ function addToolTipToTokenElement(tokenElement, token) { NER: ${token["ner"]} - Title: ${result["text_lookup"][token["text"]]["title"]}
- Author: ${result["text_lookup"][token["text"]]["author"]}
- Publishing year: ${result["text_lookup"][token["text"]]["publishing_year"]} + Title: ${resultsJSON["text_lookup"][token["text"]]["title"]}
+ Author: ${resultsJSON["text_lookup"][token["text"]]["author"]}
+ Publishing year: ${resultsJSON["text_lookup"][token["text"]]["publishing_year"]} - `, - "inDuration": 1500, - "margin": 15, - "position": "top", - "transitionMovement": 0}); + `}); } // function to remove extra informations and animations from tokens diff --git a/app/templates/corpora/pj_analyse_corpus.html.j2 b/app/templates/corpora/pj_analyse_corpus.html.j2 index 748e42b2..d021526c 100644 --- a/app/templates/corpora/pj_analyse_corpus.html.j2 +++ b/app/templates/corpora/pj_analyse_corpus.html.j2 @@ -327,10 +327,44 @@ // get context of one match if inspected via socket.io nopaque.socket.on("pj_match_context", showMatchContext); + + // live update of hits per page if hits per page value is changed + hitsPerPageInputElement = document.getElementById("display-options-form-results_per_page"); + hitsPerPageInputElement.onchange = changeHitsPerPage; + + // live update of lr context per item if context value is changed + contextPerItemElement = document.getElementById("display-options-form-result_context"); + contextPerItemElement.onchange = changeContext; + + // eventListener if pagination is used to apply new context size to new page + // and also activate inspect match if queryFinished is true + paginationElements = document.getElementsByClassName("pagination"); + for (element of paginationElements) { + element.addEventListener("click", changeContext); + element.addEventListener("click", activateInspect); + } + + // epxert mode table view + expertModeSwitchElement = document.getElementById("display-options-form-expert_mode"); + expertModeSwitchElement.addEventListener("change", function(event) { + let currentTokenElements = document.getElementsByClassName("token"); + let paginationElements = document.getElementsByClassName("pagination"); + if (event.target.checked) { + console.log("Checked!"); + expertModeOn(currentTokenElements, resultsJSON); + for (element of paginationElements) { + element.tokenElements = currentTokenElements; + element.addEventListener("click", eventHandlerCheck); + } + } else { + console.log("Unchecked!"); + expertModeOff(currentTokenElements); + console.log("unchecked! Destroy"); + } + }) }); - - // Add onclick to open download modal wen Export Results button is pressed + // Add onclick to open download modal when Export Results button is pressed queryResultsExportElement.onclick = function() { exportModal.open(); }