Commit 70d61bb6 authored by Floreal Cabanettes's avatar Floreal Cabanettes
Browse files

Add button to delete a job + some minor fixes and refactoring, Implements #120

parent 84798ebc
......@@ -234,4 +234,15 @@ class Functions:
"mem_peak": Functions.get_readable_size(item.job.mem_peak),
"time_elapsed": Functions.get_readable_time(item.job.time_elapsed)
})
return items
\ No newline at end of file
return items
@staticmethod
def is_in_gallery(id_job, mode):
if mode == "webserver":
from dgenies.database import Gallery, Job
from peewee import DoesNotExist
try:
return len(Gallery.select().where(Gallery.job == Job.get(id_job=id_job))) > 0
except DoesNotExist:
return False
return False
......@@ -30,7 +30,7 @@ import binascii
from dgenies.database import Job
if MODE == "webserver":
from dgenies.database import Session
from dgenies.database import Session, Gallery
from peewee import DoesNotExist
......@@ -969,3 +969,19 @@ class JobManager:
return {"status": status, "mem_peak": None, "time_elapsed": None, "error": error}
except FileNotFoundError:
return {"status": "unknown", "error": ""}
def delete(self):
if not os.path.exists(self.output_dir) or not os.path.isdir(self.output_dir):
return False, "Job does not exists"
if MODE == "webserver":
try:
job = Job.get(id_job=self.id_job)
except DoesNotExist:
pass
else:
is_gallery = Gallery.select().where(Gallery.job == job)
if is_gallery:
return False, "Delete a job that is in gallery is forbidden"
job.delete_instance()
shutil.rmtree(self.output_dir)
return True, ""
\ No newline at end of file
......@@ -685,4 +685,25 @@ h2.status {
h2.status,div.status-body {
margin-left: 55px;
}
div#sidebar {
position: relative;
}
div#sidebar p.bottom {
position: absolute;
bottom: 0;
right: 0;
width: 100px;
}
div#sidebar p.bottom input#delete-job {
background: #ffbba8 !important;
}
ul.nav ul.dropdown-menu {
max-height: 300px;
overflow-y: auto;
}
\ No newline at end of file
......@@ -86,6 +86,7 @@ d3.boxplot.init = function (id_res=null, from_file=false) {
}
else {
$("#supdraw").html($("<p>").html("This job does not exist!").css("margin-top", "15px"));
dgenies.result.remove_job_from_cookie(dgenies.result.id_res);
}
}
)
......
......@@ -2,6 +2,30 @@ dgenies = {};
dgenies.loading = "#loading";
dgenies.noise = true;
dgenies.init = function() {
let cookies = $.cookie("results");
cookies = (cookies !== undefined && cookies.length > 0) ? cookies.split("|") : [];
dgenies.update_results(cookies);
};
dgenies.update_results = function(results) {
let job_list_item = $("ul.nav li.result ul");
job_list_item.html("");
if (results.length > 0) {
for (let i=0; i<results.length; i++) {
let result = results[i];
job_list_item.append($("<li>").append($("<a>")
.attr("href", `/result/${result}`)
.text(result)))
}
}
else {
job_list_item.append($("<li>").append($("<a>")
.attr("href", "/run")
.text("Please run a job!")))
}
};
dgenies.notify = function (text, type="warning", delay=5000) {
$.notify({
message: text
......
......@@ -7,6 +7,7 @@ dgenies.result.controls.init = function () {
$("#sort-contigs").click(dgenies.result.controls.launch_sort_contigs);
$("#hide-noise").click(dgenies.result.controls.launch_hide_noise);
$("#summary").click(dgenies.result.controls.summary);
$("#delete-job").click(dgenies.result.controls.delete_job);
$("form#select-zone input.submit").click(dgenies.result.controls.select_zone);
$("form#export select").change(dgenies.result.export.export);
};
......@@ -120,4 +121,51 @@ dgenies.result.controls.select_zone = function() {
else {
dgenies.notify("Please select zones into zoom!", "danger", 2000);
}
};
dgenies.result.controls.do_delete_job = function () {
dgenies.post(`/delete/${dgenies.result.id_res}`,
{},
function(data) {
if (data["success"]) {
dgenies.notify("Your job has been deleted!", "success", 1500);
window.setTimeout(() => {
dgenies.result.remove_job_from_cookie(dgenies.result.id_res);
window.location = "/";
}, 1500);
}
else {
dgenies.notify("error" in data ? data["error"] : "An error has occurred. Please contact the support",
"danger")
}
})
};
dgenies.result.controls.delete_job = function () {
let dialog = $("<div>")
.attr("id", "dialog-confirm")
.attr("title", "Delete job?");
let icon = $("<span>")
.attr("class", "ui-icon ui-icon-help")
.css("float", "left")
.css("margin", "12px 12px 20px 0");
let body = $("<p>");
body.append(icon);
body.append("Confirm deletion of this job? This operation is definitive.");
dialog.append(body);
dialog.dialog({
resizable: false,
height: "auto",
width: 500,
modal: true,
buttons: {
"Yes": function() {
$( this ).dialog( "close" );
dgenies.result.controls.do_delete_job();
},
"No": function () {
$( this ).dialog( "close" );
}
}
});
};
\ No newline at end of file
......@@ -115,7 +115,7 @@ dgenies.result.export.ask_export_fasta = function () {
$( this ).dialog( "close" );
}
}
})
});
};
dgenies.result.export.export_association_table = function () {
......
......@@ -8,5 +8,36 @@ dgenies.result.id_res = null;
dgenies.result.init = function(id_res) {
dgenies.result.id_res = id_res;
dgenies.result.update_cookies();
d3.boxplot.init();
};
dgenies.result.update_cookies = function () {
let cookies = $.cookie("results");
cookies = (cookies !== undefined && cookies.length > 0) ? cookies.split("|") : [];
let index = cookies.indexOf(dgenies.result.id_res);
let need_update = false;
if (index === -1) {
need_update = true;
cookies.unshift(dgenies.result.id_res)
}
$.cookie("results", cookies.join("|"), {path: '/'});
if (need_update) {
dgenies.update_results(cookies);
}
};
dgenies.result.remove_job_from_cookie = function(job) {
let cookies = $.cookie("results");
cookies = cookies !== undefined ? cookies.split("|") : [];
let index = cookies.indexOf(job);
let need_update = false;
if (index > -1) {
need_update = true;
cookies.splice(index, 1);
}
$.cookie("results", cookies.join("|"), {path: '/'});
if (need_update) {
dgenies.update_results(cookies);
}
};
\ No newline at end of file
/*! jquery.cookie v1.4.1 | MIT */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?a(require("jquery")):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}});
\ No newline at end of file
......@@ -9,6 +9,7 @@
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}" type="text/JavaScript"></script>
<script src="{{ url_for('static', filename='js/bootstrap-notify.min.js') }}" type="text/JavaScript"></script>
<script src="{{ url_for('static', filename='js/jquery-ui.min.js') }}" type="text/JavaScript"></script>
<script src="{{ url_for('static', filename='js/jquery.cookie-1.4.1.min.js') }}" type="text/JavaScript"></script>
<script src="{{ url_for('static', filename='js/dgenies.js') }}" type="text/JavaScript"></script>
<script src="{{ url_for('static', filename='js/dgenies.prototypes.js') }}" type="text/JavaScript"></script>
{% endblock %}
......@@ -19,7 +20,7 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css">
<link rel="shortcut icon" href="{{ url_for('static', filename='images/favicon.ico') }}">
</head>
<body role="document" onload="{% block onload %}{% endblock %}">
<body role="document" onload="{% block onload %}dgenies.init();{% endblock %}">
{% block body %}
<div id="main-wrapper">
<!-- Fixed navbar -->
......@@ -39,24 +40,10 @@
<ul class="nav navbar-nav">
<li class="{% if(menu == 'index') %}active{% endif %}"><a href="/">About</a></li>
<li class="{% if(menu == 'run') %}active{% endif %}"><a href="/run">Run</a></li>
<li class="dropdown {% if(menu == 'result') %}active{% endif %}">
<li class="dropdown result {% if(menu == 'result') %}active{% endif %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Results<span
class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
{% block results %}
{% set has_job = False %}
{% if current_result and current_result not in results %}
{% set has_job = True %}
<li><a href="/result/{{ current_result }}">{{ current_result }}</a></li>
{% endif %}
{% if results | length > 0 %}
{% for result in results %}
<li><a href="/result/{{ result }}">{{ result }}</a></li>
{% endfor %}
{% elif not has_job %}
<li><a href="/run">Please run a job!</a></li>
{% endif %}
{% endblock %}
</ul>
</li>
{% if mode == "webserver" %}
......
......@@ -16,7 +16,10 @@
<script src="{{ url_for('static', filename='js/BootstrapMenu.min.js') }}" type="text/JavaScript"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/chosen.min.css') }}" type="text/css">
{% endblock %}
{% block onload %}dgenies.result.init('{{ id }}');{% endblock %}
{% block onload %}
{{ super() }}
dgenies.result.init('{{ id }}');
{% endblock %}
{% block content %}
{{ super() }}
......@@ -71,6 +74,9 @@
<p><input type="button" id="sort-contigs" value="Sort contigs"/></p>
<p><input type="button" id="hide-noise" value="Hide noise"/></p>
<p><input type="button" id="summary" value="Summary"/></p>
{% if not is_gallery %}
<p class="bottom"><input type="button" id="delete-job" value="Delete job"/></p>
{% endif %}
</form>
</div>
</div>
......
......@@ -9,7 +9,10 @@
<script src="{{ url_for('static', filename='js/jquery.fileupload-validate.js') }}"></script>
<script src="{{ url_for('static', filename='js/dgenies.run.js') }}" type="text/JavaScript"></script>
{% endblock %}
{% block onload %}dgenies.run.init('{{ s_id }}',{{ allowed_ext }}, {{ max_upload_file_size }}, '{{ mode }}');{% endblock %}
{% block onload %}
{{ super() }}
dgenies.run.init('{{ s_id }}',{{ allowed_ext }}, {{ max_upload_file_size }}, '{{ mode }}');
{% endblock %}
{% block content %}
<form id="submit_minimap" method=post action="#">
<h2 class="title-launch">Launch map analysis</h2>
......
......@@ -3,7 +3,10 @@
{{ super() }}
<script src="{{ url_for('static', filename='js/dgenies.status.js') }}" type="text/JavaScript"></script>
{% endblock %}
{% block onload %}dgenies.status.init('{{ status }}', '{{ mode }}');{% endblock %}
{% block onload %}
{{ super() }}
dgenies.status.init('{{ status }}', '{{ mode }}');
{% endblock %}
{% block content %}
<h2 class="status">Job name: {{ id_job }}</h2>
<div class="status-body">
......
......@@ -20,12 +20,6 @@ if MODE == "webserver":
from peewee import DoesNotExist
@app.context_processor
def get_launched_results():
cookie = request.cookies.get("results")
return {"results": cookie.split("|") if cookie is not None else set()}
# Main
@app.route("/", methods=['GET'])
def main():
......@@ -182,15 +176,8 @@ def status(id_job):
# Results path
@app.route("/result/<id_res>", methods=['GET'])
def result(id_res):
my_render = render_template("result.html", title=app_title, id=id_res, menu="result", current_result=id_res,
mode=MODE)
response = app.make_response(my_render)
cookie = request.cookies.get("results")
cookie = cookie.split("|") if cookie is not None else []
if id_res not in cookie:
cookie.insert(0, id_res)
response.set_cookie(key="results", value="|".join(cookie), path="/")
return response
return render_template("result.html", title=app_title, id=id_res, menu="result", current_result=id_res, mode=MODE,
is_gallery=Functions.is_in_gallery(id_res, MODE))
@app.route("/gallery", methods=['GET'])
......@@ -222,7 +209,7 @@ def get_file(file, gzip=False): # pragma: no cover
except FileNotFoundError:
abort(404)
except IOError as exc:
print(exc)
print(exc.__traceback__)
abort(500)
......@@ -664,3 +651,13 @@ def send_mail(id_res):
return "OK"
else:
abort(403)
@app.route("/delete/<id_res>", methods=['POST'])
def delete_job(id_res):
job = JobManager(id_job=id_res)
success, error = job.delete()
return jsonify({
"success": success,
"error": error
})
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment