mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	Progress on list rework
This commit is contained in:
		@@ -27,13 +27,13 @@ nopaque.socket = io({transports: ['websocket']});
 | 
			
		||||
nopaque.socket.on("user_data_stream_init", function(msg) {
 | 
			
		||||
  nopaque.user = JSON.parse(msg);
 | 
			
		||||
  for (let subscriber of nopaque.corporaSubscribers) {
 | 
			
		||||
    subscriber._init(nopaque.user.corpora);
 | 
			
		||||
    subscriber.init(nopaque.user.corpora);
 | 
			
		||||
  }
 | 
			
		||||
  for (let subscriber of nopaque.jobsSubscribers) {
 | 
			
		||||
    subscriber._init(nopaque.user.jobs);
 | 
			
		||||
    subscriber.init(nopaque.user.jobs);
 | 
			
		||||
  }
 | 
			
		||||
  for (let subscriber of nopaque.queryResultsSubscribers) {
 | 
			
		||||
    subscriber._init(nopaque.user.query_results);
 | 
			
		||||
    subscriber.init(nopaque.user.query_results);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -46,13 +46,13 @@ nopaque.socket.on("user_data_stream_update", function(msg) {
 | 
			
		||||
  jobs_patch = patch.filter(operation => operation.path.startsWith("/jobs"));
 | 
			
		||||
  query_results_patch = patch.filter(operation => operation.path.startsWith("/query_results"));
 | 
			
		||||
  for (let subscriber of nopaque.corporaSubscribers) {
 | 
			
		||||
    subscriber._update(corpora_patch);
 | 
			
		||||
    subscriber.update(corpora_patch);
 | 
			
		||||
  }
 | 
			
		||||
  for (let subscriber of nopaque.jobsSubscribers) {
 | 
			
		||||
    subscriber._update(jobs_patch);
 | 
			
		||||
    subscriber.update(jobs_patch);
 | 
			
		||||
  }
 | 
			
		||||
  for (let subscriber of nopaque.queryResultsSubscribers) {
 | 
			
		||||
    subscriber._update(query_results_patch);
 | 
			
		||||
    subscriber.update(query_results_patch);
 | 
			
		||||
  }
 | 
			
		||||
  if (["all", "end"].includes(nopaque.user.settings.job_status_site_notifications)) {
 | 
			
		||||
    for (operation of jobs_patch) {
 | 
			
		||||
@@ -69,13 +69,13 @@ nopaque.socket.on("user_data_stream_update", function(msg) {
 | 
			
		||||
nopaque.socket.on("foreign_user_data_stream_init", function(msg) {
 | 
			
		||||
  nopaque.foreignUser = JSON.parse(msg);
 | 
			
		||||
  for (let subscriber of nopaque.foreignCorporaSubscribers) {
 | 
			
		||||
    subscriber._init(nopaque.foreignUser.corpora);
 | 
			
		||||
    subscriber.init(nopaque.foreignUser.corpora);
 | 
			
		||||
  }
 | 
			
		||||
  for (let subscriber of nopaque.foreignJobsSubscribers) {
 | 
			
		||||
    subscriber._init(nopaque.foreignUser.jobs);
 | 
			
		||||
    subscriber.init(nopaque.foreignUser.jobs);
 | 
			
		||||
  }
 | 
			
		||||
  for (let subscriber of nopaque.foreignQueryResultsSubscribers) {
 | 
			
		||||
    subscriber._init(nopaque.foreignUser.query_results);
 | 
			
		||||
    subscriber.init(nopaque.foreignUser.query_results);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -87,9 +87,9 @@ nopaque.socket.on("foreign_user_data_stream_update", function(msg) {
 | 
			
		||||
  corpora_patch = patch.filter(operation => operation.path.startsWith("/corpora"));
 | 
			
		||||
  jobs_patch = patch.filter(operation => operation.path.startsWith("/jobs"));
 | 
			
		||||
  query_results_patch = patch.filter(operation => operation.path.startsWith("/query_results"));
 | 
			
		||||
  for (let subscriber of nopaque.foreignCorporaSubscribers) {subscriber._update(corpora_patch);}
 | 
			
		||||
  for (let subscriber of nopaque.foreignJobsSubscribers) {subscriber._update(jobs_patch);}
 | 
			
		||||
  for (let subscriber of nopaque.foreignQueryResultsSubscribers) {subscriber._update(query_results_patch);}
 | 
			
		||||
  for (let subscriber of nopaque.foreignCorporaSubscribers) {subscriber.update(corpora_patch);}
 | 
			
		||||
  for (let subscriber of nopaque.foreignJobsSubscribers) {subscriber.update(jobs_patch);}
 | 
			
		||||
  for (let subscriber of nopaque.foreignQueryResultsSubscribers) {subscriber.update(query_results_patch);}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
nopaque.Forms = {};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,420 +1,140 @@
 | 
			
		||||
class RessourceList extends List {
 | 
			
		||||
  constructor(idOrElement, subscriberList, type, options) {
 | 
			
		||||
    if (!type || !["Corpus", "CorpusFile", "Job", "JobInput", "QueryResult", "User"].includes(type)) {
 | 
			
		||||
      throw "Unknown Type!";
 | 
			
		||||
    }
 | 
			
		||||
    super(idOrElement, {...RessourceList.options['common'],
 | 
			
		||||
                        ...RessourceList.options[type],
 | 
			
		||||
                        ...(options ? options : {})});
 | 
			
		||||
    if (subscriberList) {subscriberList.push(this);}
 | 
			
		||||
    this.type = type;
 | 
			
		||||
class RessourceList {
 | 
			
		||||
  constructor(idOrElement, options = {}) {
 | 
			
		||||
    this.list = new List(idOrElement, {...RessourceList.options, ...options});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  init(ressources) {
 | 
			
		||||
    this.list.clear();
 | 
			
		||||
    this.add(Object.values(ressources));
 | 
			
		||||
    this.list.sort('id', {order: 'desc'});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  _init(ressources) {
 | 
			
		||||
    this.clear();
 | 
			
		||||
    this._add(Object.values(ressources));
 | 
			
		||||
    this.sort("id", {order: "desc"});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  _update(patch) {
 | 
			
		||||
  update(patch) {
 | 
			
		||||
    let item, pathArray;
 | 
			
		||||
 | 
			
		||||
    for (let operation of patch) {
 | 
			
		||||
      /* "/{ressourceName}/{ressourceId}/..." -> ["{ressourceId}", "..."] */
 | 
			
		||||
      pathArray = operation.path.split("/").slice(2);
 | 
			
		||||
      /*
 | 
			
		||||
       * '/{ressourceName}/{ressourceId}/{valueName}' -> ['{ressourceId}', {valueName}]
 | 
			
		||||
       * Example: '/jobs/1/status' -> ['1', 'status']
 | 
			
		||||
      */
 | 
			
		||||
      let [id, valueName] = operation.path.split("/").slice(2);
 | 
			
		||||
      switch(operation.op) {
 | 
			
		||||
        case "add":
 | 
			
		||||
          if (pathArray.includes("results")) {break;}
 | 
			
		||||
          this._add([operation.value]);
 | 
			
		||||
        case 'add':
 | 
			
		||||
          this.add(operation.value);
 | 
			
		||||
          break;
 | 
			
		||||
        case "remove":
 | 
			
		||||
          this.remove("id", pathArray[0]);
 | 
			
		||||
        case 'remove':
 | 
			
		||||
          this.remove(id);
 | 
			
		||||
          break;
 | 
			
		||||
        case 'replace':
 | 
			
		||||
          this.replace(id, valueName, operation.value);
 | 
			
		||||
          break;
 | 
			
		||||
        case "replace":
 | 
			
		||||
          item = this.get("id", pathArray[0])[0];
 | 
			
		||||
          switch(pathArray[1]) {
 | 
			
		||||
            case "status":
 | 
			
		||||
              item.values({status: operation.value,
 | 
			
		||||
                           "analyse-link": ["analysing", "prepared", "start analysis"].includes(operation.value) ? `/corpora/${pathArray[0]}/analyse` : ""});
 | 
			
		||||
              break;
 | 
			
		||||
            default:
 | 
			
		||||
              break;
 | 
			
		||||
          }
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _add(values, callback) {
 | 
			
		||||
    this.add(values.map(x => RessourceList.dataMappers[this.type](x)), callback);
 | 
			
		||||
    // Initialize modal and tooltipped elements in list
 | 
			
		||||
    M.AutoInit(this.listContainer);
 | 
			
		||||
  add(values) {
 | 
			
		||||
    /* WORKAROUND: Set a callback function ('() => {return;}') to force List.js
 | 
			
		||||
                   perform the add method asynchronous.
 | 
			
		||||
     * https://listjs.com/api/#add
 | 
			
		||||
     */
 | 
			
		||||
    this.list.add(values, () => {return;});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  remove(id) {
 | 
			
		||||
    this.list.remove('id', id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  replace(id, valueName, newValue) {
 | 
			
		||||
    if (!this.list.valuesNames.includes(valueName)) {return;}
 | 
			
		||||
    let item = this.list.get('id', id);
 | 
			
		||||
    item.values({[valueName]: newValue});
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RessourceList.options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RessourceList.dataMappers = {
 | 
			
		||||
  // A data mapper describes entitys rendered per row. One key value pair holds
 | 
			
		||||
  // the data to be rendered in the list.js table. Key has to correspond
 | 
			
		||||
  // with the ValueNames defined below in RessourceList.options ValueNames.
 | 
			
		||||
  // Links are declared with double ticks(") around them. The key for links
 | 
			
		||||
  // have to correspond with the class of an <a> element in the
 | 
			
		||||
  // RessourceList.options item blueprint.
 | 
			
		||||
class CorpusList extends RessourceList {
 | 
			
		||||
  constructor(listElementId, options = {}) {
 | 
			
		||||
    let listElement = document.querySelector(`#${listElementId}`);
 | 
			
		||||
    super(listElement, {...CorpusList.options, ...options});
 | 
			
		||||
    listElement.addEventListener('click', (event) => {
 | 
			
		||||
      let actionButtonElement = event.target.closest('.action-button');
 | 
			
		||||
      if (actionButtonElement === null) {return;}
 | 
			
		||||
      let corpusId = event.target.closest('tr').dataset.id;
 | 
			
		||||
      let action = actionButtonElement.dataset.action;
 | 
			
		||||
      switch (action) {
 | 
			
		||||
        case 'analyse':
 | 
			
		||||
          window.location.href = nopaque.user.corpora[corpusId].analysis_url;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    nopaque.corporaSubscribers.push(this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  /* ### Corpus mapper ### */
 | 
			
		||||
  Corpus: corpus => ({
 | 
			
		||||
    creation_date: corpus.creation_date,
 | 
			
		||||
    description: corpus.description,
 | 
			
		||||
    id: corpus.id,
 | 
			
		||||
    link: `/corpora/${corpus.id}`,
 | 
			
		||||
    status: corpus.status,
 | 
			
		||||
    title: corpus.title,
 | 
			
		||||
    title1: corpus.title,
 | 
			
		||||
    "analyse-link": ["analysing", "prepared", "start analysis"].includes(corpus.status) ? `/corpora/${corpus.id}/analyse` : "",
 | 
			
		||||
    "delete-link": `/corpora/${corpus.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-corpus-${corpus.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-corpus-${corpus.id}-modal`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### CorpusFile mapper ### TODO: replace delete-modal with delete-onclick */
 | 
			
		||||
  CorpusFile: corpus_file => ({
 | 
			
		||||
    author: corpus_file.author,
 | 
			
		||||
    filename: corpus_file.filename,
 | 
			
		||||
    id: corpus_file.id,
 | 
			
		||||
    link: `${corpus_file.corpus_id}/files/${corpus_file.id}`,
 | 
			
		||||
    "publishing-year": corpus_file.publishing_year,
 | 
			
		||||
    title: corpus_file.title,
 | 
			
		||||
    title1: corpus_file.title,
 | 
			
		||||
    "delete-link": `/corpora/${corpus_file.corpus_id}/files/${corpus_file.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-corpus-file-${corpus_file.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-corpus-file-${corpus_file.id}-modal`,
 | 
			
		||||
    "download-link": `${corpus_file.corpus_id}/files/${corpus_file.id}/download`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### Job mapper ### */
 | 
			
		||||
  Job: job => ({
 | 
			
		||||
    creation_date: job.creation_date,
 | 
			
		||||
    description: job.description,
 | 
			
		||||
    id: job.id,
 | 
			
		||||
    link: `/jobs/${job.id}`,
 | 
			
		||||
    service: job.service.name,
 | 
			
		||||
    status: job.status,
 | 
			
		||||
    title: job.title,
 | 
			
		||||
    title1: job.title,
 | 
			
		||||
    "delete-link": `/jobs/${job.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-job-${job.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-job-${job.id}-modal`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### JobInput mapper ### */
 | 
			
		||||
  JobInput: job_input => ({
 | 
			
		||||
    filename: job_input.filename,
 | 
			
		||||
    id: job_input.job_id,
 | 
			
		||||
    "download-link": `${job_input.job_id}/inputs/${job_input.id}/download`
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### QueryResult mapper ### */
 | 
			
		||||
  QueryResult: query_result => ({
 | 
			
		||||
    corpus_name: query_result.query_metadata.corpus_name,
 | 
			
		||||
    description: query_result.description,
 | 
			
		||||
    id: query_result.id,
 | 
			
		||||
    link: `/corpora/result/${query_result.id}`,
 | 
			
		||||
    query: query_result.query_metadata.query,
 | 
			
		||||
    title: query_result.title,
 | 
			
		||||
    "delete-link": `/corpora/result/${query_result.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-query-result-${query_result.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-query-result-${query_result.id}-modal`,
 | 
			
		||||
    "inspect-link": `/corpora/result/${query_result.id}/inspect`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### User mapper ### */
 | 
			
		||||
  User: user => ({
 | 
			
		||||
    confirmed: user.confirmed,
 | 
			
		||||
    email: user.email,
 | 
			
		||||
    id: user.id,
 | 
			
		||||
    link: `users/${user.id}`,
 | 
			
		||||
    role: user.role.name,
 | 
			
		||||
    username: user.username,
 | 
			
		||||
    username2: user.username,
 | 
			
		||||
    "delete-link": `/admin/users/${user.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-user-${user.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-user-${user.id}-modal`,
 | 
			
		||||
  }),
 | 
			
		||||
 | 
			
		||||
CorpusList.options = {
 | 
			
		||||
  item: `<tr>
 | 
			
		||||
           <td><a class="btn-floating disabled"><i class="material-icons">book</i></a></td>
 | 
			
		||||
           <td><b class="title"></b><br><i class="description"></i></td>
 | 
			
		||||
           <td><span class="badge new status" data-badge-caption=""></span></td>
 | 
			
		||||
           <td class="right-align">
 | 
			
		||||
             <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
             <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="edit" data-position="top" data-tooltip="Edit"><i class="material-icons">edit</i></a>
 | 
			
		||||
             <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="analyse" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
 | 
			
		||||
           </td>
 | 
			
		||||
         </tr>`,
 | 
			
		||||
  valueNames: [{data: ['id']}, {name: "status", attr: "data-status"}, 'description', 'title']
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RessourceList.options = {
 | 
			
		||||
  // common list.js options for 5 rows per page etc.
 | 
			
		||||
  common: {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]},
 | 
			
		||||
  // extended list.js options for 10 rows per page etc.
 | 
			
		||||
  extended: {
 | 
			
		||||
    page: 10,
 | 
			
		||||
    pagination: [
 | 
			
		||||
      {
 | 
			
		||||
        name: "paginationTop",
 | 
			
		||||
        paginationClass: "paginationTop",
 | 
			
		||||
        innerWindow: 8,
 | 
			
		||||
        outerWindow: 1
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        paginationClass: "paginationBottom",
 | 
			
		||||
        innerWindow: 8,
 | 
			
		||||
        outerWindow: 1,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  /* Type specific List.js options. Usually only "item" and "valueNames" gets
 | 
			
		||||
   * defined here but it is possible to define other List.js options.
 | 
			
		||||
   * item: https://listjs.com/api/#item
 | 
			
		||||
   * valueNames: https://listjs.com/api/#valueNames
 | 
			
		||||
   */
 | 
			
		||||
  Corpus: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td>
 | 
			
		||||
               <a class="btn-floating disabled">
 | 
			
		||||
                 <i class="material-icons service">book</i>
 | 
			
		||||
               </a>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <b class="title"></b><br>
 | 
			
		||||
               <i class="description"></i>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <span class="badge new status" data-badge-caption=""></span>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Edit">
 | 
			
		||||
                   <i class="material-icons">edit</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light analyse-link" data-position="top" data-tooltip="Analyse">
 | 
			
		||||
                   <i class="material-icons">search</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm corpus deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the corpus <b class="title1"></b>? All files will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "creation_date",
 | 
			
		||||
      "description",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title1",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "analyse-link", attr: "href"},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
      {name: "status", attr: "data-status"},
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  CorpusFile: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td class="filename" style="word-break: break-word;"></td>
 | 
			
		||||
             <td class="author" style="word-break: break-word;"></td>
 | 
			
		||||
             <td class="title" style="word-break: break-word;"></td>
 | 
			
		||||
             <td class="publishing-year" style="word-break: break-word;"></td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
 | 
			
		||||
                   <i class="material-icons">file_download</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Edit">
 | 
			
		||||
                   <i class="material-icons">edit</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm corpus file deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the corpus file <b class="title1"></b>? It be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "author",
 | 
			
		||||
      "filename",
 | 
			
		||||
      "publishing-year",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title1",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "download-link", attr: "href"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  Job: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td>
 | 
			
		||||
               <a class="btn-floating disabled">
 | 
			
		||||
                 <i class="material-icons service"></i>
 | 
			
		||||
               </a>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <b class="title"></b><br>
 | 
			
		||||
               <i class="description"></i>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <span class="badge new status" data-badge-caption=""></span>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to job">
 | 
			
		||||
                   <i class="material-icons">send</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm job deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the job <b class="title1"></b>? All files will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "creation_date",
 | 
			
		||||
      "description",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title1",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
      {name: "service", attr: "data-service"},
 | 
			
		||||
      {name: "status", attr: "data-status"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  JobInput: {
 | 
			
		||||
    item : `<tr>
 | 
			
		||||
              <td class="filename"></td>
 | 
			
		||||
              <td class="right-align">
 | 
			
		||||
                <a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
 | 
			
		||||
                  <i class="material-icons">file_download</i>
 | 
			
		||||
                </a>
 | 
			
		||||
              </td>
 | 
			
		||||
            </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "filename",
 | 
			
		||||
      "id",
 | 
			
		||||
      {name: "download-link", attr: "href"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  QueryResult: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td>
 | 
			
		||||
               <b class="title"></b><br>
 | 
			
		||||
               <i class="description"></i><br>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <span class="corpus_name"></span><br>
 | 
			
		||||
               <span class="query"></span>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Info">
 | 
			
		||||
                   <i class="material-icons">info</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light inspect-link" data-position="top" data-tooltip="Analyse">
 | 
			
		||||
                   <i class="material-icons">search</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm query result deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the query result <b class="title1"></b>? It will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "corpus_name",
 | 
			
		||||
      "description",
 | 
			
		||||
      "query",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title2",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "inspect-link", attr: "href"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  User: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td class="id"></td>
 | 
			
		||||
             <td class="username"></td>
 | 
			
		||||
             <td class="email"></td>
 | 
			
		||||
             <td class="role"></td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to user">
 | 
			
		||||
                   <i class="material-icons">send</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm corpus deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the job <b class="title1"></b>? All files will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "username",
 | 
			
		||||
      "username2",
 | 
			
		||||
      "email",
 | 
			
		||||
      "role",
 | 
			
		||||
      "id",
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
class JobList extends RessourceList {
 | 
			
		||||
  constructor(listElementId, options = {}) {
 | 
			
		||||
    let listElement = document.querySelector(`#${listElementId}`);
 | 
			
		||||
    super(listElement, {...JobList.options, ...options});
 | 
			
		||||
    nopaque.jobsSubscribers.push(this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
JobList.options = {
 | 
			
		||||
  item: `<tr>
 | 
			
		||||
           <td><a class="btn-floating disabled"><i class="material-icons service"></i></a></td>
 | 
			
		||||
           <td><b class="title"></b><br><i class="description"></i></td>
 | 
			
		||||
           <td><span class="badge new status" data-badge-caption=""></span></td>
 | 
			
		||||
           <td class="right-align">
 | 
			
		||||
             <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
             <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
           </td>
 | 
			
		||||
         </tr>`,
 | 
			
		||||
  valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, {name: "status", attr: "data-status"}, 'description', 'title']
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { RessourceList, };
 | 
			
		||||
 | 
			
		||||
class QueryResultList extends RessourceList {
 | 
			
		||||
  constructor(listElementId, options = {}) {
 | 
			
		||||
    let listElement = document.querySelector(`#${listElementId}`);
 | 
			
		||||
    super(listElement, {...QueryResultList.options, ...options});
 | 
			
		||||
    nopaque.queryResultsSubscribers.push(this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QueryResultList.options = {
 | 
			
		||||
  item: `<tr>
 | 
			
		||||
           <td><b class="title"></b><br><i class="description"></i><br></td>
 | 
			
		||||
           <td><span class="corpus_title"></span><br><span class="query"></span></td>
 | 
			
		||||
           <td class="right-align">
 | 
			
		||||
             <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
             <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
             <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="analyse" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
 | 
			
		||||
           </td>
 | 
			
		||||
         </tr>`,
 | 
			
		||||
  valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { CorpusList, JobList, QueryResultList };
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										420
									
								
								web/app/static/js/nopaque.lists.js.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								web/app/static/js/nopaque.lists.js.bak
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,420 @@
 | 
			
		||||
class RessourceList extends List {
 | 
			
		||||
  constructor(idOrElement, subscriberList, type, options) {
 | 
			
		||||
    if (!type || !["Corpus", "CorpusFile", "Job", "JobInput", "QueryResult", "User"].includes(type)) {
 | 
			
		||||
      throw "Unknown Type!";
 | 
			
		||||
    }
 | 
			
		||||
    super(idOrElement, {...RessourceList.options['common'],
 | 
			
		||||
                        ...RessourceList.options[type],
 | 
			
		||||
                        ...(options ? options : {})});
 | 
			
		||||
    if (subscriberList) {subscriberList.push(this);}
 | 
			
		||||
    this.type = type;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  _init(ressources) {
 | 
			
		||||
    this.clear();
 | 
			
		||||
    this._add(Object.values(ressources));
 | 
			
		||||
    this.sort("id", {order: "desc"});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  _update(patch) {
 | 
			
		||||
    let item, pathArray;
 | 
			
		||||
 | 
			
		||||
    for (let operation of patch) {
 | 
			
		||||
      /* "/{ressourceName}/{ressourceId}/..." -> ["{ressourceId}", "..."] */
 | 
			
		||||
      pathArray = operation.path.split("/").slice(2);
 | 
			
		||||
      switch(operation.op) {
 | 
			
		||||
        case "add":
 | 
			
		||||
          if (pathArray.includes("results")) {break;}
 | 
			
		||||
          this._add([operation.value]);
 | 
			
		||||
          break;
 | 
			
		||||
        case "remove":
 | 
			
		||||
          this.remove("id", pathArray[0]);
 | 
			
		||||
          break;
 | 
			
		||||
        case "replace":
 | 
			
		||||
          item = this.get("id", pathArray[0])[0];
 | 
			
		||||
          switch(pathArray[1]) {
 | 
			
		||||
            case "status":
 | 
			
		||||
              item.values({status: operation.value,
 | 
			
		||||
                           "analyse-link": ["analysing", "prepared", "start analysis"].includes(operation.value) ? `/corpora/${pathArray[0]}/analyse` : ""});
 | 
			
		||||
              break;
 | 
			
		||||
            default:
 | 
			
		||||
              break;
 | 
			
		||||
          }
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _add(values, callback) {
 | 
			
		||||
    this.add(values.map(x => RessourceList.dataMappers[this.type](x)), callback);
 | 
			
		||||
    // Initialize modal and tooltipped elements in list
 | 
			
		||||
    M.AutoInit(this.listContainer);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RessourceList.dataMappers = {
 | 
			
		||||
  // A data mapper describes entitys rendered per row. One key value pair holds
 | 
			
		||||
  // the data to be rendered in the list.js table. Key has to correspond
 | 
			
		||||
  // with the ValueNames defined below in RessourceList.options ValueNames.
 | 
			
		||||
  // Links are declared with double ticks(") around them. The key for links
 | 
			
		||||
  // have to correspond with the class of an <a> element in the
 | 
			
		||||
  // RessourceList.options item blueprint.
 | 
			
		||||
 | 
			
		||||
  /* ### Corpus mapper ### */
 | 
			
		||||
  Corpus: corpus => ({
 | 
			
		||||
    creation_date: corpus.creation_date,
 | 
			
		||||
    description: corpus.description,
 | 
			
		||||
    id: corpus.id,
 | 
			
		||||
    link: `/corpora/${corpus.id}`,
 | 
			
		||||
    status: corpus.status,
 | 
			
		||||
    title: corpus.title,
 | 
			
		||||
    title1: corpus.title,
 | 
			
		||||
    "analyse-link": ["analysing", "prepared", "start analysis"].includes(corpus.status) ? `/corpora/${corpus.id}/analyse` : "",
 | 
			
		||||
    "delete-link": `/corpora/${corpus.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-corpus-${corpus.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-corpus-${corpus.id}-modal`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### CorpusFile mapper ### TODO: replace delete-modal with delete-onclick */
 | 
			
		||||
  CorpusFile: corpus_file => ({
 | 
			
		||||
    author: corpus_file.author,
 | 
			
		||||
    filename: corpus_file.filename,
 | 
			
		||||
    id: corpus_file.id,
 | 
			
		||||
    link: `${corpus_file.corpus_id}/files/${corpus_file.id}`,
 | 
			
		||||
    "publishing-year": corpus_file.publishing_year,
 | 
			
		||||
    title: corpus_file.title,
 | 
			
		||||
    title1: corpus_file.title,
 | 
			
		||||
    "delete-link": `/corpora/${corpus_file.corpus_id}/files/${corpus_file.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-corpus-file-${corpus_file.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-corpus-file-${corpus_file.id}-modal`,
 | 
			
		||||
    "download-link": `${corpus_file.corpus_id}/files/${corpus_file.id}/download`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### Job mapper ### */
 | 
			
		||||
  Job: job => ({
 | 
			
		||||
    creation_date: job.creation_date,
 | 
			
		||||
    description: job.description,
 | 
			
		||||
    id: job.id,
 | 
			
		||||
    link: `/jobs/${job.id}`,
 | 
			
		||||
    service: job.service.name,
 | 
			
		||||
    status: job.status,
 | 
			
		||||
    title: job.title,
 | 
			
		||||
    title1: job.title,
 | 
			
		||||
    "delete-link": `/jobs/${job.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-job-${job.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-job-${job.id}-modal`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### JobInput mapper ### */
 | 
			
		||||
  JobInput: job_input => ({
 | 
			
		||||
    filename: job_input.filename,
 | 
			
		||||
    id: job_input.job_id,
 | 
			
		||||
    "download-link": `${job_input.job_id}/inputs/${job_input.id}/download`
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### QueryResult mapper ### */
 | 
			
		||||
  QueryResult: query_result => ({
 | 
			
		||||
    corpus_name: query_result.query_metadata.corpus_name,
 | 
			
		||||
    description: query_result.description,
 | 
			
		||||
    id: query_result.id,
 | 
			
		||||
    link: `/corpora/result/${query_result.id}`,
 | 
			
		||||
    query: query_result.query_metadata.query,
 | 
			
		||||
    title: query_result.title,
 | 
			
		||||
    "delete-link": `/corpora/result/${query_result.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-query-result-${query_result.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-query-result-${query_result.id}-modal`,
 | 
			
		||||
    "inspect-link": `/corpora/result/${query_result.id}/inspect`,
 | 
			
		||||
  }),
 | 
			
		||||
  /* ### User mapper ### */
 | 
			
		||||
  User: user => ({
 | 
			
		||||
    confirmed: user.confirmed,
 | 
			
		||||
    email: user.email,
 | 
			
		||||
    id: user.id,
 | 
			
		||||
    link: `users/${user.id}`,
 | 
			
		||||
    role: user.role.name,
 | 
			
		||||
    username: user.username,
 | 
			
		||||
    username2: user.username,
 | 
			
		||||
    "delete-link": `/admin/users/${user.id}/delete`,
 | 
			
		||||
    "delete-modal": `delete-user-${user.id}-modal`,
 | 
			
		||||
    "delete-modal-trigger": `delete-user-${user.id}-modal`,
 | 
			
		||||
  }),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RessourceList.options = {
 | 
			
		||||
  // common list.js options for 5 rows per page etc.
 | 
			
		||||
  common: {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]},
 | 
			
		||||
  // extended list.js options for 10 rows per page etc.
 | 
			
		||||
  extended: {
 | 
			
		||||
    page: 10,
 | 
			
		||||
    pagination: [
 | 
			
		||||
      {
 | 
			
		||||
        name: "paginationTop",
 | 
			
		||||
        paginationClass: "paginationTop",
 | 
			
		||||
        innerWindow: 8,
 | 
			
		||||
        outerWindow: 1
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        paginationClass: "paginationBottom",
 | 
			
		||||
        innerWindow: 8,
 | 
			
		||||
        outerWindow: 1,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  /* Type specific List.js options. Usually only "item" and "valueNames" gets
 | 
			
		||||
   * defined here but it is possible to define other List.js options.
 | 
			
		||||
   * item: https://listjs.com/api/#item
 | 
			
		||||
   * valueNames: https://listjs.com/api/#valueNames
 | 
			
		||||
   */
 | 
			
		||||
  Corpus: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td>
 | 
			
		||||
               <a class="btn-floating disabled">
 | 
			
		||||
                 <i class="material-icons service">book</i>
 | 
			
		||||
               </a>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <b class="title"></b><br>
 | 
			
		||||
               <i class="description"></i>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <span class="badge new status" data-badge-caption=""></span>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Edit">
 | 
			
		||||
                   <i class="material-icons">edit</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light analyse-link" data-position="top" data-tooltip="Analyse">
 | 
			
		||||
                   <i class="material-icons">search</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm corpus deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the corpus <b class="title1"></b>? All files will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "creation_date",
 | 
			
		||||
      "description",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title1",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "analyse-link", attr: "href"},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
      {name: "status", attr: "data-status"},
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  CorpusFile: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td class="filename" style="word-break: break-word;"></td>
 | 
			
		||||
             <td class="author" style="word-break: break-word;"></td>
 | 
			
		||||
             <td class="title" style="word-break: break-word;"></td>
 | 
			
		||||
             <td class="publishing-year" style="word-break: break-word;"></td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
 | 
			
		||||
                   <i class="material-icons">file_download</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Edit">
 | 
			
		||||
                   <i class="material-icons">edit</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm corpus file deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the corpus file <b class="title1"></b>? It be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "author",
 | 
			
		||||
      "filename",
 | 
			
		||||
      "publishing-year",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title1",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "download-link", attr: "href"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  Job: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td>
 | 
			
		||||
               <a class="btn-floating disabled">
 | 
			
		||||
                 <i class="material-icons service"></i>
 | 
			
		||||
               </a>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <b class="title"></b><br>
 | 
			
		||||
               <i class="description"></i>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <span class="badge new status" data-badge-caption=""></span>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to job">
 | 
			
		||||
                   <i class="material-icons">send</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm job deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the job <b class="title1"></b>? All files will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "creation_date",
 | 
			
		||||
      "description",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title1",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
      {name: "service", attr: "data-service"},
 | 
			
		||||
      {name: "status", attr: "data-status"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  JobInput: {
 | 
			
		||||
    item : `<tr>
 | 
			
		||||
              <td class="filename"></td>
 | 
			
		||||
              <td class="right-align">
 | 
			
		||||
                <a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
 | 
			
		||||
                  <i class="material-icons">file_download</i>
 | 
			
		||||
                </a>
 | 
			
		||||
              </td>
 | 
			
		||||
            </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "filename",
 | 
			
		||||
      "id",
 | 
			
		||||
      {name: "download-link", attr: "href"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  QueryResult: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td>
 | 
			
		||||
               <b class="title"></b><br>
 | 
			
		||||
               <i class="description"></i><br>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <span class="corpus_name"></span><br>
 | 
			
		||||
               <span class="query"></span>
 | 
			
		||||
             </td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Info">
 | 
			
		||||
                   <i class="material-icons">info</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light inspect-link" data-position="top" data-tooltip="Analyse">
 | 
			
		||||
                   <i class="material-icons">search</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm query result deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the query result <b class="title1"></b>? It will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "corpus_name",
 | 
			
		||||
      "description",
 | 
			
		||||
      "query",
 | 
			
		||||
      "title",
 | 
			
		||||
      "title2",
 | 
			
		||||
      {data: ["id"]},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
      {name: "inspect-link", attr: "href"},
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  User: {
 | 
			
		||||
    item: `<tr>
 | 
			
		||||
             <td class="id"></td>
 | 
			
		||||
             <td class="username"></td>
 | 
			
		||||
             <td class="email"></td>
 | 
			
		||||
             <td class="role"></td>
 | 
			
		||||
             <td>
 | 
			
		||||
               <div class="right-align">
 | 
			
		||||
                 <a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
 | 
			
		||||
                   <i class="material-icons">delete</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
                 <a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to user">
 | 
			
		||||
                   <i class="material-icons">send</i>
 | 
			
		||||
                 </a>
 | 
			
		||||
               </div>
 | 
			
		||||
               <div class="modal delete-modal">
 | 
			
		||||
                 <div class="modal-content">
 | 
			
		||||
                   <h4>Confirm corpus deletion</h4>
 | 
			
		||||
                   <p>Do you really want to delete the job <b class="title1"></b>? All files will be permanently deleted!</p>
 | 
			
		||||
                 </div>
 | 
			
		||||
                 <div class="modal-footer">
 | 
			
		||||
                   <a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                   <a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
 | 
			
		||||
                 </div>
 | 
			
		||||
               </div>
 | 
			
		||||
             </td>
 | 
			
		||||
           </tr>`,
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      "username",
 | 
			
		||||
      "username2",
 | 
			
		||||
      "email",
 | 
			
		||||
      "role",
 | 
			
		||||
      "id",
 | 
			
		||||
      {name: "link", attr: "href"},
 | 
			
		||||
      {name: "delete-link", attr: "href"},
 | 
			
		||||
      {name: "delete-modal-trigger", attr: "data-target"},
 | 
			
		||||
      {name: "delete-modal", attr: "id"},
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { RessourceList, };
 | 
			
		||||
@@ -1,33 +1,33 @@
 | 
			
		||||
class RessourceList extends List {
 | 
			
		||||
  constructor(idOrElement, options) {
 | 
			
		||||
    super(idOrElement, {...RessourceList.options['default'], ...(options ? options : {})});
 | 
			
		||||
class RessourceList {
 | 
			
		||||
  constructor(idOrElement, options = {}) {
 | 
			
		||||
    this.list = new List(idOrElement, {...RessourceList.options, ...options});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _init(ressources) {
 | 
			
		||||
    this.clear();
 | 
			
		||||
    this._add(Object.values(ressources));
 | 
			
		||||
    this.sort("id", {order: "desc"});
 | 
			
		||||
  init(ressources) {
 | 
			
		||||
    this.list.clear();
 | 
			
		||||
    this.add(Object.values(ressources));
 | 
			
		||||
    this.list.sort('id', {order: 'desc'});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  _update(patch) {
 | 
			
		||||
  update(patch) {
 | 
			
		||||
    let item, pathArray;
 | 
			
		||||
 | 
			
		||||
    for (let operation of patch) {
 | 
			
		||||
      /*
 | 
			
		||||
       * '/{ressourceName}/{ressourceId}/...' -> ['{ressourceId}', ...]
 | 
			
		||||
       * '/{ressourceName}/{ressourceId}/{valueName}' -> ['{ressourceId}', {valueName}]
 | 
			
		||||
       * Example: '/jobs/1/status' -> ['1', 'status']
 | 
			
		||||
      */
 | 
			
		||||
      pathArray = operation.path.split("/").slice(2);
 | 
			
		||||
      let [id, valueName] = operation.path.split("/").slice(2);
 | 
			
		||||
      switch(operation.op) {
 | 
			
		||||
        case "add":
 | 
			
		||||
          this.add_handler([operation.value]);
 | 
			
		||||
        case 'add':
 | 
			
		||||
          this.add(operation.value);
 | 
			
		||||
          break;
 | 
			
		||||
        case "remove":
 | 
			
		||||
          this.remove_handler(pathArray[0]);
 | 
			
		||||
        case 'remove':
 | 
			
		||||
          this.remove(id);
 | 
			
		||||
          break;
 | 
			
		||||
        case "replace":
 | 
			
		||||
          this.replace_handler(pathArray[0], pathArray[1], operation.value);
 | 
			
		||||
        case 'replace':
 | 
			
		||||
          this.replace(id, valueName, operation.value);
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
@@ -35,34 +35,93 @@ class RessourceList extends List {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  add_handler(values, callback) {
 | 
			
		||||
    if (this.hasOwnProperty('add_')) {
 | 
			
		||||
      this.add_(values, callback);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.add(values, callback);
 | 
			
		||||
    }
 | 
			
		||||
  add(values) {
 | 
			
		||||
    /* WORKAROUND: Set a callback function ('() => {return;}') to force List.js
 | 
			
		||||
                   perform the add method asynchronous.
 | 
			
		||||
     * https://listjs.com/api/#add
 | 
			
		||||
     */
 | 
			
		||||
    this.list.add(values, () => {return;});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  remove_handler(id) {
 | 
			
		||||
    if (this.hasOwnProperty('remove_')) {
 | 
			
		||||
      this.remove_(id);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.remove(id);
 | 
			
		||||
    }
 | 
			
		||||
  remove(id) {
 | 
			
		||||
    this.list.remove('id', id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  replace_handler(id, valueName, newValue) {
 | 
			
		||||
    let item = this.get('id', id);
 | 
			
		||||
    if (this.hasOwnProperty('add_'))
 | 
			
		||||
    item.values({valueName: operation.value});
 | 
			
		||||
  replace(id, valueName, newValue) {
 | 
			
		||||
    if (!this.list.valuesNames.includes(valueName)) {return;}
 | 
			
		||||
    let item = this.list.get('id', id);
 | 
			
		||||
    item.values({[valueName]: newValue});
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RessourceList.options = {
 | 
			
		||||
  // default RessourceList options
 | 
			
		||||
  default: {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]},
 | 
			
		||||
RessourceList.options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CorpusList extends RessourceList {
 | 
			
		||||
  constructor(idOrElement, options = {}) {
 | 
			
		||||
    super(idOrElement, {...CorpusList.options, ...options});
 | 
			
		||||
    nopaque.corporaSubscribers.push(this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CorpusList.options = {
 | 
			
		||||
  item: `<tr>
 | 
			
		||||
           <td><a class="btn-floating disabled"><i class="material-icons">book</i></a></td>
 | 
			
		||||
           <td><b class="title"></b><br><i class="description"></i></td>
 | 
			
		||||
           <td><span class="badge new status" data-badge-caption=""></span></td>
 | 
			
		||||
           <td class="right-align">
 | 
			
		||||
             <a class="btn-floating delete red tooltipped waves-effect waves-light" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
             <a class="btn-floating edit tooltipped waves-effect waves-light" data-position="top" data-tooltip="Edit"><i class="material-icons">edit</i></a>
 | 
			
		||||
             <a class="analyse btn-floating tooltipped waves-effect waves-light" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
 | 
			
		||||
           </td>
 | 
			
		||||
         </tr>`,
 | 
			
		||||
  valueNames: [{data: ['id']}, 'description', 'status', 'title']
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export { RessourceList, };
 | 
			
		||||
class JobList extends RessourceList {
 | 
			
		||||
  constructor(idOrElement, options = {}) {
 | 
			
		||||
    super(idOrElement, {...JobList.options, ...options});
 | 
			
		||||
    nopaque.jobsSubscribers.push(this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
JobList.options = {
 | 
			
		||||
  item: `<tr>
 | 
			
		||||
           <td><a class="btn-floating disabled"><i class="material-icons service"></i></a></td>
 | 
			
		||||
           <td><b class="title"></b><br><i class="description"></i></td>
 | 
			
		||||
           <td><span class="badge new status" data-badge-caption=""></span></td>
 | 
			
		||||
           <td class="right-align">
 | 
			
		||||
             <a class="btn-floating delete red tooltipped waves-effect waves-light" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
             <a class="btn-floating tooltipped view waves-effect waves-light" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
           </td>
 | 
			
		||||
         </tr>`,
 | 
			
		||||
  valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, 'description', 'status', 'title']
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QueryResultList extends RessourceList {
 | 
			
		||||
  constructor(idOrElement, options = {}) {
 | 
			
		||||
    super(idOrElement, {...QueryResultList.options, ...options});
 | 
			
		||||
    nopaque.queryResultsSubscribers.push(this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QueryResultList.options = {
 | 
			
		||||
  item: `<tr>
 | 
			
		||||
           <td><b class="title"></b><br><i class="description"></i><br></td>
 | 
			
		||||
           <td><span class="corpus_title"></span><br><span class="query"></span></td>
 | 
			
		||||
           <td class="right-align">
 | 
			
		||||
             <a class="btn-floating delete red tooltipped waves-effect waves-light" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
             <a class="btn-floating tooltipped view waves-effect waves-light" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
             <a class="analyse btn-floating tooltipped waves-effect waves-light" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
 | 
			
		||||
           </td>
 | 
			
		||||
         </tr>`,
 | 
			
		||||
  valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { CorpusList, JobList, QueryResultList };
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user