nopaque/app/templates/jobs/job.html.j2

258 lines
8.4 KiB
Plaintext
Raw Normal View History

2020-02-07 14:21:59 +00:00
{% extends "nopaque.html.j2" %}
{% set full_width = False %}
{% set roadmap = False %}
2020-02-12 14:57:31 +00:00
{% set title_override = '<i class="material-icons left service" data-service="{service}" style="font-size: inherit;"></i>Job'.format(service=job.service) %}
2019-08-09 09:49:09 +00:00
{% block page_content %}
<div class="col s12 m4">
<h3 id="title">{{ job.title }}</h3>
<p id="description">{{ job.description }}</p>
2020-02-12 15:24:56 +00:00
<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>
2019-08-09 09:49:09 +00:00
</div>
2019-08-09 09:49:09 +00:00
<div class="col s12 m8">
2020-02-12 13:48:29 +00:00
<ul class="collapsible expandable" id="job-list">
<li class="active">
2020-02-12 11:19:54 +00:00
<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 %}
<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>
2020-02-12 13:48:29 +00:00
<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>
</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">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>
<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">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>
<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 value="{{ job.service_version }}" id="service-version" type="text" class="validate">
<label for="service-version">Service version</label>
</div>
</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 Job</a>
</div>
</div>
</div>
</li>
2020-02-12 11:19:54 +00:00
</ul>
2019-08-09 09:49:09 +00:00
</div>
2019-11-15 10:45:04 +00:00
2019-11-04 15:58:15 +00:00
<!-- Modals -->
<div id="delete-job-modal" class="modal">
<div class="modal-content">
<h4>Confirm deletion</h4>
2020-02-12 13:48:29 +00:00
<p>Do you really want to delete the job {{job.title}}? All associated files will be permanently deleted.</p>
2019-11-04 15:58:15 +00:00
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn cancel">Cancel</a>
<a class="modal-close waves-effect waves-green btn red" href="{{ url_for('jobs.delete_job', job_id=job.id) }}">Confirm<i class="material-icons right">send</i></a>
</div>
</div>
2019-11-15 10:45:04 +00:00
<script>
class InformationUpdater {
constructor(jobId, foreignJobFlag) {
this.jobId = jobId;
this.foreignJobFlag = foreignJobFlag;
if (this.foreignJobFlag) {
nopaque.foreignJobsSubscribers.push(this);
2019-11-15 10:45:04 +00:00
} else {
nopaque.jobsSubscribers.push(this);
2019-11-15 10:45:04 +00:00
}
}
_init() {
let job;
if (this.foreignJobFlag) {
job = nopaque.foreignJobs[this.jobId];
} else {
job = nopaque.jobs[this.jobId];
}
2019-11-15 10:45:04 +00:00
// End date
this.setEndDate(job.end_date);
// Status
this.setStatus(job.status);
// End date
if (job.end_date) {this.setEndDate(job.end_date);}
2020-01-30 10:01:17 +00:00
// Results
if (job.results) {this.setResults(job.results);}
2019-11-15 10:45:04 +00:00
}
_update(patch) {
let pathArray;
2019-11-15 10:45:04 +00:00
for (let operation of patch) {
/* "/jobId/valueName" -> ["jobId", "valueName"] */
pathArray = operation.path.split("/").slice(1);
if (pathArray[0] != this.jobId) {continue;}
switch(operation.op) {
case "add":
2020-01-30 10:01:17 +00:00
if (pathArray[1] === "results") {
2020-02-03 14:58:46 +00:00
this.setResults([operation.value]);
2019-11-15 10:45:04 +00:00
}
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;
}
}
}
setEndDate(timestamp) {
let end_date;
2019-11-15 10:45:04 +00:00
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();
}
2020-01-30 10:01:17 +00:00
setResults(results) {
2020-02-03 14:58:46 +00:00
let resultsElement;
2020-01-30 10:01:17 +00:00
resultsElement = document.getElementById("results");
2020-01-30 10:01:17 +00:00
for (let result of results) {
2020-02-12 13:48:29 +00:00
resultsElement.insertAdjacentHTML(
"beforeend",
`<tr>
2020-02-03 14:58:46 +00:00
<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>
2020-02-12 13:48:29 +00:00
</tr>`
);
2020-01-30 10:01:17 +00:00
}
2019-11-15 10:45:04 +00:00
}
setStatus(status) {
2020-02-12 15:24:56 +00:00
let progressIndicator, statusElement;
if (status === "complete") {
progressIndicator = document.getElementById("progress-indicator");
progressIndicator.classList.add("hide");
2020-02-12 15:42:46 +00:00
M.Collapsible.getInstance(document.getElementById("job-list")).open(1);
2020-02-12 15:24:56 +00:00
}
2019-11-15 10:45:04 +00:00
statusElement = document.getElementById("status");
statusElement.dataset.status = status;
2019-11-15 10:45:04 +00:00
}
}
{% if job.creator == current_user %}
var informationUpdater = new InformationUpdater({{ job.id }}, false);
{% else %}
var informationUpdater = new InformationUpdater({{ job.id }}, true);
2020-02-17 11:20:09 +00:00
nopaque.socket.emit('foreign_user_ressources_init', {{ job.user_id }});
2019-11-15 10:45:04 +00:00
{% endif %}
</script>
2019-08-09 09:49:09 +00:00
{% endblock %}