mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-27 03:44:19 +00:00
284 lines
9.1 KiB
Django/Jinja
284 lines
9.1 KiB
Django/Jinja
{% extends "limited_width.html.j2" %}
|
|
|
|
{% block page_content %}
|
|
<div class="col s12 m4">
|
|
<h3 id="title">{{ job.title }}</h3>
|
|
<p id="description">{{ job.description }}</p>
|
|
<a class="btn status waves-effect waves-light" id="status"></a>
|
|
</div>
|
|
|
|
|
|
<div class="col s12 m8">
|
|
<div class="card">
|
|
<div class="card-content">
|
|
<span class="card-title">Chronometrics</span>
|
|
<div class="row">
|
|
<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>
|
|
|
|
<span class="card-title">Ressource allocations</span>
|
|
<div class="row">
|
|
<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>
|
|
|
|
<span class="card-title">Service informations</span>
|
|
<div class="row">
|
|
<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>
|
|
</div>
|
|
<div class="card-action 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>
|
|
|
|
<div class="col s12">
|
|
<h4>Input and result files</h4>
|
|
</div>
|
|
|
|
<div class="col s12 m7">
|
|
<div class="card">
|
|
<div class="card-content">
|
|
<span class="card-title">Filewise</span>
|
|
<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>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col s12 m5">
|
|
<div class="card">
|
|
<div class="card-content">
|
|
<span class="card-title">Bundled</span>
|
|
<table class="highlight responsive-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Bundlename</th>
|
|
<th>Download</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="results"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="col s12 hide">
|
|
<div class="card">
|
|
<div class="card-content">
|
|
<span class="card-title">Files</span>
|
|
<table class="highlight responsive-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Filename</th>
|
|
<th>Download</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% 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>
|
|
<td id="input-{{ input.id }}-results"></td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</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="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>
|
|
|
|
|
|
<script>
|
|
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;
|
|
|
|
if (this.foreignJobFlag) {
|
|
job = nopaque.foreignJobs[this.jobId];
|
|
} else {
|
|
job = nopaque.jobs[this.jobId];
|
|
}
|
|
|
|
// 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) {
|
|
let pathArray;
|
|
|
|
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":
|
|
if (pathArray[1] === "results") {
|
|
this.setResult(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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 resultElement, resultsElement, resultDownloadElement,
|
|
resultDownloadButtonElement, resultDownloadButtonIconElement,
|
|
resultTitleElement;
|
|
|
|
resultsElement = document.getElementById("results");
|
|
|
|
for (let result of results) {
|
|
resultElement = document.createElement("tr");
|
|
resultTitleElement = document.createElement("td");
|
|
resultTitleElement.innerText = result.filename;
|
|
resultElement.append(resultTitleElement);
|
|
resultDownloadElement = document.createElement("td");
|
|
resultDownloadButtonElement = document.createElement("a");
|
|
resultDownloadButtonElement.classList.add("waves-effect", "waves-light",
|
|
"btn-small");
|
|
resultDownloadButtonElement.href = `/jobs/${result.job_id}/results/${result.id}/download`;
|
|
resultDownloadButtonElement.setAttribute("download", "");
|
|
resultDownloadButtonIconElement = document.createElement("i");
|
|
resultDownloadButtonIconElement.classList.add("material-icons");
|
|
resultDownloadButtonIconElement.innerText = "file_download";
|
|
resultDownloadButtonElement.append(resultDownloadButtonIconElement);
|
|
resultDownloadElement.append(resultDownloadButtonElement)
|
|
resultElement.append(resultDownloadElement);
|
|
resultsElement.append(resultElement);
|
|
}
|
|
}
|
|
|
|
setStatus(status) {
|
|
let statusElement;
|
|
|
|
statusElement = document.getElementById("status");
|
|
statusElement.dataset.status = status;
|
|
}
|
|
}
|
|
|
|
{% if job.creator == current_user %}
|
|
var informationUpdater = new InformationUpdater({{ job.id }}, false);
|
|
{% else %}
|
|
var informationUpdater = new InformationUpdater({{ job.id }}, true);
|
|
nopaque.socket.emit('subscribe_foreign_user_ressources', {{ job.user_id }});
|
|
{% endif %}
|
|
</script>
|
|
{% endblock %}
|