From 251cc64005f3d382d75ac5317e9393e709984042 Mon Sep 17 00:00:00 2001 From: llj Date: Tue, 20 Aug 2013 18:30:17 +0800 Subject: [PATCH] [repo] added 'more' for dirents view --- media/css/seahub.css | 5 +- seahub/templates/repo.html | 109 +++++++++++++------ seahub/templates/snippets/repo_dir_data.html | 91 +--------------- seahub/templates/snippets/repo_dirents.html | 88 +++++++++++++++ seahub/urls.py | 1 + seahub/views/__init__.py | 16 ++- seahub/views/ajax.py | 71 +++++++++++- seahub/views/repo.py | 7 +- 8 files changed, 262 insertions(+), 126 deletions(-) create mode 100644 seahub/templates/snippets/repo_dirents.html diff --git a/media/css/seahub.css b/media/css/seahub.css index da0d92f107..6be7e8d7a1 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -1310,6 +1310,9 @@ textarea:-moz-placeholder {/* for FF */ padding-left:1em; margin-left:1em; } +#repo-file-list { + margin-bottom:100px; +} .path { margin: 1.4em 0 0; } .access-notice { margin: 0.8em 0 0.4em; } .repo-op { @@ -1371,7 +1374,7 @@ textarea:-moz-placeholder {/* for FF */ } .repo-file-list { table-layout:auto; - margin:0 0 100px; + margin:0; } .repo-file-list .star { width:30px; diff --git a/seahub/templates/repo.html b/seahub/templates/repo.html index 5759d3622d..af18e0f2f5 100644 --- a/seahub/templates/repo.html +++ b/seahub/templates/repo.html @@ -320,10 +320,6 @@ function dirOP() { $('.path .dir-link').click(dirlinkClick); -$('#download-dir').click(function() { - location.href = $(this).data('url'); -}); - $('#upload-file').click(function () { var upload_success = false; $('#upload-file-dialog').modal({ @@ -371,7 +367,19 @@ $('#add-new-file').click(function () { $('#simplemodal-container').css({'height':'auto'}); }); -$("tr:gt(0)").unbind().hover( // remove previously binded hover handler at first +// share current dir +$('#share-cur-dir').click(function() { + var op = $(this), name, aj_url, type; + name = $('#cur-dir-name').html(); + aj_url = op.data('url'); + type = 'd'; + showSharePopup(op, name, aj_url, type, cur_path); +}); + +//sort +$('#name-down, #name-up, #time-up, #time-down').click(sortDirent); + +$('.dir-item, .file-item').unbind().hover( // remove previously binded hover handler at first function() { if (no_file_op_popup) { $(this).addClass('hl').find('.repo-file-op').removeClass('vh'); @@ -386,8 +394,11 @@ $("tr:gt(0)").unbind().hover( // remove previously binded hover handler at first opOnDirent(); -//sort -$('#name-down, #name-up, #time-up, #time-down').click(function() { +} // function dirOP ends here + +dirOP(); + +function sortDirent() { var id= $(this).attr('id'), by, dir_list = [], file_list = []; @@ -423,11 +434,7 @@ $('#name-down, #name-up, #time-up, #time-down').click(function() { case 'time-up': $('#time-down').removeAttr('style'); break; case 'time-down': $('#time-up').css({'display':'inline-block'}); break; } -}); - -} // function dirOP ends here - -dirOP(); +} var loading_icon = '{% trans '; // cur_path: will be updated after reqDirdata @@ -526,17 +533,18 @@ var current_repo = [], {% endfor %} {% endif %} -function opOnDirent() { +function opOnDirent(context) { // added param 'context' for 'more' dirents requested with 'list_dir_more' +var context = context || $('.dir-item, .file-item'); -$('.dir-item .dir-link').click(dirlinkClick); +$('.dir-link', context).click(dirlinkClick); var popup_tr = ''; // the tr which the shown popup belongs to $('#main-panel').removeClass('ovhd'); // to fix 'height becomes 0 after sort' for some versions of chrome/ff. -$('.hidden-op').each(function() { +$('.hidden-op', context).each(function() { $(this).height($(this).height()); }); -$('.more-op-icon').click(function() { +$('.more-op-icon', context).click(function() { var icon = $(this), hidden_op = icon.next(); if (icon.attr('data')) { // no popup @@ -588,7 +596,7 @@ $(document).click(function(e) { } }); -$('.hidden-op li').hover( +$('.hidden-op li', context).hover( function() { $(this).css('background', '#eee'); }, @@ -596,7 +604,7 @@ $('.hidden-op li').hover( $(this).css('background', '#fff'); } ); -$('.dir-del, .file-del').click(function() { +$('.dir-del, .file-del', context).click(function() { var dirent = $(this).parents('tr'), dirent_name = dirent.data('name'), url_main; @@ -630,7 +638,7 @@ $('.dir-del, .file-del').click(function() { return false; }); -$('.file-rename, .dir-rename').click(function () { +$('.file-rename, .dir-rename', context).click(function () { var op = $(this), dirent = op.parents('tr'), form = $('#rename-form'), @@ -651,7 +659,7 @@ $('.file-rename, .dir-rename').click(function () { return false; }); -$('.file-cp, .file-mv, .dir-cp, .dir-mv').click(function () { +$('.file-cp, .file-mv, .dir-cp, .dir-mv', context).click(function () { var op = $(this), op_type, op_detail, dirent = op.parents('tr'), obj_name = dirent.data('name'), obj_type, @@ -698,7 +706,7 @@ $('.file-cp, .file-mv, .dir-cp, .dir-mv').click(function () { return false; }); -$('.file-update').click(function() { +$('.file-update', context).click(function() { var file_name = $(this).parents('.file-item').data('name'); var form = $('#update-file-form'); var upload_success = false; @@ -741,7 +749,7 @@ $('.file-update').click(function() { return false; }); -$('.file-star').click(function() { +$('.file-star', context).click(function() { var op = $(this), status = op.data('status'), file_name = op.parents('.file-item').data('name'), @@ -777,20 +785,15 @@ $('.file-star').click(function() { }); //share -$('.file-share, .dir-share, #share-cur-dir').click(function() { +$('.file-share, .dir-share', context).click(function() { var op = $(this), name, aj_url, type; - if (op.attr('id') == 'share-cur-dir') { - name = $('#cur-dir-name').html(); - aj_url = op.data('url'); + name = op.parents('tr').data('name'); + aj_url = '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name); + if (op.hasClass('dir-share')) { + aj_url += '&type=d'; type = 'd'; } else { - name = op.parents('tr').data('name'); - aj_url = '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name); type = 'f'; - if (op.hasClass('dir-share')) { - aj_url += '&type=d'; - type = 'd'; - } } showSharePopup(op, name, aj_url, type, cur_path); @@ -798,7 +801,7 @@ $('.file-share, .dir-share, #share-cur-dir').click(function() { }); {% if ENABLE_SUB_LIBRARY and not repo.is_virtual %} -$('.dir-sync').click(function() { +$('.dir-sync', context).click(function() { var dir_name = $(this).parents('.dir-item').data('name'); // check if the sub-library exists @@ -1027,6 +1030,46 @@ $(window).scroll(function() { } else { list_hd.removeClass('fixed-hd'); } + + var ele_more = $('#repo-file-list .dirent-more'); + if (ele_more.length == 1 && $(window).scrollTop() + $(window).height() >= $(document).height() - parseInt($('#repo-file-list').css('margin-bottom'))) { + $.ajax({ + url:'{% url 'list_dir_more' repo.id %}?p=' + e(cur_path) + '&start=' + e(ele_more.data('start')), + dataType: 'json', + success: function(data) { + var more_dirents = $(data['html']); + more_dirents.appendTo($('.repo-file-list')); + more_dirents.unbind().hover( // remove previously binded hover handler at first + function() { + if (no_file_op_popup) { + $(this).addClass('hl').find('.repo-file-op').removeClass('vh'); + } + }, + function() { + if (no_file_op_popup) { + $(this).removeClass('hl').find('.repo-file-op').addClass('vh'); + } + } + ); + opOnDirent(more_dirents); + $('#name-down, #name-up, #time-up, #time-down').unbind().click(sortDirent); + if (data['dirent_more']) { + ele_more.attr('data-start', data['more_start']); + } else { + ele_more.remove(); + } + }, + error: function(xhr, textStatus, errorThrown) { + var error; + if (xhr.responseText) { + error = $.parseJSON(xhr.responseText).error; + } else { + error = "{% trans "Failed. Please check the network." %}"; + } + ele_more.replaceWith('

' + error + '

'); + } + }); + } }); // webkit fires 'onpopstate' when page loads, use 'setTimeout' in 'window.onload' to avoid it. window.onload = function() { diff --git a/seahub/templates/snippets/repo_dir_data.html b/seahub/templates/snippets/repo_dir_data.html index 55438a8975..c1cdf8fa91 100644 --- a/seahub/templates/snippets/repo_dir_data.html +++ b/seahub/templates/snippets/repo_dir_data.html @@ -34,91 +34,8 @@ {% trans "Last Update" %} {% trans "Operations"%} - {% for dirent in dir_list %} - - - {% trans - - {{ dirent.obj_name }} - - - - - {% if dirent.last_modified %} - {{ dirent.last_modified|translate_seahub_time }} - {% else %} - {% trans "Fetch failed" %} - {% endif %} - - -
-
- {% trans 'Download' %} - {% if not repo.encrypted %} - {% trans "Share" %} - {% endif %} - {% if ENABLE_SUB_LIBRARY and not repo.is_virtual %} - {% trans "Sync" %} - {% endif %} -
- {% if user_perm == 'rw' %} - {% trans 'More operations'%} - - {% endif %} -
- - - {% endfor %} - {% for dirent in file_list %} - - - {% if dirent.starred %} - - {% else %} - - {% endif %} - - {% trans - - {{ dirent.obj_name }} - - - {{ dirent.file_size|filesizeformat }} - - {% if dirent.last_modified %} - {{ dirent.last_modified|translate_seahub_time }} - {% else %} - {% trans "Fetch failed" %} - {% endif %} - - -
-
- {% trans "Download"%} - {% if user_perm == 'rw' %} - {% trans "Update"%} - {% if not repo.encrypted %} - {% trans "Share" %} - {% endif %} - {% endif %} -
- {% if user_perm == 'rw' %} - {% trans - - {% endif %} -
- - - {% endfor %} + {% include 'snippets/repo_dirents.html' %} +{% if dirent_more %} +{% trans 'Loading...' %} +{% endif %} diff --git a/seahub/templates/snippets/repo_dirents.html b/seahub/templates/snippets/repo_dirents.html new file mode 100644 index 0000000000..d379f62b48 --- /dev/null +++ b/seahub/templates/snippets/repo_dirents.html @@ -0,0 +1,88 @@ +{% load seahub_tags i18n %} + {% for dirent in dir_list %} + + + {% trans + + {{ dirent.obj_name }} + + + + + {% if dirent.last_modified %} + {{ dirent.last_modified|translate_seahub_time }} + {% else %} + {% trans "Fetch failed" %} + {% endif %} + + +
+
+ {% trans 'Download' %} + {% if not repo.encrypted %} + {% trans "Share" %} + {% endif %} + {% if ENABLE_SUB_LIBRARY and not repo.is_virtual %} + {% trans "Sync" %} + {% endif %} +
+ {% if user_perm == 'rw' %} + {% trans 'More operations'%} + + {% endif %} +
+ + + {% endfor %} + {% for dirent in file_list %} + + + {% if dirent.starred %} + + {% else %} + + {% endif %} + + {% trans + + {{ dirent.obj_name }} + + + {{ dirent.file_size|filesizeformat }} + + {% if dirent.last_modified %} + {{ dirent.last_modified|translate_seahub_time }} + {% else %} + {% trans "Fetch failed" %} + {% endif %} + + +
+
+ {% trans "Download"%} + {% if user_perm == 'rw' %} + {% trans "Update"%} + {% if not repo.encrypted %} + {% trans "Share" %} + {% endif %} + {% endif %} +
+ {% if user_perm == 'rw' %} + {% trans + + {% endif %} +
+ + + {% endfor %} diff --git a/seahub/urls.py b/seahub/urls.py index d9cb9d523e..97f2a750dc 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -108,6 +108,7 @@ urlpatterns = patterns('', url(r'^ajax/contacts/$', get_contacts, name='get_contacts'), url(r'^ajax/repo/(?P[-0-9a-f]{36})/dir/$', list_dir, name='repo_dir_data'), + url(r'^ajax/repo/(?P[-0-9a-f]{36})/dir/more/$', list_dir_more, name='list_dir_more'), url(r'^ajax/repo/(?P[-0-9a-f]{36})/dir/new/$', new_dir, name='new_dir'), url(r'^ajax/repo/(?P[-0-9a-f]{36})/dir/rename/$', rename_dirent, name='rename_dir'), url(r'^ajax/repo/(?P[-0-9a-f]{36})/dir/delete/$', delete_dirent, name='delete_dir'), diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py index 8a2363bbb9..feeb8ac8da 100644 --- a/seahub/views/__init__.py +++ b/seahub/views/__init__.py @@ -184,14 +184,21 @@ def gen_path_link(path, repo_name): return zipped -def get_repo_dirents(request, repo_id, commit, path): +def get_repo_dirents(request, repo_id, commit, path, offset=-1, limit=-1): dir_list = [] file_list = [] + dirent_more = False if commit.root_id == EMPTY_SHA1: return ([], []) else: try: - dirs = seafile_api.list_dir_by_commit_and_path(commit.id, path) + if limit == -1: + dirs = seafile_api.list_dir_by_commit_and_path(commit.id, path, offset, limit) + else: + dirs = seafile_api.list_dir_by_commit_and_path(commit.id, path, offset, limit + 1) + if len(dirs) == limit + 1: + dirs = dirs[:limit] + dirent_more = True except SearpcError, e: raise Http404 # return render_error(self.request, e.msg) @@ -234,7 +241,10 @@ def get_repo_dirents(request, repo_id, commit, path): y.obj_name.lower())) file_list.sort(lambda x, y : cmp(x.obj_name.lower(), y.obj_name.lower())) - return (file_list, dir_list) + if limit == -1: + return (file_list, dir_list) + else: + return (file_list, dir_list, dirent_more) def get_unencry_rw_repos_by_user(username): """Get all unencrypted repos the user can read and write. diff --git a/seahub/views/ajax.py b/seahub/views/ajax.py index 6ac85101f1..f72f02222e 100644 --- a/seahub/views/ajax.py +++ b/seahub/views/ajax.py @@ -195,7 +195,10 @@ def list_dir(request, repo_id): if path[-1] != '/': path = path + '/' - file_list, dir_list = get_repo_dirents(request, repo.id, head_commit, path) + more_start = None + file_list, dir_list, dirent_more = get_repo_dirents(request, repo.id, head_commit, path, offset=0, limit=100) + if dirent_more: + more_start = 100 zipped = get_nav_path(path, repo.name) fileshare = get_fileshare(repo.id, username, path) dir_shared_link = get_dir_share_link(fileshare) @@ -209,6 +212,8 @@ def list_dir(request, repo_id): 'dir_shared_link': dir_shared_link, 'dir_list': dir_list, 'file_list': file_list, + 'dirent_more': dirent_more, + 'more_start': more_start, 'ENABLE_SUB_LIBRARY': settings.ENABLE_SUB_LIBRARY, } html = render_to_string('snippets/repo_dir_data.html', ctx, @@ -216,6 +221,70 @@ def list_dir(request, repo_id): return HttpResponse(json.dumps({'html': html, 'path': path}), content_type=content_type) +@login_required +def list_dir_more(request, repo_id): + """ + List 'more' entries in a directory with AJAX. + """ + if not request.is_ajax(): + raise Http404 + + content_type = 'application/json; charset=utf-8' + + repo = get_repo(repo_id) + if not repo: + err_msg = _(u'Library does not exist.') + return HttpResponse(json.dumps({'error': err_msg}), + status=400, content_type=content_type) + + username = request.user.username + user_perm = check_repo_access_permission(repo.id, username) + if user_perm is None: + err_msg = _(u'Permission denied.') + return HttpResponse(json.dumps({'error': err_msg}), + status=403, content_type=content_type) + + if repo.encrypted and not seafile_api.is_password_set(repo.id, username): + err_msg = _(u'Library is encrypted.') + return HttpResponse(json.dumps({'error': err_msg}), + status=403, content_type=content_type) + + head_commit = get_commit(repo.head_cmmt_id) + if not head_commit: + err_msg = _(u'Error: no head commit id') + return HttpResponse(json.dumps({'error': err_msg}), + status=500, content_type=content_type) + + path = request.GET.get('p', '/') + if path[-1] != '/': + path = path + '/' + + offset = int(request.GET.get('start')) + if not offset: + err_msg = _(u'Argument missing') + return HttpResponse(json.dumps({'error': err_msg}), + status=400, content_type=content_type) + more_start = None + file_list, dir_list, dirent_more = get_repo_dirents(request, repo.id, head_commit, path, offset, limit=100) + if dirent_more: + more_start = offset + 100 + + ctx = { + 'repo': repo, + 'user_perm': user_perm, + 'path': path, + 'dir_list': dir_list, + 'file_list': file_list, + 'dirent_more': dirent_more, + 'more_start': more_start, + 'ENABLE_SUB_LIBRARY': settings.ENABLE_SUB_LIBRARY, + } + html = render_to_string('snippets/repo_dirents.html', ctx, + context_instance=RequestContext(request)) + return HttpResponse(json.dumps({'html': html, 'dirent_more': dirent_more, 'more_start': more_start}), + content_type=content_type) + + def new_dirent_common(func): """Decorator for common logic in creating directory and file. """ diff --git a/seahub/views/repo.py b/seahub/views/repo.py index 2b0013b0ad..f9b9b27715 100644 --- a/seahub/views/repo.py +++ b/seahub/views/repo.py @@ -187,7 +187,10 @@ def render_repo(request, repo): search_repo_id = None if repo.encrypted else repo.id is_repo_owner = seafile_api.is_repo_owner(username, repo.id) - file_list, dir_list = get_repo_dirents(request, repo.id, head_commit, path) + more_start = None + file_list, dir_list, dirent_more = get_repo_dirents(request, repo.id, head_commit, path, offset=0, limit=100) + if dirent_more: + more_start = 100 zipped = get_nav_path(path, repo.name) repo_groups = get_shared_groups_by_repo_and_user(repo.id, username) if len(repo_groups) > 1: @@ -212,6 +215,8 @@ def render_repo(request, repo): 'repo_size': repo_size, 'dir_list': dir_list, 'file_list': file_list, + 'dirent_more': dirent_more, + 'more_start': more_start, 'path': path, 'zipped': zipped, 'accessible_repos': accessible_repos,