gridftp: support archive features in wcss
[qcg-portal.git] / qcg / templates / qcg / gridftp.html
1 {% extends 'qcg/base.html' %}
2 {% load staticfiles bootstrap3 %}
3
4 {% block extra_css %}
5     <link href="{% static 'qcg/selectize/selectize.bootstrap3.css' %}" rel="stylesheet">
6
7     <style>
8         html {
9             height: 100%;
10         }
11
12         body {
13             height: 100%;
14             margin-bottom: 0;
15         }
16
17         body > .container {
18             height: calc(100% - 122px);
19             overflow-y: hidden;
20         }
21     </style>
22 {% endblock %}
23
24 {% block extra_js %}
25     <script src="{% static 'qcg/cookie/jquery.cookie.min.js' %}"></script>
26     <script src="{% static 'qcg/globals.js' %}"></script>
27     {% include 'filex/source.js.html' %}
28
29     <script>
30         var filex = filex || {},
31             hostArchiveSupport = ['moss.man.poznan.pl', 'ui.plgrid.wcss.wroc.pl'];
32
33         $(function () {
34             'use strict';
35
36             filex.initialLoad();
37
38             var statusTimeout;
39
40             String.prototype.endsWith = function(suffix) {
41                 return this.indexOf(suffix, this.length - suffix.length) !== -1;
42             };
43
44             function status(msg) {
45                 clearTimeout(statusTimeout);
46                 statusTimeout = setTimeout(function() {
47                     $('#status').text('');
48                 }, 3000);
49
50                 $('#status').text(msg);
51             }
52
53             function failModal(msg) {
54                 return function(xhr) {
55                     var $errorModal = $('#error-modal');
56
57                     $errorModal.find('#error-modal-label').text('Błąd serwera');
58                     $errorModal.find('.modal-body').html($('<h4>', {text: msg}));
59
60                     var error = (xhr.responseJSON || {}).error || undefined;
61
62                     if (typeof error === 'string')
63                         $errorModal.find('.modal-body').append($('<pre>', {text: error}));
64
65                     filex.idle();
66                     $errorModal.modal();
67
68                     console.error(arguments);
69                 };
70             }
71
72             function conflictingName(name, modal) {
73                 if (filex.files.some(function(item) { return item.get('name') == name })) {
74                     $('<div>', {
75                         'class': 'alert alert-danger',
76                         html: '<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> Plik o podanej już nazwie istnieje!'
77                     }).prependTo(modal.find('.modal-body'));
78
79                     return true;
80                 }
81
82                 return false;
83             }
84
85             filex.files.on('change:checked reset', function() {
86                 var selected = filex.selectedFiles().length,
87                     supportsArchive = hostArchiveSupport.indexOf(filex.host) != -1;
88
89                 $('#btn-rename').toggleClass('disabled', selected != 1);
90                 $('#btn-delete').toggleClass('disabled', selected == 0);
91                 $('#btn-compress').toggleClass('disabled', !supportsArchive || selected == 0);
92
93                 if (supportsArchive && selected == 1) {
94                     var filename = filex.selectedFiles()[0].get('name'),
95                         is_archive = _.some(['.zip', '.tar.gz', '.tgz', '.tar.bz2', 'tbz'], function(ext) {
96                             return filename.endsWith(ext);
97                         });
98
99                     $('#btn-extract').toggleClass('disabled', !is_archive);
100                 }
101                 else {
102                     $('#btn-extract').addClass('disabled');
103                 }
104             });
105
106             $('form').on('show.bs.modal', function() {
107                 $(this).find('.alert').remove();
108                 this.reset();
109             }).on('shown.bs.modal', function() {
110                 $(this).find('input[type="text"]')[0].focus();
111             });
112
113             $('#btn-upload').on('click', function() {
114                 var url = '{% url 'gridftp_upload' %}?' + $.param({host: filex.host, path: filex.path.full()});
115
116                 var win = window.open(url, url, 'height=500,width=800');
117                 win.focus();
118             });
119
120             $('#btn-delete').on('click', function() {
121                 var selected = _.groupBy(filex.selectedFiles(), function(item) { return item.get('type') }),
122                     path = filex.path.full() + '/',
123                     dirs = _.map(selected.directory || [], function (item) { return path + item.get('name') }),
124                     files = _.map(selected.file || [], function (item) { return path + item.get('name') }),
125                     data = {
126                         host: filex.host,
127                         dirs: dirs,
128                         files: files
129                     },
130                     $confirmModal = $('#confirm-modal'),
131                     $confirmList = $confirmModal.find('ul').html('');
132
133                 _.each(filex.selectedFiles(), function(item) {
134                     $('<li>', {text: item.get('name')}).appendTo($confirmList);
135                 });
136
137                 $('#btn-confirm').off().on('click', function() {
138                     filex.busy();
139
140                     $.post('{% url 'filex:delete' %}', data, function(response) {
141                         var keys = Object.keys(response.fail);
142
143                         if (keys.length) {
144                             var $errorModal = $('#error-modal'),
145                                 $errorBody = $errorModal.find('.modal-body')
146                                                         .html($('<h4>', {text: 'Wystąpiły problemy podczas usuwania:'})),
147                                 $errorList = $('<dl>', {'class': 'dl-horizontal'}).appendTo($errorBody);
148
149                             $errorModal.find('#error-modal-label').text('Błąd');
150
151                             for (var i in keys) {
152                                 if(keys.hasOwnProperty(i)) {
153                                     $('<dt>', {text: keys[i].replace(path, '')}).appendTo($errorList);
154                                     $('<dd>', {text: response.fail[keys[i]]}).appendTo($errorList);
155                                 }
156                             }
157
158                             $errorModal.modal();
159                             filex.idle();
160                         }
161                         else {
162                             status('Usuwanie zakończone pomyślnie');
163                         }
164
165                         if (response.done.length)
166                             filex.reloadFiles();
167
168                     }, 'json').fail(failModal('Nie udało się usunąć plików'));
169
170                     $confirmModal.modal('hide');
171                 });
172
173                 $confirmModal.modal();
174             });
175
176             $('#mkdir-form').on('submit', function(e) {
177                 var $this = $(this);
178
179                 e.preventDefault();
180
181                 if (conflictingName($this.find('#id_name').val(), $this))
182                     return;
183
184                 filex.busy();
185                 $this.modal('hide');
186
187                 $this.find('#id_host').val(filex.host);
188                 $this.find('#id_path').val(filex.path.full());
189
190                 $.post($this.attr('action'), $this.serialize(), function() {
191                     status('Katalog utworzono pomyślnie');
192                     filex.reloadFiles();
193                 }, 'json').fail(failModal('Nie udało się utworzyć katalogu'));
194             });
195
196             $('#rename-form').on('show.bs.modal', function() {
197                 $(this).find('#id_dst').val(filex.selectedFiles()[0].get('name'));
198             }).on('submit', function(e) {
199                 e.preventDefault();
200
201                 var $this = $(this),
202                     path = filex.path.full() + '/',
203                     newName = $this.find('#id_dst').val(),
204                     data = {
205                         host: filex.host,
206                         src: path + filex.selectedFiles()[0].get('name'),
207                         dst: path + newName
208                     };
209
210                 if (conflictingName(newName, $this))
211                     return;
212
213                 filex.busy();
214                 $this.modal('hide');
215
216                 $.post($this.attr('action'), data, function() {
217                     status('Nazwę zmieniono pomyślnie');
218                     filex.reloadFiles();
219                 }, 'json').fail(failModal('Nie udało się zmienić nazwy'));
220             });
221
222             $('#compress-form').on('submit', function(e) {
223                 e.preventDefault();
224
225                 var $this = $(this),
226                     name = $this.find('#id_archive').val(),
227                     type = $this.find('#id_type').val(),
228                     path = filex.path.full(),
229                     archive = name + (name.endsWith(type) ? '' : type),
230                     data = {
231                         host: filex.host,
232                         path: path,
233                         files: _.map(filex.selectedFiles(), function (item) { return item.get('name') }),
234                         archive: path  + '/' + archive
235                     };
236
237                 if (conflictingName(archive, $this))
238                     return;
239
240                 filex.busy();
241                 $this.modal('hide');
242
243                 $.post($this.attr('action'), data, function() {
244                     status('Archiwum utworzono pomyślnie');
245                     filex.reloadFiles();
246                 }, 'json').fail(failModal('Nie udało się utworzyć archiwum'));
247             });
248
249             $('#btn-extract').on('click', function() {
250                 filex.busy();
251
252                 var data = {
253                     host: filex.host,
254                     path: filex.path.full() + '/' + filex.selectedFiles()[0].get('name'),
255                     dst: filex.path.full()
256                 };
257
258                 $.post('{% url 'filex:extract' %}', data, function() {
259                     status('Archiwum rozpakowano pomyślnie');
260                     filex.reloadFiles();
261                 }, 'json').fail(failModal('Nie udało się rozpakować archiwum'));
262             });
263         })
264     </script>
265 {% endblock extra_js %}
266
267 {% block title %}Zarządzanie plikami GridFTP{% endblock %}
268
269 {% block container %}
270     {% include 'filex/source.html' %}
271
272     <div id="confirm-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirm-modal-label" aria-hidden="true">
273         <div class="modal-dialog">
274             <div class="modal-content">
275                 <div class="modal-header">
276                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
277                         <span aria-hidden="true">&times;</span>
278                     </button>
279                     <h4 class="modal-title" id="confirm-modal-label">Usuwanie plików</h4>
280                 </div>
281                 <div class="modal-body">
282                     <h4>Czy na pewno usunąć następujące elementy?</h4>
283                     <ul></ul>
284                 </div>
285                 <div class="modal-footer">
286                     <button type="button" class="btn btn-default" data-dismiss="modal">Anuluj</button>
287                     <button id="btn-confirm" type="button" class="btn btn-primary">OK</button>
288                 </div>
289             </div>
290         </div>
291     </div>
292
293     <div id="error-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="error-modal-label" aria-hidden="true">
294         <div class="modal-dialog">
295             <div class="modal-content">
296                 <div class="modal-header">
297                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
298                         <span aria-hidden="true">&times;</span>
299                     </button>
300                     <h4 class="modal-title" id="error-modal-label"></h4>
301                 </div>
302                 <div class="modal-body">
303                 </div>
304                 <div class="modal-footer">
305                     <button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
306                 </div>
307             </div>
308         </div>
309     </div>
310
311     <form id="mkdir-form" action="{% url 'filex:mkdir' %}" class="modal fade form-horizontal" tabindex="-1" role="dialog" aria-labelledby="mkdir-modal-label" aria-hidden="true">
312         <div class="modal-dialog">
313             <div class="modal-content">
314                 <div class="modal-header">
315                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
316                         <span aria-hidden="true">&times;</span>
317                     </button>
318                     <h4 class="modal-title" id="mkdir-modal-label">Nowy katalog</h4>
319                 </div>
320                 <div class="modal-body">
321                     {% csrf_token %}
322                     {% bootstrap_form new_dir_form layout='horizontal' %}
323                 </div>
324                 <div class="modal-footer">
325                     <button type="button" class="btn btn-default" data-dismiss="modal">Anuluj</button>
326                     <button type="submit" class="btn btn-primary">OK</button>
327                 </div>
328             </div>
329         </div>
330     </form>
331
332     <form id="rename-form" action="{% url 'filex:move' %}" class="modal fade form-horizontal" tabindex="-1" role="dialog" aria-labelledby="rename-modal-label" aria-hidden="true">
333         <div class="modal-dialog">
334             <div class="modal-content">
335                 <div class="modal-header">
336                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
337                         <span aria-hidden="true">&times;</span>
338                     </button>
339                     <h4 class="modal-title" id="rename-modal-label">Zmień nazwę</h4>
340                 </div>
341                 <div class="modal-body">
342                     {% csrf_token %}
343                     {% bootstrap_form rename_form layout='horizontal' %}
344                 </div>
345                 <div class="modal-footer">
346                     <button type="button" class="btn btn-default" data-dismiss="modal">Anuluj</button>
347                     <button type="submit" class="btn btn-primary">OK</button>
348                 </div>
349             </div>
350         </div>
351     </form>
352
353     <form id="compress-form" action="{% url 'filex:compress' %}" class="modal fade form-horizontal" tabindex="-1" role="dialog" aria-labelledby="compress-modal-label" aria-hidden="true">
354         <div class="modal-dialog">
355             <div class="modal-content">
356                 <div class="modal-header">
357                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
358                         <span aria-hidden="true">&times;</span>
359                     </button>
360                     <h4 class="modal-title" id="compress-modal-label">Podaj nazwę archiwum</h4>
361                 </div>
362                 <div class="modal-body">
363                     {% csrf_token %}
364                     {% bootstrap_form archive_form layout='horizontal' %}
365                 </div>
366                 <div class="modal-footer">
367                     <button type="button" class="btn btn-default" data-dismiss="modal">Anuluj</button>
368                     <button type="submit" class="btn btn-primary">OK</button>
369                 </div>
370             </div>
371         </div>
372     </form>
373 {% endblock container %}
374
375 {% block footer %}
376     <footer class="navbar navbar-default navbar-fixed-bottom">
377         <div class="container">
378             <div class="btn-toolbar" role="toolbar" style="float: left">
379                 <div class="btn-group" role="group">
380                     <button id="btn-upload" class="btn btn-default navbar-btn">Wgraj plik</button>
381                     <button class="btn btn-default navbar-btn" data-toggle="modal" data-target="#mkdir-form">Utwórz katalog</button>
382                 </div>
383                 <div class="btn-group" role="group">
384                     <button id="btn-rename" class="btn btn-default navbar-btn disabled" data-toggle="modal" data-target="#rename-form">Zmień nazwę</button>
385                     <button id="btn-delete" class="btn btn-default navbar-btn disabled">Usuń</button>
386                 </div>
387                 <div class="btn-group" role="group">
388                     <button id="btn-compress" class="btn btn-default navbar-btn disabled" data-toggle="modal" data-target="#compress-form">Spakuj</button>
389                     <button id="btn-extract" class="btn btn-default navbar-btn disabled">Rozpakuj</button>
390                 </div>
391             </div>
392             <p id="status" class="navbar-text"></p>
393         </div>
394     </footer>
395 {% endblock footer %}