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