This commit is contained in:
Stephan Porada 2020-09-14 15:02:01 +02:00
parent 3efe32bcf7
commit 72753d445a
7 changed files with 119 additions and 127 deletions

View File

@ -69,11 +69,14 @@ class Client {
* The detail object can hold any type of data the View needs to know about * The detail object can hold any type of data the View needs to know about
* to represent those to the user. * to represent those to the user.
*/ */
notifyView(caseIdentifier, detailObject={}) { notifyView(caseIdentifier, detailObject={}, notificationType='info',
raiseModalFeedback=true) {
detailObject.caseIdentifier = caseIdentifier; detailObject.caseIdentifier = caseIdentifier;
detailObject.client = this; detailObject.client = this;
detailObject.notificationType = notificationType;
detailObject.raiseModalFeedback = raiseModalFeedback;
const event = new CustomEvent('notify-view', { detail: detailObject }); const event = new CustomEvent('notify-view', { detail: detailObject });
console.info('Client dispatching Notification with detail object in details:', console[notificationType]('Client dispatching Notification with detail object in details:',
detailObject); detailObject);
document.dispatchEvent(event); document.dispatchEvent(event);
} }

View File

@ -31,9 +31,9 @@ function recieveConnected(type, client) {
client.getMetaData(); client.getMetaData();
} else { } else {
let errorText = `Error ${response.code} - ${response.msg}`; let errorText = `Error ${response.code} - ${response.msg}`;
console.group('Connection failed!') console.group('Connection failed!');
console.error(`corpus_analysis_init: ${errorText}`); console.error(`corpus_analysis_init: ${errorText}`);
client.notifyView('connecting-failed', { msg: errorText }); client.notifyView('client-failed', { msg: errorText }, 'error');
console.groupEnd(); console.groupEnd();
} }
}); });
@ -58,11 +58,12 @@ function recieveMetaData(type, client) {
client.eventListeners[type].executeCallbacks([response.payload]); client.eventListeners[type].executeCallbacks([response.payload]);
console.groupEnd(); console.groupEnd();
} else { } else {
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.group('Failed to recieve meta data.'); console.group('Failed to recieve meta data.');
console.error('corpus_analysis_meta_data: Client failed to recieve', console.error('corpus_analysis_meta_data: Client failed to recieve',
'meta data via socket.on'); 'meta data via socket.on');
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.error(`corpus_analysis_meta_data: ${errorText}`); console.error(`corpus_analysis_meta_data: ${errorText}`);
client.notifyView('client-failed', { msg: errorText }, 'error');
console.groupEnd(); console.groupEnd();
} }
}); });
@ -89,13 +90,17 @@ function recieveQueryStatus(type, client) {
client.eventListeners[type].executeCallbacks([response.payload]); client.eventListeners[type].executeCallbacks([response.payload]);
console.groupEnd(); console.groupEnd();
} else { } else {
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.group('corpus_analysis_query: Client failed recieving', console.group('corpus_analysis_query: Client failed recieving',
'query process status via socket.on'); 'query process status via socket.on');
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
if (response.payload.code == 1281) { if (response.payload.code == 1281) {
errorText += ' - Invalid Query'; errorText += ' - Invalid Query';
console.error(`corpus_analysis_query: ${errorText}`);
client.notifyView('client-failed', { msg: errorText }, 'error', false);
} else {
console.error(`corpus_analysis_query: ${errorText}`);
client.notifyView('client-failed', { msg: errorText }, 'error');
} }
console.error(`corpus_analysis_query: ${errorText}`);
console.groupEnd(); console.groupEnd();
} }
}); });
@ -121,10 +126,11 @@ function recieveQueryData(type, client) {
console.info('Added chunk data to results.data.'); console.info('Added chunk data to results.data.');
console.groupEnd(); console.groupEnd();
} else { } else {
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.group('corpus_analysis_query_results: Client failed recieving', console.group('corpus_analysis_query_results: Client failed recieving',
'the results via socket.on'); 'the results via socket.on');
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.error(`corpus_analysis_query: ${errorText}`); console.error(`corpus_analysis_query: ${errorText}`);
client.notifyView('client-failed', { msg: errorText }, 'error');
console.groupEnd(); console.groupEnd();
} }
}); });
@ -150,11 +156,12 @@ function recieveResultsData(type, client) {
response.type]); response.type]);
console.groupEnd(); console.groupEnd();
} else { } else {
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.group('Failed to recieve results data.'); console.group('Failed to recieve results data.');
console.error('corpus_analysis_inspect_match: Client failed to recieve', console.error('corpus_analysis_inspect_match: Client failed to recieve',
'results data via socket.on'); 'results data via socket.on');
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.error(`corpus_analysis_inspect_match: ${errorText}`); console.error(`corpus_analysis_inspect_match: ${errorText}`);
client.notifyView('client-failed', { msg: errorText }, 'error');
console.groupEnd(); console.groupEnd();
} }
}); });
@ -178,7 +185,7 @@ function recieveViewNotification(type, client) {
default: default:
console.error('Recieved unkown notification case identifier from View'); console.error('Recieved unkown notification case identifier from View');
// do something to not crash the analysis session? // do something to not crash the analysis session?
// maybe unnecessary // maybe unnecessary?
} }
}); });
} }

View File

@ -54,6 +54,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. 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?) // notification listeners listening for client notifications (or other in the future?)
this.notificationListeners = {}; this.notificationListeners = {};
this.knownHTMLElements = new Set();
} }
/** /**
@ -84,23 +85,44 @@ class ResultsList extends List {
*/ */
getHTMLElements(arrayOfSelectors) { getHTMLElements(arrayOfSelectors) {
for (let selector of arrayOfSelectors) { for (let selector of arrayOfSelectors) {
let element; // Check if identified Element should be initialized as a modal.
let elements; let modalInit = false;
if (selector.startsWith('#')) { let options;
element = document.querySelector(selector); if (Array.isArray(selector)) {
} else { selector = selector[0];
elements = document.querySelectorAll(selector); modalInit = true;
elements = [...elements]; options = selector[1];
} }
let cleanKey = []; // Check if the current selector has already been used.
selector = selector.replace(/_/g, '-'); if (this.knownHTMLElements.has(selector)) {
selector.match(/\w+/g).forEach((word) => { continue;
let tmp = word[0].toUpperCase() + word.slice(1); } else {
cleanKey.push(tmp); // Get element or elements.
}); let element;
cleanKey[0] = cleanKey[0].toLowerCase(); let elements;
cleanKey = cleanKey.join(''); if (selector.startsWith('#')) {
this[cleanKey] = element ? element: elements; element = document.querySelector(selector);
} else {
elements = document.querySelectorAll(selector);
elements = [...elements];
}
// Create valid javascript instance field name.
let cleanKey = [];
selector = selector.replace(/_/g, '-');
selector.match(/\w+/g).forEach((word) => {
let tmp = word[0].toUpperCase() + word.slice(1);
cleanKey.push(tmp);
});
cleanKey[0] = cleanKey[0].toLowerCase();
cleanKey = cleanKey.join('');
this[cleanKey] = element ? element: elements;
// Initialize current element as modal if true.
if (modalInit) {
this[cleanKey] = M.Modal.init(this[cleanKey], options);
}
}
// Add current selector to knwonHTMLElements.
this.knownHTMLElements.add(selector);
} }
} }
@ -294,59 +316,16 @@ class ResultsList extends List {
} }
// ### functions to inspect imported Matches // ### functions to inspect imported Matches
// This function creates an object that is similar to the object that is
// being recieved as an answere to the getMatchWithContext Method, which is
// triggering an socket.io event.
// It is used as an input for show match context in the context of imported
// results to be able to inspect matches.
createFakeResponse() {
contextModal.open();
// match nr for user to display derived from data_index
let contextMatchNrElement = document.getElementById("context-match-nr");
contextMatchNrElement.textContent = this.contextId + 1;
let cpos_lookup;
let fake_response = {};
let contextResultsElement;
// function to create one match object from entire imported results
// that is passed into the results.jsList.showMatchContext() function
fake_response["payload"] = {};
let dataIndex = event.target.closest("tr").dataset.index;
this.contextId = dataIndex;
fake_response.payload["matches"] = [results.data.matches[dataIndex]];
contextResultsElement = document.getElementById("context-results");
contextResultsElement.innerHTML = "";
let {lc, c, rc} = this.helperCreateCpos(results.data.cpos_ranges,
fake_response.payload.matches[0]);
cpos_lookup = {};
for (let cpos of lc) {
cpos_lookup[cpos] = results.data.cpos_lookup[cpos];
}
for (let cpos of c) {
cpos_lookup[cpos] = results.data.cpos_lookup[cpos];
}
for (let cpos of rc) {
cpos_lookup[cpos] = results.data.cpos_lookup[cpos];
}
fake_response.payload["cpos_lookup"] = cpos_lookup
fake_response.payload["cpos_ranges"] = results.data.cpos_ranges;
fake_response.payload["query"] = results.data.query;
fake_response.payload["context_id"] = dataIndex + 1;
fake_response.payload["match_count"] = fake_response.payload.matches.length
fake_response.payload["corpus_type"] = "inspect-result"
return fake_response
}
// gets result cpos infos for dataIndexes (use list of length 1 for one match) to send back to // gets result cpos infos for dataIndexes (use list of length 1 for one match) to send back to
// the server // the server
inspect(client, results, dataIndex, type) { inspect(client, results, dataIndex, type) {
// initialize context modal // initialize context modal
this.getHTMLElements([ this.getHTMLElements([
'#context-modal', ['#context-modal', true],
'#context-results', '#context-results',
'#create-inspect-menu', '#create-inspect-menu',
'#create-from-inspect', '#create-from-inspect',
]); ]);
this.contextModal = M.Modal.init(this.contextModal);
// get result infos from server and show them in context modal // get result infos from server and show them in context modal
this.contextId = dataIndex[0]; this.contextId = dataIndex[0];
this.contextResults.innerHTML = ""; // clear it from old inspects this.contextResults.innerHTML = ""; // clear it from old inspects
@ -552,9 +531,6 @@ class ResultsList extends List {
toHideArray = []; toHideArray = [];
toShowArray = array; toShowArray = array;
} }
// console.log(array);
// console.log("#######");
// console.log(toHideArray);
for (let s of toHideArray) { for (let s of toHideArray) {
s.classList.add("hide"); s.classList.add("hide");
} }
@ -786,7 +762,7 @@ class ResultsList extends List {
<table class="highlight"> <table class="highlight">
<thead> <thead>
<tr> <tr>
<th>Meta data Description</th> <th>Meta Data Description</th>
<th>Value</th> <th>Value</th>
</tr> </tr>
</thead> </thead>

View File

@ -33,14 +33,20 @@ function connectedCallback(resultsList, detail) {
resultsList.analysisInitModal.close(); resultsList.analysisInitModal.close();
} }
function connectingFaildeCallback(resultsList, detail) { function clientFailedCallback(resultsList, detail) {
resultsList.getHTMLElements([ resultsList.getHTMLElements([
'#analysis-init-progress', '#analysis-init-progress',
'#analysis-init-error' '#analysis-init-error',
'#user-feedback',
]); ]);
resultsList.analysisInitProgress.classList.toggle('hide'); if (detail.raiseModalFeedback) {
resultsList.analysisInitError.classList.toggle('hide'); resultsList.analysisInitModal.open();
resultsList.analysisInitError.textContent = detail.msg; resultsList.analysisInitProgress.classList.toggle('hide');
resultsList.analysisInitError.classList.toggle('hide');
resultsList.analysisInitError.textContent = detail.msg;
} else {
nopaque.flash(detail.msg, 'error')
}
} }
function queryDataPreparingCallback(resultsList, detail) { function queryDataPreparingCallback(resultsList, detail) {
@ -114,10 +120,12 @@ function queryDataRecievingCallback(resultsList, detail) {
} else if (!client.dynamicMode) { } else if (!client.dynamicMode) {
resultsList.add(resultItems, (items) => { resultsList.add(resultItems, (items) => {
for (let item of items) { for (let item of items) {
console.log(item);
item.elm = resultsList.createResultRowElement(item, item.elm = resultsList.createResultRowElement(item,
results.data, results.data,
client, client,
true); true);
console.log(item);
} }
}); });
// update user feedback about query status // update user feedback about query status
@ -183,7 +191,7 @@ function resultsDataRecievedCallback(resultsList, detail) {
export { export {
connectingCallback, connectingCallback,
connectedCallback, connectedCallback,
connectingFaildeCallback, clientFailedCallback,
queryDataPreparingCallback, queryDataPreparingCallback,
queryDataRecievingCallback, queryDataRecievingCallback,
queryDataRecievedCallback, queryDataRecievedCallback,

View File

@ -10,7 +10,7 @@
import { import {
connectingCallback, connectingCallback,
connectedCallback, connectedCallback,
connectingFaildeCallback, clientFailedCallback,
queryDataPreparingCallback, queryDataPreparingCallback,
queryDataRecievingCallback, queryDataRecievingCallback,
queryDataRecievedCallback, queryDataRecievedCallback,
@ -24,6 +24,11 @@ function recieveClientNotification(eventType, resultsList) {
document.addEventListener(eventType, (event) => { document.addEventListener(eventType, (event) => {
let caseIdentifier = event.detail.caseIdentifier; let caseIdentifier = event.detail.caseIdentifier;
switch (caseIdentifier) { switch (caseIdentifier) {
case 'client-failed':
console.error('View recieved notification:', caseIdentifier);
// execute callbacks
clientFailedCallback(resultsList, event.detail);
break;
case 'connecting': case 'connecting':
console.info('View recieved notification:', caseIdentifier); console.info('View recieved notification:', caseIdentifier);
connectingCallback(resultsList, event.detail); connectingCallback(resultsList, event.detail);
@ -33,11 +38,6 @@ function recieveClientNotification(eventType, resultsList) {
console.info('View recieved notification:', caseIdentifier); console.info('View recieved notification:', caseIdentifier);
connectedCallback(resultsList, event.detail); connectedCallback(resultsList, event.detail);
break; break;
case 'connecting-failed':
console.info('View recieved notification:', caseIdentifier);
// execute callbacks
connectingFaildeCallback(resultsList, event.detail);
break;
case 'query-data-prepareing': case 'query-data-prepareing':
console.info('View recieved notification:', caseIdentifier); console.info('View recieved notification:', caseIdentifier);
// execute callbacks // execute callbacks

View File

@ -12,27 +12,27 @@
padding-bottom: 0px;"> padding-bottom: 0px;">
<!-- Query form --> <!-- Query form -->
<div class="row"> <div class="row">
<form class="col s12" id="query-form"> <form class="col s12" id="query-form">
<div class="row"> <div class="row">
<div class="input-field col s12 m10"> <div class="input-field col s12 m10">
<i class="material-icons prefix">search</i> <i class="material-icons prefix">search</i>
{{ query_form.query() }} {{ query_form.query() }}
{{ query_form.query.label }} {{ query_form.query.label }}
<span class="helper-text"> <span class="helper-text">
<a href="http://cwb.sourceforge.net/files/CQP_Tutorial/"> <a href="http://cwb.sourceforge.net/files/CQP_Tutorial/">
<i class="material-icons" style="font-size: inherit;">help <i class="material-icons" style="font-size: inherit;">help
</i> </i>
CQP query language tutorial CQP query language tutorial
</a> </a>
</span> </span>
</div>
<div class="col s12 m2 center-align" style="margin-top: 1.75em;">
{{ M.render_field(query_form.submit, material_icon='send',
style='width:100%;') }}
</div>
</div> </div>
<div class="col s12 m2 center-align" style="margin-top: 1.75em;"> </form>
{{ M.render_field(query_form.submit, material_icon='send', </div>
style='width:100%;') }}
</div>
</div>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -233,8 +233,14 @@ document.addEventListener("DOMContentLoaded", () => {
'#full-results-export', '#full-results-export',
'#inspect-results-export', '#inspect-results-export',
'#meta-data-modal-content', '#meta-data-modal-content',
'#meta-data-modal', ['#meta-data-modal', {
'#query-results-download-modal', 'preventScrolling': false,
'opacity': 0.0,
'dismissible': false,
'onOpenEnd': (() => {document.querySelector(".modal-overlay").remove()})
}
],
['#query-results-download-modal', {}],
'#query-results-table', '#query-results-table',
'#show-meta-data', '#show-meta-data',
'#sub-results-create', '#sub-results-create',
@ -299,14 +305,8 @@ document.addEventListener("DOMContentLoaded", () => {
/** /**
* The following event listener handles the show metadata button and its * The following event listener handles the show metadata button and its
* functionality. Before the needed modal is initialized. * functionality.
*/ */
resultsList.metaDataModal= M.Modal.init(resultsList.metaDataModal, {
'preventScrolling': false,
'opacity': 0.0,
'dismissible': false,
'onOpenEnd': (() => {document.querySelector(".modal-overlay").remove()})
});
resultsList.showMetaData.onclick = () => { resultsList.showMetaData.onclick = () => {
resultsList.metaDataModalContent.textContent = ''; resultsList.metaDataModalContent.textContent = '';
let table = resultsList.createMetaDataForModal(results.metaData); let table = resultsList.createMetaDataForModal(results.metaData);
@ -353,8 +353,6 @@ document.addEventListener("DOMContentLoaded", () => {
resultsList.notifyClient('get-results', { resultsType: 'sub-results', resultsList.notifyClient('get-results', { resultsType: 'sub-results',
dataIndexes: dataIndexes}); dataIndexes: dataIndexes});
} }
// 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 // 3. Open download modal when full results export button is pressed
resultsList.fullResultsExport.onclick = (event) => { resultsList.fullResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open(); resultsList.queryResultsDownloadModal.open();

View File

@ -163,7 +163,13 @@ document.addEventListener("DOMContentLoaded", () => {
'#full-results-create', '#full-results-create',
'#inspect-results-export', '#inspect-results-export',
'#meta-data-modal-content', '#meta-data-modal-content',
'#meta-data-modal', ['#meta-data-modal', {
'preventScrolling': false,
'opacity': 0.0,
'dismissible': false,
'onOpenEnd': (() => {document.querySelector(".modal-overlay").remove()})
}
],
'#query-results-table', '#query-results-table',
'#show-meta-data', '#show-meta-data',
'#sub-results-create', '#sub-results-create',
@ -171,10 +177,10 @@ document.addEventListener("DOMContentLoaded", () => {
// Hide buttons which are not needed when just inspecting results // Hide buttons which are not needed when just inspecting results
resultsList.inspectResultsExport.classList.add('hide'); resultsList.inspectResultsExport.classList.add('hide');
// Execute client event listener callbacks manually because dynamicMode is false // Execute client event listener callbacks manually because dynamicMode is false
client.eventListeners['corpus_analysis_query'].executeCallbacks([resultsJson]) client.eventListeners['corpus_analysis_query'].executeCallbacks([resultsJson]);
// Save meta data to results after the init callback from line above // Save meta data to results after the init callback from line above
results.metaData = metaDataJson; results.metaData = metaDataJson;
client.eventListeners['corpus_analysis_query_results'].executeCallbacks([resultsJson]) client.eventListeners['corpus_analysis_query_results'].executeCallbacks([resultsJson]);
/** /**
* The following listener handles what functions are called when the user * The following listener handles what functions are called when the user
* does use the page navigation to navigate to a new page. * does use the page navigation to navigate to a new page.
@ -233,14 +239,8 @@ document.addEventListener("DOMContentLoaded", () => {
/** /**
* The following event listener handles the show metadata button and its * The following event listener handles the show metadata button and its
* functionality. Before the needed modal is initialized. * functionality.
*/ */
resultsList.metaDataModal= M.Modal.init(resultsList.metaDataModal, {
'preventScrolling': false,
'opacity': 0.0,
'dismissible': false,
'onOpenEnd': (() => {document.querySelector(".modal-overlay").remove()})
});
resultsList.showMetaData.onclick = () => { resultsList.showMetaData.onclick = () => {
resultsList.metaDataModalContent.textContent = ''; resultsList.metaDataModalContent.textContent = '';
let table = resultsList.createMetaDataForModal(results.metaData); let table = resultsList.createMetaDataForModal(results.metaData);