1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-02 07:47:32 +00:00

[repo] added 'more' for dirents view

This commit is contained in:
llj 2013-08-20 18:30:17 +08:00
parent 928e53095a
commit 251cc64005
8 changed files with 262 additions and 126 deletions

View File

@ -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;

View File

@ -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 = '<img src="{{MEDIA_URL}}img/loading-icon.gif" alt="{% trans "Loading..." %}" class="vam" />';
// 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('<p class="error">' + error + '</p>');
}
});
}
});
// webkit fires 'onpopstate' when page loads, use 'setTimeout' in 'window.onload' to avoid it.
window.onload = function() {

View File

@ -34,91 +34,8 @@
<th class="dirent-update">{% trans "Last Update" %} <span id="time-up" class="tri-bg tri-up-order-bg"></span> <span id="time-down" class="tri-bg tri-down-order-bg"></span></th>
<th class="dirent-op">{% trans "Operations"%}</th>
</tr>
{% for dirent in dir_list %}
<tr class="dir-item" data-name="{{dirent.obj_name}}" data-time="{% if dirent.last_modified %}{{ dirent.last_modified }}{%else %}0{% endif %}">
<td class="star"></td>
<td class="dirent-icon"><img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="{% trans "Directory icon"%}" /></td>
<td>
<span class="dirent-name"><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}" class="dir-link">{{ dirent.obj_name }}</a></span>
</td>
<td class="dirent-size"></td>
<td class="dirent-update">
{% if dirent.last_modified %}
{{ dirent.last_modified|translate_seahub_time }}
{% else %}
{% trans "Fetch failed" %}
{% endif %}
</td>
<td class="dirent-op">
<div class="repo-file-op vh">
<div class="displayed-op">
<a class="op download" href="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans 'Download' %}</a>
{% if not repo.encrypted %}
<a class="op dir-share" href="#" data-link="{{ dirent.sharelink }}" data-token="{{ dirent.sharetoken }}">{% trans "Share" %}</a>
{% endif %}
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual %}
<a class="op dir-sync" href="#">{% trans "Sync" %}</a>
{% endif %}
</div>
{% if user_perm == 'rw' %}
<img src="{{ MEDIA_URL }}img/dropdown-arrow.png" title="{% trans 'More operations'%}" alt="{% trans 'More operations'%}" class="more-op-icon" data="no-popup" />
<ul class="hidden-op hide">
<li><a class="op dir-del" href="#">{% trans "Delete"%}</a></li>
<li><a class="op dir-rename" href="#">{% trans "Rename"%}</a></li>
<li><a class="op dir-mv" href="#">{% trans "Move"%}</a></li>
<li><a class="op dir-cp" href="#">{% trans "Copy"%}</a></li>
</ul>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
{% for dirent in file_list %}
<tr class="file-item" data-name="{{dirent.obj_name}}" data-time="{% if dirent.last_modified %}{{ dirent.last_modified }} {%else %}0{% endif %}">
<td class="star alc">
{% if dirent.starred %}
<span title="{% trans 'starred' %}" class="icon-star file-star" data-status="starred"></span>
{% else %}
<span title="{% trans 'unstarred' %}" class="icon-star-empty file-star" data-status="unstarred"></span>
{% endif %}
</td>
<td class="dirent-icon"><img src="{{ MEDIA_URL }}img/file/{{ dirent.obj_name|file_icon_filter }}" alt="{% trans "File"%}" /></td>
<td>
<span class="dirent-name"><a class="op" href="{% url 'repo_view_file' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.obj_name }}</a></span>
</td>
<td class="dirent-size">{{ dirent.file_size|filesizeformat }}</td>
<td class="dirent-update">
{% if dirent.last_modified %}
{{ dirent.last_modified|translate_seahub_time }}
{% else %}
{% trans "Fetch failed" %}
{% endif %}
</td>
<td class="dirent-op">
<div class="repo-file-op vh">
<div class="displayed-op">
<a class="op download" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name|urlencode }}&op=download">{% trans "Download"%}</a>
{% if user_perm == 'rw' %}
<a class="op file-update" href="#">{% trans "Update"%}</a>
{% if not repo.encrypted %}
<a class="op file-share" href="#" data-link="{{ dirent.sharelink }}" data-token="{{ dirent.sharetoken }}">{% trans "Share" %}</a>
{% endif %}
{% endif %}
</div>
{% if user_perm == 'rw' %}
<img src="{{ MEDIA_URL }}img/dropdown-arrow.png" title="{% trans "More Operations"%}" alt="{% trans "More Operations"%}" class="more-op-icon" data="no-popup" />
<ul class="hidden-op hide">
<li><a class="op file-del" href="#">{% trans "Delete"%}</a></li>
<li><a class="op file-rename" href="#">{% trans "Rename" %}</a></li>
<li><a class="op file-mv" href="#">{% trans "Move" %}</a></li>
<li><a class="op file-cp" href="#">{% trans "Copy" %}</a></li>
<li><a class="op file-history" href="{% url 'file_revisions' repo.props.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans "History" %}</a></li>
</ul>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
{% include 'snippets/repo_dirents.html' %}
</table>
{% if dirent_more %}
<img class="dirent-more loading-tip" src="{{MEDIA_URL}}img/loading-icon.gif" alt="{% trans 'Loading...' %}" data-start="{{more_start}}" />
{% endif %}

View File

@ -0,0 +1,88 @@
{% load seahub_tags i18n %}
{% for dirent in dir_list %}
<tr class="dir-item" data-name="{{dirent.obj_name}}" data-time="{% if dirent.last_modified %}{{ dirent.last_modified }}{%else %}0{% endif %}">
<td class="star"></td>
<td class="dirent-icon"><img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="{% trans "Directory icon"%}" /></td>
<td>
<span class="dirent-name"><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}" class="dir-link">{{ dirent.obj_name }}</a></span>
</td>
<td class="dirent-size"></td>
<td class="dirent-update">
{% if dirent.last_modified %}
{{ dirent.last_modified|translate_seahub_time }}
{% else %}
{% trans "Fetch failed" %}
{% endif %}
</td>
<td class="dirent-op">
<div class="repo-file-op vh">
<div class="displayed-op">
<a class="op download" href="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans 'Download' %}</a>
{% if not repo.encrypted %}
<a class="op dir-share" href="#" data-link="{{ dirent.sharelink }}" data-token="{{ dirent.sharetoken }}">{% trans "Share" %}</a>
{% endif %}
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual %}
<a class="op dir-sync" href="#">{% trans "Sync" %}</a>
{% endif %}
</div>
{% if user_perm == 'rw' %}
<img src="{{ MEDIA_URL }}img/dropdown-arrow.png" title="{% trans 'More operations'%}" alt="{% trans 'More operations'%}" class="more-op-icon" data="no-popup" />
<ul class="hidden-op hide">
<li><a class="op dir-del" href="#">{% trans "Delete"%}</a></li>
<li><a class="op dir-rename" href="#">{% trans "Rename"%}</a></li>
<li><a class="op dir-mv" href="#">{% trans "Move"%}</a></li>
<li><a class="op dir-cp" href="#">{% trans "Copy"%}</a></li>
</ul>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
{% for dirent in file_list %}
<tr class="file-item" data-name="{{dirent.obj_name}}" data-time="{% if dirent.last_modified %}{{ dirent.last_modified }} {%else %}0{% endif %}">
<td class="star alc">
{% if dirent.starred %}
<span title="{% trans 'starred' %}" class="icon-star file-star" data-status="starred"></span>
{% else %}
<span title="{% trans 'unstarred' %}" class="icon-star-empty file-star" data-status="unstarred"></span>
{% endif %}
</td>
<td class="dirent-icon"><img src="{{ MEDIA_URL }}img/file/{{ dirent.obj_name|file_icon_filter }}" alt="{% trans "File"%}" /></td>
<td>
<span class="dirent-name"><a class="op" href="{% url 'repo_view_file' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.obj_name }}</a></span>
</td>
<td class="dirent-size">{{ dirent.file_size|filesizeformat }}</td>
<td class="dirent-update">
{% if dirent.last_modified %}
{{ dirent.last_modified|translate_seahub_time }}
{% else %}
{% trans "Fetch failed" %}
{% endif %}
</td>
<td class="dirent-op">
<div class="repo-file-op vh">
<div class="displayed-op">
<a class="op download" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name|urlencode }}&op=download">{% trans "Download"%}</a>
{% if user_perm == 'rw' %}
<a class="op file-update" href="#">{% trans "Update"%}</a>
{% if not repo.encrypted %}
<a class="op file-share" href="#" data-link="{{ dirent.sharelink }}" data-token="{{ dirent.sharetoken }}">{% trans "Share" %}</a>
{% endif %}
{% endif %}
</div>
{% if user_perm == 'rw' %}
<img src="{{ MEDIA_URL }}img/dropdown-arrow.png" title="{% trans "More Operations"%}" alt="{% trans "More Operations"%}" class="more-op-icon" data="no-popup" />
<ul class="hidden-op hide">
<li><a class="op file-del" href="#">{% trans "Delete"%}</a></li>
<li><a class="op file-rename" href="#">{% trans "Rename" %}</a></li>
<li><a class="op file-mv" href="#">{% trans "Move" %}</a></li>
<li><a class="op file-cp" href="#">{% trans "Copy" %}</a></li>
<li><a class="op file-history" href="{% url 'file_revisions' repo.props.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans "History" %}</a></li>
</ul>
{% endif %}
</div>
</td>
</tr>
{% endfor %}

View File

@ -108,6 +108,7 @@ urlpatterns = patterns('',
url(r'^ajax/contacts/$', get_contacts, name='get_contacts'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dir/$', list_dir, name='repo_dir_data'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dir/more/$', list_dir_more, name='list_dir_more'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dir/new/$', new_dir, name='new_dir'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dir/rename/$', rename_dirent, name='rename_dir'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dir/delete/$', delete_dirent, name='delete_dir'),

View File

@ -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.

View File

@ -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.
"""

View File

@ -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,