Merge remote-tracking branch 'jmchilton/1801_hdca_delete' into release_18.01

This commit is contained in:
Dannon Baker
2018-02-05 13:06:01 -05:00
6 changed files with 81 additions and 25 deletions
@@ -1,5 +1,6 @@
import DATASET_MODEL from "mvc/dataset/dataset-model";
import BASE_MVC from "mvc/base-mvc";
import Utils from "utils/utils";
import _l from "utils/localization";
//==============================================================================
@@ -280,16 +281,19 @@ var DatasetCollection = Backbone.Model.extend(BASE_MVC.LoggableMixin)
return parsed;
},
/** save this dataset, _Mark_ing it as deleted (just a flag) */
delete: function(options) {
/** save this collection, _Mark_ing it as deleted (just a flag) */
delete: function(recursive, purge, options) {
recursive = recursive || false;
purge = purge || false;
if (this.get("deleted")) {
return jQuery.when();
}
return this.save({ deleted: true }, options);
options = Utils.merge(options, {"method": "delete"});
return this.save({ deleted: true, recursive: recursive, purge: purge }, options);
},
/** save this dataset, _Mark_ing it as undeleted */
/** save this collection, _Mark_ing it as undeleted */
undelete: function(options) {
if (!this.get("deleted") || this.get("purged")) {
if (!this.get("deleted")) {
return jQuery.when();
}
return this.save({ deleted: false }, options);
@@ -302,7 +302,7 @@ var DatasetListItemView = _super.extend(
)}">
<span class="fa fa-floppy-o"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<ul class="dropdown-menu" role="menu">
<li>
<a href="${urls.download}">
${_l("Download dataset")}
@@ -11,6 +11,13 @@ var HDCAListItemEdit = _super.extend(
/** @lends HDCAListItemEdit.prototype */ {
/** logger used to record this.log messages, commonly set to console */
//logger : console,
/** set up: options */
initialize: function(attributes) {
_super.prototype.initialize.call(this, attributes);
/** allow user purge of dataset files? */
this.purgeAllowed = attributes.purgeAllowed || false;
},
/** Override to return editable versions of the collection panels */
_getFoldoutPanelClass: function() {
@@ -25,22 +32,46 @@ var HDCAListItemEdit = _super.extend(
return _super.prototype._renderPrimaryActions.call(this).concat([this._renderDeleteButton()]);
},
/** Render icon-button to delete this collection. */
_renderDeleteButton: function() {
var deleted = this.model.get("deleted");
return faIconButton({
title: deleted ? _l("Dataset collection is already deleted") : _l("Delete"),
classes: "delete-btn",
faIcon: "fa-times",
disabled: deleted,
onclick: () => {
// ...bler... tooltips being left behind in DOM (hover out never called on deletion)
this.$el.find(".icon-btn.delete-btn").trigger("mouseout");
this.model["delete"]();
}
});
return $(`
<div class="dropdown">
<a class="delete-btn icon-btn" title="${_l('Delete')}" data-toggle="dropdown">
<span class="fa fa-times"></span>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li>
<a href="" class="delete-collection">
${_l("Collection Only")}
</a>
</li>
<li>
<a href="" class="delete-collection-and-datasets">
${_l("Delete Datasets")}
</a>
</li>
<li style="display: ${this.purgeAllowed ? 'inherit' : 'none'}">
<a href="" class="delete-collection-and-purge-datasets">
${_l("Permanently Delete Datasets")}
</a>
</li>
</ul>
</div>`);
},
// ......................................................................... misc
events: _.extend(_.clone(_super.prototype.events), {
"click .delete-collection": function(ev) {
this.model["delete"]();
},
"click .delete-collection-and-datasets": function(ev) {
this.model["delete"](true);
},
"click .delete-collection-and-purge-datasets": function(ev) {
this.model["delete"](true, true);
}
}),
// ......................................................................... misc
/** string rep */
toString: function() {
+1 -1
View File
@@ -40,7 +40,7 @@
.icon-btn-group {
display: inline-block;
.icon-btn:not(:last-child) {
.icon-btn:not(:last-of-type) {
margin: 0px;
border-radius: 0px;
border-right: none;
+11 -1
View File
@@ -215,10 +215,20 @@ class DatasetCollectionManager(object):
collection_type_description = self.collection_type_descriptions.for_collection_type(collection_type)
return builder.BoundCollectionBuilder(dataset_collection, collection_type_description)
def delete(self, trans, instance_type, id):
def delete(self, trans, instance_type, id, recursive=False, purge=False):
dataset_collection_instance = self.get_dataset_collection_instance(trans, instance_type, id, check_ownership=True)
dataset_collection_instance.deleted = True
trans.sa_session.add(dataset_collection_instance)
if recursive:
for dataset in dataset_collection_instance.collection.dataset_instances:
self.hda_manager.error_unless_owner(dataset, user=trans.get_user(), current_history=trans.history)
if not dataset.deleted:
dataset.deleted = True
if purge and not dataset.purged:
self.hda_manager.purge(dataset)
trans.sa_session.flush()
def update(self, trans, instance_type, id, payload):
@@ -624,22 +624,26 @@ class HistoryContentsController(BaseAPIController, UsesLibraryMixin, UsesLibrary
# TODO: allow anonymous del/purge and test security on this
@expose_api
def delete(self, trans, history_id, id, purge=False, **kwd):
def delete(self, trans, history_id, id, purge=False, recursive=False, **kwd):
"""
delete( self, trans, history_id, id, **kwd )
* DELETE /api/histories/{history_id}/contents/{id}
delete the HDA with the given ``id``
* DELETE /api/histories/{history_id}/contents/{type}s/{id}
delete the history content with the given ``id`` and specified type (defaults to dataset)
.. note:: Currently does not stop any active jobs for which this dataset is an output.
:type id: str
:param id: the encoded id of the history to delete
:type recursive: bool
:param recursive: if True, and deleted an HDCA also delete containing HDAs
:type purge: bool
:param purge: if True, purge the HDA
:param purge: if True, purge the target HDA or child HDAs of the target HDCA
:type kwd: dict
:param kwd: (optional) dictionary structure containing:
* payload: a dictionary itself containing:
* purge: if True, purge the HDA
* recursive: if True, see above.
.. note:: that payload optionally can be placed in the query string of the request.
This allows clients that strip the request body to still purge the dataset.
@@ -654,7 +658,14 @@ class HistoryContentsController(BaseAPIController, UsesLibraryMixin, UsesLibrary
if contents_type == "dataset":
return self.__delete_dataset(trans, history_id, id, purge=purge, **kwd)
elif contents_type == "dataset_collection":
trans.app.dataset_collections_service.delete(trans, "history", id)
purge = util.string_as_bool(purge)
recursive = util.string_as_bool(recursive)
if kwd.get('payload', None):
# payload takes priority
purge = util.string_as_bool(kwd['payload'].get('purge', purge))
recursive = util.string_as_bool(kwd['payload'].get('recursive', recursive))
trans.app.dataset_collections_service.delete(trans, "history", id, recursive=recursive, purge=purge)
return {'id' : id, "deleted": True}
else:
return self.__handle_unknown_contents_type(trans, contents_type)