diff --git a/app/templates/jobs/job.html.j2 b/app/templates/jobs/job.html.j2 index 45b81ceabdd4e0ea414f1ac658a384b8194c32cf..1f4b524546573fc9aee74070053c9abe3c73acdd 100644 --- a/app/templates/jobs/job.html.j2 +++ b/app/templates/jobs/job.html.j2 @@ -1,130 +1,125 @@ {% extends "nopaque.html.j2" %} -{% set headline = '<i class="material-icons left service" data-service="{service}" style="font-size: inherit;"></i>Job'.format(service=job.service) %} +{% 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 m4"> - <h3 id="title">{{ job.title }}</h3> - <p id="description">{{ job.description }}</p> - <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> - <span class="chip status white-text" id="status"></span> -</div> - +<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 s12 m8"> - <ul class="collapsible expandable" id="job-list"> - <li class="active"> - <div class="collapsible-header"> - <i class="material-icons">input</i>Input files - </div> - <div class="collapsible-body"> - <table class="highlight responsive-table"> - <thead> - <tr> - <th>Filename</th> - <th>Download</th> - </tr> - </thead> - <tbody id="inputs"> - {% for input in job.inputs|sort(attribute="id", reverse=true) %} - <tr> - <td id="input-{{ input.id }}-filename">{{ input.filename }}</td> - <td id="input-{{ input.id }}-download"> - <a class="waves-effect waves-light btn-small" download href="{{ url_for('jobs.download_job_input', job_id=job.id, job_input_id=input.id) }}"> - <i class="material-icons">file_download</i> - </a> - </td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - </li> - <li> - <div class="collapsible-header"><i class="material-icons">done</i>Result files</div> - <div class="collapsible-body"> - <table class="highlight responsive-table"> - <thead> - <tr> - <th>Bundlename</th> - <th>Download</th> - </tr> - </thead> - <tbody id="results"></tbody> - </table> - </div> - </li> - <li> - <div class="collapsible-header"><i class="material-icons">settings</i>Settings</div> - <div class="collapsible-body"> - <div class="row"> - <div class="col s12">Chronometrics</div> - <div class="col s12 m6"> - <div class="input-field"> - <input disabled value="{{ job.creation_date.strftime('%m/%d/%Y, %H:%M:%S %p') }}" id="creation-date" type="text" class="validate"> - <label for="creation-date">Creation date</label> + <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 class="col s12 m6"> - <div class="input-field"> - <input disabled value="" id="end-date" type="text" class="validate"> - <label for="end-date">End date</label> - </div> + </div> + + <div class="col s12"> + <p class="description">{{ job.description }}</p> + </div> + + <div class="col s12"> </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">Ressource allocations</div> - <div class="col s12 m6"> - <div class="input-field"> - <input disabled value="{{ job.mem_mb }}" id="mem-mb" type="text" class="validate"> - <label for="mem-mb">Memory</label> - </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 class="col s12 m6"> - <div class="input-field"> - <input disabled value="{{ job.n_cores }}" id="n-cores" type="text" class="validate"> - <label for="n-cores">CPU cores</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">Service informations</div> - <div class="col s12 m4"> - <div class="input-field"> - <input disabled value="{{ job.service }}" id="service" type="text" class="validate"> - <label for="service">Service</label> - </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 class="col s12 m4"> - <div class="input-field"> - <input disabled value="{{ job.service_args|e }}" id="service-args" type="text" class="validate"> - <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 class="col s12 m4"> - <div class="input-field"> - <input disabled value="{{ job.service_version }}" id="service-version" type="text" class="validate"> - <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"> + <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"> + {% for input in job.inputs %} + <div class="col s12 m6"> + <a class="btn waves-effect waves-light" download href="{{ url_for('jobs.download_job_input', job_id=job.id, job_input_id=input.id) }}"> + <i class="material-icons left">file_download</i>{{ input.filename }} + </a> + </div> + {% endfor %} </div> - <div class="col s12 right-align"> - <a href="#" class="waves-effect waves-light btn"><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> +</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"> + <div class="results row"> + <div class="show-if-only-child"> + <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> + </div> </div> </div> </div> - </li> - </ul> + </div> + </div> </div> @@ -132,7 +127,7 @@ <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> + <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> @@ -159,14 +154,12 @@ 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); - // End date - if (job.end_date) {this.setEndDate(job.end_date);} - // Results - if (job.results) {this.setResults(job.results);} } _update(patch) { @@ -179,7 +172,7 @@ switch(operation.op) { case "add": if (pathArray[1] === "results") { - this.setResults([operation.value]); + this.addResults([operation.value]); } break; case "delete": @@ -198,51 +191,61 @@ } } - setEndDate(timestamp) { - let end_date; - - if (timestamp === null) { - end_date = "N.a."; - } else { - end_date = new Date(timestamp * 1000).toLocaleString("en-US"); - } - document.getElementById("end-date").value = end_date; - M.updateTextFields(); - } - - setResults(results) { - let resultsArray, resultsElement; - resultsArray = Object.values(results) + 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; }); - resultsElement = document.getElementById("results"); + resultsHTML = ""; for (let result of resultsArray) { - resultsElement.insertAdjacentHTML( - "beforeend", - `<tr> - <td>${result.filename}</td> - <td> - <a class="btn-small waves-effect waves-light" download href="/jobs/${result.job_id}/results/${result.id}/download"> - <i class="material-icons">file_download</i> - </a> - </td> - </tr>` - ); + if (result.filename.endsWith(".pdf.zip")) { + resultType = "PDF"; + } else if (result.filename.endsWith(".txt.zip")) { + resultType = "TXT"; + } else if (result.filename.endsWith(".vrt.zip")) { + resultType = "VRT"; + } else if (result.filename.endsWith(".xml.zip")) { + resultType = "XML"; + } else { + resultType = "ALL"; + } + resultsHTML += `<div class="col s4 m3 l2"> + <a class="btn waves-effect waves-light" download href="/jobs/${result.job_id}/results/${result.id}/download"> + <i class="material-icons left">file_download</i>${resultType} + </a> + </div>`; + } + 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, statusElement; + let progressIndicator, statusElements; if (status === "complete") { progressIndicator = document.getElementById("progress-indicator"); progressIndicator.classList.add("hide"); - M.Collapsible.getInstance(document.getElementById("job-list")).open(1); } - statusElement = document.getElementById("status"); - statusElement.dataset.status = status; + statusElements = document.querySelectorAll(".status"); + for (let statusElement of statusElements) { + statusElement.dataset.status = status; + } } }