mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	Remove asynch rework because it was already event driven
This commit is contained in:
		@@ -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 {
 | 
			
		||||
  constructor(corpusId, socket) {
 | 
			
		||||
  constructor(corpusId, socket, logging=false) {
 | 
			
		||||
    this.corpusId = corpusId;
 | 
			
		||||
    this.socket = socket;
 | 
			
		||||
    this.displays = {};
 | 
			
		||||
    this.logging = logging;
 | 
			
		||||
    this.socket = socket;
 | 
			
		||||
    this.socketEventListeners = {};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setDisplay(type, display) {
 | 
			
		||||
    this.displays[type] = display;
 | 
			
		||||
  // Registers one or more SocketEventListeners to the CorpusAnalysisClient.
 | 
			
		||||
  setSocketEventListeners(socketEventListeners) {
 | 
			
		||||
    for (let listener of socketEventListeners) {
 | 
			
		||||
      this.socketEventListeners[listener.type] = listener.listenerFunction;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async initSession() {
 | 
			
		||||
    let request = await this.requestSession();
 | 
			
		||||
    let recvieveSession = await this.recvieveSession();
 | 
			
		||||
    console.log("corpus_analysis_init: Waiting for response");  // this happens inbetween the two functions above
 | 
			
		||||
  loadListeners() {
 | 
			
		||||
    for (let [type, listener] of Object.entries(this.socketEventListeners)) {
 | 
			
		||||
      listener(this);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  requestSession() { // should be private with ES2020
 | 
			
		||||
    console.log("corpus_analysis_init: Emitting to server");
 | 
			
		||||
  // Registers a CorpusAnalysisDisplay object to the CorpusAnalysisClient.
 | 
			
		||||
  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) {
 | 
			
		||||
      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);
 | 
			
		||||
        resolve();
 | 
			
		||||
    })
 | 
			
		||||
    this.socket.emit('corpus_analysis_init', this.corpusId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  recvieveSession() { // should be private with ES2020
 | 
			
		||||
    this.socket.on("corpus_analysis_init", (response) => {
 | 
			
		||||
      console.log("corpus_analysis_init: Recieving response from server");
 | 
			
		||||
      if (response.code === 200) {
 | 
			
		||||
        console.log("corpus_analysis_init: Initialization succeeded");
 | 
			
		||||
        if (this.displays.init != undefined) {
 | 
			
		||||
          this.displays.init.element.M_Modal.close();
 | 
			
		||||
          this.displays.init.setVisibilityByStatus("success");
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        let errorText = `Error ${response.code} - ${response.msg}`;
 | 
			
		||||
        if (this.displays.init.errorContainer != undefined)  {
 | 
			
		||||
          this.displays.init.errorContainer.innerHTML = `<p class="red-text">` +
 | 
			
		||||
                   `<i class="material-icons tiny">error</i> ${errorText}</p>`;
 | 
			
		||||
        }
 | 
			
		||||
        if (this.displays.init != undefined)  {
 | 
			
		||||
          this.displays.init.setVisibilityByStatus("error");
 | 
			
		||||
        }
 | 
			
		||||
        console.error(`corpus_analysis_init: ${errorText}`);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  // /**
 | 
			
		||||
  //  * Sends a query to the server and handles the response to that query.
 | 
			
		||||
  //  * This function uses helper functions.
 | 
			
		||||
  //  */
 | 
			
		||||
  // query(queryStr) {
 | 
			
		||||
  //   let requestQueryData = this.requestQueryData(queryStr);
 | 
			
		||||
  //   let recieveQueryProcessStatus = this.recieveQueryProcessStatus();
 | 
			
		||||
  //   let recieveQueryData = this.recieveQueryData();
 | 
			
		||||
  //   console.info('corpus_analysis_query: Client waiting for query data');  // this happens inbetween the two functions above
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sends the query string to the server.
 | 
			
		||||
   * Should be a private method if ES2020 is finalized (Maybe?)
 | 
			
		||||
   */
 | 
			
		||||
  requestQueryData(queryStr) {
 | 
			
		||||
    console.info('corpus_analysis_query: Client requesting query data via',
 | 
			
		||||
                 'socket.emit for the query', queryStr);
 | 
			
		||||
    // 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 {
 | 
			
		||||
  constructor(element) {
 | 
			
		||||
    // with this function initalized modals can also be handeld
 | 
			
		||||
    this.element = (() => {if (element instanceof HTMLElement) {
 | 
			
		||||
                            return element;
 | 
			
		||||
                          } else {
 | 
			
		||||
                            element = element["$el"][0];
 | 
			
		||||
                            element = element['$el'][0];
 | 
			
		||||
                            return element;
 | 
			
		||||
                          }
 | 
			
		||||
    })(); // with this function modals can also be handeld
 | 
			
		||||
    this.errorContainer = element.querySelector(".error-container");
 | 
			
		||||
    this.showOnError = element.querySelectorAll(".show-on-error");
 | 
			
		||||
    this.showOnSuccess = element.querySelectorAll(".show-on-success");
 | 
			
		||||
    this.showWhileWaiting = element.querySelectorAll(".show-while-waiting");
 | 
			
		||||
    this.hideOnComplete = element.querySelectorAll(".hide-on-complete")
 | 
			
		||||
    })();
 | 
			
		||||
    this.errorContainer = element.querySelector('.error-container');
 | 
			
		||||
    this.showOnError = element.querySelectorAll('.show-on-error');
 | 
			
		||||
    this.showOnSuccess = element.querySelectorAll('.show-on-success');
 | 
			
		||||
    this.showWhileWaiting = element.querySelectorAll('.show-while-waiting');
 | 
			
		||||
    this.hideOnComplete = element.querySelectorAll('.hide-on-complete')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Changes the visibility of its own
 | 
			
		||||
  setVisibilityByStatus(status) {
 | 
			
		||||
    switch (status) {
 | 
			
		||||
      case "error":
 | 
			
		||||
      case 'error':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.remove("hide");
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case "success":
 | 
			
		||||
      case 'success':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.remove("hide");
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case "waiting":
 | 
			
		||||
      case 'waiting':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.remove("hide");
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        // Hide all
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add("hide");
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        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};
 | 
			
		||||
							
								
								
									
										60
									
								
								web/app/static/js/modules/nopaque.listenerFunctions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								web/app/static/js/modules/nopaque.listenerFunctions.js
									
									
									
									
									
										Normal 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};
 | 
			
		||||
@@ -67,11 +67,20 @@
 | 
			
		||||
 | 
			
		||||
<!-- import modules -->
 | 
			
		||||
<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,
 | 
			
		||||
          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", () => {
 | 
			
		||||
    // init some modals
 | 
			
		||||
    const initLoadingElement = document.getElementById("init-display");
 | 
			
		||||
@@ -81,12 +90,48 @@
 | 
			
		||||
    const initLoadingDisplay = new CorpusAnalysisDisplay(initLoadingModal);
 | 
			
		||||
    // set up CorpusAnalysisClient
 | 
			
		||||
    const client = new CorpusAnalysisClient({{ corpus_id }}, nopaque.socket);
 | 
			
		||||
    console.info("CorpusAnalysisClient created as client:", client);
 | 
			
		||||
    // register display elements to client
 | 
			
		||||
    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
 | 
			
		||||
    console.log("CorpusAnalysisClient created as client:", client);
 | 
			
		||||
    client.initSession();
 | 
			
		||||
 | 
			
		||||
    client.requestSession();
 | 
			
		||||
    // 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>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user