Skip to content

Commit 5f56c43

Browse files
author
Max Burnette
committed
implementation of bulk deletion, tagging of files
1 parent 2a827fa commit 5f56c43

File tree

2 files changed

+197
-68
lines changed

2 files changed

+197
-68
lines changed

app/views/datasets/filesAndFolders.scala.html

Lines changed: 197 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
filepage: Int, next: Boolean, fileList:List[File], fileComments: Map[UUID, Int], space: Option[String],
33
filter: Option[String])(implicit user: Option[models.User])
44

5+
@import play.api.Play.current
6+
57
<!-- Breadcrumbs -->
68
@if(folderHierarchy.length > 0 ) {
79
<div><h2 id='folderpath'>
@@ -52,7 +54,7 @@
5254
</div>
5355
</td>
5456
<td width="20%" >
55-
<div id="selected-count-box"></div>
57+
<div id="selected-count-box">Marked Files (<b>0</b>)</div>
5658
</td>
5759
<td width="30%">
5860
<label class="sortchoice" for="js-sort-single">Sort By:
@@ -82,57 +84,216 @@
8284
//$('#selected-count-box').html('Marked Files (<b>'+fileUUIDs.length+'</b>)')
8385
$('#selected-count-box').html('<div class="dropdown"><a href="#" class="dropdown-toggle" ' +
8486
'data-toggle="dropdown" aria-expanded="false"> Marked Files (<b>'+fileUUIDs.length+'</b>)' +
85-
'<b class="caret"></b></a><ul class="dropdown-menu"><li>' +
86-
'<a onclick="deleteSelectedFiles();">Delete All</a></li></ul>' +
87+
'<b class="caret"></b></a><ul class="dropdown-menu">' +
88+
// TODO: Show All if only marked are shown
89+
'<li><a onclick="showOnlyMarked();"><span class="glyphicon glyphicon-ok"/>&nbsp;Show Only Marked</a></li>' +
90+
'<li><a onclick="downloadMarked();"><span class="glyphicon glyphicon-download-alt"/>&nbsp;Download All</a></li>' +
91+
'<li><a onclick="confirmTagMarked();"><span class="glyphicon glyphicon-tag"/>&nbsp;Tag All</a></li>' +
92+
'<li><a onclick="confirmDeleteMarked();"><span class="glyphicon glyphicon-trash"/>&nbsp;Delete All</a></li>' +
93+
'<li><a onclick="clearMarked();"><span class="glyphicon glyphicon-erase"/>&nbsp;Clear All</a></li></ul>' +
8794
'</div>')
8895
} else {
8996
$('#selected-count-box').html('Marked Files (<b>0</b>)')
9097
}
9198
}
9299

93-
function deleteSelectedFiles() {
94-
console.log("Are you sure?");
100+
function confirmDeleteMarked() {
101+
var selected = $.cookie('[email protected]');
102+
if (selected) {
103+
selected = selected.split(',');
104+
if (selected.length > 0) {
105+
var msg = "Are you sure you want to delete "+String(selected.length)+" marked files?";
106+
107+
var modalHTML = '<div id="confirm-delete" class="modal fade" role="dialog">';
108+
modalHTML += '<div class="modal-dialog">';
109+
modalHTML += '<div class="modal-content">';
110+
modalHTML += '<div class="modal-header">';
111+
modalHTML += '<button type="button" class="close" data-dismiss="modal">&times;</button>';
112+
modalHTML += '<h4 class="modal-title">Confirm</h4>';
113+
modalHTML += '</div>';
114+
modalHTML += '<div class="modal-body">';
115+
modalHTML += '<p>' + msg + '</p>';
116+
modalHTML += '</div>';
117+
modalHTML += '<div class="modal-footer">';
118+
modalHTML += '<button type="button" class="btn btn-link" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> Cancel</button>';
119+
modalHTML += '<a type="button" class="btn btn-primary" id="OKModalButton" onclick="deleteAllMarked();" data-dismiss="modal"><span class="glyphicon glyphicon-ok"></span> OK</a>';
120+
modalHTML += '</div>';
121+
modalHTML += '</div>';
122+
modalHTML += '</div>';
123+
modalHTML += '</div>';
124+
125+
var confirmModal = $(modalHTML);
126+
confirmModal.modal();
127+
confirmModal.modal("show");
128+
} else {
129+
notify("No files currently marked", "warning")
130+
}
131+
} else {
132+
notify("No files currently marked", "warning")
133+
}
134+
}
135+
136+
function deleteAllMarked() {
137+
// TODO: Would be nice to have a bulk endpoint for this eventually that takes a string of comma-separated UUIDs
138+
var selected = $.cookie('[email protected]');
139+
if (selected) {
140+
selected = selected.split(',');
141+
for (entry in selected) {
142+
var request = jsRoutes.api.Files.removeFile(selected[entry]).ajax({
143+
type: 'DELETE'
144+
});
145+
// If this is in request.done, only one ID gets removed in the for loop, so remove them all now
146+
removeFileFromMarked(selected[entry]);
147+
request.done(function (response, textStatus, jqXHR) {
148+
getUpdatedFilesAndFolders();
149+
});
150+
request.fail(function (jqXHR, textStatus, errorThrown){
151+
console.error("The following error occured: " + textStatus, errorThrown);
152+
notify("Could not delete marked file "+selected[entry]+": " + errorThrown, "error");
153+
// Add it back to selected list
154+
addFileToMarked(selected[entry]);
155+
});
156+
}
157+
}
158+
}
159+
160+
function showOnlyMarked() {
95161
confirmDeleteMarked('@dataset.id');
96162
}
97163

164+
function downloadMarked() {
165+
// TODO: Downloading selected files as Zip - look at downloading folders tasks
166+
console.log("Not implemented.")
167+
}
168+
169+
function confirmTagMarked() {
170+
var selected = $.cookie('[email protected]');
171+
if (selected) {
172+
var modalHTML = `
173+
<div id="enter-tag" class="modal fade" role="dialog">
174+
<div class="modal-dialog">
175+
<div class="modal-content">
176+
<div class="modal-header">
177+
<button type="button" class="close" data-dismiss="modal">&times;</button>
178+
<h4 class="modal-title">Tag All Marked Files</h4>
179+
</div>
180+
<div class="modal-body">
181+
<p>
182+
Multiple tags may be entered, separated by commas.
183+
</p>
184+
<input maxlength="@play.api.Play.configuration.getInt("clowder.tagLength").getOrElse(100)"
185+
type="text" id="bulk-tag-selector" class="form-control add-resource" placeholder="Enter a tag...">
186+
187+
</div>
188+
<div class="modal-footer">
189+
<button type="button" class="btn btn-link" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> Cancel</button>
190+
<a type="button" class="btn btn-primary" id="OKModalButton" onclick="tagMarked()"><span class="glyphicon glyphicon-ok"></span> OK</a>
191+
</div>
192+
</div>
193+
</div>
194+
</div>
195+
`;
196+
197+
var confirmModal = $(modalHTML);
198+
confirmModal.modal();
199+
confirmModal.modal("show");
200+
} else {
201+
notify("No files currently marked", "warning")
202+
}
203+
}
204+
205+
function tagMarked() {
206+
// TODO: Would be nice to have a bulk endpoint for this eventually that takes a string of comma-separated UUIDs
207+
var tag = $('#bulk-tag-selector')[0].value;
208+
if (tag.length > 0) {
209+
var selected = $.cookie('[email protected]');
210+
if (selected) {
211+
selected = selected.split(',');
212+
for (entry in selected) {
213+
var request = jsRoutes.api.Files.addTags(selected[entry]).ajax({
214+
type: 'POST',
215+
dataType: 'json',
216+
contentType: 'application/json',
217+
data: JSON.stringify({
218+
"tags": tag.split(',')
219+
})
220+
});
221+
request.done(function (response, textStatus, jqXHR) {
222+
getUpdatedFilesAndFolders();
223+
});
224+
request.fail(function (jqXHR, textStatus, errorThrown) {
225+
console.error("The following error occured: " + textStatus, errorThrown);
226+
notify("Could not tag marked file " + selected[entry] + ": " + errorThrown, "error");
227+
});
228+
}
229+
}
230+
}
231+
232+
233+
234+
235+
236+
if (tag.length > 0) {
237+
var request = jsRoutes.api.Selected.tagAll(tag.split(",")).ajax({
238+
type: 'POST'
239+
});
240+
request.done(function (response, textStatus, jqXHR) {
241+
notify("Tag(s) successfully added.", "success", false, 2000);
242+
});
243+
request.fail(function (jqXHR, textStatus, errorThrown){
244+
console.error("The following error occured: " + textStatus, errorThrown);
245+
notify("Could not tag selections: " + errorThrown, "error");
246+
});
247+
248+
} else {
249+
console.log("No tag was provided.")
250+
}
251+
$("#enter-tag").modal("hide")
252+
}
253+
254+
function clearMarked() {
255+
// Set cookie to empty, redraw the file list to get corrected display
256+
$.cookie('[email protected]', "");
257+
getUpdatedFilesAndFolders();
258+
}
259+
260+
function addFileToMarked(file_id) {
261+
// TODO: Use Play framework cookies instead of jquery flavor for better security
262+
var selected = $.cookie('[email protected]');
263+
if (selected) {
264+
if (selected.indexOf(file_id) == -1)
265+
selected += ","+file_id;
266+
} else {
267+
selected = file_id;
268+
}
269+
$.cookie('[email protected]', selected);
270+
271+
$("a[data-id='"+file_id+"'] span.glyphicon").removeClass('glyphicon-plus');
272+
$("a[data-id='"+file_id+"'] span.glyphicon").addClass('glyphicon-ok');
273+
updateSelectedFileCount();
274+
}
275+
276+
function removeFileFromMarked(file_id) {
277+
var selected = $.cookie('[email protected]');
278+
if (selected && selected.indexOf(file_id) > -1) {
279+
selected = selected.replace(file_id+',', '').replace(','+file_id, '').replace(file_id, '');
280+
$.cookie('[email protected]', selected, {expires: 14});
281+
}
282+
283+
$("a[data-id='"+file_id+"'] span.glyphicon").removeClass('glyphicon-ok');
284+
$("a[data-id='"+file_id+"'] span.glyphicon").addClass('glyphicon-plus');
285+
updateSelectedFileCount();
286+
}
287+
98288
$(document).ready(function() {
99289
$('.fileselect').click(function() {
100290
var file_id = $(this).data("id");
101291

102292
if ($("a[data-id='" + file_id + "'] span.glyphicon").hasClass('glyphicon-plus')) {
103-
// SELECT THE FILE
104-
// TODO: Add Clear All option
105-
var selected = $.cookie('[email protected]');
106-
if (selected) {
107-
if (selected.indexOf(file_id) == -1)
108-
selected += ","+file_id;
109-
} else {
110-
selected = file_id;
111-
}
112-
$.cookie('[email protected]', selected);
113-
114-
$("a[data-id='"+file_id+"'] span.glyphicon").removeClass('glyphicon-plus');
115-
$("a[data-id='"+file_id+"'] span.glyphicon").addClass('glyphicon-ok');
116-
updateSelectedFileCount();
293+
addFileToMarked(file_id)
117294
} else {
118-
// DESELECT THE FILE
119-
var selected = $.cookie('[email protected]');
120-
if (selected && selected.indexOf(file_id) > -1) {
121-
selected = selected.replace(file_id+',', '').replace(','+file_id, '').replace(file_id, '');
122-
$.cookie('[email protected]', selected, {expires: 14});
123-
}
295+
removeFileFromMarked(file_id);
124296

125-
$("a[data-id='"+file_id+"'] span.glyphicon").removeClass('glyphicon-ok');
126-
$("a[data-id='"+file_id+"'] span.glyphicon").addClass('glyphicon-plus');
127-
updateSelectedFileCount();
128-
// TODO: plain jquery cookies? logout could still see them. play uses key
129-
// TODO: show only marked files
130-
// TODO: Downloading selected files as Zip - look at downloading folders tasks
131-
// make separate tasks for my SIMPL task for a sprint with more granularity
132-
133-
// TODO: convert selection datasets to a collection
134-
// TODO: Selections become Favorites
135-
// TODO: recently viewed list?
136297
}
137298
});
138299

public/javascripts/deleteUtils.js

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -48,38 +48,6 @@ function confirmDeleteSelected() {
4848
}
4949
}
5050

51-
function confirmDeleteMarked(datasetId) {
52-
console.log(datasetId);
53-
var selected = $.cookie('selected-files-'+datasetId);
54-
if (selected) {
55-
var msg = "Are you sure you want to delete the selected files?";
56-
57-
var modalHTML = '<div id="confirm-delete" class="modal fade" role="dialog">';
58-
modalHTML += '<div class="modal-dialog">';
59-
modalHTML += '<div class="modal-content">';
60-
modalHTML += '<div class="modal-header">';
61-
modalHTML += '<button type="button" class="close" data-dismiss="modal">&times;</button>';
62-
modalHTML += '<h4 class="modal-title">Confirm</h4>';
63-
modalHTML += '</div>';
64-
modalHTML += '<div class="modal-body">';
65-
modalHTML += '<p>' + msg + '</p>';
66-
modalHTML += '</div>';
67-
modalHTML += '<div class="modal-footer">';
68-
modalHTML += '<button type="button" class="btn btn-link" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> Cancel</button>';
69-
modalHTML += '<a type="button" class="btn btn-primary" id="OKModalButton" href="javascript:deleteAllSelections()"><span class="glyphicon glyphicon-ok"></span> OK</a>';
70-
modalHTML += '</div>';
71-
modalHTML += '</div>';
72-
modalHTML += '</div>';
73-
modalHTML += '</div>';
74-
75-
var confirmModal = $(modalHTML);
76-
confirmModal.modal();
77-
confirmModal.modal("show");
78-
} else {
79-
notify("No files currently selected", "warning")
80-
}
81-
}
82-
8351
function confirmDeleteTemplate(message, resourceType, resourceId, isreload, url) {
8452
var modalHTML = '<div id="confirm-delete" class="modal fade" role="dialog">';
8553
modalHTML += '<div class="modal-dialog">';

0 commit comments

Comments
 (0)