Skip to content
Snippets Groups Projects
job.html.j2 9.84 KiB
{% extends "nopaque.html.j2" %}

{% set headline = '<i class="left material-icons service" data-service="{service}" style="font-size: inherit;"></i>Job view'.format(service=job.service) %}

{% block page_content %}
<div class="col s12">
  <div class="card">
    <div class="card-content">
      <div class="row">
        <div class="col s8 m9 l10">
          <span class="card-title title">{{ job.title }}</span>
        </div>

        <div class="col s4 m3 l2 right-align">
          <span class="chip status white-text"></span>
          <div class="active preloader-wrapper small" id="progress-indicator">
            <div class="spinner-layer spinner-blue-only">
              <div class="circle-clipper left">
                <div class="circle"></div>
              </div>
              <div class="gap-patch">
                <div class="circle"></div>
              </div>
              <div class="circle-clipper right">
                <div class="circle"></div>
              </div>
            </div>
          </div>
        </div>

        <div class="col s12">
          <p class="description">{{ job.description }}</p>
        </div>

        <div class="col s12">&nbsp;</div>

        <div class="col s12 m6">
          <div class="input-field">
            <input disabled id="creation-date" type="text" value="{{ job.creation_date.strftime('%m/%d/%Y, %H:%M:%S %p') }}">
            <label for="creation-date">Creation date</label>
          </div>
        </div>

        <div class="col s12 m6">
          <div class="input-field">
            <input class="end-date" disabled id="end-date" type="text" value="">
            <label for="end-date">End date</label>
          </div>
        </div>

        <div class="col s12 m4">
          <div class="input-field">
            <input disabled id="service" type="text" value="{{ job.service }}">
            <label for="service">Service</label>
          </div>
        </div>

        <div class="col s12 m4">
          <div class="input-field">
            <input disabled id="service-args" type="text" value="{{ job.service_args|e }}">
            <label for="service-args">Service arguments</label>
          </div>
        </div>

        <div class="col s12 m4">
          <div class="input-field">
            <input disabled id="service-version" type="text" value="{{ job.service_version }}">
            <label for="service-version">Service version</label>
          </div>
        </div>
      </div>
    </div>
    <div class="card-action right-align">
      <a href="#" class="btn disabled waves-effect waves-light"><i class="material-icons left">settings</i>Export Parameters</a>
      <a data-target="delete-job-modal" class="waves-effect waves-light btn red modal-trigger"><i class="material-icons left">delete</i>Delete</a>
    </div>
  </div>
</div>

<div class="col s12">
  <div class="card">
    <div class="card-content" id="inputs">
      <div class="row">
        <div class="col s12 m2">
          <span class="card-title"><i class="left material-icons" style="font-size: inherit;">input</i>Inputs</span>
          <p>Original input files.</p>
        </div>
        <div class="col s12 m10">
          <div class="inputs row">
            <ul class="pagination paginationTop"></ul>
            {{ job_input_table }}
            <ul class="pagination paginationBottom"></ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<div class="col s12">
  <div class="card">
    <div class="card-content">
      <div class="row">
        <div class="col s12 m2">
          <span class="card-title"><i class="left material-icons" style="font-size: inherit;">done</i>Results</span>
          <p>Processed result files.</p>
        </div>
        <div class="col s12 m10">
          <table class="highlight responsive-table">
            <thead>
              <tr>
                <th>Result Type</th>
                <th>Archive Name</th>
                <th>Download</th>
              </tr>
            </thead>
            <tbody class="results">
              <tr class="show-if-only-child">
                <td colspan="3">
                  <span class="card-title">
                    <i class="left material-icons" style="font-size: inherit;">file_download</i>Nothing here...
                  </span>
                  <p>
                    No results available (yet). Is the job already completed?
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</div>


<!-- Modals -->
<div id="delete-job-modal" class="modal">
  <div class="modal-content">
    <h4>Confirm deletion</h4>
    <p>Do you really want to delete the job {{ job.title }}? All associated 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" href="{{ url_for('jobs.delete_job', job_id=job.id) }}"><i class="material-icons left">delete</i>Delete</a>
  </div>
</div>


<script>
// job_input_table code
var options = {page: 5,
               pagination: [
                 {
                   name: "paginationTop",
                   paginationClass: "paginationTop",
                   innerWindow: 8,
                   outerWindow: 1
                 },
                 {
                    paginationClass: "paginationBottom",
                    innerWindow: 8,
                    outerWindow: 1
                  }
                ],
               valueNames: ['filename']};
  var jobInputList = new List('inputs', options);


  class InformationUpdater {
    constructor(jobId, foreignJobFlag) {
      this.jobId = jobId;
      this.foreignJobFlag = foreignJobFlag;

      if (this.foreignJobFlag) {
        nopaque.foreignJobsSubscribers.push(this);
      } else {
        nopaque.jobsSubscribers.push(this);
      }
    }

    _init() {
      let job;

      job = (this.foreignJobFlag ? nopaque.foreignUser.jobs[this.jobId]
                                 : nopaque.user.jobs[this.jobId]);
      // Results
      this.addResults(job.results);
      // End date
      this.setEndDate(job.end_date);
      // Status
      this.setStatus(job.status);
    }

    _update(patch) {
      let pathArray;

      for (let operation of patch) {
        /* "/jobs/{jobId}/..." -> ["{jobId}", ...] */
        pathArray = operation.path.split("/").slice(2);
        if (pathArray[0] != this.jobId) {continue;}
        switch(operation.op) {
          case "add":
            if (pathArray[1] === "results") {
              this.addResults([operation.value]);
            }
            break;
          case "delete":
            location.reload();
            break;
          case "replace":
            if (pathArray[1] === "end_date") {
              this.setEndDate(operation.value);
            } else if (pathArray[1] === "status") {
              this.setStatus(operation.value);
            }
            break;
          default:
            break;
        }
      }
    }

    addResults(results) {
      let resultsArray, resultsElements, resultsHTML, resultType;
      resultsArray = Object.values(results);
      resultsArray.sort(function (a, b) {
        if (a.filename < b.filename) {return -1;}
        if (a.filename > b.filename) {return 1;}
        return 0;
      });
      resultsHTML = ``;
      for (let result of resultsArray) {
        if (result.filename.endsWith(".pdf.zip")) {
          resultType = "PDF file with text layer";
        } else if (result.filename.endsWith(".txt.zip")) {
          resultType = "Raw text files";
        } else if (result.filename.endsWith(".vrt.zip")) {
          resultType = "VRT(XML dialect) files holding the NLP data";
        } else if (result.filename.endsWith(".xml.zip")) {
          resultType = "XML files";
        } else if (result.filename.endsWith(".poco.zip")) {
          resultType = "HCOR und image files needed for Post correction(PoCo)";
        } else {
          resultType = "All result files created during this job";
        }
        resultsHTML += `
                        <tr>
                          <td>${resultType}</td>
                          <td>${result.filename}</td>
                          <td>
                            <a class="btn-floating waves-effect waves-light" download href="/jobs/${result.job_id}/results/${result.id}/download">
                              <i class="material-icons left">file_download</i>
                            </a>
                          </td>
                        </tr>
                       `;
      };
      resultsHTML += `
                      </tbody>
                      </table>
                     `;
      resultsElements = document.querySelectorAll(".results");
      for (let resultsElement of resultsElements) {
        resultsElement.innerHTML += resultsHTML;
      }
    }

    setEndDate(timestamp) {
      let endDate;

      if (timestamp === null) {
        endDate = "N.a.";
      } else {
        endDate = new Date(timestamp * 1000).toLocaleString("en-US");
      }
      document.getElementById("end-date").value = endDate;
      M.updateTextFields();
    }
    setStatus(status) {
      let progressIndicator, statusElements;
      if (status === "complete") {
        progressIndicator = document.getElementById("progress-indicator");
        progressIndicator.classList.add("hide");
      }
      statusElements = document.querySelectorAll(".status");
      for (let statusElement of statusElements) {
        statusElement.dataset.status = status;
      }
    }
  }

  {% if job.creator == current_user %}
  var informationUpdater = new InformationUpdater({{ job.id }}, false);
  {% else %}
  var informationUpdater = new InformationUpdater({{ job.id }}, true);
  document.addEventListener("DOMContentLoaded", () => {
    nopaque.socket.emit("foreign_user_data_stream_init", {{ job.user_id }});
  });
  {% endif %}
</script>
{% endblock %}