diff --git a/beat/web/experiments/api.py b/beat/web/experiments/api.py index 0f7ab797df3811a9c86bc49c8a19db22159ce421..2c1f926f1c0b400d3c8a5e2583566d07047a0eb3 100644 --- a/beat/web/experiments/api.py +++ b/beat/web/experiments/api.py @@ -154,6 +154,9 @@ def experiment_dispatcher(request, username, toolchain_author_name, toolchain_na elif request.method == 'DELETE': return delete_experiment(request, username, toolchain_author_name, toolchain_name, version, label) + elif request.method == 'RESET': + return reset_experiment(request, username, toolchain_author_name, toolchain_name, version, label) + return HttpResponse(status=400) @@ -1421,3 +1424,45 @@ def delete_experiment(request, username, toolchain_author_name, toolchain_name, return HttpResponse(status=204) except: return report_server_error() + + +#---------------------------------------------------------- + + +def reset_experiment(request, username, toolchain_author_name, toolchain_name, version, label): + + # Check that the user can do that + if not(check_api_user(request)): + return HttpResponse(status=403) + + if request.user.is_anonymous(): + return HttpResponse(status=401) + + if request.user.username != username: + return HttpResponse(status=403) + + + # Retrieve the experiment + try: + experiment = Experiment.objects.get(author__username=username, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + label=label + ) + except: + return HttpResponse(status=404) + + + # Check that the experiment can still be deleted + if not(experiment.modifiable()): + return HttpResponse("The experiment isn't resetable anymore (either shared with someone else, or needed by an attestation)", + content_type='text/plain', status=403) + + + # Reset of the experiment + try: + experiment.soft_reset() + return HttpResponse(status=204) + except: + return report_server_error() diff --git a/beat/web/experiments/static/experiments/css/style.css b/beat/web/experiments/static/experiments/css/style.css index 28a73db366ad2ae1aba33ff4e3a92ed595b52f26..2d660f93f07af51477c576797e7785ff9ae36ad7 100644 --- a/beat/web/experiments/static/experiments/css/style.css +++ b/beat/web/experiments/static/experiments/css/style.css @@ -48,6 +48,20 @@ a.button_delete:hover border-color: #CD504A; } + +a.button_reset +{ + float: right; + height: 24px; + line-height: 24px; + min-width: 6em; + width: 6em; + outline: medium none; + color: #990000; + margin-right: 5px; +} + + div.non_modal_back { opacity: 0; diff --git a/beat/web/experiments/templates/experiments/experiment.html b/beat/web/experiments/templates/experiments/experiment.html index b307ea0258d5979332f106c7e8210a72a11b3b85..e70329537d4a63cb74ca8f2f37dfc20dcab398bc 100644 --- a/beat/web/experiments/templates/experiments/experiment.html +++ b/beat/web/experiments/templates/experiments/experiment.html @@ -15,6 +15,7 @@ <link rel="stylesheet" href="{% static "toolchains/css/viewer.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/contribution-sharing.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/contribution-deletion.css" %}" type="text/css" media="screen" /> + <link rel="stylesheet" href="{% static "ui/css/contribution-reset.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/spinner-bars.css" %}" type="text/css" media="screen" /> {% endblock %} @@ -30,6 +31,7 @@ <script src="{% static "experiments/js/dialogs.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "algorithms/js/utils.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "ui/js/deletion.js" %}" type="text/javascript" charset="utf-8"></script> + <script src="{% static "ui/js/reset.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "ui/js/sharing.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "ui/js/rgraph/RGraph.common.core.js" %}" type="text/javascript" charset="utf-8"></script> @@ -104,6 +106,7 @@ { {% if experiment.modifiable %} $('a.button_delete').show(); + $('a.button_reset').show(); {% endif %} $('a.button_cancel').hide(); } @@ -188,6 +191,7 @@ {% ifequal request.user experiment.author %} {% if experiment.modifiable %} <a href="#" class="button button_delete" title="Delete the experiment" style="display:none">Delete</a> + <a href="#" class="button button_reset" title="Reset the experiment" style="display:none">Reset</a> {% endif %} {% ifnotequal experiment.status "C" %} <a href="#" class="button button_cancel" title="Cancel the experiment" style="display:none">Cancel</a> @@ -263,6 +267,7 @@ {% experiment_sharing "sharing" %} {% experiment_deletion "deletion" %} + {% experiment_reset "reset" %} {% experiment_cancellation "cancellation" %} @@ -306,6 +311,15 @@ if (data.done) $('a.button_delete').show(); + + $('a.button_reset').click(function() { + beat.ui.reset.show('reset', '{{ experiment.fullname }}', + '{{ URL_PREFIX }}/api/experiments/', + '{{ URL_PREFIX }}/user/{{ experiment.author.username }}/?tab=experiments'); + }); + + if (data.done) + $('a.button_reset').show(); {% endif %} {% ifnotequal experiment.status "C" %} diff --git a/beat/web/experiments/templates/experiments/setup.html b/beat/web/experiments/templates/experiments/setup.html index c075f337ae183214cada067838b87c63a490816c..6d4c7e437a90ecd68045c2861ec403407aa4b959 100644 --- a/beat/web/experiments/templates/experiments/setup.html +++ b/beat/web/experiments/templates/experiments/setup.html @@ -14,6 +14,7 @@ <link rel="stylesheet" href="{% static "toolchains/css/viewer.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "experiments/css/style.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/contribution-deletion.css" %}" type="text/css" media="screen" /> + <link rel="stylesheet" href="{% static "ui/css/contribution-reset.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/smart-selector.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/list-selector.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/spinner-bars.css" %}" type="text/css" media="screen" /> @@ -79,6 +80,7 @@ {% smart_selector "smart_selector" %} {% algorithm_mapping "algorithm_mapping" %} {% experiment_deletion "deletion" %} + {% experiment_reset "reset" %} {% list_selector "list_selector" %} diff --git a/beat/web/experiments/templatetags/experiment_tags.py b/beat/web/experiments/templatetags/experiment_tags.py index ae131942e1899f3fb133d6f9ec1529e158537280..a181a262894b13d73240973786686497b19d9359 100644 --- a/beat/web/experiments/templatetags/experiment_tags.py +++ b/beat/web/experiments/templatetags/experiment_tags.py @@ -127,6 +127,19 @@ register.inclusion_tag('ui/contribution_deletion.html')(experiment_deletion) #-------------------------------------------------- +def experiment_reset(id): + return { 'dialog_id': id, + 'URL_PREFIX': settings.URL_PREFIX, + 'contribution_label': 'experiment', + } + + +register.inclusion_tag('ui/contribution_reset.html')(experiment_reset) + + +#-------------------------------------------------- + + def experiment_cancellation(id): return { 'dialog_id': id, 'URL_PREFIX': settings.URL_PREFIX, diff --git a/beat/web/navigation/templates/navigation/user.html b/beat/web/navigation/templates/navigation/user.html index 38e78fd86ce33c72d2eb64e0f066902f61d53183..52cd6f63f3b921836163b0e68fc16e94d2e3cb7a 100644 --- a/beat/web/navigation/templates/navigation/user.html +++ b/beat/web/navigation/templates/navigation/user.html @@ -20,6 +20,7 @@ {% else %} <link rel="stylesheet" href="{% static "ui/css/contribution-list.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/contribution-deletion.css" %}" type="text/css" media="screen" /> + <link rel="stylesheet" href="{% static "ui/css/contribution-reset.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/contribution-sharing.css" %}" type="text/css" media="screen" /> <link rel="stylesheet" href="{% static "ui/css/contribution-forking.css" %}" type="text/css" media="screen" /> {% endifequal %} @@ -31,6 +32,7 @@ {{ block.super }} <script src="{% static "ui/js/deletion.js" %}" type="text/javascript" charset="utf-8"></script> + <script src="{% static "ui/js/reset.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "ui/js/sharing.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "ui/js/forking.js" %}" type="text/javascript" charset="utf-8"></script> diff --git a/beat/web/ui/static/ui/css/contribution-reset.css b/beat/web/ui/static/ui/css/contribution-reset.css new file mode 100644 index 0000000000000000000000000000000000000000..3665af61258a671933d5f0655e2b3391f79a86d1 --- /dev/null +++ b/beat/web/ui/static/ui/css/contribution-reset.css @@ -0,0 +1,26 @@ +div.contribution_reset span.contribution_name +{ + font-weight: bold; +} + + +div.contribution_reset p.warning +{ + color: #FF0000; +} + + +button#button-reset-reset +{ + font-weight: bold; + color: #990000; +} + + +button#button-reset-reset:hover +{ + background-color: #B33630; + background-image: linear-gradient(#DC5F59, #B33630); + border-color: #CD504A; + color: #FFFFFF; +} diff --git a/beat/web/ui/static/ui/js/list.js b/beat/web/ui/static/ui/js/list.js index 0425d726a1afd5c9cfadf0af65858956fa70eae2..dc822413ca7b498a26281e0df8515808c3034582 100644 --- a/beat/web/ui/static/ui/js/list.js +++ b/beat/web/ui/static/ui/js/list.js @@ -418,6 +418,23 @@ beat.ui.list.ContributionList.prototype._add_contribution_to_list = function( }); } + if (this.callbacks.reset && + ((this.mode == beat.ui.list.MODE_SEARCH) || contribution.can_be_deleted)) + { + var reset_button = document.createElement('a'); + reset_button.href = '#'; + reset_button.className = 'button_reset button'; + reset_button.textContent = 'Reset'; + reset_button.title = 'Reset this ' + this.contribution_label; + li.appendChild(reset_button); + + $(reset_button).click(function() { + panel.callbacks.reset(contribution.name); + return false; + }); + } + + if (this.callbacks.share && (contribution.accessibility !== 'public')) { var share_button = document.createElement('a'); diff --git a/beat/web/ui/static/ui/js/reset.js b/beat/web/ui/static/ui/js/reset.js new file mode 100644 index 0000000000000000000000000000000000000000..28ad4635a3077f8f00e90688282ad3acf97b8fb6 --- /dev/null +++ b/beat/web/ui/static/ui/js/reset.js @@ -0,0 +1,74 @@ +/* beat.ui.reset.js + + Implementation of the 'contribution reset' dialog +*/ + + +// Declaration of our namespaces +if (beat === undefined) + var beat = {} + +if (beat.ui === undefined) + beat.ui = {} + +if (beat.ui.reset === undefined) + beat.ui.reset = {} + + + +beat.ui.reset.show = function(dialog_id, contribution_fullname, api_url, redirect_url) +{ + // Create the dialog + $('#' + dialog_id).dialog({ + autoOpen: false, + resizable: false, + width: Math.min($(window).width() * 0.6, 700), + position: { my: "center", at: "center", of: window }, + modal: true, + closeOnEscape: true, + buttons: [ + { + id: 'button-' + dialog_id + '-reset', + text: 'Yes, reset it', + click: function() { + var data = {}; + + $.ajax({ + type: "RESET", + url: api_url + contribution_fullname + '/', + + success: function(data) { + $('#' + dialog_id).dialog("close"); + window.location.href = redirect_url; + }, + + error: function(jqXHR, textStatus, errorThrown) { + if ((jqXHR.status == 403) && (jqXHR.responseText.length > 0)) + alert(jqXHR.responseText); + else + alert('Error: ' + errorThrown); + + $(this).dialog("close"); + } + }); + } + }, + { + id: 'button-' + dialog_id + '-cancel', + text: 'Cancel', + click: function() { + $(this).dialog("close"); + } + } + ] + }); + + + // Initialise the dialog content + $('#' + dialog_id + ' .contribution_name').text(contribution_fullname); + // $('#button-' + dialog_id + '-reset').button("disable"); + + + // Display the dialog + $('#' + dialog_id).dialog("open"); +} diff --git a/beat/web/ui/templates/ui/contribution_reset.html b/beat/web/ui/templates/ui/contribution_reset.html new file mode 100644 index 0000000000000000000000000000000000000000..8a9f65091b103e03a00d56301b7abe42eb498e2f --- /dev/null +++ b/beat/web/ui/templates/ui/contribution_reset.html @@ -0,0 +1,5 @@ +<div id="{{ dialog_id }}" class="contribution_reset" title="Please confirm..." style="display:none"> + <p class="label">Are you sure you want to reset the {{ contribution_label }} <span class="contribution_name">{{ contribution_name }}</span>?</p> + + <p class="warning">Once you reset this {{ contribution_label }}, there is no going back. Please be certain.</p> +</div>