mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2025-02-07 15:00:51 +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.logging = logging;
|
||||||
this.requestQueryProgress = 0;
|
this.requestQueryProgress = 0;
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.socketEventListeners = {};
|
this.eventListeners = {};
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
|
||||||
|
|
||||||
@ -44,9 +44,9 @@ class Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registers one or more SocketEventListeners to the Client.
|
// Registers one or more SocketEventListeners to the Client.
|
||||||
setSocketEventListeners(socketEventListeners) {
|
setSocketEventListeners(eventListeners) {
|
||||||
for (let socketEventListener of socketEventListeners) {
|
for (let eventListener of eventListeners) {
|
||||||
this.socketEventListeners[socketEventListener.type] = socketEventListener;
|
this.eventListeners[eventListener.type] = eventListener;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class Client {
|
|||||||
* type strings because they double as the socket event event names.
|
* type strings because they double as the socket event event names.
|
||||||
*/
|
*/
|
||||||
loadSocketEventListeners() {
|
loadSocketEventListeners() {
|
||||||
for (let [type, listener] of Object.entries(this.socketEventListeners)) {
|
for (let [type, listener] of Object.entries(this.eventListeners)) {
|
||||||
listener.listenerFunction(type, this);
|
listener.listenerFunction(type, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,8 +66,8 @@ class Client {
|
|||||||
*/
|
*/
|
||||||
notifyView(caseIdentifier, detailObject={}) {
|
notifyView(caseIdentifier, detailObject={}) {
|
||||||
detailObject.caseIdentifier = caseIdentifier;
|
detailObject.caseIdentifier = caseIdentifier;
|
||||||
const event = new CustomEvent('notify', { detail: detailObject });
|
const event = new CustomEvent('notify-view', { detail: detailObject });
|
||||||
console.info('Dispatching Notification:', caseIdentifier);
|
console.info('Client dispatching Notification:', caseIdentifier);
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,16 +105,38 @@ class Client {
|
|||||||
'socket.emit for the query', queryStr);
|
'socket.emit for the query', queryStr);
|
||||||
this.socket.emit('corpus_analysis_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.
|
* This class is used to create an SocketEventListener.
|
||||||
* Input are an identifying type string, the listener function and callbacks
|
* Input are an identifying type string, the listener function and callbacks
|
||||||
* which will be executed as part of the listener function. The identifying
|
* which will be executed as part of the listener function. The identifying
|
||||||
* type string is also used as the socket event event identifier.
|
* type string is also used as the socket event event identifier.
|
||||||
*/
|
*/
|
||||||
class SocketEventListener {
|
class ClientEventListener {
|
||||||
constructor(type, listenerFunction, args=null) {
|
constructor(type, listenerFunction) {
|
||||||
this.listenerCallbacks = {};
|
this.listenerCallbacks = {};
|
||||||
this.listenerFunction = listenerFunction;
|
this.listenerFunction = listenerFunction;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -127,8 +149,8 @@ class SocketEventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Shorthand to execute all registered callbacks with same args in insertion
|
/** Shorthand to execute all registered callbacks with same defaultArgs
|
||||||
* order.
|
* in insertion order.
|
||||||
* NOTE:
|
* NOTE:
|
||||||
* Since ECMAScript 2015, objects do preserve creation order for
|
* Since ECMAScript 2015, objects do preserve creation order for
|
||||||
* string and Symbol keys. In JavaScript engines that comply with the
|
* string and Symbol keys. In JavaScript engines that comply with the
|
||||||
@ -136,11 +158,18 @@ class SocketEventListener {
|
|||||||
* yield the keys in order of insertion.
|
* yield the keys in order of insertion.
|
||||||
* So all modern Browsers.
|
* So all modern Browsers.
|
||||||
*/
|
*/
|
||||||
executeCallbacks(payload) {
|
executeCallbacks(defaultArgs) {
|
||||||
for (let [type, listenerCallback] of Object.entries(this.listenerCallbacks)) {
|
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 Classes from this module
|
||||||
export {
|
export {
|
||||||
Client,
|
Client,
|
||||||
SocketEventListener,
|
ClientEventListener,
|
||||||
ListenerCallback,
|
ListenerCallback,
|
||||||
};
|
};
|
@ -46,116 +46,24 @@ function saveQueryData(args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function querySetup(payload, client) {
|
function getResultsData(args) {
|
||||||
// deletes old data from query issued before this new query
|
let [resultsType, dataIndexes, client, results, rest] = arguments;
|
||||||
client.results.clearAll();
|
client.notifyView('results-data-recieving');
|
||||||
// load necessary HTMLElements with selectory syntax and save them as fields
|
client.getResultsData(resultsType, dataIndexes, results);
|
||||||
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 saveResultsData(args) {
|
||||||
* This callback should be registered to the SocketEventListener 'recieveQueryData'
|
let [payload, client, results, rest] = arguments;
|
||||||
* It takes the incoming chunk and renders the results using the
|
// code to save results data depending on type
|
||||||
* results.jsList object. It can either handle live incoming data chunks or
|
console.info('Results data has been saved.');
|
||||||
* already loaded/imported results data.
|
client.notifyView('results-data-recieved');
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// export callbacks
|
// 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
|
* This file contains the listener functions which can be assigned to the
|
||||||
* coprus_analysis client. So that the incoming data/status informations will
|
* 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.
|
* 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(`corpus_analysis_meta_data: ${response.code} - ${response.msg}`);
|
||||||
console.info(response);
|
console.info(response);
|
||||||
// executing the registered callbacks
|
// executing the registered callbacks
|
||||||
client.socketEventListeners[type].executeCallbacks(response.payload);
|
client.eventListeners[type].executeCallbacks([response.payload]);
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
} else {
|
} else {
|
||||||
console.group('Failed to recieve meta data.');
|
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(`corpus_analysis_query: ${response.code} - ${response.msg}`);
|
||||||
console.info(response);
|
console.info(response);
|
||||||
// executing the registered callbacks
|
// executing the registered callbacks
|
||||||
client.socketEventListeners[type].executeCallbacks(response.payload);
|
client.eventListeners[type].executeCallbacks([response.payload]);
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
} else {
|
} else {
|
||||||
console.group('corpus_analysis_query: Client failed recieving',
|
console.group('corpus_analysis_query: Client failed recieving',
|
||||||
@ -113,7 +118,7 @@ function recieveQueryData(type, client) {
|
|||||||
/**
|
/**
|
||||||
* Execute registered callbacks and notify View.
|
* 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.info('Added chunk data to results.data.');
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
} else {
|
} else {
|
||||||
@ -125,18 +130,72 @@ function recieveQueryData(type, client) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} 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.');
|
console.info('Client loading imported query data from database.');
|
||||||
// executing the registered callbacks
|
// executing the registered callbacks
|
||||||
client.socketEventListeners[type].executeCallbacks();
|
client.eventListeners[type].executeCallbacks();
|
||||||
console.groupEnd();
|
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 listeners from this module
|
||||||
export {
|
export {
|
||||||
recieveConnected,
|
recieveConnected,
|
||||||
recieveMetaData,
|
recieveMetaData,
|
||||||
recieveQueryStatus,
|
recieveQueryStatus,
|
||||||
recieveQueryData
|
recieveQueryData,
|
||||||
|
recieveViewNotification,
|
||||||
|
recieveResultsData,
|
||||||
};
|
};
|
@ -8,6 +8,7 @@ class Results {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.data = new Data();
|
this.data = new Data();
|
||||||
this.metaData = new MetaData();
|
this.metaData = new MetaData();
|
||||||
|
this.fullResultsData = new Data();
|
||||||
this.subResultsData = new Data();
|
this.subResultsData = new Data();
|
||||||
console.info('Initialized the Results object.');
|
console.info('Initialized the Results object.');
|
||||||
}
|
}
|
||||||
@ -15,12 +16,12 @@ class Results {
|
|||||||
init() {
|
init() {
|
||||||
this.data.init();
|
this.data.init();
|
||||||
this.metaData.init();
|
this.metaData.init();
|
||||||
|
this.fullResultsData = new Data();
|
||||||
this.subResultsData.init();
|
this.subResultsData.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Data {
|
class Data {
|
||||||
// Sets empty object structure. Also usefull to delete old results.
|
// Sets empty object structure. Also usefull to delete old results.
|
||||||
// matchCount default is 0
|
// matchCount default is 0
|
||||||
@ -94,29 +95,6 @@ class Data {
|
|||||||
this.download(downloadElement, dataStr, resultFilename, "text/json", ".json")
|
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 {
|
class MetaData {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* This class implements a NotificationListener that is listening for the
|
* This class implements a NotificationListener that is listening for the
|
||||||
* specified
|
* specified
|
||||||
*/
|
*/
|
||||||
class NotificationListener {
|
class ViewEventListener {
|
||||||
constructor(type, listenerFunction) {
|
constructor(type, listenerFunction) {
|
||||||
this.listenerFunction = listenerFunction;
|
this.listenerFunction = listenerFunction;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -61,7 +61,7 @@ class ResultsList extends List {
|
|||||||
* class field in the ResultsList object with the query selector
|
* class field in the ResultsList object with the query selector
|
||||||
* string as the key. The selector will be converted to a valid JavaScript
|
* string as the key. The selector will be converted to a valid JavaScript
|
||||||
* Field name i. e. #html-id-string -> this.htmlIdString
|
* 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.
|
* method.
|
||||||
*/
|
*/
|
||||||
// TODO: multipleResults=false, atattchSomeCallback=false ?
|
// TODO: multipleResults=false, atattchSomeCallback=false ?
|
||||||
@ -73,6 +73,7 @@ class ResultsList extends List {
|
|||||||
element = document.querySelector(selector);
|
element = document.querySelector(selector);
|
||||||
} else {
|
} else {
|
||||||
elements = document.querySelectorAll(selector);
|
elements = document.querySelectorAll(selector);
|
||||||
|
elements = [...elements];
|
||||||
}
|
}
|
||||||
let cleanKey = [];
|
let cleanKey = [];
|
||||||
selector = selector.replace(/_/g, '-');
|
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.
|
* 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 ######
|
// ###### Functions to inspect one match, to show more details ######
|
||||||
// activate inspect buttons if progress is 100
|
// activate inspect buttons if progress is 100
|
||||||
activateInspect() {
|
activateInspect() {
|
||||||
@ -786,7 +779,7 @@ class ResultsList extends List {
|
|||||||
return matchRowElement
|
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) {
|
createMetaDataForModal(metaDataObject) {
|
||||||
let html = `<div class="col s12">
|
let html = `<div class="col s12">
|
||||||
<table class="highlight">
|
<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.
|
// 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 metadataKey = event.target.dataset.metadataKey;
|
||||||
let textKey = event.target.dataset.textKey;
|
let textKey = event.target.dataset.textKey;
|
||||||
let textData = metaDataObject[metadataKey][textKey];
|
let textData = metaData[metadataKey][textKey];
|
||||||
let bibliographicData = document.getElementById(`bibliographic-data-${metadataKey}-${textKey}`);
|
let bibliographicData = document.querySelector(`#bibliographic-data-${metadataKey}-${textKey}`);
|
||||||
bibliographicData.innerHTML = "";
|
bibliographicData.textContent = '';
|
||||||
for (let [key, value] of Object.entries(textData)) {
|
for (let [key, value] of Object.entries(textData)) {
|
||||||
bibliographicData.insertAdjacentHTML("afterbegin",
|
bibliographicData.insertAdjacentHTML("afterbegin",
|
||||||
`
|
`
|
||||||
@ -854,4 +847,4 @@ class ResultsList extends List {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// export classses
|
// export classses
|
||||||
export { NotificationListener, ResultsList };
|
export { ViewEventListener, ResultsList };
|
@ -98,8 +98,14 @@ function queryDataRecievedCallback(resultsList, detail) {
|
|||||||
// show or enable some things for the user
|
// show or enable some things for the user
|
||||||
resultsList.queryResultsCreate.classList.toggle('disabled');
|
resultsList.queryResultsCreate.classList.toggle('disabled');
|
||||||
resultsList.addToSubResults.removeAttribute("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
|
// export the callbacks
|
||||||
@ -110,4 +116,6 @@ export {
|
|||||||
queryDataPreparingCallback,
|
queryDataPreparingCallback,
|
||||||
queryDataRecievingCallback,
|
queryDataRecievingCallback,
|
||||||
queryDataRecievedCallback,
|
queryDataRecievedCallback,
|
||||||
|
resultsDataRecievingCallback,
|
||||||
|
resultsDataRecievedCallback,
|
||||||
};
|
};
|
@ -14,43 +14,55 @@ import {
|
|||||||
queryDataPreparingCallback,
|
queryDataPreparingCallback,
|
||||||
queryDataRecievingCallback,
|
queryDataRecievingCallback,
|
||||||
queryDataRecievedCallback,
|
queryDataRecievedCallback,
|
||||||
|
resultsDataRecievingCallback,
|
||||||
|
resultsDataRecievedCallback,
|
||||||
} from './callbacks.js';
|
} from './callbacks.js';
|
||||||
|
|
||||||
function recieveNotification(eventType, resultsList) {
|
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 'connecting':
|
case 'connecting':
|
||||||
console.info('Recieved notification:', caseIdentifier);
|
console.info('View recieved notification:', caseIdentifier);
|
||||||
connectingCallback(resultsList, event.detail);
|
connectingCallback(resultsList, event.detail);
|
||||||
// execute callback
|
// execute callback
|
||||||
break;
|
break;
|
||||||
case 'connected':
|
case 'connected':
|
||||||
console.info('Recieved notification:', caseIdentifier);
|
console.info('View recieved notification:', caseIdentifier);
|
||||||
connectedCallback(resultsList, event.detail);
|
connectedCallback(resultsList, event.detail);
|
||||||
break;
|
break;
|
||||||
case 'connecting-failed':
|
case 'connecting-failed':
|
||||||
console.info('Recieved notification:', caseIdentifier);
|
console.info('View recieved notification:', caseIdentifier);
|
||||||
// execute callback
|
// execute callback
|
||||||
connectingFaildeCallback(resultsList, event.detail);
|
connectingFaildeCallback(resultsList, event.detail);
|
||||||
break;
|
break;
|
||||||
case 'query-data-prepareing':
|
case 'query-data-prepareing':
|
||||||
console.info('Recieved notification:', caseIdentifier);
|
console.info('View recieved notification:', caseIdentifier);
|
||||||
// execute callback
|
// execute callback
|
||||||
queryDataPreparingCallback(resultsList, event.detail);
|
queryDataPreparingCallback(resultsList, event.detail);
|
||||||
break;
|
break;
|
||||||
case 'query-data-recieving':
|
case 'query-data-recieving':
|
||||||
console.info('Recieved notification:', caseIdentifier);
|
console.info('View recieved notification:', caseIdentifier);
|
||||||
// execute callback
|
// execute callback
|
||||||
queryDataRecievingCallback(resultsList, event.detail);
|
queryDataRecievingCallback(resultsList, event.detail);
|
||||||
break;
|
break;
|
||||||
case 'query-data-recieved':
|
case 'query-data-recieved':
|
||||||
console.info('Recieved notification:', caseIdentifier);
|
console.info('View recieved notification:', caseIdentifier);
|
||||||
// execute callback
|
// execute callback
|
||||||
queryDataRecievedCallback(resultsList, event.detail);
|
queryDataRecievedCallback(resultsList, event.detail);
|
||||||
break;
|
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:
|
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?
|
// do something to not crash the analysis session?
|
||||||
// maybe unnecessary
|
// maybe unnecessary
|
||||||
}
|
}
|
||||||
@ -58,4 +70,4 @@ function recieveNotification(eventType, resultsList) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// export listeners
|
// 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:
|
* First Phase:
|
||||||
* Document content is loaded and scripts are being imported and executed.
|
* Document content is loaded and scripts are being imported and executed.
|
||||||
*/
|
*/
|
||||||
|
// import Client classes
|
||||||
import {
|
import {
|
||||||
Client,
|
Client,
|
||||||
SocketEventListener,
|
ClientEventListener,
|
||||||
ListenerCallback,
|
ListenerCallback,
|
||||||
} from '../../static/js/modules/corpus_analysis/client/Client.js';
|
} from '../../static/js/modules/corpus_analysis/client/Client.js';
|
||||||
|
// import client listener functions
|
||||||
import {
|
import {
|
||||||
recieveConnected,
|
recieveConnected,
|
||||||
recieveMetaData,
|
recieveMetaData,
|
||||||
recieveQueryStatus,
|
recieveQueryStatus,
|
||||||
recieveQueryData,
|
recieveQueryData,
|
||||||
|
recieveViewNotification,
|
||||||
|
recieveResultsData,
|
||||||
} from '../../static/js/modules/corpus_analysis/client/listeners.js';
|
} from '../../static/js/modules/corpus_analysis/client/listeners.js';
|
||||||
import {
|
// import client listener callbacks
|
||||||
Results,
|
|
||||||
} from '../../static/js/modules/corpus_analysis/model/Results.js';
|
|
||||||
import {
|
import {
|
||||||
prepareQueryData,
|
prepareQueryData,
|
||||||
saveQueryData,
|
saveQueryData,
|
||||||
saveMetaData,
|
saveMetaData,
|
||||||
|
getResultsData,
|
||||||
|
saveResultsData,
|
||||||
} from '../../static/js/modules/corpus_analysis/client/callbacks.js';
|
} from '../../static/js/modules/corpus_analysis/client/callbacks.js';
|
||||||
import {
|
import {
|
||||||
NotificationListener,
|
Results,
|
||||||
|
} from '../../static/js/modules/corpus_analysis/model/Results.js';
|
||||||
|
import {
|
||||||
|
ViewEventListener,
|
||||||
ResultsList,
|
ResultsList,
|
||||||
} from '../../static/js/modules/corpus_analysis/view/ResultsView.js';
|
} from '../../static/js/modules/corpus_analysis/view/ResultsView.js';
|
||||||
import {
|
import {
|
||||||
recieveNotification,
|
recieveClientNotification,
|
||||||
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
|
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
|
||||||
import {
|
import {
|
||||||
scrollToTop,
|
scrollToTop,
|
||||||
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js'
|
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js'
|
||||||
|
import {
|
||||||
|
loadingSpinnerHTML,
|
||||||
|
} from '../../static/js/modules/corpus_analysis/view/spinner.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Second Phase:
|
* Second Phase:
|
||||||
@ -120,44 +130,59 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
let resultsList = new ResultsList('result-list', ResultsList.options);
|
let resultsList = new ResultsList('result-list', ResultsList.options);
|
||||||
/**
|
/**
|
||||||
* Register listeners listening to socket.io events and their callbacks
|
* 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);
|
recieveConnected);
|
||||||
const listenForMetaData = new SocketEventListener('corpus_analysis_meta_data',
|
const listenForMetaData = new ClientEventListener('corpus_analysis_meta_data',
|
||||||
recieveMetaData);
|
recieveMetaData);
|
||||||
const metaDataCallback = new ListenerCallback('corpus_analysis_meta_data',
|
const metaDataCallback = new ListenerCallback('corpus_analysis_meta_data',
|
||||||
saveMetaData,
|
saveMetaData,
|
||||||
[client, results]);
|
[client, results]);
|
||||||
listenForMetaData.setCallbacks([metaDataCallback]);
|
listenForMetaData.setCallbacks([metaDataCallback]);
|
||||||
const listenForQueryStatus = new SocketEventListener('corpus_analysis_query',
|
const listenForQueryStatus = new ClientEventListener('corpus_analysis_query',
|
||||||
recieveQueryStatus);
|
recieveQueryStatus);
|
||||||
const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
|
const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
|
||||||
prepareQueryData,
|
prepareQueryData,
|
||||||
[client, results]);
|
[client, results]);
|
||||||
listenForQueryStatus.setCallbacks([queryStatusCallback]);
|
listenForQueryStatus.setCallbacks([queryStatusCallback]);
|
||||||
const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
|
const listenForQueryData = new ClientEventListener('corpus_analysis_query_results',
|
||||||
recieveQueryData);
|
recieveQueryData);
|
||||||
const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
|
const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
|
||||||
saveQueryData,
|
saveQueryData,
|
||||||
[client, results]);
|
[client, results]);
|
||||||
listenForQueryData.setCallbacks([queryDataCallback]);
|
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,
|
client.setSocketEventListeners([listenForConnected,
|
||||||
listenForQueryStatus,
|
listenForQueryStatus,
|
||||||
listenForQueryData,
|
listenForQueryData,
|
||||||
listenForMetaData]);
|
listenForMetaData,
|
||||||
|
listenForViewNotification,
|
||||||
|
listenForResults]);
|
||||||
client.loadSocketEventListeners();
|
client.loadSocketEventListeners();
|
||||||
/**
|
/**
|
||||||
* Register resultsList listeners listening to nitification events.
|
* Register resultsList listeners listening to nitification events.
|
||||||
*/
|
*/
|
||||||
const listenForNotification = new NotificationListener('notify',
|
const listenForClientNotification = new ViewEventListener('notify-view',
|
||||||
recieveNotification);
|
recieveClientNotification);
|
||||||
resultsList.setNotificationListeners([listenForNotification]);
|
resultsList.setNotificationListeners([listenForClientNotification]);
|
||||||
resultsList.loadNotificationListeners();
|
resultsList.loadNotificationListeners();
|
||||||
// Connect client to server
|
// Connect client to server
|
||||||
client.notifyView('connecting');
|
client.notifyView('connecting');
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
// Send a query and recieve its answer data
|
// Send a query and recieve its answer data
|
||||||
let queryFormElement = document.querySelector('#query-form');
|
let queryFormElement = document.querySelector('#query-form');
|
||||||
queryFormElement.addEventListener('submit', (event) => {
|
queryFormElement.addEventListener('submit', (event) => {
|
||||||
@ -181,20 +206,66 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
results.data.getQueryStr(queryFormElement);
|
results.data.getQueryStr(queryFormElement);
|
||||||
client.query(results.data.query);
|
client.query(results.data.query);
|
||||||
});
|
});
|
||||||
/**
|
// Get all needed HTMLElements for the following event listeners
|
||||||
* Display events
|
|
||||||
* 1. live update of hits per page if hits per page value is changed
|
|
||||||
*/
|
|
||||||
resultsList.getHTMLElements([
|
resultsList.getHTMLElements([
|
||||||
'#display-options-form-results_per_page',
|
'#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.displayOptionsFormResultsPerPage.onchange = () => {
|
||||||
resultsList.changeHitsPerPage();
|
resultsList.changeHitsPerPage();
|
||||||
};
|
};
|
||||||
resultsList.displayOptionsFormResultContext.onchange = () => {
|
resultsList.displayOptionsFormResultContext.onchange = () => {
|
||||||
resultsList.changeContext();
|
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="divider" style="margin-bottom: 10px;"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<button id="show-metadata"
|
<button id="show-meta-data"
|
||||||
class="waves-effect
|
class="waves-effect
|
||||||
waves-light
|
waves-light
|
||||||
btn-flat
|
btn-flat
|
||||||
|
Loading…
x
Reference in New Issue
Block a user