mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2025-01-31 03:49:03 +00:00
Add logic for data export etc.
This commit is contained in:
parent
763183435d
commit
64f8f82fe8
@ -16,7 +16,7 @@ class Client {
|
||||
this.logging = logging;
|
||||
this.requestQueryProgress = 0;
|
||||
this.socket = socket;
|
||||
this.socketEventListeners = {};
|
||||
this.eventListeners = {};
|
||||
this.connected = false;
|
||||
|
||||
|
||||
@ -44,9 +44,9 @@ class Client {
|
||||
}
|
||||
|
||||
// Registers one or more SocketEventListeners to the Client.
|
||||
setSocketEventListeners(socketEventListeners) {
|
||||
for (let socketEventListener of socketEventListeners) {
|
||||
this.socketEventListeners[socketEventListener.type] = socketEventListener;
|
||||
setSocketEventListeners(eventListeners) {
|
||||
for (let eventListener of eventListeners) {
|
||||
this.eventListeners[eventListener.type] = eventListener;
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ class Client {
|
||||
* type strings because they double as the socket event event names.
|
||||
*/
|
||||
loadSocketEventListeners() {
|
||||
for (let [type, listener] of Object.entries(this.socketEventListeners)) {
|
||||
for (let [type, listener] of Object.entries(this.eventListeners)) {
|
||||
listener.listenerFunction(type, this);
|
||||
}
|
||||
}
|
||||
@ -66,8 +66,8 @@ class Client {
|
||||
*/
|
||||
notifyView(caseIdentifier, detailObject={}) {
|
||||
detailObject.caseIdentifier = caseIdentifier;
|
||||
const event = new CustomEvent('notify', { detail: detailObject });
|
||||
console.info('Dispatching Notification:', caseIdentifier);
|
||||
const event = new CustomEvent('notify-view', { detail: detailObject });
|
||||
console.info('Client dispatching Notification:', caseIdentifier);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
@ -105,16 +105,38 @@ class Client {
|
||||
'socket.emit for the query', queryStr);
|
||||
this.socket.emit('corpus_analysis_query', queryStr);
|
||||
}
|
||||
|
||||
// create results data either from all results or from all marked sub results
|
||||
getResultsData(resultsType, dataIndexes, results) {
|
||||
// TODO: where to put all the stuff that deactivates all the buttons because cqp server cannot handle mutliple requests?
|
||||
// Triggers emit to get full match context from server for a number of
|
||||
// matches identified by their data_index.
|
||||
let tmp_first_cpos = [];
|
||||
let tmp_last_cpos = [];
|
||||
for (let dataIndex of dataIndexes) {
|
||||
tmp_first_cpos.push(results.data.matches[dataIndex].c[0]);
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to create an SocketEventListener.
|
||||
* Input are an identifying type string, the listener function and callbacks
|
||||
* which will be executed as part of the listener function. The identifying
|
||||
* type string is also used as the socket event event identifier.
|
||||
*/
|
||||
class SocketEventListener {
|
||||
constructor(type, listenerFunction, args=null) {
|
||||
class ClientEventListener {
|
||||
constructor(type, listenerFunction) {
|
||||
this.listenerCallbacks = {};
|
||||
this.listenerFunction = listenerFunction;
|
||||
this.type = type;
|
||||
@ -127,8 +149,8 @@ class SocketEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
/** Shorthand to execute all registered callbacks with same args in insertion
|
||||
* order.
|
||||
/** Shorthand to execute all registered callbacks with same defaultArgs
|
||||
* in insertion order.
|
||||
* NOTE:
|
||||
* Since ECMAScript 2015, objects do preserve creation order for
|
||||
* string and Symbol keys. In JavaScript engines that comply with the
|
||||
@ -136,11 +158,18 @@ class SocketEventListener {
|
||||
* yield the keys in order of insertion.
|
||||
* So all modern Browsers.
|
||||
*/
|
||||
executeCallbacks(payload) {
|
||||
executeCallbacks(defaultArgs) {
|
||||
for (let [type, listenerCallback] of Object.entries(this.listenerCallbacks)) {
|
||||
listenerCallback.callbackFunction(payload, ...listenerCallback.args);
|
||||
listenerCallback.callbackFunction(...defaultArgs,
|
||||
...listenerCallback.args);
|
||||
}
|
||||
}
|
||||
// use this if you only want to execute a specific registered callback
|
||||
executeCallback(defaultArgs, type) {
|
||||
let listenerCallback = this.listenerCallbacks[type];
|
||||
listenerCallback.callbackFunction(...defaultArgs,
|
||||
...listenerCallback.args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,6 +188,6 @@ class ListenerCallback {
|
||||
// export Classes from this module
|
||||
export {
|
||||
Client,
|
||||
SocketEventListener,
|
||||
ClientEventListener,
|
||||
ListenerCallback,
|
||||
};
|
@ -46,116 +46,24 @@ function saveQueryData(args) {
|
||||
}
|
||||
}
|
||||
|
||||
function querySetup(payload, client) {
|
||||
// deletes old data from query issued before this new query
|
||||
client.results.clearAll();
|
||||
// load necessary HTMLElements with selectory syntax and save them as fields
|
||||
client.getHTMLElements(['#query-progress-bar', '#query-results-user-feedback',
|
||||
'#recieved-match-count', '#total-match-count',
|
||||
'#text-lookup-count', '#text-lookup-titles',
|
||||
'#query-results-create', '#add-to-sub-results']);
|
||||
client.recievedMatchCount.textContent = 0;
|
||||
client.totalMatchCount.textContent = `${payload.match_count}`;
|
||||
client.queryResultsUserFeedback.classList.toggle('hide');
|
||||
client.queryProgressBar.classList.toggle('hide');
|
||||
client.queryProgressBar.lastElementChild.style.width = '0%';
|
||||
if (client.dynamicMode) {
|
||||
client.addToSubResults.toggleAttribute('disabled');
|
||||
client.queryResultsCreate.classList.toggle('disabled');
|
||||
}
|
||||
function getResultsData(args) {
|
||||
let [resultsType, dataIndexes, client, results, rest] = arguments;
|
||||
client.notifyView('results-data-recieving');
|
||||
client.getResultsData(resultsType, dataIndexes, results);
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback should be registered to the SocketEventListener 'recieveQueryData'
|
||||
* It takes the incoming chunk and renders the results using the
|
||||
* results.jsList object. It can either handle live incoming data chunks or
|
||||
* already loaded/imported results data.
|
||||
*/
|
||||
function queryRenderResults(payload, client) {
|
||||
client.getHTMLElements(['#recieved-match-count', '#match-count',
|
||||
'#display-options-form-expert_mode']);
|
||||
const renderResults = (data) => {
|
||||
/**
|
||||
* resultItem saves the incoming chunk matches as objects to add those later
|
||||
* to the client.results.jsList
|
||||
*/
|
||||
let resultItems = [];
|
||||
// get infos for full match row
|
||||
for (let [index, match] of data.matches.entries()) {
|
||||
resultItems.push({...match, ...{'index': index + client.results.data.matches.length}});
|
||||
}
|
||||
client.results.jsList.add(resultItems, (items) => {
|
||||
for (let item of items) {
|
||||
item.elm = client.results.jsList.createResultRowElement(item, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (client.dynamicMode) {
|
||||
if (payload.chunk.cpos_ranges == true) {
|
||||
client.results.data['cpos_ranges'] = true;
|
||||
} else {
|
||||
client.results.data['cpos_ranges'] = false;
|
||||
}
|
||||
renderResults(payload.chunk);
|
||||
helperQueryRenderResults(payload, client);
|
||||
console.info('Result progress is:', client.requestQueryProgress);
|
||||
if (client.requestQueryProgress === 100) {
|
||||
/**
|
||||
* activate, hide or show elements if all reults have been recieved
|
||||
* also load some new elements taht have not ben loaded before
|
||||
*/
|
||||
client.queryProgressBar.classList.toggle('hide');
|
||||
client.queryResultsUserFeedback.classList.toggle('hide');
|
||||
client.queryResultsCreate.classList.toggle('disabled');
|
||||
client.addToSubResults.toggleAttribute('disabled');
|
||||
// addToSubResultsElement.removeAttribute("disabled");
|
||||
// // inital expert mode check and sub results activation
|
||||
// client.results.jsList.activateInspect();
|
||||
// if (addToSubResultsElement.checked) {
|
||||
// client.results.jsList.activateAddToSubResults();
|
||||
// }
|
||||
// if (expertModeSwitchElement.checked) {
|
||||
// client.results.jsList.expertModeOn("query-display");
|
||||
// }
|
||||
}
|
||||
} else if (!client.dynamicMode) {
|
||||
renderResults(payload);
|
||||
helperQueryRenderResults({'chunk': payload}, client);
|
||||
client.queryProgressBar.classList.toggle('hide');
|
||||
client.queryResultsUserFeedback.classList.toggle('hide');
|
||||
client.results.jsList.activateInspect();
|
||||
if (client.displayOptionsFormExpertMode.checked) {
|
||||
client.results.jsList.expertModeOn("query-display");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that saves result data into the client.results.data object.
|
||||
* Also does some showing and hiding of Elements and user feedback text.
|
||||
*/
|
||||
function helperQueryRenderResults (payload, client) {
|
||||
// updating table on finished item creation callback via createResultRowElement
|
||||
client.results.jsList.update();
|
||||
client.results.jsList.changeContext(); // sets lr context on first result load
|
||||
// incorporating new chunk results into full results
|
||||
client.results.data.matches.push(...payload.chunk.matches);
|
||||
client.results.data.addData(payload.chunk.cpos_lookup, 'cpos_lookup');
|
||||
client.results.data.addData(payload.chunk.text_lookup, 'text_lookup');
|
||||
// complete metaData
|
||||
// client.results.metaData.add();
|
||||
// show user current and total match count
|
||||
client.recievedMatchCount.textContent = `${client.results.data.matches.length}`;
|
||||
client.textLookupCount.textContent = `${Object.keys(client.results.data.text_lookup).length}`;
|
||||
let titles = new Array();
|
||||
for (let [key, value] of Object.entries(client.results.data.text_lookup)) {
|
||||
titles.push(`${value.title} (${value.publishing_year})`);
|
||||
};
|
||||
client.textLookupTitles.textContent = `${titles.join(", ")}`;
|
||||
// update progress bar and requestQueryProgress
|
||||
client.queryProgressBar.lastElementChild.style.width = `${payload.progress}%`;
|
||||
client.requestQueryProgress = payload.progress;
|
||||
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');
|
||||
}
|
||||
|
||||
// export callbacks
|
||||
export { prepareQueryData, saveMetaData, saveQueryData };
|
||||
export {
|
||||
prepareQueryData,
|
||||
saveMetaData,
|
||||
saveQueryData,
|
||||
getResultsData,
|
||||
saveResultsData,
|
||||
};
|
@ -1,9 +1,14 @@
|
||||
/**
|
||||
* This file contains the listener functions which can be assigned to the
|
||||
* coprus_analysis client. So that the incoming data/status informations will
|
||||
* be handled.
|
||||
* be handled. There are several listeners listening for socket .io events.
|
||||
* Further below one javascript custom event listener is specified. This
|
||||
* listener listens for javascript custom events which are being dispatched by
|
||||
* the View (resultsList).
|
||||
*/
|
||||
|
||||
// Listeners for socket io events
|
||||
|
||||
/**
|
||||
* Recieves a corpus analysis connected signal via socket.io.
|
||||
*/
|
||||
@ -50,7 +55,7 @@ function recieveMetaData(type, client) {
|
||||
console.info(`corpus_analysis_meta_data: ${response.code} - ${response.msg}`);
|
||||
console.info(response);
|
||||
// executing the registered callbacks
|
||||
client.socketEventListeners[type].executeCallbacks(response.payload);
|
||||
client.eventListeners[type].executeCallbacks([response.payload]);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.group('Failed to recieve meta data.');
|
||||
@ -81,7 +86,7 @@ function recieveQueryStatus(type, client) {
|
||||
console.info(`corpus_analysis_query: ${response.code} - ${response.msg}`);
|
||||
console.info(response);
|
||||
// executing the registered callbacks
|
||||
client.socketEventListeners[type].executeCallbacks(response.payload);
|
||||
client.eventListeners[type].executeCallbacks([response.payload]);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.group('corpus_analysis_query: Client failed recieving',
|
||||
@ -113,7 +118,7 @@ function recieveQueryData(type, client) {
|
||||
/**
|
||||
* Execute registered callbacks and notify View.
|
||||
*/
|
||||
client.socketEventListeners[type].executeCallbacks(response.payload);
|
||||
client.eventListeners[type].executeCallbacks([response.payload]);
|
||||
console.info('Added chunk data to results.data.');
|
||||
console.groupEnd();
|
||||
} else {
|
||||
@ -125,18 +130,72 @@ function recieveQueryData(type, client) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.group('corpus_analysis_query_results: Loading query data.')
|
||||
console.group('corpus_analysis_query_results: Loading query data.');
|
||||
console.info('Client loading imported query data from database.');
|
||||
// executing the registered callbacks
|
||||
client.socketEventListeners[type].executeCallbacks();
|
||||
client.eventListeners[type].executeCallbacks();
|
||||
console.groupEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieves the data requested by the create Results or sub results button
|
||||
*/
|
||||
function recieveResultsData(type, client) {
|
||||
client.socket.on(type, (response) => {
|
||||
/**
|
||||
* Check if request for session was OK.
|
||||
* If OK execute registered callbacks and notify View.
|
||||
*/
|
||||
if (response.code === 200) {
|
||||
console.group('Client recieving results data')
|
||||
console.info('corpus_analysis_inspect_match: Client recieving results data',
|
||||
'via socket.on');
|
||||
console.info(`corpus_analysis_inspect_match: ${response.code} - ${response.msg}`);
|
||||
console.info(response);
|
||||
// executing the registered callbacks
|
||||
client.eventListeners[type].executeCallbacks([response.payload]);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.group('Failed to recieve results data.');
|
||||
console.error('corpus_analysis_inspect_match: Client failed to recieve',
|
||||
'results data via socket.on');
|
||||
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
|
||||
console.error(`corpus_analysis_inspect_match: ${errorText}`);
|
||||
console.groupEnd();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the javascript custom event listener, listening for events
|
||||
* dispatched by the View.
|
||||
*/
|
||||
function recieveViewNotification(type, client) {
|
||||
document.addEventListener(type, (event) => {
|
||||
let caseIdentifier = event.detail.caseIdentifier;
|
||||
switch(caseIdentifier) {
|
||||
case 'get-results':
|
||||
console.info('Client getting full results for export.');
|
||||
// execute callback or functions
|
||||
client.eventListeners[type].executeCallback([event.detail.resultsType,
|
||||
event.detail.dataIndexes],
|
||||
caseIdentifier);
|
||||
break
|
||||
default:
|
||||
console.error('Recieved unkown notification case identifier from View');
|
||||
// do something to not crash the analysis session?
|
||||
// maybe unnecessary
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// export listeners from this module
|
||||
export {
|
||||
recieveConnected,
|
||||
recieveMetaData,
|
||||
recieveQueryStatus,
|
||||
recieveQueryData
|
||||
recieveQueryData,
|
||||
recieveViewNotification,
|
||||
recieveResultsData,
|
||||
};
|
@ -8,6 +8,7 @@ class Results {
|
||||
constructor() {
|
||||
this.data = new Data();
|
||||
this.metaData = new MetaData();
|
||||
this.fullResultsData = new Data();
|
||||
this.subResultsData = new Data();
|
||||
console.info('Initialized the Results object.');
|
||||
}
|
||||
@ -15,12 +16,12 @@ class Results {
|
||||
init() {
|
||||
this.data.init();
|
||||
this.metaData.init();
|
||||
this.fullResultsData = new Data();
|
||||
this.subResultsData.init();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Data {
|
||||
// Sets empty object structure. Also usefull to delete old results.
|
||||
// matchCount default is 0
|
||||
@ -94,29 +95,6 @@ class Data {
|
||||
this.download(downloadElement, dataStr, resultFilename, "text/json", ".json")
|
||||
}
|
||||
|
||||
// create results data either from all results or from al lmarked sub results
|
||||
createResultsData(type) {
|
||||
// deactivate inspect, because cqp server cannot handle multiple requests
|
||||
results.jsList.deactivateInspect();
|
||||
activateInspectInteraction.setCallback("noCheck",
|
||||
results.jsList.deactivateInspect,
|
||||
results.jsList);
|
||||
// set flag that results are being created to avoid reactivation of
|
||||
// sub results creation if marked matches are changed
|
||||
resultCreationRunning = true;
|
||||
console.log(resultCreationRunning);
|
||||
if (type === "sub-results") {
|
||||
resultsCreateElement.classList.add("disabled"); // cqp server cannot handle more than one request at a time. Thus we deactivate the resultsCreateElement
|
||||
let tmp = [...results.jsList.addToSubResultsIdsToShow].sort(function(a, b){return a-b});
|
||||
let dataIndexes = [];
|
||||
tmp.forEach((index) => dataIndexes.push(index - 1));
|
||||
results.jsList.getMatchWithContext(dataIndexes, "sub-results");
|
||||
} else if (type === "results") {
|
||||
subResultsCreateElement.classList.add("disabled"); // cqp server cannot handle more than one request at a time. Thus we deactivate the subResultsCreateElement
|
||||
let dataIndexes = [...Array(results.data.match_count).keys()];
|
||||
results.jsList.getMatchWithContext(dataIndexes, "results");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MetaData {
|
||||
|
@ -2,7 +2,7 @@
|
||||
* This class implements a NotificationListener that is listening for the
|
||||
* specified
|
||||
*/
|
||||
class NotificationListener {
|
||||
class ViewEventListener {
|
||||
constructor(type, listenerFunction) {
|
||||
this.listenerFunction = listenerFunction;
|
||||
this.type = type;
|
||||
@ -61,7 +61,7 @@ class ResultsList extends List {
|
||||
* class field in the ResultsList object with the query selector
|
||||
* string as the key. The selector will be converted to a valid JavaScript
|
||||
* Field name i. e. #html-id-string -> this.htmlIdString
|
||||
* The value will be the identifed element fetched with the querySelector
|
||||
* The value will be the identifed element or elements fetched with the querySelector
|
||||
* method.
|
||||
*/
|
||||
// TODO: multipleResults=false, atattchSomeCallback=false ?
|
||||
@ -73,6 +73,7 @@ class ResultsList extends List {
|
||||
element = document.querySelector(selector);
|
||||
} else {
|
||||
elements = document.querySelectorAll(selector);
|
||||
elements = [...elements];
|
||||
}
|
||||
let cleanKey = [];
|
||||
selector = selector.replace(/_/g, '-');
|
||||
@ -106,6 +107,17 @@ class ResultsList extends List {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions sends events to the Client to trigger specific functions to
|
||||
* trigger new data requests from the server.
|
||||
*/
|
||||
notifyClient(caseIdentifier, detailObject={}) {
|
||||
detailObject.caseIdentifier = caseIdentifier;
|
||||
const event = new CustomEvent('notify-client', { detail: detailObject });
|
||||
console.info('Client dispatching Notification:', caseIdentifier);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates cpos either from ranges or not.
|
||||
*/
|
||||
@ -255,25 +267,6 @@ class ResultsList extends List {
|
||||
}
|
||||
}
|
||||
|
||||
// Triggers emit to get full match context from server for a number of
|
||||
// matches identified by their data_index.
|
||||
getMatchWithContext(dataIndexes, type) {
|
||||
let tmp_first_cpos = [];
|
||||
let tmp_last_cpos = [];
|
||||
for (let dataIndex of dataIndexes) {
|
||||
tmp_first_cpos.push(results.data.matches[dataIndex].c[0]);
|
||||
tmp_last_cpos.push(results.data.matches[dataIndex].c[1]);
|
||||
}
|
||||
nopaque.socket.emit("corpus_analysis_inspect_match",
|
||||
{
|
||||
type: type,
|
||||
data_indexes: dataIndexes,
|
||||
first_cpos: tmp_first_cpos,
|
||||
last_cpos: tmp_last_cpos,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ###### Functions to inspect one match, to show more details ######
|
||||
// activate inspect buttons if progress is 100
|
||||
activateInspect() {
|
||||
@ -786,7 +779,7 @@ class ResultsList extends List {
|
||||
return matchRowElement
|
||||
}
|
||||
|
||||
// creates the HTML table code for the metadata vie in the corpus analysis interface
|
||||
// creates the HTML table code for the metadata view in the corpus analysis interface
|
||||
createMetaDataForModal(metaDataObject) {
|
||||
let html = `<div class="col s12">
|
||||
<table class="highlight">
|
||||
@ -838,12 +831,12 @@ class ResultsList extends List {
|
||||
}
|
||||
|
||||
// Creates the text details for the texts shown in the corpus analysis metadata modal.
|
||||
createTextDetails(metaDataObject) {
|
||||
createTextDetails(metaData) {
|
||||
let metadataKey = event.target.dataset.metadataKey;
|
||||
let textKey = event.target.dataset.textKey;
|
||||
let textData = metaDataObject[metadataKey][textKey];
|
||||
let bibliographicData = document.getElementById(`bibliographic-data-${metadataKey}-${textKey}`);
|
||||
bibliographicData.innerHTML = "";
|
||||
let textData = metaData[metadataKey][textKey];
|
||||
let bibliographicData = document.querySelector(`#bibliographic-data-${metadataKey}-${textKey}`);
|
||||
bibliographicData.textContent = '';
|
||||
for (let [key, value] of Object.entries(textData)) {
|
||||
bibliographicData.insertAdjacentHTML("afterbegin",
|
||||
`
|
||||
@ -854,4 +847,4 @@ class ResultsList extends List {
|
||||
};
|
||||
|
||||
// export classses
|
||||
export { NotificationListener, ResultsList };
|
||||
export { ViewEventListener, ResultsList };
|
@ -98,8 +98,14 @@ function queryDataRecievedCallback(resultsList, detail) {
|
||||
// show or enable some things for the user
|
||||
resultsList.queryResultsCreate.classList.toggle('disabled');
|
||||
resultsList.addToSubResults.removeAttribute("disabled");
|
||||
}
|
||||
|
||||
function resultsDataRecievingCallback(resultsList, detail) {
|
||||
// hide or disable elments taht would trigger another cqp data request
|
||||
}
|
||||
|
||||
function resultsDataRecievedCallback(resultsList, detail) {
|
||||
// hide or show the right stuff
|
||||
}
|
||||
|
||||
// export the callbacks
|
||||
@ -110,4 +116,6 @@ export {
|
||||
queryDataPreparingCallback,
|
||||
queryDataRecievingCallback,
|
||||
queryDataRecievedCallback,
|
||||
resultsDataRecievingCallback,
|
||||
resultsDataRecievedCallback,
|
||||
};
|
@ -14,43 +14,55 @@ import {
|
||||
queryDataPreparingCallback,
|
||||
queryDataRecievingCallback,
|
||||
queryDataRecievedCallback,
|
||||
resultsDataRecievingCallback,
|
||||
resultsDataRecievedCallback,
|
||||
} from './callbacks.js';
|
||||
|
||||
function recieveNotification(eventType, resultsList) {
|
||||
function recieveClientNotification(eventType, resultsList) {
|
||||
document.addEventListener(eventType, (event) => {
|
||||
let caseIdentifier = event.detail.caseIdentifier;
|
||||
switch (caseIdentifier) {
|
||||
case 'connecting':
|
||||
console.info('Recieved notification:', caseIdentifier);
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
connectingCallback(resultsList, event.detail);
|
||||
// execute callback
|
||||
break;
|
||||
case 'connected':
|
||||
console.info('Recieved notification:', caseIdentifier);
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
connectedCallback(resultsList, event.detail);
|
||||
break;
|
||||
case 'connecting-failed':
|
||||
console.info('Recieved notification:', caseIdentifier);
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
// execute callback
|
||||
connectingFaildeCallback(resultsList, event.detail);
|
||||
break;
|
||||
case 'query-data-prepareing':
|
||||
console.info('Recieved notification:', caseIdentifier);
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
// execute callback
|
||||
queryDataPreparingCallback(resultsList, event.detail);
|
||||
break;
|
||||
case 'query-data-recieving':
|
||||
console.info('Recieved notification:', caseIdentifier);
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
// execute callback
|
||||
queryDataRecievingCallback(resultsList, event.detail);
|
||||
break;
|
||||
case 'query-data-recieved':
|
||||
console.info('Recieved notification:', caseIdentifier);
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
// execute callback
|
||||
queryDataRecievedCallback(resultsList, event.detail);
|
||||
break;
|
||||
case 'results-data-recieving':
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
// execute callback
|
||||
resultsDataRecievedCallback(resultsList, event.detail);
|
||||
break;
|
||||
case 'results-data-recieved':
|
||||
console.info('View recieved notification:', caseIdentifier);
|
||||
// execute callback
|
||||
resultsDataRecievedCallback(resultsList, event.detail);
|
||||
break;
|
||||
default:
|
||||
console.error('Recieved unkown notification case identifier');
|
||||
console.error('Recieved unkown notification case identifier from Client');
|
||||
// do something to not crash the analysis session?
|
||||
// maybe unnecessary
|
||||
}
|
||||
@ -58,4 +70,4 @@ function recieveNotification(eventType, resultsList) {
|
||||
}
|
||||
|
||||
// export listeners
|
||||
export { recieveNotification };
|
||||
export { recieveClientNotification };
|
17
web/app/static/js/modules/corpus_analysis/view/spinner.js
Normal file
17
web/app/static/js/modules/corpus_analysis/view/spinner.js
Normal file
@ -0,0 +1,17 @@
|
||||
// loading spinner animation HTML
|
||||
const loadingSpinnerHTML = `
|
||||
<div class="preloader-wrapper button-icon-spinner small active">
|
||||
<div class="spinner-layer spinner-green-only">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div><div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div><div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
//export
|
||||
export { loadingSpinnerHTML };
|
@ -70,35 +70,45 @@
|
||||
* First Phase:
|
||||
* Document content is loaded and scripts are being imported and executed.
|
||||
*/
|
||||
// import Client classes
|
||||
import {
|
||||
Client,
|
||||
SocketEventListener,
|
||||
ClientEventListener,
|
||||
ListenerCallback,
|
||||
} from '../../static/js/modules/corpus_analysis/client/Client.js';
|
||||
// import client listener functions
|
||||
import {
|
||||
recieveConnected,
|
||||
recieveMetaData,
|
||||
recieveQueryStatus,
|
||||
recieveQueryData,
|
||||
recieveViewNotification,
|
||||
recieveResultsData,
|
||||
} from '../../static/js/modules/corpus_analysis/client/listeners.js';
|
||||
import {
|
||||
Results,
|
||||
} from '../../static/js/modules/corpus_analysis/model/Results.js';
|
||||
// import client listener callbacks
|
||||
import {
|
||||
prepareQueryData,
|
||||
saveQueryData,
|
||||
saveMetaData,
|
||||
getResultsData,
|
||||
saveResultsData,
|
||||
} from '../../static/js/modules/corpus_analysis/client/callbacks.js';
|
||||
import {
|
||||
NotificationListener,
|
||||
Results,
|
||||
} from '../../static/js/modules/corpus_analysis/model/Results.js';
|
||||
import {
|
||||
ViewEventListener,
|
||||
ResultsList,
|
||||
} from '../../static/js/modules/corpus_analysis/view/ResultsView.js';
|
||||
import {
|
||||
recieveNotification,
|
||||
recieveClientNotification,
|
||||
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
|
||||
import {
|
||||
scrollToTop,
|
||||
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js'
|
||||
import {
|
||||
loadingSpinnerHTML,
|
||||
} from '../../static/js/modules/corpus_analysis/view/spinner.js'
|
||||
|
||||
/**
|
||||
* Second Phase:
|
||||
@ -120,44 +130,59 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
let resultsList = new ResultsList('result-list', ResultsList.options);
|
||||
/**
|
||||
* Register listeners listening to socket.io events and their callbacks
|
||||
* Afterwards load them.
|
||||
* Afterwards load them. Also registers listeners listening for custom
|
||||
* javascript events.
|
||||
*/
|
||||
const listenForConnected = new SocketEventListener('corpus_analysis_init',
|
||||
const listenForConnected = new ClientEventListener('corpus_analysis_init',
|
||||
recieveConnected);
|
||||
const listenForMetaData = new SocketEventListener('corpus_analysis_meta_data',
|
||||
const listenForMetaData = new ClientEventListener('corpus_analysis_meta_data',
|
||||
recieveMetaData);
|
||||
const metaDataCallback = new ListenerCallback('corpus_analysis_meta_data',
|
||||
saveMetaData,
|
||||
[client, results]);
|
||||
listenForMetaData.setCallbacks([metaDataCallback]);
|
||||
const listenForQueryStatus = new SocketEventListener('corpus_analysis_query',
|
||||
const listenForQueryStatus = new ClientEventListener('corpus_analysis_query',
|
||||
recieveQueryStatus);
|
||||
const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
|
||||
prepareQueryData,
|
||||
[client, results]);
|
||||
listenForQueryStatus.setCallbacks([queryStatusCallback]);
|
||||
const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
|
||||
const listenForQueryData = new ClientEventListener('corpus_analysis_query_results',
|
||||
recieveQueryData);
|
||||
const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
|
||||
saveQueryData,
|
||||
[client, results]);
|
||||
listenForQueryData.setCallbacks([queryDataCallback]);
|
||||
const listenForResults = new ClientEventListener('corpus_analysis_inspect_match',
|
||||
recieveResultsData);
|
||||
const resultsDataCallback = new ListenerCallback('corpus_analysis_inspect_match',
|
||||
saveResultsData,
|
||||
[client, results]);
|
||||
listenForResults.setCallbacks([resultsDataCallback]);
|
||||
// listen for javascript custom notifications
|
||||
const listenForViewNotification = new ClientEventListener('notify-client',
|
||||
recieveViewNotification);
|
||||
const getResultsCallback = new ListenerCallback('get-results',
|
||||
getResultsData,
|
||||
[client, results]);
|
||||
listenForViewNotification.setCallbacks([getResultsCallback]);
|
||||
client.setSocketEventListeners([listenForConnected,
|
||||
listenForQueryStatus,
|
||||
listenForQueryData,
|
||||
listenForMetaData]);
|
||||
listenForMetaData,
|
||||
listenForViewNotification,
|
||||
listenForResults]);
|
||||
client.loadSocketEventListeners();
|
||||
/**
|
||||
* Register resultsList listeners listening to nitification events.
|
||||
*/
|
||||
const listenForNotification = new NotificationListener('notify',
|
||||
recieveNotification);
|
||||
resultsList.setNotificationListeners([listenForNotification]);
|
||||
const listenForClientNotification = new ViewEventListener('notify-view',
|
||||
recieveClientNotification);
|
||||
resultsList.setNotificationListeners([listenForClientNotification]);
|
||||
resultsList.loadNotificationListeners();
|
||||
// Connect client to server
|
||||
client.notifyView('connecting');
|
||||
client.connect();
|
||||
|
||||
// Send a query and recieve its answer data
|
||||
let queryFormElement = document.querySelector('#query-form');
|
||||
queryFormElement.addEventListener('submit', (event) => {
|
||||
@ -181,20 +206,66 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
results.data.getQueryStr(queryFormElement);
|
||||
client.query(results.data.query);
|
||||
});
|
||||
/**
|
||||
* Display events
|
||||
* 1. live update of hits per page if hits per page value is changed
|
||||
*/
|
||||
// Get all needed HTMLElements for the following event listeners
|
||||
resultsList.getHTMLElements([
|
||||
'#display-options-form-results_per_page',
|
||||
'#display-options-form-result_context'
|
||||
'#display-options-form-result_context',
|
||||
'#show-meta-data',
|
||||
'#meta-data-modal',
|
||||
'#meta-data-modal-content',
|
||||
'#query-results-create'
|
||||
|
||||
]);
|
||||
/**
|
||||
* Display events: Following event listeners are handleing the
|
||||
* live update of hits per page if hits per page value is changed and the
|
||||
* context size of every match.
|
||||
*/
|
||||
resultsList.displayOptionsFormResultsPerPage.onchange = () => {
|
||||
resultsList.changeHitsPerPage();
|
||||
};
|
||||
resultsList.displayOptionsFormResultContext.onchange = () => {
|
||||
resultsList.changeContext();
|
||||
};
|
||||
/**
|
||||
* The following event listener handel the Show metadata button and its
|
||||
* functionality. Before the needed modal is initialized.
|
||||
*/
|
||||
let deleteOverlay = () => {
|
||||
let overlay = document.querySelector(".modal-overlay");
|
||||
overlay.remove();
|
||||
};
|
||||
resultsList.metaDataModal= M.Modal.init(resultsList.metaDataModal, {
|
||||
'preventScrolling': false,
|
||||
'opacity': 0.0,
|
||||
'dismissible': false,
|
||||
'onOpenEnd': deleteOverlay
|
||||
});
|
||||
resultsList.showMetaData.onclick = () => {
|
||||
resultsList.metaDataModalContent.textContent = '';
|
||||
let table = resultsList.createMetaDataForModal(results.metaData);
|
||||
resultsList.metaDataModalContent.insertAdjacentHTML('afterbegin', table);
|
||||
resultsList.metaDataModal.open();
|
||||
let collapsibles = resultsList.metaDataModalContent.querySelectorAll(".text-metadata");
|
||||
for (let collapsible of collapsibles) {
|
||||
collapsible.onclick = () => {
|
||||
let elems = resultsList.metaDataModalContent.querySelectorAll('.collapsible');
|
||||
let instances = M.Collapsible.init(elems, {accordion: false});
|
||||
resultsList.createTextDetails(results.metaData);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* The following event listeners are handeling the data export.
|
||||
*/
|
||||
resultsList.queryResultsCreate.onclick = () => {
|
||||
resultsList.queryResultsCreate.querySelector('i').classList.toggle('hide');
|
||||
resultsList.queryResultsCreate.innerText = 'Creating...';
|
||||
resultsList.queryResultsCreate.insertAdjacentHTML('afterbegin',
|
||||
loadingSpinnerHTML);
|
||||
resultsList.notifyClient('get-results', { resultsType: 'full-results',
|
||||
dataIndexes: [...Array(results.data.match_count).keys()]});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@ result.-->
|
||||
<div class="divider" style="margin-bottom: 10px;"></div>
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<button id="show-metadata"
|
||||
<button id="show-meta-data"
|
||||
class="waves-effect
|
||||
waves-light
|
||||
btn-flat
|
||||
|
Loading…
x
Reference in New Issue
Block a user