New context options

This commit is contained in:
Stephan Porada 2020-04-15 14:55:29 +02:00
parent 34e8d952b6
commit 9031ca5845
4 changed files with 133 additions and 80 deletions

View File

@ -93,7 +93,7 @@ def corpus_analysis_inspect_match(payload):
try: try:
corpus = client.corpora.get('CORPUS') corpus = client.corpora.get('CORPUS')
s = corpus.structural_attributes.get('s') s = corpus.structural_attributes.get('s')
payload = s.export(payload['first_cpos'], payload['last_cpos'], context=3) payload = s.export(payload['first_cpos'], payload['last_cpos'], context=10)
payload['cpos_ranges'] = True payload['cpos_ranges'] = True
except cqi.errors.CQiException as e: except cqi.errors.CQiException as e:
payload = {'code': e.code, 'desc': e.description, 'msg': e.name} payload = {'code': e.code, 'desc': e.description, 'msg': e.name}

View File

@ -1,7 +1,7 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import (BooleanField, FileField, StringField, SubmitField, from wtforms import (BooleanField, FileField, StringField, SubmitField,
ValidationError, IntegerField, SelectField) ValidationError, IntegerField, SelectField)
from wtforms.validators import DataRequired, Length from wtforms.validators import DataRequired, Length, NumberRange
class AddCorpusFileForm(FlaskForm): class AddCorpusFileForm(FlaskForm):
@ -88,19 +88,9 @@ class DisplayOptionsForm(FlaskForm):
class InspectDisplayOptionsForm(FlaskForm): class InspectDisplayOptionsForm(FlaskForm):
expert_mode_inspect = BooleanField('Expert mode') expert_mode_inspect = BooleanField('Expert mode')
highlight_sentences = BooleanField('Highlight sentences') highlight_sentences = BooleanField('Highlight sentences')
context_sentences = SelectField('Context sentences', context_sentences = IntegerField('Context sentences',
choices=[('', 'Choose your option'), validators=[NumberRange(min=0, max=10)],
('1', '1'), default=3)
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5'),
('6', '6'),
('7', '7'),
('8', '8'),
('9', '9'),
('10', '10')],
default=3)
class QueryDownloadForm(FlaskForm): class QueryDownloadForm(FlaskForm):

View File

@ -177,62 +177,111 @@ class ResultsList extends List {
); );
} }
HTMLTStroElement(htmlStr) {
// https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
let template = document.createElement("template");
htmlStr = htmlStr.trim();
template.innerHTML = htmlStr;
return template.content.firstChild;
}
showMatchContext(response) { showMatchContext(response) {
this.contextData;
let c; let c;
let contextData;
let contextModalLoading; let contextModalLoading;
let contextModalReady; let contextModalReady;
let contextResultsElement; let contextResultsElement;
let expertModeSwitchElement; let expertModeSwitchElement;
let lc; let lc;
let modalTokenElements;
let partElement; let partElement;
let rc; let rc;
let token; let token;
let tokenElement; let tokenHTMLArray;
let tokenElements; let uniqueS;
contextData = response.payload; let htmlTokenStr;
let tokenHTMlElement;
this.contextData = response.payload;
contextResultsElement = document.getElementById("context-results"); contextResultsElement = document.getElementById("context-results");
expertModeSwitchElement = document.getElementById("display-options-form-expert_mode"); expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
uniqueS = new Set();
// check if cpos ranges are used or not // check if cpos ranges are used or not
if (contextData.cpos_ranges == true) { if (this.contextData.cpos_ranges == true) {
// python range like function from MDN // python range like function from MDN
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Sequence_generator_(range) // 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)); 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) lc = range(this.contextData.match.lc[0], this.contextData.match.lc[1], 1)
c = range(contextData.match.c[0], contextData.match.c[1], 1) c = range(this.contextData.match.c[0], this.contextData.match.c[1], 1)
rc = range(contextData.match.rc[0], contextData.match.rc[1], 1) rc = range(this.contextData.match.rc[0], this.contextData.match.rc[1], 1)
} else { } else {
lc = contextData.match.lc; lc = this.contextData.match.lc;
c = contextData.match.c; c = this.contextData.match.c;
rc = contextData.match.rc; rc = this.contextData.match.rc;
} }
// create sentence strings as tokens // create sentence strings as tokens
partElement = document.createElement("p"); tokenHTMLArray = [];
for (let cpos of lc) { for (let cpos of lc) {
token = contextData.cpos_lookup[cpos]; token = this.contextData.cpos_lookup[cpos];
partElement.insertAdjacentHTML("beforeend", uniqueS.add(token.s)
`<span class="token" data-cpos="${cpos}">${token.word} </span>`); htmlTokenStr = `<span class="token"` +
contextResultsElement.append(partElement); `data-sid="${token.s}"` +
`data-cpos="${cpos}">` +
`${token.word}` +
`</span>`;
tokenHTMlElement = this.HTMLTStroElement(htmlTokenStr)
tokenHTMLArray.push(tokenHTMlElement);
} }
for (let cpos of c) { for (let cpos of c) {
token = contextData.cpos_lookup[cpos]; token = this.contextData.cpos_lookup[cpos];
partElement.insertAdjacentHTML("beforeend", uniqueS.add(token.s)
`<span class="token bold light-green" data-cpos="${cpos}"` + htmlTokenStr = `<span class="token bold light-green"` +
`style="text-decoration-line: underline;">${token.word} </span>`); `data-sid="${token.s}"` +
contextResultsElement.append(partElement); `data-cpos="${cpos}"` +
`style="text-decoration-line: underline;">` +
`${token.word}` +
`</span>`;
tokenHTMlElement = this.HTMLTStroElement(htmlTokenStr)
tokenHTMLArray.push(tokenHTMlElement);
} }
for (let cpos of rc) { for (let cpos of rc) {
token = contextData.cpos_lookup[cpos]; token = this.contextData.cpos_lookup[cpos];
partElement.insertAdjacentHTML("beforeend", uniqueS.add(token.s)
`<span class="token" data-cpos="${cpos}">${token.word} </span>`); htmlTokenStr = `<span class="token"` +
contextResultsElement.append(partElement); `data-sid="${token.s}"` +
`data-cpos="${cpos}">` +
`${token.word}` +
`</span>`;
tokenHTMlElement = this.HTMLTStroElement(htmlTokenStr)
tokenHTMLArray.push(tokenHTMlElement);
} }
console.log(tokenHTMLArray);
console.log(uniqueS);
partElement = document.createElement("p");
for (let sId of uniqueS) {
let htmlSentence = `<div class="sentence s12" data-sid="${sId}">`;
let sentenceElement = this.HTMLTStroElement(htmlSentence);
for (let tokenElement of tokenHTMLArray) {
if (tokenElement.dataset.sid == sId) {
sentenceElement.appendChild(tokenElement);
sentenceElement.insertAdjacentHTML("beforeend", `<span>&nbsp;</span>`);
} else {
continue;
}
}
partElement.appendChild(sentenceElement);
}
contextResultsElement.appendChild(partElement);
if (expertModeSwitchElement.checked) { if (expertModeSwitchElement.checked) {
tokenElements = partElement.getElementsByClassName("token");
this.expertModeOn(); this.expertModeOn();
} }
} }
changeSentenceContext(sValue) {
}
// ###### Display options changing live how the matches are being displayed ###### // ###### Display options changing live how the matches are being displayed ######
// Event function that changes the shown hits per page. // Event function that changes the shown hits per page.
@ -309,6 +358,9 @@ class ResultsList extends List {
// console.log("Create Tooltip on mouseover."); // console.log("Create Tooltip on mouseover.");
let token; let token;
token = results.resultsJSON.cpos_lookup[event.target.dataset.cpos]; token = results.resultsJSON.cpos_lookup[event.target.dataset.cpos];
if (!token) {
token = this.contextData.cpos_lookup[event.target.dataset.cpos];
}
this.addToolTipToTokenElement(event.target, token); this.addToolTipToTokenElement(event.target, token);
} }
@ -321,7 +373,6 @@ class ResultsList extends List {
expertModeOn() { expertModeOn() {
// console.log("Expert mode is on."); // console.log("Expert mode is on.");
let token;
this.currentExpertTokenElements = document.getElementsByClassName("token"); this.currentExpertTokenElements = document.getElementsByClassName("token");
this.tooltipEventCreateBind = this.tooltipEventCreate.bind(this); this.tooltipEventCreateBind = this.tooltipEventCreate.bind(this);
this.tooltipEventDestroyBind = this.tooltipEventDestroy.bind(this); this.tooltipEventDestroyBind = this.tooltipEventDestroy.bind(this);

View File

@ -201,38 +201,46 @@
<h4>Match context</h4> <h4>Match context</h4>
<div class="divider"></div> <div class="divider"></div>
<div class="section" id="inspect-display-options"> <div class="section" id="inspect-display-options">
<h5>Display options</h5> <form>
<div class="row"> <h5>Display options</h5>
<div class="col s9"> <div class="row">
<p>Expert Mode</p> <div class="col s9">
</div> <p>{{ inspect_display_options_form.expert_mode_inspect.label.text }}</p>
<div class="col s3 right-align"> </div>
<div class="switch"> <div class="col s3 right-align">
<label> <div class="switch">
{{ inspect_display_options_form.expert_mode_inspect() }} <label>
<span class="lever"></span> {{ inspect_display_options_form.expert_mode_inspect() }}
</label> <span class="lever"></span>
</label>
</div>
</div>
<div class="col s9">
<p>{{ inspect_display_options_form.highlight_sentences.label.text }}</p>
</div>
<div class="col s3 right-align">
<div class="switch">
<label>
{{ inspect_display_options_form.highlight_sentences() }}
<span class="lever"></span>
</label>
</div>
</div>
<div class="col s6">
<p>Nr. of sentences around the match</p>
</div>
<div class="col s6 right-align">
<div class="input-field">
<p class="range-field">
<input type="range" id="context-sentences"
min="1"
max="10"
value="3" />
</p>
</div>
</div> </div>
</div> </div>
<div class="col s9"> </form>
<p>Highlight sentences</p>
</div>
<div class="col s3 right-align">
<div class="switch">
<label>
{{ inspect_display_options_form.highlight_sentences() }}
<span class="lever"></span>
</label>
</div>
</div>
<div class="col s12 m6">
<div class="input-field">
<i class="material-icons prefix">format_list_numbered</i>
{{ inspect_display_options_form.context_sentences() }}
{{ inspect_display_options_form.context_sentences.label }}
</div>
</div>
</div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<div class="section" id="context-results"> <div class="section" id="context-results">
@ -257,16 +265,20 @@
var collapsibleElements; // All collapsibleElements on this page var collapsibleElements; // All collapsibleElements on this page
var collapsibleElements; // all collapsibles on site var collapsibleElements; // all collapsibles on site
var contextModal; // Modal to open on inspect for further match context var contextModal; // Modal to open on inspect for further match context
var contextPerItemElement;
var contextSentencesElement;
var displayOptionsData; // Getting form data from display options var displayOptionsData; // Getting form data from display options
var displayOptionsFormElement; // Form holding the display informations var displayOptionsFormElement; // Form holding the display informations
var downloadResultsJSONElement; // button for downloading results as JSON var downloadResultsJSONElement; // button for downloading results as JSON
var expertModeSwitchElement; // Expert mode switch Element var expertModeSwitchElement; // Expert mode switch Element
var exportModal; // Download options modal var exportModal; // Download options modal
var firstPageElement; // first page element of resultsList pagination var firstPageElement; // first page element of resultsList pagination
var hitsPerPageInputElement;
var initDisplay; // CorpusAnalysisDisplay object first undfined on DOMContentLoaded defined var initDisplay; // CorpusAnalysisDisplay object first undfined on DOMContentLoaded defined
var initDisplayElement; // Element for initialization using initDisplay var initDisplayElement; // Element for initialization using initDisplay
var initModal; var initModal;
var matchCountElement; // Total nr. of matches will be displayed in this element var matchCountElement; // Total nr. of matches will be displayed in this element
var paginationElements;
var progress; // global progress value var progress; // global progress value
var queryDisplay; // CorpusAnalysisDisplay object first undfined on DOMContentLoaded defined var queryDisplay; // CorpusAnalysisDisplay object first undfined on DOMContentLoaded defined
var queryDisplayElement; // Element for initialization using queryDisplay var queryDisplayElement; // Element for initialization using queryDisplay
@ -282,20 +294,19 @@
var resultsListOptions; // specifies ResultsList options var resultsListOptions; // specifies ResultsList options
var textLookupCountElement // Nr of texts the matches occured in will be shown in this element var textLookupCountElement // Nr of texts the matches occured in will be shown in this element
var xpath; // xpath to grab first resultsList page pagination element var xpath; // xpath to grab first resultsList page pagination element
var hitsPerPageInputElement;
var paginationElements;
var contextPerItemElement;
// ###### Initialize variables ###### // ###### Initialize variables ######
client = undefined; client = undefined;
collapsibleElements = document.querySelector('.collapsible.expandable'); collapsibleElements = document.querySelector('.collapsible.expandable');
contextModal = document.getElementById("context-modal"); contextModal = document.getElementById("context-modal");
contextSentencesElement = document.getElementById("context-sentences");
displayOptionsFormElement = document.getElementById("display-options-form"); displayOptionsFormElement = document.getElementById("display-options-form");
expertModeSwitchElement = document.getElementById("display-options-form-expert_mode"); expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
exportModal = document.getElementById("query-results-download-modal"); exportModal = document.getElementById("query-results-download-modal");
initDisplay = undefined; initDisplay = undefined;
initDisplayElement = document.getElementById("init-display"); initDisplayElement = document.getElementById("init-display");
matchCountElement = document.getElementById("match-count"); matchCountElement = document.getElementById("match-count");
paginationElements = document.getElementsByClassName("pagination");
queryDisplay = undefined; queryDisplay = undefined;
queryDisplayElement = document.getElementById("query-display"); queryDisplayElement = document.getElementById("query-display");
queryFormElement = document.getElementById("query-form"); queryFormElement = document.getElementById("query-form");
@ -305,7 +316,6 @@
queryResultsUserFeedbackElement = document.getElementById("query-results-user-feedback"); queryResultsUserFeedbackElement = document.getElementById("query-results-user-feedback");
receivedMatchCountElement = document.getElementById("received-match-count"); receivedMatchCountElement = document.getElementById("received-match-count");
textLookupCountElement = document.getElementById("text-lookup-count"); textLookupCountElement = document.getElementById("text-lookup-count");
paginationElements = document.getElementsByClassName("pagination");
// ###### js list options and intialization ###### // ###### js list options and intialization ######
displayOptionsData = ResultsList.getDisplayOptions(displayOptionsFormElement); displayOptionsData = ResultsList.getDisplayOptions(displayOptionsFormElement);
@ -388,6 +398,12 @@
contextPerItemElement = document.getElementById("display-options-form-result_context"); contextPerItemElement = document.getElementById("display-options-form-result_context");
contextPerItemElement.onchange = results.resultsList.changeContext; contextPerItemElement.onchange = results.resultsList.changeContext;
// live update of context sentences in inspect modal
contextSentencesElement.onchange = (event) => {
let sValue = event.target.value;
console.log(sValue);
}
// eventListener if pagination is used to apply new context size to new page // eventListener if pagination is used to apply new context size to new page
// and also activate inspect match if progress is 100 // and also activate inspect match if progress is 100
for (let element of paginationElements) { for (let element of paginationElements) {
@ -395,10 +411,6 @@
element.addEventListener("click", results.resultsList.activateInspect); element.addEventListener("click", results.resultsList.activateInspect);
} }
// epxert mode table view
// TODO: Redo this
// - This replicates itself on expertModeSwitchElement use
// - Replication should be fixed
expertModeSwitchElement.addEventListener("change", (event) => { expertModeSwitchElement.addEventListener("change", (event) => {
if (event.target.checked) { if (event.target.checked) {
results.resultsList.expertModeOn(); results.resultsList.expertModeOn();