diff --git a/seahub/forms.py b/seahub/forms.py index 00f1c64897..abfda021f8 100644 --- a/seahub/forms.py +++ b/seahub/forms.py @@ -213,5 +213,5 @@ class RepoSettingForm(forms.Form): repo_id = forms.CharField(error_messages={'required': _('Repo id is required')}) repo_name = forms.CharField(error_messages={'required': _('Library name is required')}) repo_desc = forms.CharField(error_messages={'required': _('Library description is required')}) - days = forms.IntegerField(error_messages={'required': _('Days can\'t be empty'), - 'invalid': _('Please enter a number')}) + days = forms.IntegerField(required=False, + error_messages={'invalid': _('Please enter a number')}) diff --git a/seahub/settings.py b/seahub/settings.py index 14b3a34449..787b6b2097 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -346,6 +346,8 @@ SEND_EMAIL_ON_RESETTING_USER_PASSWD = True # Whether to send email when a system ENABLE_PUBFILE = False +ENABLE_SUB_LIBRARY = False + ##################### # External settings # ##################### diff --git a/seahub/templates/repo.html b/seahub/templates/repo.html index 1a8a77ee5d..e10822da07 100644 --- a/seahub/templates/repo.html +++ b/seahub/templates/repo.html @@ -116,9 +116,12 @@
{% trans 'Download' %} - {% if not repo.encrypted %} + {% if not repo.encrypted %} {% trans "Share" %} - {% endif %} + {% endif %} + {% if ENABLE_SUB_LIBRARY and not repo.is_virtual %} + {% trans "Sub-library" %} + {% endif %}
{% if user_perm == 'rw' %} {% trans 'More operations'%} @@ -239,12 +242,14 @@


-
+ {% if not ENABLE_SUB_LIBRARY or not repo.is_virtual %} +
{% trans "Keep full history" %}
{% trans "Don't keep history" %}
0 %}checked="checked"{% endif %} /> {% trans "Only keep a period of history:" %} {% trans "days" %}
+ {% endif %}

@@ -358,6 +363,7 @@ $('#repo-setting-btn').click(function () { $('#repo-setting-form').modal({appendTo:'#main'}); }); +{% if not ENABLE_SUB_LIBRARY or not repo.is_virtual %} $('#repo-setting-form input[name="history"]').change(function() { var value = $(this).attr('value'); if (value == 'full_history' || value == 'no_history') { @@ -366,8 +372,10 @@ $('#repo-setting-form input[name="history"]').change(function() { $('#repo-setting-form input[name="days"]').attr('disabled', false).removeClass('input-disabled'); } }); +{% endif %} $('#repo-setting-form').submit(function() { + {% if not ENABLE_SUB_LIBRARY or not repo.is_virtual %} var days; var value = $(this).find('input[name="history"]:checked').val(); @@ -378,6 +386,7 @@ $('#repo-setting-form').submit(function() { } else { days = 0; } + {% endif %} var submit_btn = $(this).children('input[type="submit"]'); disable(submit_btn); @@ -390,7 +399,9 @@ $('#repo-setting-form').submit(function() { 'repo_id': $('#repo-setting-form input[name="repo_id"]').val(), 'repo_name': $('#repo-setting-form input[name="repo_name"]').val(), 'repo_desc': $('#repo-setting-form input[name="repo_desc"]').val(), + {% if not ENABLE_SUB_LIBRARY or not repo.is_virtual %} 'days': days + {% endif %} }, success: function(data) { if (data['success']) { @@ -919,6 +930,45 @@ $('#mv-dir-list h5').click(function() { next.addClass('hide'); } }); + +{% if ENABLE_SUB_LIBRARY and not repo.is_virtual %} +$('.create-sub-repo').click(function() { + var repo_name = $(this).data('name'); + var orig_path = '{{path}}' + repo_name; + + feedback('{% trans "Creating sub-library..." %}', 'info'); + + $.ajax({ + url: '{{ SITE_ROOT }}repo/create_sub_repo/', + type: 'POST', + cache: false, + beforeSend: prepareCSRFToken, + dataType: 'json', + data: { + orig_repo_id: '{{repo.id}}', + orig_path: orig_path, + repo_name: repo_name, + repo_desc: repo_name + }, + success:function(data) { + if (data['success']) { + var sub_repo_id = data['repo_id']; + feedback('{% trans "Created sub-library" %} ' + repo_name + '', 'info'); + } else { + feedback(data['error'], 'error'); + } + }, + error:function(xhr, textStatus, errorThrown) { + if (xhr.responseText) { + feedback(jQuery.parseJSON(xhr.responseText).error, 'error'); + } else { + feedback("{% trans "Failed. Please check the network." %}", 'error'); + } + } + }); +}); +{% endif %} + {% if path == '/' %} {% include "snippets/list_commit_detail.html" %} {% endif %} diff --git a/seahub/templates/snippets/my_owned_repos.html b/seahub/templates/snippets/my_owned_repos.html index f50fa0d1ff..7f6efdc8ac 100644 --- a/seahub/templates/snippets/my_owned_repos.html +++ b/seahub/templates/snippets/my_owned_repos.html @@ -4,6 +4,9 @@
@@ -20,6 +23,7 @@ {% trans "Operations" %} {% for repo in owned_repos %} + {% if not ENABLE_SUB_LIBRARY or not repo.is_virtual %} {% trans {{ repo.props.name }} @@ -35,6 +39,7 @@ + {% endif %} {% endfor %} {% else %} @@ -47,6 +52,53 @@
{% endif %}
+ +{% if ENABLE_SUB_LIBRARY %} +
+{% if sub_repos %} + + + + + + + + + {% for repo in sub_repos %} + + + + + {% if repo.latest_modify %} + + {% else %} + + {% endif %} + + + {% endfor %} +
{% trans "Name" %}{% trans "Origin" %}{% trans "Last Update" %}{% trans "Operations" %}
+ {% if repo.virtual_perm == 'rw' %} + {% trans + {% else %} + {% trans + {% endif %} + {{ repo.name }}{{ repo.abbrev_origin_path }}{{ repo.latest_modify|translate_seahub_time }}-- + + {% if repo.is_original_owner %} + + {% endif %} + +
+{% else %} +
+

{% trans "You have not created any sub-libraries" %}

+

{% trans "You can create a sub-library from a directory inside a library. A sub-library can be independently synced and shared. Files in the sub-library will be automatically kept in sync with the directory of the origin library." %}

+
+{% endif %} +
+{% endif %} +
{% if in_repos %} @@ -92,6 +144,7 @@ {% endif %} +
{% if starred_files %}
diff --git a/seahub/urls.py b/seahub/urls.py index 5d650b34ee..0b887864f9 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -81,6 +81,7 @@ urlpatterns = patterns('', url(r'^repo/(?P[-0-9a-f]{36})/file/edit/$', file_edit, name='file_edit'), url(r'^repo/(?P[-0-9a-f]{36})/(?P[^/]+)/$', repo_access_file, name='repo_access_file'), (r'^repo/save_settings$', repo_save_settings), + url(r'^repo/create_sub_repo/$', create_sub_repo, name='create_sub_repo'), url(r'^f/(?P[a-f0-9]{10})/$', view_shared_file, name='view_shared_file'), url(r'^d/(?P[a-f0-9]{10})/$', view_shared_dir, name='view_shared_dir'), diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py index d4e9797ec1..768e2f13e8 100644 --- a/seahub/views/__init__.py +++ b/seahub/views/__init__.py @@ -85,7 +85,8 @@ if HAS_OFFICE_CONVERTER: import seahub.settings as settings from seahub.settings import FILE_PREVIEW_MAX_SIZE, INIT_PASSWD, USE_PDFJS, FILE_ENCODING_LIST, \ - FILE_ENCODING_TRY_LIST, SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, SEND_EMAIL_ON_RESETTING_USER_PASSWD + FILE_ENCODING_TRY_LIST, SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, SEND_EMAIL_ON_RESETTING_USER_PASSWD, \ + ENABLE_SUB_LIBRARY # Get an instance of a logger logger = logging.getLogger(__name__) @@ -347,14 +348,15 @@ def repo_save_settings(request): status=500, content_type=content_type) # set library history - res = set_repo_history_limit(repo_id, days) - if res == 0: - messages.success(request, _(u'Settings saved.')) - return HttpResponse(json.dumps({'success': True}), - content_type=content_type) - else: - return HttpResponse(json.dumps({'error': _(u'Failed to save settings on server')}), - status=400, content_type=content_type) + if days != None: + res = set_repo_history_limit(repo_id, days) + if res != 0: + return HttpResponse(json.dumps({'error': _(u'Failed to save settings on server')}), + status=400, content_type=content_type) + + messages.success(request, _(u'Settings saved.')) + return HttpResponse(json.dumps({'success': True}), + content_type=content_type) else: return HttpResponse(json.dumps({'error': str(form.errors.values()[0])}), status=400, content_type=content_type) @@ -787,6 +789,23 @@ def myhome(request): # Get all personal groups I joined. joined_groups = get_personal_groups_by_user(request.user.username) + def get_abbrev_origin_path(repo_name, path): + if len(path) > 20: + abbrev_path = path[-20:] + return repo_name + '/...' + abbrev_path + else: + return repo_name + path + + # compose abbrev origin path for display + sub_repos = [] + if ENABLE_SUB_LIBRARY: + sub_repos = seafile_api.get_virtual_repos_by_owner(email) + for repo in sub_repos: + repo.abbrev_origin_path = get_abbrev_origin_path(repo.origin_repo_name, + repo.origin_path) + calculate_repo_last_modify(sub_repos) + sub_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify)) + # Personal repos that I owned. owned_repos = seafserv_threaded_rpc.list_owned_repos(email) calculate_repo_last_modify(owned_repos) @@ -888,6 +907,8 @@ def myhome(request): "TRAFFIC_STATS_ENABLED": TRAFFIC_STATS_ENABLED, "traffic_stat": traffic_stat, "ENABLE_PAYMENT": getattr(settings, 'ENABLE_PAYMENT', False), + "ENABLE_SUB_LIBRARY": ENABLE_SUB_LIBRARY, + "sub_repos": sub_repos, }, context_instance=RequestContext(request)) @login_required @@ -1515,6 +1536,39 @@ def repo_create(request): return HttpResponseBadRequest(json.dumps(form.errors), content_type=content_type) +@login_required +def create_sub_repo(request): + if not request.is_ajax() or request.method != 'POST': + return Http404 + + result = {} + content_type = 'application/json; charset=utf-8' + + orig_repo_id = request.POST.get('orig_repo_id', '') + orig_path = request.POST.get('orig_path', '') + repo_name = request.POST.get('repo_name', '') + repo_desc = request.POST.get('repo_desc', '') + owner = request.user.username + + if not orig_repo_id or not orig_path or not repo_name or not repo_desc: + return HttpResponseBadRequest("Invalid arguments", content_type=content_type) + + try: + repo_id = seafile_api.create_virtual_repo(orig_repo_id, orig_path, + repo_name, repo_desc, owner) + except SearpcError, e: + result['error'] = e.msg + return HttpResponse(json.dumps(result), content_type=content_type) + + result['success'] = True + result['repo_id'] = repo_id + repo_created.send(sender=None, + org_id=-1, + creator=owner, + repo_id=repo_id, + repo_name=repo_name) + return HttpResponse(json.dumps(result), content_type=content_type) + def render_file_revisions (request, repo_id): """List all history versions of a file.""" path = request.GET.get('p', '/') diff --git a/seahub/views/repo.py b/seahub/views/repo.py index 40ea75a29f..d158da46ce 100644 --- a/seahub/views/repo.py +++ b/seahub/views/repo.py @@ -20,6 +20,7 @@ from seahub.views import gen_path_link, get_user_permission, get_repo_dirents from seahub.utils import get_ccnetapplet_root, is_file_starred, \ gen_file_upload_url, get_httpserver_root, gen_shared_link, \ EMPTY_SHA1, get_user_repos +from seahub.settings import ENABLE_SUB_LIBRARY # Get an instance of a logger logger = logging.getLogger(__name__) @@ -84,6 +85,7 @@ def get_unencry_rw_repos_by_user(username): owned_repos, shared_repos, groups_repos, public_repos = get_user_repos(username) accessible_repos = [] + for r in owned_repos: if not has_repo(accessible_repos, r) and not r.encrypted: r.has_subdir = check_has_subdir(r) @@ -165,7 +167,6 @@ def render_repo(request, repo): Show repo direntries based on requested path If user does not have permission to view repo return permission deny page - """ username = request.user.username user_perm = check_repo_access_permission(repo.id, username) @@ -242,6 +243,7 @@ def render_repo(request, repo): 'dir_shared_link': dir_shared_link, 'history_limit': history_limit, 'search_repo_id': search_repo_id, + 'ENABLE_SUB_LIBRARY': ENABLE_SUB_LIBRARY, }, context_instance=RequestContext(request)) @login_required