diff --git a/media/css/seahub.css b/media/css/seahub.css index 6be7e8d7a1..d67a55c1ec 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -262,7 +262,17 @@ input.btn-disabled:hover {/*for input*/ *[data-href] { cursor: pointer; } - +.op-icon-btn {/* icon btn */ + font-size:14px; + padding:4px 12px; + line-height:20px; + text-shadow:0 1px 1px rgba(255, 255, 255, 0.75); + background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #ffffff, #e6e6e6);background-image:-webkit-linear-gradient(top, #ffffff, #e6e6e6);background-image:linear-gradient(to bottom, #ffffff, #e6e6e6);background-repeat:repeat-x;border:1px solid #cccccc;border-bottom-color:#b3b3b3;border-radius:4px;box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); +} +.op-icon-btn:hover { + background-color: #E6E6E6; + background-position: 0 -15px; /* to rm background-image */ +} .op-list li, .modalCloseImg, .add { @@ -439,8 +449,8 @@ textarea:-moz-placeholder {/* for FF */ } .checkbox-orig, .checkbox { - width:13px; - height:13px; + width:14px; + height:14px; } .checkbox-checked { background:transparent url('../img/tick.png') no-repeat scroll 1px 3px; @@ -1376,15 +1386,18 @@ textarea:-moz-placeholder {/* for FF */ table-layout:auto; margin:0; } +.repo-file-list .select { + width:15px; +} .repo-file-list .star { - width:30px; + width:25px; } .repo-file-list .dirent-icon { - width:32px; + width:27px; } .repo-file-list .dirent-name { display:inline-block; - width:405px; + width:400px; } .repo-file-list .dirent-size { width:89px; @@ -1395,15 +1408,20 @@ textarea:-moz-placeholder {/* for FF */ .repo-file-list .dirent-op { width:250px; } +.repo-file-list .checkbox-label, +.repo-file-list .checkbox { + margin:0; +} .repo-file-list th { padding-top:20px; } -.repo-file-list .fixed-hd { +#repo-file-list .fixed-hd { position:fixed; width:950px; background:#fff; top:0; z-index:11; /*make it on top of dirent op(popup)*/ + border-color:#efefef; /*for repo-file-list-topbar*/ } .repo-file-list .fixed-hd th { box-shadow:0 2px 2px -3px #aaa; @@ -1416,6 +1434,7 @@ textarea:-moz-placeholder {/* for FF */ .file-star { cursor:pointer; line-height:19px; + vertical-align:middle; } .repo-file-list .repo-file-op { position:relative; @@ -1485,6 +1504,18 @@ textarea:-moz-placeholder {/* for FF */ color:#666; margin-left:5px; } +#dirents-op { + position:fixed; +} +#dirents-op .op-icon-btn { + display:block; + margin-bottom:6px; +} +#dirents-op .op-icon-btn .icon-trash { + display:inline-block; + width:14px; + text-align:center; +} .lsch, .lsch-encrypted, .file-diff { diff --git a/seahub/templates/base.html b/seahub/templates/base.html index 26c032aa31..e3a7f03734 100644 --- a/seahub/templates/base.html +++ b/seahub/templates/base.html @@ -466,6 +466,8 @@ $(document).click(function(e) { {'name':'plus-sign-alt', 'con':'f0fe'}, {'name':'upload', 'con':'f01b'}, {'name':'ban-circle', 'con':'f05e'}, + {'name':'move', 'con':'f047'}, + {'name':'copy', 'con':'f0c5'}, {'name':'upload-alt', 'con':'f093'} ]; function setCon(icon, icon_class_prefix, icon_list) { diff --git a/seahub/templates/repo.html b/seahub/templates/repo.html index f0674eec09..bd68039c22 100644 --- a/seahub/templates/repo.html +++ b/seahub/templates/repo.html @@ -44,6 +44,13 @@ + {% if user_perm == 'rw' %} +
' + "{% trans "Are you sure you want to delete these selected items?" %}" + '
'); + $('#confirm-yes').unbind().click(del_dirents); +}); +var del_dirents = function() { + $('#confirm-popup').append('' + "{% trans "Processing..." %}" + '
'); + var dirents = $('.checkbox-checked').parents('.dir-item, .file-item'), + dirents_names = []; + dirents.each(function() { + dirents_names.push($(this).data('name')); + }); + $.ajax({ + url: '{% url 'delete_dirents' repo.id %}' + '?parent_dir=' + e(cur_path), + type: 'POST', + dataType: 'json', + beforeSend: prepareCSRFToken, + traditional: true, + data: { + 'dirents_names': dirents_names + }, + success: function(data) { + var deleted_len = data['deleted'].length, + msg_s, msg_f; + + if (deleted_len > 0) { + if (deleted_len == dirents_names.length) { + dirents.remove(); + } else { + dirents.each(function() { + if ($(this).data('name') in data['deleted']) { + $(this).remove(); + } + }); + } + if (data['deleted'].length > 1) { + msg_s = "{% trans "Successfully deleted %(name)s and %(amount)s other items." %}"; + } else { + msg_s = "{% trans "Successfully deleted %(name)s." %}"; + } + msg_s = msg_s.replace('%(name)s', data['deleted'][0]).replace('%(amount)s', data['deleted'].length - 1); + feedback(msg_s, 'success'); + updateCmt(); + } + + if (data['undeleted'].length > 0) { + if (data['undeleted'].length > 1) { + msg_f = "{% trans "Internal error. Failed to delete %(name)s and %(amount)s other items." %}" + } else { + msg_f = "{% trans "Internal error. Failed to delete %(name)s." %}" + } + msg_f = msg_f.replace('%(name)s', data['undeleted'][0]).replace('%(amount)s', data['undeleted'].length - 1); + feedback(msg_f, 'error'); + } + $.modal.close(); + $('#dirents-op').addClass('hide'); + $('th.select .checkbox').removeClass('checkbox-checked'); + }, + error: function(xhr, textStatus, errorThrown) { + $.modal.close(); + ajaxErrorHandler(xhr, textStatus, errorThrown); + } + }); +}; + +$('#mv-dirents, #cp-dirents').click(function() { + var form = $('#mv-form'), op; + form.modal({appendTo:'#main', autoResize:true, focus:false}); + $('#simplemodal-container').css({'width':'auto', 'height':'auto'}); + + if ($(this).attr('id') == 'mv-dirents') { + op = 'mv'; + form.prepend("' + "{% trans "Processing..." %}" + '
'); + $.ajax({ + url: url_main + '?parent_dir=' + e(cur_path), + type: 'POST', + dataType: 'json', + beforeSend: prepareCSRFToken, + traditional: true, + data: { + 'file_names': file_names, + 'dir_names': dir_names, + 'dst_repo': dst_repo, + 'dst_path': dst_path + }, + success: function(data) { + var success_len = data['success'].length, + msg_s, msg_f; + + $.modal.close(); + $('#dirents-op').addClass('hide'); + $('th.select .checkbox').removeClass('checkbox-checked'); + + if (success_len > 0) { + if (op == 'mv') { + if (success_len == files.length + dirs.length) { + files.remove(); + dirs.remove(); + } else { + files.each(function() { + if ($(this).data('name') in data['success']) { + $(this).remove(); + } + }); + dirs.each(function() { + if ($(this).data('name') in data['success']) { + $(this).remove(); + } + }); + } + if (data['success'].length > 1) { + msg_s = "{% trans "Successfully moved %(name)s and %(amount)s other items." %}"; + } else { + msg_s = "{% trans "Successfully moved %(name)s." %}"; + } + } else { + $('.checkbox').removeClass('checkbox-checked'); + if (data['success'].length > 1) { + msg_s = "{% trans "Successfully copied %(name)s and %(amount)s other items." %}"; + } else { + msg_s = "{% trans "Successfully copied %(name)s." %}"; + } + } + msg_s = msg_s.replace('%(name)s', data['success'][0]).replace('%(amount)s', data['success'].length - 1); + msg_s += ' ' + "{% trans "View" %}" + ''; + feedback(msg_s, 'success'); + updateCmt(); + } + + if (data['failed'].length > 0) { + if (op == 'mv') { + if (data['failed'].length > 1) { + msg_f = "{% trans "Internal error. Failed to move %(name)s and %(amount)s other items." %}"; + } else { + msg_f = "{% trans "Internal error. Failed to move %(name)s." %}"; + } + } else { + if (data['failed'].length > 1) { + msg_f = "{% trans "Internal error. Failed to copy %(name)s and %(amount)s other items." %}"; + } else { + msg_f = "{% trans "Internal error. Failed to copy %(name)s." %}"; + } + } + msg_f = msg_f.replace('%(name)s', data['failed'][0]).replace('%(amount)s', data['failed'].length - 1); + feedback(msg_f, 'error'); + } + }, + error: function(xhr, textStatus, errorThrown) { + $.modal.close(); + ajaxErrorHandler(xhr, textStatus, errorThrown); + } + }); + return false; + }); +}); // js on repo file list var no_file_op_popup = true; @@ -376,6 +588,28 @@ $('#share-cur-dir').click(function() { showSharePopup(op, name, aj_url, type, cur_path); }); +//select all or not +$('th .checkbox-orig').unbind().click(function() { + var dirents_op = $('#dirents-op'); + + // keep all checkbox in the same state: selected or not + // a case: select all, and then scroll to req 'more'... + $(this).parent().toggleClass('checkbox-checked'); + if ($(this).parent().hasClass('checkbox-checked')) { + $('.checkbox').addClass('checkbox-checked'); + } else { + $('.checkbox').removeClass('checkbox-checked'); + } + + // show buttons or not + if ($('.checkbox-checked', $('.dir-item, .file-item')).length > 0) { + dirents_op.removeClass('hide'); + setDirentsOpPos(); + } else { + dirents_op.addClass('hide'); + } +}); + //sort $('#name-down, #name-up, #time-up, #time-down').click(sortDirent); @@ -410,11 +644,12 @@ function sortDirent() { case 'time-down': by = function(a, b) { return a.time < b.time ? 1 : -1 };break; } + // when 'name' is like '123', `data('name')` return number 123 $('.dir-item').each(function() { - dir_list.push({'name':$(this).data('name'), 'time':$(this).data('time'), 'element':this}); + dir_list.push({'name':$(this).attr('data-name'), 'time':$(this).data('time'), 'element':this}); }); $('.file-item').each(function() { - file_list.push({'name':$(this).data('name'), 'time':$(this).data('time'), 'element':this}); + file_list.push({'name':$(this).attr('data-name'), 'time':$(this).data('time'), 'element':this}); }); dir_list.sort(by); @@ -464,19 +699,28 @@ function changeLocation(data) { } } function reqDirData(url, func) { + var orig_wtop = $(window).scrollTop(); $.ajax({ url: url, cache: false, dataType: 'json', success: function(data) { $('#repo-file-list').html(data['html']); + + // both original dir list and new dir list are long + var repo_top = $('#repo-top'), + h = repo_top.offset().top + repo_top.outerHeight(true); + if (orig_wtop > h && $(window).scrollTop() == orig_wtop) { + $(window).scrollTop(h); + } + cur_path = data['path']; // update cur_path if (func) { func(data); } dirOP(); - // in case the 'discuss' popup is open before this request - $('#discuss-to-group, #discuss-to-group-caret').addClass('hide'); + // in case the 'discuss' & #dirents-op popup is open before this request + $('#discuss-to-group, #discuss-to-group-caret, #dirents-op').addClass('hide'); }, error:function(xhr, textStatus, errorThrown) { if (xhr.responseText) { @@ -536,7 +780,21 @@ var current_repo = [], {% endif %} function opOnDirent(context) { // added param 'context' for 'more' dirents requested with 'list_dir_more' -var context = context || $('.dir-item, .file-item'); + var context = context || $('.dir-item, .file-item'); + +// select +$('.checkbox-orig', context).unbind().click(function() { + var dirents_op = $('#dirents-op'); + + $(this).parent().toggleClass('checkbox-checked'); + // show buttons or not + if ($('.checkbox-checked', context).length > 0) { + dirents_op.removeClass('hide'); + setDirentsOpPos(); + } else { + dirents_op.addClass('hide'); + } +}); $('.dir-link', context).click(dirlinkClick); @@ -629,13 +887,7 @@ $('.dir-del, .file-del', context).click(function() { updateCmt(); } }, - error:function(xhr, textStatus, errorThrown) { - if (xhr.responseText) { - feedback(jQuery.parseJSON(xhr.responseText).error, 'error'); - } else { - feedback("{% trans "Failed. Please check the network." %}", 'error'); - } - } + error: ajaxErrorHandler }); return false; }); @@ -938,6 +1190,11 @@ $('#add-new-file-form, #add-new-dir-form, #rename-form, #mv-form').submit(functi obj_name = $('[name="obj_name"]', form).val(), obj_type = $('[name="obj_type"]', form).val(), op_obj = form.data('op_obj'); + + if (!op_obj) { // for mv-dirents, cp-dirents + return false; + } + if (!$.trim(dst_repo) || !$.trim(dst_path)) { $('.error', form).removeClass('hide'); return false; @@ -1026,11 +1283,17 @@ $('#private-share-form').submit(function() { }); var last_start = 0; // for 'list_dir_more' $(window).scroll(function() { - var file_topbar = $('.repo-file-list-topbar'), - list_hd = $('.repo-file-list tr:first-child'); - if ($(window).scrollTop() > file_topbar.offset().top + file_topbar.outerHeight(true)) { - list_hd.addClass('fixed-hd').css({'left':file_topbar.offset().left}); + var repo_top = $('#repo-top'), + file_topbar = $('.repo-file-list-topbar'), + list_hd = $('.repo-file-list tr:first-child'), + repo_top_left = $('.block-inner', repo_top).offset().left, + file_topbar_h = file_topbar.outerHeight(true); + + if ($(window).scrollTop() > repo_top.offset().top + repo_top.outerHeight(true)) { + file_topbar.addClass('fixed-hd').css({'left': repo_top_left}); + list_hd.addClass('fixed-hd').css({'left': repo_top_left, 'top':file_topbar_h}); } else { + file_topbar.removeClass('fixed-hd'); list_hd.removeClass('fixed-hd'); } @@ -1057,7 +1320,6 @@ $(window).scroll(function() { } ); opOnDirent(more_dirents); - $('#name-down, #name-up, #time-up, #time-down').unbind().click(sortDirent); if (data['dirent_more']) { ele_more.data('start', data['more_start']); } else { diff --git a/seahub/templates/snippets/repo_dir_data.html b/seahub/templates/snippets/repo_dir_data.html index c1cdf8fa91..c8764c91e1 100644 --- a/seahub/templates/snippets/repo_dir_data.html +++ b/seahub/templates/snippets/repo_dir_data.html @@ -27,6 +27,9 @@+ + | {% trans "Name"%} | diff --git a/seahub/templates/snippets/repo_dirents.html b/seahub/templates/snippets/repo_dirents.html index d379f62b48..4ccd44ecf3 100644 --- a/seahub/templates/snippets/repo_dirents.html +++ b/seahub/templates/snippets/repo_dirents.html @@ -1,6 +1,9 @@ {% load seahub_tags i18n %} {% for dirent in dir_list %}||
---|---|---|---|
+ + | ![]() |
@@ -41,6 +44,9 @@ {% endfor %} {% for dirent in file_list %} | |
+ + |
{% if dirent.starred %}
diff --git a/seahub/urls.py b/seahub/urls.py
index 97f2a750dc..e4e72a3600 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -103,6 +103,9 @@ urlpatterns = patterns('',
### Ajax ###
(r'^ajax/repo/(?P |