Remove asynch rework because it was already event driven

This commit is contained in:
Stephan Porada 2020-08-07 17:32:10 +02:00
parent 6b1f588f29
commit 25ea9ba583
3 changed files with 218 additions and 65 deletions

View File

@ -1,121 +1,169 @@
/**
* This class is used to create an CorpusAnalysisClient object.
* The client handels the client server communication.
* It requests data (e.g. the analysis session or query results) from the
* the server and recieves them.
*/
class CorpusAnalysisClient { class CorpusAnalysisClient {
constructor(corpusId, socket) { constructor(corpusId, socket, logging=false) {
this.corpusId = corpusId; this.corpusId = corpusId;
this.socket = socket;
this.displays = {}; this.displays = {};
this.logging = logging;
this.socket = socket;
this.socketEventListeners = {};
} }
setDisplay(type, display) { // Registers one or more SocketEventListeners to the CorpusAnalysisClient.
this.displays[type] = display; setSocketEventListeners(socketEventListeners) {
for (let listener of socketEventListeners) {
this.socketEventListeners[listener.type] = listener.listenerFunction;
}
} }
async initSession() { loadListeners() {
let request = await this.requestSession(); for (let [type, listener] of Object.entries(this.socketEventListeners)) {
let recvieveSession = await this.recvieveSession(); listener(this);
console.log("corpus_analysis_init: Waiting for response"); // this happens inbetween the two functions above }
} }
requestSession() { // should be private with ES2020 // Registers a CorpusAnalysisDisplay object to the CorpusAnalysisClient.
console.log("corpus_analysis_init: Emitting to server"); setDisplay(type, corpusAnalysisDisplay) {
this.displays[type] = corpusAnalysisDisplay;
}
// /**
// * Initializes the interactive corpus analysis session via socket.io.
// * This function uses helper functions.
// */
// initSession() {
// let request = this.requestSession();
// let recvieveSession = this.recvieveSession();
// console.info('corpus_analysis_init: Client waiting for response'); // this happens inbetween the two functions above
// }
/**
* Requests a corpus analysis session via socket.io.
* Opens a loading modal at the start of the request
* Should be a private method if ES2020 is finalized (Maybe?)
*/
requestSession() {
console.info('corpus_analysis_init: Client requesting session via',
'socket.emit');
if (this.displays.init != undefined) { if (this.displays.init != undefined) {
this.displays.init.element.M_Modal.open(); this.displays.init.element.M_Modal.open();
this.displays.init.setVisibilityByStatus("waiting"); this.displays.init.setVisibilityByStatus('waiting');
} }
return new Promise((resolve, reject) => { this.socket.emit('corpus_analysis_init', this.corpusId);
this.socket.emit("corpus_analysis_init", this.corpusId);
resolve();
})
} }
recvieveSession() { // should be private with ES2020 // /**
this.socket.on("corpus_analysis_init", (response) => { // * Sends a query to the server and handles the response to that query.
console.log("corpus_analysis_init: Recieving response from server"); // * This function uses helper functions.
if (response.code === 200) { // */
console.log("corpus_analysis_init: Initialization succeeded"); // query(queryStr) {
if (this.displays.init != undefined) { // let requestQueryData = this.requestQueryData(queryStr);
this.displays.init.element.M_Modal.close(); // let recieveQueryProcessStatus = this.recieveQueryProcessStatus();
this.displays.init.setVisibilityByStatus("success"); // let recieveQueryData = this.recieveQueryData();
} // console.info('corpus_analysis_query: Client waiting for query data'); // this happens inbetween the two functions above
} else { // }
let errorText = `Error ${response.code} - ${response.msg}`;
if (this.displays.init.errorContainer != undefined) { /**
this.displays.init.errorContainer.innerHTML = `<p class="red-text">` + * Sends the query string to the server.
`<i class="material-icons tiny">error</i> ${errorText}</p>`; * Should be a private method if ES2020 is finalized (Maybe?)
} */
if (this.displays.init != undefined) { requestQueryData(queryStr) {
this.displays.init.setVisibilityByStatus("error"); console.info('corpus_analysis_query: Client requesting query data via',
} 'socket.emit for the query', queryStr);
console.error(`corpus_analysis_init: ${errorText}`); // TODO: Display stuff
} this.socket.emit('corpus_analysis_query', queryStr);
});
} }
} }
/**
* This class is used to create an CorpusAnalysisDisplay object.
* Input is one HTMLElement that can then be hidden or shown depending on
* its CSS classes.
*/
class CorpusAnalysisDisplay { class CorpusAnalysisDisplay {
constructor(element) { constructor(element) {
// with this function initalized modals can also be handeld
this.element = (() => {if (element instanceof HTMLElement) { this.element = (() => {if (element instanceof HTMLElement) {
return element; return element;
} else { } else {
element = element["$el"][0]; element = element['$el'][0];
return element; return element;
} }
})(); // with this function modals can also be handeld })();
this.errorContainer = element.querySelector(".error-container"); this.errorContainer = element.querySelector('.error-container');
this.showOnError = element.querySelectorAll(".show-on-error"); this.showOnError = element.querySelectorAll('.show-on-error');
this.showOnSuccess = element.querySelectorAll(".show-on-success"); this.showOnSuccess = element.querySelectorAll('.show-on-success');
this.showWhileWaiting = element.querySelectorAll(".show-while-waiting"); this.showWhileWaiting = element.querySelectorAll('.show-while-waiting');
this.hideOnComplete = element.querySelectorAll(".hide-on-complete") this.hideOnComplete = element.querySelectorAll('.hide-on-complete')
} }
// Changes the visibility of its own
setVisibilityByStatus(status) { setVisibilityByStatus(status) {
switch (status) { switch (status) {
case "error": case 'error':
for (let element of this.showOnError) { for (let element of this.showOnError) {
element.classList.remove("hide"); element.classList.remove('hide');
} }
for (let element of this.showOnSuccess) { for (let element of this.showOnSuccess) {
element.classList.add("hide"); element.classList.add('hide');
} }
for (let element of this.showWhileWaiting) { for (let element of this.showWhileWaiting) {
element.classList.add("hide"); element.classList.add('hide');
} }
break; break;
case "success": case 'success':
for (let element of this.showOnError) { for (let element of this.showOnError) {
element.classList.add("hide"); element.classList.add('hide');
} }
for (let element of this.showOnSuccess) { for (let element of this.showOnSuccess) {
element.classList.remove("hide"); element.classList.remove('hide');
} }
for (let element of this.showWhileWaiting) { for (let element of this.showWhileWaiting) {
element.classList.add("hide"); element.classList.add('hide');
} }
break; break;
case "waiting": case 'waiting':
for (let element of this.showOnError) { for (let element of this.showOnError) {
element.classList.add("hide"); element.classList.add('hide');
} }
for (let element of this.showOnSuccess) { for (let element of this.showOnSuccess) {
element.classList.add("hide"); element.classList.add('hide');
} }
for (let element of this.showWhileWaiting) { for (let element of this.showWhileWaiting) {
element.classList.remove("hide"); element.classList.remove('hide');
} }
break; break;
default: default:
// Hide all // Hide all
for (let element of this.showOnError) { for (let element of this.showOnError) {
element.classList.add("hide"); element.classList.add('hide');
} }
for (let element of this.showOnSuccess) { for (let element of this.showOnSuccess) {
element.classList.add("hide"); element.classList.add('hide');
} }
for (let element of this.showWhileWaiting) { for (let element of this.showWhileWaiting) {
element.classList.add("hide"); element.classList.add('hide');
} }
} }
} }
} }
export {CorpusAnalysisClient, CorpusAnalysisDisplay}; /**
* This class is used to create an CorpusAnalysisDisplay object.
* Input is one HTMLElement that can then be hidden or shown depending on
* its CSS classes.
*/
class SocketEventListener {
constructor(type, listenerFunction) {
this.listenerFunction = listenerFunction;
this.type = type;
}
}
// export both Classes from this module
export {CorpusAnalysisClient, CorpusAnalysisDisplay, SocketEventListener};

View File

@ -0,0 +1,60 @@
/**
* Recieves a corpus analysis session via socket.io.
* Closes the loading modal that has been opend with requestSession at the
* start of the request.
*/
function recieveSession(client) {
client.socket.on('corpus_analysis_init', (response) => {
console.group('recieve session')
console.info('corpus_analysis_init: Client recieving session/or error',
'codes via socket.on');
if (response.code === 200) {
console.info('corpus_analysis_init: Initialization succeeded');
console.info(response);
console.groupEnd();
if (client.displays.init != undefined) {
client.displays.init.element.M_Modal.close();
client.displays.init.setVisibilityByStatus('success');
}
} else {
let errorText = `Error ${response.code} - ${response.msg}`;
if (client.displays.init.errorContainer != undefined) {
client.displays.init.errorContainer.innerHTML = `<p class="red-text">`
+ `<i class="material-icons tiny">error</i>${errorText}</p>`;
}
if (client.displays.init != undefined) {
client.displays.init.setVisibilityByStatus('error');
}
console.error(`corpus_analysis_init: ${errorText}`);
}
});
}
/**
* Recieves the query process status before any actual results are being
* transmitted. So it recieves error codes if a query failed or
* was invalid etc.
*/
function recieveQueryStatus(client) {
client.socket.on('corpus_analysis_query', (response) => {
console.group('corpus_analysis_query: Client recieving query process',
'status via socket.on');
console.info(response);
console.groupEnd();
});
}
/**
* Recieves the query data from the request and handles it.
*/
function recieveQueryData(client) {
client.socket.on('corpus_analysis_query_results', (response) => {
console.group('corpus_analysis_query_results: Client recieving query',
'data via socket.on');
console.info(response);
console.groupEnd();
});
}
// export listeners from this module
export {recieveSession, recieveQueryStatus, recieveQueryData};

View File

@ -67,11 +67,20 @@
<!-- import modules --> <!-- import modules -->
<script type="module"> <script type="module">
// ### First Phase: document content is loaded and scripts are run ### /**
* First Phase:
* document content is loaded and scripts are being imported and executed
*/
import {CorpusAnalysisClient, import {CorpusAnalysisClient,
CorpusAnalysisDisplay} from "../../static/js/modules/nopaque.CorpusAnalysisClient.js"; CorpusAnalysisDisplay,
SocketEventListener} from '../../static/js/modules/nopaque.CorpusAnalysisClient.js';
import {recieveSession, recieveQueryStatus,
recieveQueryData} from '../../static/js/modules/nopaque.listenerFunctions.js'
// ### Second Phase: asynchronous and event-driven ### /**
* Second Phase:
* Asynchronus and event driven code
*/
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
// init some modals // init some modals
const initLoadingElement = document.getElementById("init-display"); const initLoadingElement = document.getElementById("init-display");
@ -81,12 +90,48 @@
const initLoadingDisplay = new CorpusAnalysisDisplay(initLoadingModal); const initLoadingDisplay = new CorpusAnalysisDisplay(initLoadingModal);
// set up CorpusAnalysisClient // set up CorpusAnalysisClient
const client = new CorpusAnalysisClient({{ corpus_id }}, nopaque.socket); const client = new CorpusAnalysisClient({{ corpus_id }}, nopaque.socket);
console.info("CorpusAnalysisClient created as client:", client);
// register display elements to client // register display elements to client
client.setDisplay("init", initLoadingDisplay); client.setDisplay("init", initLoadingDisplay);
// register listeners and load them
const listenForSession = new SocketEventListener('corpus_analysis_init',
recieveSession);
const listenForQueryStatus = new SocketEventListener('corpus_analysis_query',
recieveQueryStatus);
const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
recieveQueryData);
client.setSocketEventListeners([listenForSession, listenForQueryStatus,
listenForQueryData]);
client.loadListeners();
// Session initialization // Session initialization
console.log("CorpusAnalysisClient created as client:", client); client.requestSession();
client.initSession(); // send a query and recieve its answer data
let queryFormElement = document.getElementById("query-form");
queryFormElement.addEventListener("submit", (event) => {
try {
/**
* Selects first page of result list if pagination is already available
* from an query submitted before.
* This avoids confusion for the user e.g.: The user was on page 24
* reviewing the results and issues a new query. He would not see any
* results until the new results reach page 24 or he clicks on another
* valid result page element from the new pagination.
*/
let xpath = '//a[@class="page" and text()=1]';
let firstPageElement = document.evaluate(xpath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null).singleNodeValue;
firstPageElement.click();
} catch (e) {
}
// Prevent page from reloading on submit
event.preventDefault();
// Get query string and send query to server
// results.data.getQueryStr(queryFormElement);
client.requestQueryData('"this" []* "that" within 10 words;');
});
}); });
</script> </script>
{% endblock %} {% endblock %}