From 4293deceb3413666c4eb0387ebcbc997e210bb5f Mon Sep 17 00:00:00 2001 From: lian Date: Mon, 16 Nov 2015 10:16:10 +0800 Subject: [PATCH 01/17] [api] add get group members api --- seahub/api2/views.py | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/seahub/api2/views.py b/seahub/api2/views.py index 6fa3d9519b..0254d985d0 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -3449,10 +3449,55 @@ class Groups(APIView): "Operation can only be rename.") class GroupMembers(APIView): - authentication_classes = (TokenAuthentication, ) + authentication_classes = (TokenAuthentication, SessionAuthentication) permission_classes = (IsAuthenticated,) throttle_classes = (UserRateThrottle, ) + def get(self, request, group_id, format=None): + """ + Get group members. + """ + try: + group_id_int = int(group_id) + except ValueError: + return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid group ID') + + try: + group = seaserv.get_group(group_id_int) + except SearpcError as e: + logger.error(e) + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, + 'Failed to get group.') + if not group: + return api_error(status.HTTP_404_NOT_FOUND, 'Group not found') + + try: + is_group_user = seaserv.is_group_user(group_id_int, + request.user.username) + except SearpcError as e: + logger.error(e) + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, + 'Failed to check if is group user.') + if not is_group_user: + return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') + + try: + members = seaserv.get_group_members(group.id) + except SearpcError as e: + logger.error(e) + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, + 'Failed to get group members.') + members_json = [] + for m in members: + members_json.append({ + 'username': m.user_name, + "fullname": email2nickname(m.user_name), + "avatar": avatar(m.user_name, 32) + }) + + return HttpResponse(json.dumps(members_json), + content_type=json_content_type) + def put(self, request, group_id, format=None): """ Add group members. From 93f98bce159d7c22a4fff67fdc9df407e84e9816 Mon Sep 17 00:00:00 2001 From: llj Date: Thu, 19 Nov 2015 17:08:44 +0800 Subject: [PATCH 02/17] [nav] removed top nav; redesigned side nav for home_base --- media/css/seahub.css | 61 ------------------------- seahub/templates/base.html | 36 --------------- seahub/templates/base_for_backbone.html | 28 +----------- seahub/templates/home_base.html | 33 ++++++++++++- seahub/templates/myhome_base.html | 16 ------- 5 files changed, 32 insertions(+), 142 deletions(-) diff --git a/media/css/seahub.css b/media/css/seahub.css index d238a2ba48..2291c1d927 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -1439,14 +1439,6 @@ textarea:-moz-placeholder {/* for FF */ #user-info-popup { width:220px; } -#top-nav-grp-info { - width:235px; - top:40px; - font-size:14px; -} -#top-nav-grp-info .outer-caret { - left:38px; -} #notice-popup .outer-caret { left:143px; } @@ -1463,35 +1455,10 @@ textarea:-moz-placeholder {/* for FF */ color:#333; font-weight:normal; } -#top-nav-grp-list .item { - padding:5px 10px; - border:none; -} -#top-nav-grp-list .item.hl { - background:#fafafa; - cursor:pointer; -} -#top-nav-grp-list .name { - display:inline-block; - width:142px; -} .top-info-popup a.item:hover { background:#fafafa; text-decoration:none; } -#top-nav-grp-info .avatar { - border-radius:1000px; - margin-right:5px; - vertical-align:middle; -} -#top-nav-grp-info .op-icon { - font-size:24px; - color:#999; - margin:0; -} -#top-nav-grp-info .all-grp { - padding-left:50px; -} #msg-file-share { margin-top:8px; position:relative; @@ -1529,34 +1496,6 @@ textarea:-moz-placeholder {/* for FF */ #logo { margin-right:30px; } -#header .nav { - float:left; - padding-top:8px; - font-size:15px; -} -#header .nav-item { - float: left; - height:21px; - padding-bottom:19px; - margin:0 14px; -} -.ru #header .nav-item { - margin:0 11px; -} -#header .nav .a, -#header .nav .a:visited { - color:#8A948F; - font-weight:bold; - text-decoration:none; - white-space:nowrap;/* for ipad */ -} -#header .nav .a.cur { - color:#000; -} -#header .nav .a:hover { - color: #ff9933; - text-decoration: underline; -} /* footer */ #footer { diff --git a/seahub/templates/base.html b/seahub/templates/base.html index bb474e7017..a95108aee4 100644 --- a/seahub/templates/base.html +++ b/seahub/templates/base.html @@ -180,42 +180,6 @@ $('#info-bar .close').click(function() { }); {% endif %} -{% if grps %} -$(function() { - var grp_nav = $('#top-nav-grp'); - grp_nav.after('
'); - var popup = $('#top-nav-grp-info'); - var popup_con = '
'; - popup_con += '{% trans "All Groups" %}'; - popup.html(popup_con); - $('.item', popup).hover( - function() { - $(this).addClass('hl').children('a').removeClass('vh'); - }, - function() { - $(this).removeClass('hl').children('a').addClass('vh'); - } - ) - .click(function() { - location.href = $(this).data('url'); - }); - - popup.css({'right': (grp_nav.outerWidth() - popup.outerWidth())/6 * 5}); - grp_nav.parent('.nav-item').hover( - function() { - popup.removeClass('hide'); - }, - function() { - popup.addClass('hide'); - } - ); -}); -{% endif %} - {% if has_file_search %} {% include 'snippets/search_js.html' %} {% endif %} diff --git a/seahub/templates/base_for_backbone.html b/seahub/templates/base_for_backbone.html index bad051c583..808b8915d2 100644 --- a/seahub/templates/base_for_backbone.html +++ b/seahub/templates/base_for_backbone.html @@ -47,33 +47,7 @@ logo {% endif %} - {% block nav %} - - {% endblock %} + {% block nav %}{% endblock %} {% block header_right %} {% if request.user.is_authenticated %} diff --git a/seahub/templates/home_base.html b/seahub/templates/home_base.html index 7dec12da4e..a49a7244d4 100644 --- a/seahub/templates/home_base.html +++ b/seahub/templates/home_base.html @@ -4,14 +4,43 @@ {% block left_panel %}
+

{% trans "Files" %}

+ +
-

{% trans "Personal" %}

+

{% trans "Tools" %}

{% if user.permissions.can_add_repo %} {% endif %}
    -
  • {% trans "Libraries" %}
  • {% trans "Starred" %}
  • {% if events_enabled %}
  • {% trans "Activities" %}
  • diff --git a/seahub/templates/myhome_base.html b/seahub/templates/myhome_base.html index 4bdff041e8..6f541559b4 100644 --- a/seahub/templates/myhome_base.html +++ b/seahub/templates/myhome_base.html @@ -1,20 +1,4 @@ {% extends "base.html" %} {% load i18n %} {% block nav %} - {% endblock %} From e5c5c2b9e7d294db9d3b94b36413d899d5aef2cc Mon Sep 17 00:00:00 2001 From: llj Date: Sat, 21 Nov 2015 15:29:42 +0800 Subject: [PATCH 03/17] redesigned side nav; removed 'top group nav' --- media/css/seahub.css | 27 ++++- seahub/templates/home_base.html | 23 ++-- seahub/templates/js/templates.html | 125 ++++++++++---------- seahub/templates/libraries.html | 23 +--- static/scripts/app/router.js | 26 ++-- static/scripts/app/views/group-side-nav.js | 96 --------------- static/scripts/app/views/group.js | 20 +--- static/scripts/app/views/myhome-side-nav.js | 100 ---------------- static/scripts/app/views/myhome.js | 13 +- static/scripts/app/views/organization.js | 4 - static/scripts/app/views/top-group-nav.js | 52 -------- 11 files changed, 123 insertions(+), 386 deletions(-) delete mode 100644 static/scripts/app/views/group-side-nav.js delete mode 100644 static/scripts/app/views/myhome-side-nav.js delete mode 100644 static/scripts/app/views/top-group-nav.js diff --git a/media/css/seahub.css b/media/css/seahub.css index 2291c1d927..449bd84011 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -690,6 +690,10 @@ textarea:-moz-placeholder {/* for FF */ color:#333; font-weight:normal; } +.side-tabnav-tabs .tab .grp-list a { + font-size:14px; + padding:0; +} .side-tabnav-tabs .tab a:hover { background-color:#feefb8; text-decoration:none; @@ -712,9 +716,30 @@ textarea:-moz-placeholder {/* for FF */ .side-tabnav-tabs .tab-cur a { color:#fff; } -.side-tabnav-tabs .tab-cur a { +.side-tabnav-tabs .tab-cur a, +.side-tabnav-tabs .tab-cur .grp-list .cur a { font-weight:bold; } +.side-tabnav-tabs .tab-cur .grp-list a { + background:transparent; + font-weight:normal; + color:#333; +} +.side-tabnav-tabs .tab .grp-list a:hover, +.side-tabnav-tabs .tab-cur .grp-list a:hover { + background-color:#feefb8; +} +#group-nav .grp-list { + max-height:105px; + overflow:auto; +} +#group-nav .sharp { + display:inline-block; + width:42px; + margin-right:5px; + text-align:right; + color:#aaa; +} .side-textnav .hd { margin:2em 0 .5em; } diff --git a/seahub/templates/home_base.html b/seahub/templates/home_base.html index a49a7244d4..0321384ce9 100644 --- a/seahub/templates/home_base.html +++ b/seahub/templates/home_base.html @@ -18,19 +18,19 @@ {% if user.permissions.can_view_org %}
  • {% trans "Organization" %}
  • {% endif %} -
  • - {% if grps %} - {% trans "Groups" %} - @@ -93,6 +93,11 @@ $('#enable-mods').click(function() { $('#simplemodal-container').css('height', 'auto'); return false; }); +$('#group-nav a:first').click(function() { + $('#group-nav .toggle-icon').toggleClass('icon-caret-left icon-caret-down'); + $('#group-nav .grp-list').slideToggle(); + return false; +}); {% endif %} {% endblock %} diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 6c548e181e..140590f5f8 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -90,23 +90,6 @@ <%= mtime_relative %> <%- owner_nickname %> - - + - {% endblock %} diff --git a/static/scripts/app/views/side-nav.js b/static/scripts/app/views/side-nav.js new file mode 100644 index 0000000000..0385878d0d --- /dev/null +++ b/static/scripts/app/views/side-nav.js @@ -0,0 +1,107 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'common' +], function($, _, Backbone, Common) { + 'use strict'; + + var sideNavView = Backbone.View.extend({ + el: '#side-nav', + + template: _.template($("#side-nav-tmpl").html()), + enableModTemplate: _.template($("#myhome-mods-enable-form-tmpl").html()), + + initialize: function() { + this.default_cur_tab = 'mine'; + this.data = { + 'cur_tab': this.default_cur_tab, + 'can_add_repo': app.pageOptions.can_add_repo, + }; + this.render(); + this.$el.show(); + }, + + render: function() { + this.$el.html(this.template(this.data)); + return this; + }, + + events: { + 'click #group-nav a:first': 'toggleGroupList', + 'mouseenter #group-nav .grp-list': 'mouseEnterGroupList', + 'mouseleave #group-nav .grp-list': 'mouseLeaveGroupList', + 'click #enable-mods': 'enableMods' + }, + + toggleGroupList: function () { + $('#group-nav .toggle-icon').toggleClass('icon-caret-left icon-caret-down'); + $('#group-nav .grp-list').slideToggle(); + return false; + }, + + mouseEnterGroupList: function () { + $('#group-nav .grp-list').css({'overflow': 'auto'}); + }, + + mouseLeaveGroupList: function () { + $('#group-nav .grp-list').css({'overflow': 'hidden'}); + }, + + enableMods: function () { + var mods_enabled = app.pageOptions.user_mods_enabled; + var form = $(this.enableModTemplate({ + 'mods_available': app.pageOptions.user_mods_available, + 'mods_enabled': mods_enabled + })); + form.modal(); + $('#simplemodal-container').css('height', 'auto'); + + $('.checkbox-orig', form).click(function() { + $(this).parent().toggleClass('checkbox-checked'); + }); + + var checkbox = $('[name="personal_wiki"]'), + original_checked = checkbox.prop('checked'), + _this = this; + form.submit(function() { + var cur_checked = checkbox.prop('checked'); + if (cur_checked == original_checked) { + return false; + } + Common.ajaxPost({ + form: form, + form_id: form.attr('id'), + post_url: Common.getUrl({ + 'name': 'toggle_personal_modules' + }), + post_data: {'personal_wiki': cur_checked }, + after_op_success: function () { + if (cur_checked) { + mods_enabled.push('personal wiki'); + } else { + var index = mods_enabled.indexOf('personal wiki'); + if (index > -1) { + mods_enabled.splice(index, 1); // rm the item + } + } + $.modal.close(); + _this.render(); + } + }); + return false; + }); + }, + + setCurTab: function (cur_tab, options) { + this.data.cur_tab = cur_tab || this.default_cur_tab; + if (options) { + $.extend(this.data, options); + } + this.render(); + } + + }); + + return sideNavView; +}); From 385b32154d591742d71fdabd2ad27f61a2e7d9ee Mon Sep 17 00:00:00 2001 From: llj Date: Tue, 24 Nov 2015 12:10:17 +0800 Subject: [PATCH 05/17] [hd] modified mine/shared/org ...pages --- seahub/templates/js/templates.html | 17 +++--- seahub/templates/libraries.html | 59 ++++++++----------- static/scripts/app/views/myhome-repos.js | 21 +++---- .../scripts/app/views/myhome-shared-repos.js | 19 +++--- static/scripts/app/views/myhome-sub-repos.js | 17 ++---- static/scripts/app/views/organization.js | 22 ++++--- static/scripts/app/views/side-nav.js | 1 + 7 files changed, 64 insertions(+), 92 deletions(-) diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 140590f5f8..9a1543cbdf 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -137,13 +137,12 @@ + {% endblock %} diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index d091438c7e..0224721f09 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -548,12 +548,12 @@ {% endif %} <% if (cur_tab == 'group') { %> -
  • +
  • {% trans "Groups" %}
    • #{% trans "All Groups" %}
    • {% for grp in grps %} - class="cur"<% }%>> + class="tab-cur"<% }%>> #{{ grp.group_name }} {% endfor %} @@ -561,8 +561,13 @@ <% } else { %>
    • + <% if (show_group_list) { %> + {% trans "Groups" %} +
        + <% } else { %> {% trans "Groups" %}
          + <% } %>
        • #{% trans "All Groups" %}
        • diff --git a/static/scripts/app/views/side-nav.js b/static/scripts/app/views/side-nav.js index c93d401387..bd51f8b945 100644 --- a/static/scripts/app/views/side-nav.js +++ b/static/scripts/app/views/side-nav.js @@ -16,6 +16,7 @@ define([ this.default_cur_tab = 'mine'; this.data = { 'cur_tab': this.default_cur_tab, + 'show_group_list': false, // when cur_tab is not 'group' 'mods_enabled': app.pageOptions.user_mods_enabled, 'can_add_repo': app.pageOptions.can_add_repo, }; @@ -30,8 +31,6 @@ define([ events: { 'click #group-nav a:first': 'toggleGroupList', - 'mouseenter #group-nav .grp-list': 'mouseEnterGroupList', - 'mouseleave #group-nav .grp-list': 'mouseLeaveGroupList', 'click #enable-mods': 'enableMods' }, @@ -41,14 +40,6 @@ define([ return false; }, - mouseEnterGroupList: function () { - $('#group-nav .grp-list').css({'overflow': 'auto'}); - }, - - mouseLeaveGroupList: function () { - $('#group-nav .grp-list').css({'overflow': 'hidden'}); - }, - enableMods: function () { var mods_enabled = app.pageOptions.user_mods_enabled; var form = $(this.enableModTemplate({ @@ -99,6 +90,7 @@ define([ if (options) { $.extend(this.data, options); } + this.data.show_group_list = $('#group-nav .grp-list:visible').length ? true : false; this.render(); } From 2b9923c70053abe7a3effd8e075f4647c4d5213d Mon Sep 17 00:00:00 2001 From: llj Date: Fri, 4 Dec 2015 17:26:04 +0800 Subject: [PATCH 09/17] [groups] removed 'sideTips', use 'side nav' --- media/css/seahub.css | 24 ------------------------ seahub/templates/js/templates.html | 2 +- seahub/templates/libraries.html | 10 ---------- static/scripts/app/router.js | 9 ++++++++- static/scripts/app/views/groups.js | 3 --- 5 files changed, 9 insertions(+), 39 deletions(-) diff --git a/media/css/seahub.css b/media/css/seahub.css index 8c0d744ca1..06da39bf2c 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -584,30 +584,6 @@ textarea:-moz-placeholder {/* for FF */ top:-11px; left:-10px; } -/**** info-item *****/ -.info-item { - border: 1px solid #eee; - border-radius: 2px; - margin-bottom: 12px; -} -.info-item h3, -.info-item p { - margin:0; -} -.info-item h3 { - font-size:1.15em; -} -.info-item-top { - padding: 4px 10px; - background: #f8f8f8; - border-bottom: 1px solid #eee; -} -.info-item-bottom { - padding: 8px 10px; -} -.info-item p.not-last { - margin-bottom:0.4em; -} /**** tabnav *****/ .tabnav-tabs, .tabnav-tab { diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 0224721f09..f6939ccd94 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -551,7 +551,7 @@
        • {% trans "Groups" %}
            -
          • #{% trans "All Groups" %}
          • + class="tab-cur"<% }%>>#{% trans "All Groups" %} {% for grp in grps %} class="tab-cur"<% }%>> #{{ grp.group_name }} diff --git a/seahub/templates/libraries.html b/seahub/templates/libraries.html index 13afa50403..65c94b03c9 100644 --- a/seahub/templates/libraries.html +++ b/seahub/templates/libraries.html @@ -11,16 +11,6 @@ {% endblock %} {% block left_panel %} -
            -

            {% trans "Tips" %}

            -
            - {% if user.permissions.can_add_group %} -

            {% trans "After creating a group, you can add members and share libraries into it." %}

            - {% else %} -

            {% trans "Since you are a guest user now, you can not create groups." %}

            - {% endif %} -
            -
            {% endblock %} diff --git a/static/scripts/app/router.js b/static/scripts/app/router.js index fcdc23bc0e..406df78e27 100644 --- a/static/scripts/app/router.js +++ b/static/scripts/app/router.js @@ -149,12 +149,19 @@ define([ showGroups: function () { this.switchCurrentView(this.groupsView); this.groupsView.show(); + this.sideNavView.setCurTab('group', { + 'cur_group_tab': 'groups', + 'cur_group_id': '' + }); }, showGroupRepos: function(group_id) { this.switchCurrentView(this.groupView); this.groupView.showRepoList(group_id); - this.sideNavView.setCurTab('group', {'cur_group_id': group_id}); + this.sideNavView.setCurTab('group', { + 'cur_group_tab': '', + 'cur_group_id': group_id + }); }, showGroupRepoDir: function(group_id, repo_id, path) { diff --git a/static/scripts/app/views/groups.js b/static/scripts/app/views/groups.js index eed9d3314c..655699a0df 100644 --- a/static/scripts/app/views/groups.js +++ b/static/scripts/app/views/groups.js @@ -16,7 +16,6 @@ define([ this.listenTo(this.groups, 'add', this.addOne); this.listenTo(this.groups, 'reset', this.reset); - this.$sideTips = $('#groups-side-tips'); this.$loadingTip = this.$('.loading-tip'); this.$groupList = $('#group-list'); this.$emptyTip = this.$('.empty-tips'); @@ -82,13 +81,11 @@ define([ }, show: function() { - this.$sideTips.show(); this.$el.show(); this.render(); }, hide: function() { - this.$sideTips.hide(); this.$el.hide(); }, From d1bcd3e113fcef66491f4b16b59c2e9e928f5d18 Mon Sep 17 00:00:00 2001 From: lian Date: Mon, 7 Dec 2015 11:33:49 +0800 Subject: [PATCH 10/17] [api2.1] add rename, transfer and delete group api --- seahub/api2/endpoints/groups.py | 125 ++++++++++++++++++++++++++++- seahub/urls.py | 1 + tests/api/endpoints/test_groups.py | 43 ++++++++-- 3 files changed, 162 insertions(+), 7 deletions(-) diff --git a/seahub/api2/endpoints/groups.py b/seahub/api2/endpoints/groups.py index 988ae6cf28..d21c784280 100644 --- a/seahub/api2/endpoints/groups.py +++ b/seahub/api2/endpoints/groups.py @@ -20,9 +20,10 @@ from seahub.api2.authentication import TokenAuthentication from seahub.avatar.settings import GROUP_AVATAR_DEFAULT_SIZE from seahub.avatar.templatetags.group_avatar_tags import api_grp_avatar_url, \ get_default_group_avatar_url -from seahub.utils import is_org_context +from seahub.utils import is_org_context, is_valid_username from seahub.utils.timeutils import dt, utc_to_local from seahub.group.utils import validate_group_name, check_group_name_conflict +from seahub.group.views import remove_group_common from seahub.base.templatetags.seahub_tags import email2nickname, \ translate_seahub_time @@ -167,3 +168,125 @@ class Groups(APIView): "admins": self._get_group_admins(g.id), } return Response(new_group, status=status.HTTP_201_CREATED) + + def put(self, request, group_id): + """ Rename, transfer a group + """ + + group_id = int(group_id) + try: + group = seaserv.get_group(group_id) + except SearpcError as e: + logger.error(e) + error_msg = _(u'Internal Server Error') + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + if not group: + error_msg = _(u'Group does not exist.') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + # only group staff can rename or transfer a group + username = request.user.username + if not seaserv.check_group_staff(group_id, username): + error_msg = _(u'Permission denied') + return api_error(status.HTTP_403_FORBIDDEN, error_msg) + + operation = request.DATA.get('operation', '') + if operation.lower() == 'rename': + new_group_name = request.DATA.get('new_group_name', None) + if not new_group_name: + error_msg = _(u'Argument missing') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + # Check whether group name is validate. + if not validate_group_name(new_group_name): + error_msg = _(u'Group name can only contain letters, numbers, blank, hyphen or underscore') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + # Check whether group name is duplicated. + if check_group_name_conflict(request, new_group_name): + error_msg = _(u'There is already a group with that name.') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + try: + seaserv.ccnet_threaded_rpc.set_group_name(group_id, new_group_name) + except SearpcError as e: + logger.error(e) + error_msg = _(u'Internal Server Error') + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + elif operation.lower() == 'transfer': + email = request.DATA.get('email') + if not email: + error_msg = _(u'Argument missing') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + if not is_valid_username(email): + error_msg = _('Email %s is not valid.') % email + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + if email != username: + try: + if not seaserv.is_group_user(group_id, email): + seaserv.ccnet_threaded_rpc.group_add_member(group_id, username, email) + + seaserv.ccnet_threaded_rpc.set_group_creator(group_id, email) + seaserv.ccnet_threaded_rpc.group_set_admin(group_id, email) + except SearpcError as e: + logger.error(e) + error_msg = _(u'Internal Server Error') + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + else: + error_msg = _(u'Operation can only be rename or transfer.') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + g = seaserv.get_group(group_id) + val = utc_to_local(dt(g.timestamp)) + avatar_url, is_default, date_uploaded = api_grp_avatar_url(group_id, + GROUP_AVATAR_DEFAULT_SIZE) + + group_info = { + "id": g.id, + "name": g.group_name, + "creator": g.creator_name, + "created_at": val.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(val).format('O'), + "avatar_url": request.build_absolute_uri(avatar_url), + "admins": self._get_group_admins(g.id), + } + return Response(group_info, status=status.HTTP_200_OK) + + def delete(self, request, group_id): + """ Delete a group + """ + + group_id = int(group_id) + try: + group = seaserv.get_group(group_id) + except SearpcError as e: + logger.error(e) + error_msg = _(u'Internal Server Error') + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + if not group: + error_msg = _(u'Group does not exist.') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + # only group staff can delete a group + username = request.user.username + if not seaserv.check_group_staff(group_id, username): + error_msg = _(u'Permission denied') + return api_error(status.HTTP_403_FORBIDDEN, error_msg) + + org_id = None + if is_org_context(request): + org_id = request.user.org.org_id + + try: + remove_group_common(group_id, username, org_id=org_id) + except SearpcError as e: + logger.error(e) + error_msg = _(u'Internal Server Error') + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + return Response({'success': True}, status=status.HTTP_200_OK) + diff --git a/seahub/urls.py b/seahub/urls.py index 93606f1c37..08bdd35586 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -192,6 +192,7 @@ urlpatterns = patterns( ### Apps ### (r'^api2/', include('seahub.api2.urls')), url(r'^api/v2.1/groups/$', Groups.as_view(), name='api-v2.1-groups'), + url(r'^api/v2.1/groups/(?P\d+)/$', Groups.as_view(), name='api-v2.1-group'), (r'^avatar/', include('seahub.avatar.urls')), (r'^notification/', include('seahub.notifications.urls')), (r'^contacts/', include('seahub.contacts.urls')), diff --git a/tests/api/endpoints/test_groups.py b/tests/api/endpoints/test_groups.py index 9f2875fb69..66ff20411f 100644 --- a/tests/api/endpoints/test_groups.py +++ b/tests/api/endpoints/test_groups.py @@ -7,6 +7,7 @@ from seaserv import seafile_api from seahub.test_utils import BaseTestCase from seahub.api2.endpoints.groups import Groups +from tests.common.utils import randstring class GroupsTest(BaseTestCase): @@ -61,7 +62,7 @@ class GroupsTest(BaseTestCase): assert self.group_id in group_ids def test_create_group(self): - new_group_name = 'new-group-1' + new_group_name = 'new-group-' + randstring(6) resp = self.client.post(self.url, {'group_name': new_group_name}) self.assertEqual(201, resp.status_code) @@ -74,7 +75,7 @@ class GroupsTest(BaseTestCase): self.remove_group(json_resp['id']) def test_create_group_with_cn_name(self): - new_group_name = u'中文' + new_group_name = u'中文' + randstring(6) resp = self.client.post(self.url, {'group_name': new_group_name}) self.assertEqual(201, resp.status_code) @@ -90,15 +91,45 @@ class GroupsTest(BaseTestCase): self.assertEqual(400, resp.status_code) def test_can_not_create_group_with_invalid_name(self): - group_name = 'new%group-2' + new_group_name = 'new%group-' + randstring(6) - resp = self.client.post(self.url, {'group_name': group_name}) + resp = self.client.post(self.url, {'group_name': new_group_name}) self.assertEqual(400, resp.status_code) @patch.object(Groups, '_can_add_group') def test_can_not_create_group_with_invalid_permission(self, mock_can_add_group): mock_can_add_group.return_value = False - group_name = 'new-group-3' + new_group_name = 'new-group-' + randstring(6) - resp = self.client.post(self.url, {'group_name': group_name}) + resp = self.client.post(self.url, {'group_name': new_group_name}) self.assertEqual(403, resp.status_code) + + def test_can_rename_group(self): + new_group_name = 'new-group-' + randstring(6) + url = reverse('api-v2.1-group', args=[self.group_id]) + data = 'operation=rename&new_group_name=%s' % new_group_name + + resp = self.client.put(url, data, 'application/x-www-form-urlencoded') + self.assertEqual(200, resp.status_code) + + json_resp = json.loads(resp.content) + assert json_resp['name'] == new_group_name + + def test_can_transfer_group(self): + new_creator = self.admin.email + url = reverse('api-v2.1-group', args=[self.group_id]) + data = 'operation=transfer&email=%s' % new_creator + + resp = self.client.put(url, data, 'application/x-www-form-urlencoded') + self.assertEqual(200, resp.status_code) + + json_resp = json.loads(resp.content) + assert json_resp['creator'] == new_creator + + def test_can_delete_group(self): + url = reverse('api-v2.1-group', args=[self.group_id]) + resp = self.client.delete(url) + self.assertEqual(200, resp.status_code) + + json_resp = json.loads(resp.content) + assert json_resp['success'] is True From 8469c3331a56e4fe5080e3098b7133ecd9dad474 Mon Sep 17 00:00:00 2001 From: llj Date: Tue, 8 Dec 2015 15:59:48 +0800 Subject: [PATCH 11/17] [group] modified icons --- media/css/seahub.css | 4 +++- media/css/sf_font2/seafile-font2.eot | Bin 6222 -> 6922 bytes media/css/sf_font2/seafile-font2.ttf | Bin 6028 -> 6728 bytes media/css/sf_font2/seafile-font2.woff | Bin 4100 -> 4440 bytes seahub/templates/js/templates.html | 10 +++++----- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/media/css/seahub.css b/media/css/seahub.css index 06da39bf2c..ffe6ad4e50 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -128,6 +128,8 @@ .sf2-icon-x1:before { content:"\e01d"; } .sf2-icon-tick:before { content:"\e01e"; } .sf2-icon-x2:before { content:"\e01f"; } +.sf2-icon-user2:before { content:"\e020"; } +.sf2-icon-msgs2:before { content:"\e021"; } /******* tags **********/ html { background:#fff; } @@ -1204,7 +1206,7 @@ textarea:-moz-placeholder {/* for FF */ #group-top .op-icon { display:inline-block; font-size:22px; - margin:4px 0 0 5px; + margin:4px 15px 0 0; } .commit-list-topbar, .file-audit-list-topbar, diff --git a/media/css/sf_font2/seafile-font2.eot b/media/css/sf_font2/seafile-font2.eot index 12bafe7f6c0fadc8b3eefbaa5bff9e25aa5ecd06..d6de997a7af74b204c9dae0616d294570e8bbce4 100644 GIT binary patch delta 1359 zcmZ{kPizxM6o=o;F1u@ou=!)J!8nd%JKo0j#_L&oy*PxXl!StuP&;Y_YJ+8BJBbuK z20ImSSqb%k5E2558>fg~;8H14kB9@}ga9G+#sR4+TsXi1j-j)FM4J(Z(dhT>yqRxy zr1x0AVhZm406+Mz3nst)YIgJb)D8RWg76f;p9Fxw(Ie9{Py&JG-86?z%%@1|THyi! zI!W`wQlrwkPa^jKFi+X>#9ar)R=* zI?NRc_``S?t@Y3xU1@ae^R6;(Qb3EKw6?xfIo6pg&<%d1xzMPbZ$S(0((e|{p=PB~ z`}5?B2LRs7l>OaWZ+CiKcLD&uH7a!z5M4#b=IpEOvV8Cz^k51Ao?RthX6#TrNPz^n z`xK?n=ncGxM!Ki*5*LL~_dZUck*znlj(F*!^nPoBU+uGbh(Z88L@%KSd=P;YKrS51 zW=w-9UXP%L1+Pajh?&jAxUcYcV-r?VvnJvrW69ufax8S};;)N8ciO*{mX}M#TJ3GY zG^VBuv+$h66O)sPIN3gNkQU^%am(Hs9~#zE!6Dtb2oE7hpcm*bP#_M|@Dr6$!)h!? zk5?V3k4}-WDyRne7Wo{pOw3XADPCc89I27qA@tE)bi9X=A_@r^7Hfgi4q_8MqOB(sUDq4t3v_Ve`$JAlt)JA4qEA-2h&978OI92j5}brz*r zM0OzC(9*^ZMp1@ESr(Zr%CX2|(HDLD^Dn1Q!z?4LKiTPTXoS@#tUh7&iKCzS-@|Jp zhjoH=1M3-1&k~_gYn-W_+g)94FKx8jtLsh8X%Joa-XS$g8;H}*K6MVKp}?cb%_q+M H-!}3u9%EEX delta 678 zcmYk4%}X0W7{;HO#Ap?&;72?NQPXS8zR|=4EY)bXVntI5;-$(OKN2u;{X%<6Zv_z~ zZvTQpPra0;XR(K#lva8a527dU@lq@4yZRz7%>MRyW_J0pGdr@$*YLY7oS$X$8^!G>FZ37} zU%8lAUddR4e^XQZfpN~Gd28E70bh7N&bhN-2*uU3Zhzxc%EiW16N(nzczb*~})JHMRaX{*bCkRTQluHc4A((r8jq zFDv4~LqRZl^CWsv5TW2vJcxJ@6v3MZLC}jA4|3X^O30hTPd*b40Xu?A>Z;m++sF!Eh6eq2bPUG=+vbchEE& z0)J-(CD71voT(wscG>oQ`4&6ZZE_F-FM5GKK^M3o2nm2pAe>I=8g@zjyd2=AewT*z zbSljLhkqLxHDZb}8W|di`37Sn{*#w4Or2`CP8VlpiiK+RYhKrO?$q@BdmM?5jYT7P z}d)pF;+4^i|1y#p6SU>uGS895+_Gvs*Ll3H~N24r5=@DAj* z#8P2P(e0A>;W(0mneAxRT(GzC`}`s zMj09zH2SM={`uwPX{cqG_Qz}eH3if9nAXR%KDP8z|2({cGmMHERb$i?tEMquuh!32 t&#$k{wWb$at+|DUV)ca1e)oVJB7MVZV85G%)ga;3*xlFG__uRl_yvbBPjLVM delta 653 zcmYL{OGq106o&sh6RT3xfW~wo#Mf4n6JHsqk7_cCq-}~t+=z_v5y8YETB@sLCxRI0 zbeWalO2N`}U36Dyprz|BYP;&*Y}AsTi3eN^-~9jOUcUSIGI$uwK>=t&9y$`H`TDt? z_k9BVHn$zq(U^$@9&t`^?tD2H3c~qiz?t0RnpP5eibN%wKY{L>KoqDfiIxy2@&+c zaL(KNJrwCPoU8UTo^|9mbM72ms7JMLyqPu#<;WgXqz VdTPn-+}DQk=5^+Tc(M1VD)QlcIdP&qtMi3-= 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 delta 4004 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

            *4U#enT0bo*Z)Z<2FNQt&$j+40 zSk>M1#TPc3vM`)wo%@4GiOJg{hRqk<@1T5EWsCLn*%-ZIY(6*rt=^A#P?9+-n-ZbI zT{QE|rfsF&@C*(rWKqa8j% zdnXK++K4^At;OQ$;W0*Kp4?@cr{;*2czAw5ncHT4;NA@?2FA;@I!$}h9V*t=AdX9^ z?PDw0KS}%z4mad1(0seG|9g6M{c^C`&-K}mLN(k0WvF?`Vn^IHHOW5xJ{+sOYys$c zo&)!=A&oF!;mFPeRV|3O@>P}=(oQNCs zynx;hng#&)FLQHto~LqQpk;M-ai&Jn2zgNa;Q?sM0rS+WP?ZZ>OVQ_0p1q8ibC3q2 z+{P&h2wwvD&6%20pF=Mhbf2F?&2}Owu1PB(zf)0M;-h-3jHCb}q-Z<;uQcGIe{gO^ zI#G4H(D0fEG5?~_oh{pgGERwsig1z1*&Fx~M%$Qr2)zhWlD}PKDFSdnoV*JG2*3ll z2q**Q+(|My=*DPqEt>fLn2c079|?~fVUpWVT3XBik@3D zA*;**?b6TdF9tP}VzND#;Lzp^p1Tiuh8iB=J2iq1L`(bL70C=b#7XqZCzXC{=JDKZ z<{N5QBC2~XY-x-rj+V2i+-3N^He@T*_Lgs&G<>)H-FBzY!uV!#gQDUlRX9zk6eMZM zrs51-p60OGs5i6RKqY8NS&_0LCe%Jl8MXWcpWxVEp*hQydLOPE_z-BHZy3JYi^zP{ ic;UI<+|ivhZqEn`GY#XU|DM?cL7T|rMIQV)K=VJOCrHHr diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index f6939ccd94..a0ee574444 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -640,12 +640,12 @@ {% endif %}

            - <% if (!is_pub) { %> - - <% } %> - <% if (is_staff) { %> - + + <% } %> + + <% if (!is_pub) { %> + <% } %>
From 46d9fea299c3e74a88b9a5d511a53c9a56594e5b Mon Sep 17 00:00:00 2001 From: lian Date: Tue, 8 Dec 2015 16:40:17 +0800 Subject: [PATCH 12/17] [api-v2.1] update transfer group api --- seahub/api2/endpoints/groups.py | 3 +++ tests/api/endpoints/test_groups.py | 8 ++++++++ tests/seahub/views/test_sysadmin.py | 2 ++ 3 files changed, 13 insertions(+) diff --git a/seahub/api2/endpoints/groups.py b/seahub/api2/endpoints/groups.py index d21c784280..94222f14a5 100644 --- a/seahub/api2/endpoints/groups.py +++ b/seahub/api2/endpoints/groups.py @@ -236,6 +236,9 @@ class Groups(APIView): logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + else: + error_msg = _('You can not transfer a group to yourself') + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) else: error_msg = _(u'Operation can only be rename or transfer.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) diff --git a/tests/api/endpoints/test_groups.py b/tests/api/endpoints/test_groups.py index 66ff20411f..4812d46be1 100644 --- a/tests/api/endpoints/test_groups.py +++ b/tests/api/endpoints/test_groups.py @@ -126,6 +126,14 @@ class GroupsTest(BaseTestCase): json_resp = json.loads(resp.content) assert json_resp['creator'] == new_creator + def test_can_not_transfer_group_to_myself(self): + new_creator = self.user.email + url = reverse('api-v2.1-group', args=[self.group_id]) + data = 'operation=transfer&email=%s' % new_creator + + resp = self.client.put(url, data, 'application/x-www-form-urlencoded') + self.assertEqual(400, resp.status_code) + def test_can_delete_group(self): url = reverse('api-v2.1-group', args=[self.group_id]) resp = self.client.delete(url) diff --git a/tests/seahub/views/test_sysadmin.py b/tests/seahub/views/test_sysadmin.py index cbfd7452c7..891a9cb939 100644 --- a/tests/seahub/views/test_sysadmin.py +++ b/tests/seahub/views/test_sysadmin.py @@ -198,6 +198,8 @@ class UserInfoTest(BaseTestCase): self.admin_repo_id = r.id # set common user as staff in admin user's group + ccnet_threaded_rpc.group_add_member(self.admin_group_1_id, + self.admin.email, self.user.email) ccnet_threaded_rpc.group_set_admin(self.admin_group_1_id, self.user.email) # add common user to admin user's another group From c31f201d5bfe68d3e8482f4874d828886d36ea2a Mon Sep 17 00:00:00 2001 From: lian Date: Tue, 8 Dec 2015 18:43:32 +0800 Subject: [PATCH 13/17] update groups api --- seahub/api2/endpoints/groups.py | 29 ++++++++++++++++------------- tests/api/endpoints/test_groups.py | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/seahub/api2/endpoints/groups.py b/seahub/api2/endpoints/groups.py index 94222f14a5..ba8a6503b2 100644 --- a/seahub/api2/endpoints/groups.py +++ b/seahub/api2/endpoints/groups.py @@ -225,20 +225,23 @@ class Groups(APIView): error_msg = _('Email %s is not valid.') % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) - if email != username: - try: - if not seaserv.is_group_user(group_id, email): - seaserv.ccnet_threaded_rpc.group_add_member(group_id, username, email) - - seaserv.ccnet_threaded_rpc.set_group_creator(group_id, email) - seaserv.ccnet_threaded_rpc.group_set_admin(group_id, email) - except SearpcError as e: - logger.error(e) - error_msg = _(u'Internal Server Error') - return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) - else: - error_msg = _('You can not transfer a group to yourself') + if email == group.creator_name: + error_msg = _('%s is already group owner') % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + try: + if not seaserv.is_group_user(group_id, email): + seaserv.ccnet_threaded_rpc.group_add_member(group_id, username, email) + + if not seaserv.check_group_staff(group_id, email): + seaserv.ccnet_threaded_rpc.group_set_admin(group_id, email) + + seaserv.ccnet_threaded_rpc.set_group_creator(group_id, email) + except SearpcError as e: + logger.error(e) + error_msg = _(u'Internal Server Error') + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + else: error_msg = _(u'Operation can only be rename or transfer.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) diff --git a/tests/api/endpoints/test_groups.py b/tests/api/endpoints/test_groups.py index 4812d46be1..09946c4e39 100644 --- a/tests/api/endpoints/test_groups.py +++ b/tests/api/endpoints/test_groups.py @@ -126,7 +126,7 @@ class GroupsTest(BaseTestCase): json_resp = json.loads(resp.content) assert json_resp['creator'] == new_creator - def test_can_not_transfer_group_to_myself(self): + def test_can_not_transfer_group_to_group_owner(self): new_creator = self.user.email url = reverse('api-v2.1-group', args=[self.group_id]) data = 'operation=transfer&email=%s' % new_creator From 4c3e5ab06719e13ba96941d800b6cf5557b54f4e Mon Sep 17 00:00:00 2001 From: llj Date: Wed, 9 Dec 2015 15:08:15 +0800 Subject: [PATCH 14/17] [group] dir view: bugfix for side nav --- static/scripts/app/router.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/static/scripts/app/router.js b/static/scripts/app/router.js index 406df78e27..b54518534d 100644 --- a/static/scripts/app/router.js +++ b/static/scripts/app/router.js @@ -172,7 +172,10 @@ define([ } this.switchCurrentView(this.groupView); this.groupView.showDir(group_id, repo_id, path); - this.sideNavView.setCurTab('group', {'cur_group_id': group_id}); + this.sideNavView.setCurTab('group', { + 'cur_group_tab': '', + 'cur_group_id': group_id + }); }, showOrgRepos: function() { From 03d075a00ba5d605dcc226bf528db34bf910a570 Mon Sep 17 00:00:00 2001 From: llj Date: Fri, 11 Dec 2015 20:41:16 +0800 Subject: [PATCH 15/17] [group members] redesigned it --- media/css/seahub.css | 52 +++++++++ .../group/templates/group/group_members.html | 37 ------ seahub/group/urls.py | 3 +- seahub/group/views.py | 20 ---- seahub/templates/js/templates.html | 9 +- seahub/templates/libraries.html | 22 +++- seahub/templates/my_group_repos.html | 50 -------- seahub/urls.py | 1 + .../scripts/app/collections/group-members.js | 19 +++ static/scripts/app/router.js | 6 + static/scripts/app/views/group-member.js | 47 ++++++++ static/scripts/app/views/group-members.js | 110 ++++++++++++++++++ static/scripts/app/views/group.js | 26 ++++- static/scripts/common.js | 2 + 14 files changed, 284 insertions(+), 120 deletions(-) delete mode 100644 seahub/group/templates/group/group_members.html delete mode 100644 seahub/templates/my_group_repos.html create mode 100644 static/scripts/app/collections/group-members.js create mode 100644 static/scripts/app/views/group-member.js create mode 100644 static/scripts/app/views/group-members.js diff --git a/media/css/seahub.css b/media/css/seahub.css index ffe6ad4e50..ec8ba519a2 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -1140,6 +1140,45 @@ textarea:-moz-placeholder {/* for FF */ color:#fff; text-decoration:none; } +/**** popover ****/ /* e.g. top notice popup, group members popup */ +.popover { + width:240px; + background:#fff; + border:1px solid #c9c9c9; + border-radius:3px; + box-shadow:0 0 1px #f3f3f3; +} +.popover-hd { + padding:5px 0 3px; + border-bottom:1px solid #dfdfe1; + margin:0 10px; +} +.popover-title { + text-align:center; + margin:0; +} +.popover-close { + font-size:16px; + color:#b9b9b9; + margin:4px 0 0; +} +.popover-con { + padding:0 10px; + overflow:auto; +} +/**** user-item ****/ /* e.g. group member in 'group members' panel */ +.user-item { + margin:5px 0; +} +.user-item .avatar { + border-radius:1000px; +} +.user-item .txt { + margin-left:40px; +} +.user-item .txt-item { + margin:0; +} /********** container ***********/ #main, #footer { width:950px; @@ -3696,6 +3735,7 @@ img.thumbnail { border-radius:3px; margin:0; } +/**** #groups ****/ /* groups page */ #groups .group-name { font-size:16px; margin:15px 0 10px; @@ -3706,3 +3746,15 @@ img.thumbnail { #groups .empty-tips { margin:10px 0 40px; } +/**** #group ****/ /* group page */ +#group { + position:relative; +} +#group-members { + position:absolute; + top:77px; + right:0; +} +#group-members .outer-caret { + right:66px; +} diff --git a/seahub/group/templates/group/group_members.html b/seahub/group/templates/group/group_members.html deleted file mode 100644 index 4812526b37..0000000000 --- a/seahub/group/templates/group/group_members.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends 'group/group_base.html' %} - -{% load seahub_tags avatar_tags i18n %} -{% block cur_members %}tab-cur{%endblock%} - -{% block right_panel %} -
-

{% trans "Members" %}

-{% if group.view_perm != 'pub' and not is_staff %} - -{% endif %} -
- -{% endblock %} - -{% block extra_script %}{{block.super}} - - -{% endblock %} diff --git a/seahub/group/urls.py b/seahub/group/urls.py index 51682e7061..3f98169422 100644 --- a/seahub/group/urls.py +++ b/seahub/group/urls.py @@ -1,6 +1,6 @@ from django.conf.urls.defaults import * -from views import group_info, group_members, group_member_operations, group_add_admin, \ +from views import group_info, group_member_operations, group_add_admin, \ group_manage, msg_reply, msg_reply_new, group_recommend, \ create_group_repo, attention, group_message_remove, \ group_remove_admin, group_discuss, group_wiki, group_wiki_create, \ @@ -32,7 +32,6 @@ urlpatterns = patterns('', url(r'^(?P\d+)/revoke_pub/$', group_revoke_public, name='group_revoke_pub'), url(r'^(?P\d+)/quit/$', group_quit, name='group_quit'), url(r'^(?P[\d]+)/create-repo/$', create_group_repo, name='create_group_repo'), - url(r'^(?P[\d]+)/members/$', group_members, name='group_members'), (r'^(?P[\d]+)/member/(?P[^/]+)/$', group_member_operations), url(r'^(?P\d+)/msgdel/(?P\d+)/$', group_message_remove, name='group_message_remove'), url(r'^(?P\d+)/admin/add/$', group_add_admin, name='group_add_admin'), diff --git a/seahub/group/views.py b/seahub/group/views.py index c89a6af5a1..3778d68015 100644 --- a/seahub/group/views.py +++ b/seahub/group/views.py @@ -592,26 +592,6 @@ def group_info(request, group): 'repo_password_min_length': config.REPO_PASSWORD_MIN_LENGTH, }, context_instance=RequestContext(request)) -@group_check -def group_members(request, group): - if group.view_perm == 'pub': - raise Http404 - - # Get all group members. - members = get_group_members(group.id) - - # get available modules(wiki, etc) - mods_available = get_available_mods_by_group(group.id) - mods_enabled = get_enabled_mods_by_group(group.id) - - return render_to_response("group/group_members.html", { - "members": members, - "group" : group, - "is_staff": group.is_staff, - "mods_enabled": mods_enabled, - "mods_available": mods_available, - }, context_instance=RequestContext(request)) - def send_group_member_add_mail(request, group, from_user, to_user): c = { 'email': from_user, diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index a0ee574444..14b9ccab59 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -643,7 +643,7 @@ <% if (is_staff) { %> <% } %> - + <% if (!is_pub) { %> <% } %> @@ -905,3 +905,10 @@

{% trans "No library is shared to this group" %}

<% } %> + diff --git a/seahub/templates/libraries.html b/seahub/templates/libraries.html index 65c94b03c9..96e0fb9769 100644 --- a/seahub/templates/libraries.html +++ b/seahub/templates/libraries.html @@ -130,26 +130,38 @@ {% endif %} -
+
-
+
- + +

- -

+
+
+
+ +

{% trans "Members" %}

+
+
+ +
    +

    +
    +
    +

    {% trans "Organization" %}

    diff --git a/seahub/templates/my_group_repos.html b/seahub/templates/my_group_repos.html deleted file mode 100644 index c2b0903ded..0000000000 --- a/seahub/templates/my_group_repos.html +++ /dev/null @@ -1,50 +0,0 @@ -{% load seahub_tags group_avatar_tags i18n %}
    - {% if group_repos %} - - - - - - - - - - - - {% for repo in group_repos %} - - {% if repo.show_group_name %} - - - {% else %} - - - {% endif %} - - - - {% if repo.last_modified %} - - {% else %} - - {% endif %} - - - {% endfor %} -
    {% trans "Group" %}{% trans "Name" %}{% trans "Description" %}{% trans "Last Update" %}{% trans "Shared By" %}
    {% grp_avatar repo.group.id 20 %}{{ repo.group.group_name }} - {% if repo.encrypted %} - {% trans - {% else %} - {% if repo.user_perm == 'rw' %} - {% trans - {% else %} - {% trans - {% endif %} - {% endif %} - {{ repo.repo_name }}{{ repo.repo_desc }}{{ repo.last_modified|translate_seahub_time }}--{{ repo.user|email2nickname }}
    - {% else %} -
    -

    {% trans "No library is shared to your groups" %}

    -
    - {% endif %} -
    diff --git a/seahub/urls.py b/seahub/urls.py index 08bdd35586..dd0e10ccec 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -98,6 +98,7 @@ urlpatterns = patterns( url(r'^lib/(?P[-0-9a-f]{36})/file(?P.*)$', view_lib_file, name='view_lib_file'), url(r'^#common/lib/(?P[-0-9a-f]{36})/(?P.*)$', fake_view, name='view_common_lib_dir'), url(r'^#group/(?P\d+)/$', fake_view, name='view_group'), + url(r'^#group/(?P\d+)/members/$', fake_view, name='group_members'), url(r'^#groups/', fake_view, name='group_list'), # url(r'^home/my/lib/(?P[-0-9a-f]{36})/dir/(?P.*)$', myhome_lib, name='myhome_lib'), diff --git a/static/scripts/app/collections/group-members.js b/static/scripts/app/collections/group-members.js new file mode 100644 index 0000000000..4f64cc192f --- /dev/null +++ b/static/scripts/app/collections/group-members.js @@ -0,0 +1,19 @@ +define([ + 'underscore', + 'backbone', + 'common' +], function(_, Backbone, Common) { + 'use strict'; + + var GroupMemberCollection = Backbone.Collection.extend({ + setGroupId: function(group_id) { + this.group_id = group_id; + }, + + url: function() { + return Common.getUrl({name: 'group_members', group_id: this.group_id}); + } + }); + + return GroupMemberCollection; +}); diff --git a/static/scripts/app/router.js b/static/scripts/app/router.js index b54518534d..173c7e9d5f 100644 --- a/static/scripts/app/router.js +++ b/static/scripts/app/router.js @@ -25,6 +25,7 @@ define([ 'groups/': 'showGroups', 'group/:group_id/': 'showGroupRepos', 'group/:group_id/lib/:repo_id(/*path)': 'showGroupRepoDir', + 'group/:group_id/members/': 'showGroupMembers', 'org/': 'showOrgRepos', 'org/lib/:repo_id(/*path)': 'showOrgRepoDir', 'common/lib/:repo_id(/*path)': 'showCommonDir', @@ -178,6 +179,11 @@ define([ }); }, + showGroupMembers: function(group_id) { + this.showGroupRepos(group_id); + this.groupView.showMembers(); + }, + showOrgRepos: function() { this.switchCurrentView(this.orgView); this.orgView.showRepoList(); diff --git a/static/scripts/app/views/group-member.js b/static/scripts/app/views/group-member.js new file mode 100644 index 0000000000..6d6eeeb043 --- /dev/null +++ b/static/scripts/app/views/group-member.js @@ -0,0 +1,47 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'common' +], function($, _, Backbone, Common) { + 'use strict'; + + var View = Backbone.View.extend({ + tagName: 'li', + className: 'user-item cspt ovhd', + + template: _.template($('#group-member-tmpl').html()), + + events: { + 'mouseenter': 'highlight', + 'mouseleave': 'rmHighlight', + 'click': 'visitMemberProfile' + }, + + initialize: function() { + }, + + render: function() { + this.$el.html(this.template(this.model.attributes)); + return this; + }, + + highlight: function() { + this.$el.addClass('hl'); + }, + + rmHighlight: function() { + this.$el.removeClass('hl'); + }, + + visitMemberProfile: function() { + location.href = Common.getUrl({ + 'name': 'user_profile', + 'username': encodeURIComponent(this.model.get('email')) + }); + } + + }); + + return View; +}); diff --git a/static/scripts/app/views/group-members.js b/static/scripts/app/views/group-members.js new file mode 100644 index 0000000000..9c047e4c67 --- /dev/null +++ b/static/scripts/app/views/group-members.js @@ -0,0 +1,110 @@ +define([ + 'jquery', + 'underscore', + 'backbone', + 'common', + 'app/collections/group-members', + 'app/views/group-member' +], function($, _, Backbone, Common, GroupMembers, ItemView) { + 'use strict'; + + var View = Backbone.View.extend({ + el: '#group-members', + + initialize: function(options) { + this.collection = new GroupMembers(); + this.listenTo(this.collection, 'add', this.addOne); + this.listenTo(this.collection, 'reset', this.reset); + + this.$loadingTip = this.$('.loading-tip'); + this.$listContainer = $('#group-member-list'); + this.$error = this.$('.error'); + + var _this = this; + $(window).resize(function () { + _this.setConMaxHeight(); + }); + $(document).click(function(e) { + var target = e.target || event.srcElement; + var $popup = _this.$el, + $popup_switch = $('#group-members-icon'); + + if ($('#group-members:visible').length && + !$popup.is(target) && + !$popup.find('*').is(target) && + !$popup_switch.is(target)) { + _this.hide(); + } + }); + }, + + events: { + 'click .close': 'hide' + }, + + addOne: function(item, collection, options) { + var view = new ItemView({ + model: item + }); + this.$listContainer.append(view.render().el); + }, + + reset: function() { + this.$error.hide(); + this.$loadingTip.hide(); + this.$listContainer.empty(); + this.collection.each(this.addOne, this); + this.$listContainer.show(); + }, + + render: function() { + this.$listContainer.hide(); + this.$loadingTip.show(); + + var _this = this; + this.collection.setGroupId(this.group_id); + this.collection.fetch({ + cache: false, + reset: true, + data: {'avatar_size': 32}, + success: function (collection, response, opts) { + }, + error: function (collection, response, opts) { + _this.$loadingTip.hide(); + var err_msg; + if (response.responseText) { + if (response['status'] == 401 || response['status'] == 403) { + err_msg = gettext("Permission error"); + } else { + err_msg = gettext("Error"); + } + } else { + err_msg = gettext('Please check the network.'); + } + _this.$error.html(err_msg).show(); + } + }); + }, + + // set max-height for '.popover-con' + setConMaxHeight: function() { + this.$('.popover-con').css({'max-height': $(window).height() - this.$el.offset().top - this.$('.popover-hd').outerHeight(true) - 2}); // 2: top, bottom border width of $el + }, + + show: function(options) { + this.group_id = options.group_id; + this.$el.show(); + this.setConMaxHeight(); + this.render(); + app.router.navigate('group/' + this.group_id + '/members/'); + }, + + hide: function() { + this.$el.hide(); + app.router.navigate('group/' + this.group_id + '/'); + } + + }); + + return View; +}); diff --git a/static/scripts/app/views/group.js b/static/scripts/app/views/group.js index 497d4cb377..25c5d4be27 100644 --- a/static/scripts/app/views/group.js +++ b/static/scripts/app/views/group.js @@ -5,18 +5,20 @@ define([ 'common', 'app/collections/group-repos', 'app/views/group-repo', - 'app/views/add-group-repo' + 'app/views/add-group-repo', + 'app/views/group-members' ], function($, _, Backbone, Common, GroupRepos, GroupRepoView, - AddGroupRepoView) { + AddGroupRepoView, GroupMembersView) { 'use strict'; var GroupView = Backbone.View.extend({ - el: '#group-repo-tabs', + el: '#group', groupTopTemplate: _.template($('#group-top-tmpl').html()), reposHdTemplate: _.template($('#shared-repos-hd-tmpl').html()), events: { + 'click #group-members-icon': 'toggleMembersPanel', 'click .repo-create': 'createRepo', 'click .by-name': 'sortByName', 'click .by-time': 'sortByTime' @@ -27,8 +29,8 @@ define([ this.$table = this.$('table'); this.$tableHead = this.$('thead'); this.$tableBody = this.$('tbody'); - this.$loadingTip = this.$('.loading-tip'); - this.$emptyTip = this.$('.empty-tips'); + this.$loadingTip = this.$('#group-repos .loading-tip'); + this.$emptyTip = this.$('#group-repos .empty-tips'); this.repos = new GroupRepos(); this.listenTo(this.repos, 'add', this.addOne); @@ -36,6 +38,7 @@ define([ this.dirView = options.dirView; + this.membersView = new GroupMembersView(); }, addOne: function(repo, collection, options) { @@ -185,6 +188,19 @@ define([ this.hideRepoList(); this.dirView.hide(); this.$emptyTip.hide(); + }, + + showMembers: function () { + this.membersView.show({'group_id': this.group_id}); + }, + + toggleMembersPanel: function () { + var panel_id = this.membersView.el.id; + if ($('#' + panel_id + ':visible').length) { // the panel is shown + this.membersView.hide(); + } else { + this.showMembers(); + } } }); diff --git a/static/scripts/common.js b/static/scripts/common.js index c6db8fc5ad..e8bc324224 100644 --- a/static/scripts/common.js +++ b/static/scripts/common.js @@ -104,6 +104,7 @@ define([ case 'repo_set_password': return siteRoot + 'repo/set_password/'; case 'groups': return siteRoot + 'api/v2.1/groups/'; case 'group_repos': return siteRoot + 'api2/groups/' + options.group_id + '/repos/'; + case 'group_members': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/members/'; case 'group_basic_info': return siteRoot + 'ajax/group/' + options.group_id + '/basic-info/'; case 'toggle_group_modules': return siteRoot + 'ajax/group/' + options.group_id + '/toggle-modules/'; case 'toggle_personal_modules': return siteRoot + 'ajax/toggle-personal-modules/'; @@ -117,6 +118,7 @@ define([ case 'search_user': return siteRoot + 'api2/search-user/'; case 'dir_shared_items': return siteRoot + 'api2/repos/' + options.repo_id + '/dir/shared_items/'; case 'events': return siteRoot + 'api2/events/'; + case 'user_profile': return siteRoot + 'profile/' + options.username + '/'; } }, From 1f15e387524b97c89c839b5557a9a03074a4650a Mon Sep 17 00:00:00 2001 From: llj Date: Tue, 15 Dec 2015 10:59:44 +0800 Subject: [PATCH 16/17] [group members] use double size for member avatars --- seahub/settings.py | 2 +- static/scripts/app/views/group-members.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/seahub/settings.py b/seahub/settings.py index 67b22a1997..49b05da232 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -287,7 +287,7 @@ AVATAR_DEFAULT_URL = '/avatars/default.png' AVATAR_DEFAULT_NON_REGISTERED_URL = '/avatars/default-non-register.jpg' AVATAR_MAX_AVATARS_PER_USER = 1 AVATAR_CACHE_TIMEOUT = 14 * 24 * 60 * 60 -AUTO_GENERATE_AVATAR_SIZES = (16, 20, 24, 28, 32, 36, 40, 48, 60, 80, 290) +AUTO_GENERATE_AVATAR_SIZES = (16, 20, 24, 28, 32, 36, 40, 48, 60, 64, 80, 290) # Group avatar GROUP_AVATAR_STORAGE_DIR = 'avatars/groups' GROUP_AVATAR_DEFAULT_URL = 'avatars/groups/default.png' diff --git a/static/scripts/app/views/group-members.js b/static/scripts/app/views/group-members.js index 9c047e4c67..1c0087cef5 100644 --- a/static/scripts/app/views/group-members.js +++ b/static/scripts/app/views/group-members.js @@ -66,7 +66,7 @@ define([ this.collection.fetch({ cache: false, reset: true, - data: {'avatar_size': 32}, + data: {'avatar_size': 64}, success: function (collection, response, opts) { }, error: function (collection, response, opts) { From de63d7284c97fbfc28d961337efd01abd630b3fc Mon Sep 17 00:00:00 2001 From: llj Date: Tue, 15 Dec 2015 11:33:07 +0800 Subject: [PATCH 17/17] [group members] removed some spaces --- static/scripts/app/views/group-members.js | 6 +++--- static/scripts/app/views/group.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/static/scripts/app/views/group-members.js b/static/scripts/app/views/group-members.js index 1c0087cef5..29012b8d86 100644 --- a/static/scripts/app/views/group-members.js +++ b/static/scripts/app/views/group-members.js @@ -21,7 +21,7 @@ define([ this.$error = this.$('.error'); var _this = this; - $(window).resize(function () { + $(window).resize(function() { _this.setConMaxHeight(); }); $(document).click(function(e) { @@ -67,9 +67,9 @@ define([ cache: false, reset: true, data: {'avatar_size': 64}, - success: function (collection, response, opts) { + success: function(collection, response, opts) { }, - error: function (collection, response, opts) { + error: function(collection, response, opts) { _this.$loadingTip.hide(); var err_msg; if (response.responseText) { diff --git a/static/scripts/app/views/group.js b/static/scripts/app/views/group.js index 25c5d4be27..018c4f4fce 100644 --- a/static/scripts/app/views/group.js +++ b/static/scripts/app/views/group.js @@ -190,11 +190,11 @@ define([ this.$emptyTip.hide(); }, - showMembers: function () { + showMembers: function() { this.membersView.show({'group_id': this.group_id}); }, - toggleMembersPanel: function () { + toggleMembersPanel: function() { var panel_id = this.membersView.el.id; if ($('#' + panel_id + ':visible').length) { // the panel is shown this.membersView.hide();