mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	first change with new MVCish pattern
This commit is contained in:
		@@ -30,7 +30,7 @@ def init_corpus_analysis(corpus_id):
 | 
			
		||||
                                   corpus_id, current_user.id, request.sid)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@socketio.on('corpus_analysis_get_meta_data')
 | 
			
		||||
@socketio.on('corpus_analysis_meta_data')
 | 
			
		||||
@socketio_login_required
 | 
			
		||||
def corpus_analysis_get_meta_data(corpus_id):
 | 
			
		||||
    # get meta data from db
 | 
			
		||||
@@ -69,7 +69,7 @@ def corpus_analysis_get_meta_data(corpus_id):
 | 
			
		||||
    payload = metadata
 | 
			
		||||
    response = {'code': 200, 'desc': 'Corpus meta data', 'msg': 'OK',
 | 
			
		||||
                'payload': payload}
 | 
			
		||||
    socketio.emit('corpus_analysis_send_meta_data', response, room=request.sid)
 | 
			
		||||
    socketio.emit('corpus_analysis_meta_data', response, room=request.sid)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@socketio.on('corpus_analysis_query')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This class is used to create a Client 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, if it dynamicMode is true.
 | 
			
		||||
 * It communicates with the server (e.g. connection or query)
 | 
			
		||||
 * and recieves data from it, if dynamicMode is true.
 | 
			
		||||
 * If dynamicMode is false, the client can also handle data that is already
 | 
			
		||||
 * loaded and not coming in in chunks.
 | 
			
		||||
 * loaded and is not coming in in chunks.
 | 
			
		||||
 */
 | 
			
		||||
class Client {
 | 
			
		||||
  constructor({corpusId = null,
 | 
			
		||||
@@ -12,16 +12,18 @@ class Client {
 | 
			
		||||
               logging = true,
 | 
			
		||||
               dynamicMode = true} = {}) {
 | 
			
		||||
    this.corpusId = corpusId;
 | 
			
		||||
    this.displays = {};
 | 
			
		||||
    this.dynamicMode = dynamicMode;
 | 
			
		||||
    this.logging = logging;
 | 
			
		||||
    this.requestQueryProgress = 0;
 | 
			
		||||
    this.results = undefined;  // holds the results object later on
 | 
			
		||||
    this.socket = socket;
 | 
			
		||||
    this.socketEventListeners = {};
 | 
			
		||||
    this.recivedMetaData = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Disable all console logging.
 | 
			
		||||
     * This is global. So every other log message in every other Class or
 | 
			
		||||
     * function used in conjunction with the client either logs or does not
 | 
			
		||||
     * log depending on the logging flag.
 | 
			
		||||
     * Credits to https://gist.github.com/kmonsoor/0244fdb4ad79a4826371e58a1a5fa984
 | 
			
		||||
     */
 | 
			
		||||
    if (!logging) {
 | 
			
		||||
@@ -37,6 +39,7 @@ class Client {
 | 
			
		||||
        });
 | 
			
		||||
      })();
 | 
			
		||||
    }
 | 
			
		||||
    console.info("Client initialized:", this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Registers one or more SocketEventListeners to the Client.
 | 
			
		||||
@@ -56,10 +59,10 @@ class Client {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // TODO: get rid of this disply stuff and send commands to the viewer
 | 
			
		||||
  // on what to do/show/hide etc
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * This functions sends events to the View to trigger specific functions that
 | 
			
		||||
   * are handleing the represnetation of data stored in the model.
 | 
			
		||||
   */
 | 
			
		||||
  notifyView(SendWhatToDo) {
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
@@ -108,6 +111,12 @@ class Client {
 | 
			
		||||
    this.socket.emit('corpus_analysis_init', this.corpusId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getMetaData() {
 | 
			
		||||
    console.info('corpus_analysis_meta_data: Client getting meta data via',
 | 
			
		||||
                 'socket.emit.');
 | 
			
		||||
    this.socket.emit('corpus_analysis_meta_data', this.corpusId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Emits query to the server via socket.io. Server will send the results
 | 
			
		||||
   * back.
 | 
			
		||||
@@ -119,80 +128,6 @@ class Client {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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];
 | 
			
		||||
                            return element;
 | 
			
		||||
                          }
 | 
			
		||||
    })();
 | 
			
		||||
    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':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case 'success':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case 'waiting':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        // Hide all
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class is used to create an SocketEventListener.
 | 
			
		||||
 * Input are an identifying type string, the listener function and callbacks
 | 
			
		||||
@@ -200,7 +135,7 @@ class CorpusAnalysisDisplay {
 | 
			
		||||
 * type string is also used as the socket event event identifier.
 | 
			
		||||
 */
 | 
			
		||||
class SocketEventListener {
 | 
			
		||||
  constructor(type, listenerFunction) {
 | 
			
		||||
  constructor(type, listenerFunction, args=null) {
 | 
			
		||||
    this.listenerCallbacks = {};
 | 
			
		||||
    this.listenerFunction = listenerFunction;
 | 
			
		||||
    this.type = type;
 | 
			
		||||
@@ -222,9 +157,10 @@ class SocketEventListener {
 | 
			
		||||
   * yield the keys in order of insertion.
 | 
			
		||||
   * So all modern Browsers.
 | 
			
		||||
   */
 | 
			
		||||
  executeCallbacks(args) {
 | 
			
		||||
  executeCallbacks(payload) {
 | 
			
		||||
    for (let [type, listenerCallback] of Object.entries(this.listenerCallbacks)) {
 | 
			
		||||
      listenerCallback.callbackFunction(...args);
 | 
			
		||||
      listenerCallback.args.unshift(payload);
 | 
			
		||||
      listenerCallback.callbackFunction(...listenerCallback.args);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -235,7 +171,8 @@ class SocketEventListener {
 | 
			
		||||
 * callback functions.
 | 
			
		||||
 */
 | 
			
		||||
class ListenerCallback {
 | 
			
		||||
  constructor(type, callbackFunction) {
 | 
			
		||||
  constructor(type, callbackFunction, argsList) {
 | 
			
		||||
    this.args = argsList;
 | 
			
		||||
    this.callbackFunction = callbackFunction;
 | 
			
		||||
    this.type = type;
 | 
			
		||||
  }
 | 
			
		||||
@@ -245,6 +182,5 @@ class ListenerCallback {
 | 
			
		||||
export {
 | 
			
		||||
  Client,
 | 
			
		||||
  SocketEventListener,
 | 
			
		||||
  CorpusAnalysisDisplay,
 | 
			
		||||
  ListenerCallback,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,9 +1,35 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This callback is called on a socket.on "corpus_analysis_send_meta_data".
 | 
			
		||||
 * Handels incoming corpus metadata
 | 
			
		||||
 */
 | 
			
		||||
function saveMetaData() {
 | 
			
		||||
  let [payload, client, results, rest] = arguments;
 | 
			
		||||
  results.metaData.init(payload)
 | 
			
		||||
  client.recivedMetaData = true;
 | 
			
		||||
  console.info('Metada saved:', results.metaData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This callback should be registered to the SocketEventListener 'recieveQueryStatus'.
 | 
			
		||||
 * It just gets the incoming status data of the issued query
 | 
			
		||||
 * and does some preperation work like hiding or showing elements and deleting
 | 
			
		||||
 * the data from the last query.
 | 
			
		||||
 */
 | 
			
		||||
function prepareQueryData() {
 | 
			
		||||
  // deletes old data from query issued before this new query
 | 
			
		||||
  let [payload, client, results, rest] = arguments;
 | 
			
		||||
  results.init();
 | 
			
		||||
  client.requestQueryProgress = 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function saveQueryData(args) {
 | 
			
		||||
  let [payload, client, results, rest] = arguments;
 | 
			
		||||
  results.data.addData(payload);
 | 
			
		||||
  client.requestQueryProgress = payload.progress;
 | 
			
		||||
  console.info('Query data chunk saved', results.data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function querySetup(payload, client) {
 | 
			
		||||
  // deletes old data from query issued before this new query
 | 
			
		||||
  client.results.clearAll();
 | 
			
		||||
@@ -12,7 +38,6 @@ function querySetup(payload, client) {
 | 
			
		||||
                          '#recieved-match-count', '#total-match-count',
 | 
			
		||||
                          '#text-lookup-count', '#text-lookup-titles',
 | 
			
		||||
                          '#query-results-create', '#add-to-sub-results']);
 | 
			
		||||
  client.requestQueryProgress = 0;
 | 
			
		||||
  client.recievedMatchCount.textContent = 0;
 | 
			
		||||
  client.totalMatchCount.textContent = `${payload.match_count}`;
 | 
			
		||||
  client.queryResultsUserFeedback.classList.toggle('hide');
 | 
			
		||||
@@ -117,4 +142,4 @@ function helperQueryRenderResults (payload, client) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// export callbacks
 | 
			
		||||
export { querySetup, queryRenderResults };
 | 
			
		||||
export { prepareQueryData, saveMetaData, saveQueryData };
 | 
			
		||||
@@ -1,40 +1,57 @@
 | 
			
		||||
import { querySetup, queryRenderResults } from './nopaque.listenerCallbacks.js'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Recieves a corpus analysis session via socket.io.
 | 
			
		||||
 * Closes the loading modal that has been opend with requestSession at the
 | 
			
		||||
 * start of the request.
 | 
			
		||||
 * Recieves a corpus analysis connected signal via socket.io.
 | 
			
		||||
 */
 | 
			
		||||
function recieveSession(type, client) {
 | 
			
		||||
function recieveConnected(type, client) {
 | 
			
		||||
  client.socket.on(type, (response) => {
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if request for session was OK.
 | 
			
		||||
     * If OK execute callbacks and hide/show displays.
 | 
			
		||||
     * If OK execute registered callbacks and notify View.
 | 
			
		||||
     */
 | 
			
		||||
    console.group('recieve session')
 | 
			
		||||
    if (response.code === 200) {
 | 
			
		||||
      console.info('corpus_analysis_init: Client recieving session/or error',
 | 
			
		||||
      console.group('Connected!')
 | 
			
		||||
      console.info('corpus_analysis_init: Client recieving connected codes',
 | 
			
		||||
                   'codes via socket.on');
 | 
			
		||||
      console.info(`corpus_analysis_init: ${response.code} - ${response.msg}`);
 | 
			
		||||
      console.info('corpus_analysis_init: Initialization succeeded');
 | 
			
		||||
      console.info(response);
 | 
			
		||||
      // Handling hide/show of displays
 | 
			
		||||
      if (client.displays.init != undefined) {
 | 
			
		||||
        client.displays.init.element.M_Modal.close();
 | 
			
		||||
        client.displays.init.setVisibilityByStatus('success');
 | 
			
		||||
      }
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
      // get meta data immediately
 | 
			
		||||
      client.getMetaData();
 | 
			
		||||
    } 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.group('Connection failed!')
 | 
			
		||||
      console.error(`corpus_analysis_init: ${errorText}`);
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Recieves meta data from the server via socket.io.
 | 
			
		||||
 */
 | 
			
		||||
function recieveMetaData(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 meta data')
 | 
			
		||||
      console.info('corpus_analysis_meta_data: Client recieving meta data',
 | 
			
		||||
      'via socket.on');
 | 
			
		||||
      console.info(`corpus_analysis_meta_data: ${response.code} - ${response.msg}`);
 | 
			
		||||
      console.info(response);
 | 
			
		||||
      // executing the registered callbacks
 | 
			
		||||
      client.socketEventListeners[type].executeCallbacks(response.payload);
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    } else {
 | 
			
		||||
      console.group('Failed to recieve meta data.');
 | 
			
		||||
      console.error('corpus_analysis_meta_data: Client failed to recieve',
 | 
			
		||||
                    'meta data via socket.on');
 | 
			
		||||
      let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
 | 
			
		||||
      console.error(`corpus_analysis_meta_data: ${errorText}`);
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    }
 | 
			
		||||
    console.groupEnd();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -47,36 +64,27 @@ function recieveSession(type, client) {
 | 
			
		||||
function recieveQueryStatus(type, client) {
 | 
			
		||||
  client.socket.on(type, (response) => {
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if issued query was OK.
 | 
			
		||||
     * If OK execute registered callbacks and hide/show displays.
 | 
			
		||||
     * Check if request for session was OK.
 | 
			
		||||
     * If OK execute registered callbacks and notify View.
 | 
			
		||||
     */
 | 
			
		||||
    console.group('corpus_analysis_query: Client recieving query process',
 | 
			
		||||
                  'status via socket.on');
 | 
			
		||||
    if (response.code === 200) {
 | 
			
		||||
      console.group('corpus_analysis_query: Client recieving query process',
 | 
			
		||||
      'status via socket.on');
 | 
			
		||||
      console.info(`corpus_analysis_query: ${response.code} - ${response.msg}`);
 | 
			
		||||
      console.info(response);
 | 
			
		||||
      // Handling hide/show of displays
 | 
			
		||||
      if (client.displays.query != undefined)  {
 | 
			
		||||
        client.displays.query.setVisibilityByStatus("success");
 | 
			
		||||
      }
 | 
			
		||||
      // executing the registered callbacks
 | 
			
		||||
      client.socketEventListeners[type].executeCallbacks([response.payload, client]);
 | 
			
		||||
      client.socketEventListeners[type].executeCallbacks(response.payload);
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    } else {
 | 
			
		||||
      console.group('corpus_analysis_query: Client failed recieving',
 | 
			
		||||
                    'query process status via socket.on');
 | 
			
		||||
      let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
 | 
			
		||||
      if (response.payload.code == 1281) {
 | 
			
		||||
        errorText += ' - Invalid Query';
 | 
			
		||||
      }
 | 
			
		||||
      nopaque.flash(errorText, "error");
 | 
			
		||||
      if (client.displays.query.errorContainer != undefined)  {
 | 
			
		||||
        client.displays.query.errorContainer.innerHTML = `<p class="red-text">`+
 | 
			
		||||
                  `<i class="material-icons tiny">error</i> ${errorText}</p>`;
 | 
			
		||||
      }
 | 
			
		||||
      if (client.displays.query != undefined)  {
 | 
			
		||||
        client.displays.query.setVisibilityByStatus("error");
 | 
			
		||||
      }
 | 
			
		||||
      console.error(`corpus_analysis_query: ${errorText}`);
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    }
 | 
			
		||||
    console.groupEnd();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -84,24 +92,43 @@ function recieveQueryStatus(type, client) {
 | 
			
		||||
 * Recieves the query data from the request and handles it.
 | 
			
		||||
 */
 | 
			
		||||
function recieveQueryData(type, client) {
 | 
			
		||||
  console.group('corpus_analysis_query_results: Client recieving or loading',
 | 
			
		||||
                'query data.');
 | 
			
		||||
  /**
 | 
			
		||||
   * Check if request for session was OK.
 | 
			
		||||
   * If OK execute registered callbacks and notify View.
 | 
			
		||||
   */
 | 
			
		||||
  if (client.dynamicMode) {
 | 
			
		||||
    console.info('Client recieving query data via socket.on');
 | 
			
		||||
    client.socket.on(type, (response) => {
 | 
			
		||||
    console.info('Recieved chunk', response);
 | 
			
		||||
    // executing the registered callbacks
 | 
			
		||||
    client.socketEventListeners[type].executeCallbacks([response.payload, client]);
 | 
			
		||||
    console.info('Added chunk data to results.data and rendered it with',
 | 
			
		||||
                 'results.jsList');
 | 
			
		||||
    if (response.code === 200) {
 | 
			
		||||
      console.group('corpus_analysis_query_results: Recieveing query data')
 | 
			
		||||
      console.info('Client recieving query data via socket.on');
 | 
			
		||||
      console.info('Recieved chunk', response);
 | 
			
		||||
      /**
 | 
			
		||||
       * Execute registered callbacks and notify View.
 | 
			
		||||
       */
 | 
			
		||||
      client.socketEventListeners[type].executeCallbacks(response.payload);
 | 
			
		||||
      console.info('Added chunk data to results.data.');
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    } else {
 | 
			
		||||
      console.group('corpus_analysis_query_results: Client failed recieving',
 | 
			
		||||
                    'the results via socket.on');
 | 
			
		||||
      let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
 | 
			
		||||
      console.error(`corpus_analysis_query: ${errorText}`);
 | 
			
		||||
      console.groupEnd();
 | 
			
		||||
    }
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    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.results.data, client]);
 | 
			
		||||
    client.socketEventListeners[type].executeCallbacks();
 | 
			
		||||
    console.groupEnd();
 | 
			
		||||
  }
 | 
			
		||||
  console.groupEnd();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// export listeners from this module
 | 
			
		||||
export { recieveSession, recieveQueryStatus, recieveQueryData };
 | 
			
		||||
export {
 | 
			
		||||
  recieveConnected,
 | 
			
		||||
  recieveMetaData,
 | 
			
		||||
  recieveQueryStatus,
 | 
			
		||||
  recieveQueryData
 | 
			
		||||
};
 | 
			
		||||
@@ -5,17 +5,15 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class Results {
 | 
			
		||||
  constructor(data, jsList , metaData) {
 | 
			
		||||
  this.data = data;
 | 
			
		||||
  this.jsList = jsList;
 | 
			
		||||
  this.metaData = metaData
 | 
			
		||||
  constructor() {
 | 
			
		||||
  this.data = new Data();
 | 
			
		||||
  this.metaData = new MetaData();
 | 
			
		||||
  this.resultsData = new Data();
 | 
			
		||||
  this.subResultsData = new Data();
 | 
			
		||||
  console.info('Initialized the Results object.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clearAll() {
 | 
			
		||||
    this.jsList.clear();
 | 
			
		||||
    this.jsList.update();
 | 
			
		||||
  init() {
 | 
			
		||||
    this.data.init();
 | 
			
		||||
    this.metaData.init();
 | 
			
		||||
    this.resultsData.init()
 | 
			
		||||
@@ -28,7 +26,7 @@ class Results {
 | 
			
		||||
class Data {
 | 
			
		||||
  // Sets empty object structure. Also usefull to delete old results.
 | 
			
		||||
  // matchCount default is 0
 | 
			
		||||
  init(matchCount = 0, type = "results") {
 | 
			
		||||
  init(matchCount=0, type="results") {
 | 
			
		||||
    this.matches = [];  // list of all c with lc and rc
 | 
			
		||||
    this.cpos_lookup = {};  // object contains all this key value pair
 | 
			
		||||
    this.text_lookup = {};  // same as above for all text ids
 | 
			
		||||
@@ -125,7 +123,7 @@ class Data {
 | 
			
		||||
class MetaData {
 | 
			
		||||
  // Sets empty object structure when no input is given.
 | 
			
		||||
  // if json object like input is given class fields are created from this
 | 
			
		||||
  init(json = {}) {
 | 
			
		||||
  init(json={}) {
 | 
			
		||||
    Object.assign(this, json);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								web/app/static/js/modules/corpus_analysis/view/Display.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								web/app/static/js/modules/corpus_analysis/view/Display.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This class is used to create an Display object.
 | 
			
		||||
 * Input is one HTMLElement that can then be hidden or shown depending on
 | 
			
		||||
 * its CSS classes.
 | 
			
		||||
 */
 | 
			
		||||
class Display {
 | 
			
		||||
  constructor(element) {
 | 
			
		||||
    // with this function initalized modals can also be handeld
 | 
			
		||||
    this.element = (() => {if (element instanceof HTMLElement) {
 | 
			
		||||
                            return element;
 | 
			
		||||
                          } else {
 | 
			
		||||
                            element = element['$el'][0];
 | 
			
		||||
                            return element;
 | 
			
		||||
                          }
 | 
			
		||||
    })();
 | 
			
		||||
    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':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case 'success':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case 'waiting':
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.remove('hide');
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        // Hide all
 | 
			
		||||
        for (let element of this.showOnError) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showOnSuccess) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
        for (let element of this.showWhileWaiting) {
 | 
			
		||||
          element.classList.add('hide');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -65,7 +65,102 @@
 | 
			
		||||
{% include 'modals/export_query_results.html.j2' %}
 | 
			
		||||
{% include 'modals/context_modal.html.j2' %}
 | 
			
		||||
 | 
			
		||||
<script type="text/javascript"
 | 
			
		||||
        src="web/app/static/js/modules/corpus_analysis/main.js">
 | 
			
		||||
<!-- import modules -->
 | 
			
		||||
<script type="module">
 | 
			
		||||
/**
 | 
			
		||||
 * First Phase:
 | 
			
		||||
 * Document content is loaded and scripts are being imported and executed.
 | 
			
		||||
 */
 | 
			
		||||
import {
 | 
			
		||||
  Client,
 | 
			
		||||
  SocketEventListener,
 | 
			
		||||
  ListenerCallback,
 | 
			
		||||
} from '../../static/js/modules/corpus_analysis/client/Client.js';
 | 
			
		||||
import {
 | 
			
		||||
  recieveConnected,
 | 
			
		||||
  recieveMetaData,
 | 
			
		||||
  recieveQueryStatus,
 | 
			
		||||
  recieveQueryData,
 | 
			
		||||
} from '../../static/js/modules/corpus_analysis/client/listeners.js';
 | 
			
		||||
import {
 | 
			
		||||
  Results,
 | 
			
		||||
} from '../../static/js/modules/corpus_analysis/model/Results.js';
 | 
			
		||||
import {
 | 
			
		||||
  prepareQueryData,
 | 
			
		||||
  saveQueryData,
 | 
			
		||||
  saveMetaData,
 | 
			
		||||
} from '../../static/js/modules/corpus_analysis/client/callbacks.js';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Second Phase:
 | 
			
		||||
 * Asynchronus and event driven code
 | 
			
		||||
 */
 | 
			
		||||
document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
  // Initialize the client for server client communication in dynamic mode
 | 
			
		||||
  let corpusId = {{ corpus_id }}
 | 
			
		||||
  const client = new Client({'corpusId': corpusId,
 | 
			
		||||
                             'socket': nopaque.socket,
 | 
			
		||||
                             'logging': true,
 | 
			
		||||
                             'dynamicMode': true});
 | 
			
		||||
  /**
 | 
			
		||||
  * Initializing the results object as a model holding all the data of a query.
 | 
			
		||||
  * Also holds the metadata of one query.
 | 
			
		||||
  */
 | 
			
		||||
  let results = new Results();
 | 
			
		||||
  /**
 | 
			
		||||
  * Register listeners listening to socket.io events and their callbacks
 | 
			
		||||
  * Afterwards load them.
 | 
			
		||||
  */
 | 
			
		||||
  const listenForConnected = new SocketEventListener('corpus_analysis_init',
 | 
			
		||||
                                                     recieveConnected);
 | 
			
		||||
  const listenForMetaData = new SocketEventListener('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',
 | 
			
		||||
                                                       recieveQueryStatus);
 | 
			
		||||
  const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
 | 
			
		||||
                                                   prepareQueryData,
 | 
			
		||||
                                                   [client, results]);
 | 
			
		||||
  listenForQueryStatus.setCallbacks([queryStatusCallback]);
 | 
			
		||||
  const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
 | 
			
		||||
                                                     recieveQueryData);
 | 
			
		||||
  const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
 | 
			
		||||
                                                 saveQueryData,
 | 
			
		||||
                                                 [client, results]);
 | 
			
		||||
  listenForQueryData.setCallbacks([queryDataCallback]);
 | 
			
		||||
  client.setSocketEventListeners([listenForConnected,
 | 
			
		||||
                                  listenForQueryStatus,
 | 
			
		||||
                                  listenForQueryData,
 | 
			
		||||
                                  listenForMetaData]);
 | 
			
		||||
  client.loadSocketEventListeners();
 | 
			
		||||
  // Connect client to server
 | 
			
		||||
  client.connect();
 | 
			
		||||
  // 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 firstPageElement = document.querySelector('a.page');
 | 
			
		||||
      firstPageElement.click();
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      // No page element is present if first query is submitted.
 | 
			
		||||
    }
 | 
			
		||||
    // Prevent page from reloading on submit
 | 
			
		||||
    event.preventDefault();
 | 
			
		||||
    // Get query string and send query to server
 | 
			
		||||
    results.data.getQueryStr(queryFormElement);
 | 
			
		||||
    client.query(results.data.query);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user