mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-11 11:51:27 +00:00
[group members] redesigned it
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -1,37 +0,0 @@
|
||||
{% extends 'group/group_base.html' %}
|
||||
|
||||
{% load seahub_tags avatar_tags i18n %}
|
||||
{% block cur_members %}tab-cur{%endblock%}
|
||||
|
||||
{% block right_panel %}
|
||||
<div class="hd">
|
||||
<h3 class="fleft">{% trans "Members" %}</h3>
|
||||
{% if group.view_perm != 'pub' and not is_staff %}
|
||||
<button id="quit-group" data-url="{% url 'group_quit' group.id %}" class="fright">{% trans "Leave group" %}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<ul class="user-list">
|
||||
{% for m in members %}
|
||||
{% with e=m.user_name id=m.user_name %}
|
||||
<li class="user ovhd">
|
||||
<a href="{% url 'user_profile' id %}" class="pic fleft">{% avatar e 48 %}</a>
|
||||
<div class="txt fright">
|
||||
<a class="name" href="{% url 'user_profile' id %}">{{ e|email2nickname }}</a>
|
||||
<p>{{ e }}</p>
|
||||
</div>
|
||||
</li>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}{{block.super}}
|
||||
<script type="text/javascript">
|
||||
addConfirmTo($('#quit-group'), {
|
||||
'title': "{% trans "Quit Group" %}",
|
||||
'con': "{% trans "Are you sure you want to quit this group?" %}",
|
||||
'post': true
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@@ -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<group_id>\d+)/revoke_pub/$', group_revoke_public, name='group_revoke_pub'),
|
||||
url(r'^(?P<group_id>\d+)/quit/$', group_quit, name='group_quit'),
|
||||
url(r'^(?P<group_id>[\d]+)/create-repo/$', create_group_repo, name='create_group_repo'),
|
||||
url(r'^(?P<group_id>[\d]+)/members/$', group_members, name='group_members'),
|
||||
(r'^(?P<group_id>[\d]+)/member/(?P<user_name>[^/]+)/$', group_member_operations),
|
||||
url(r'^(?P<group_id>\d+)/msgdel/(?P<msg_id>\d+)/$', group_message_remove, name='group_message_remove'),
|
||||
url(r'^(?P<group_id>\d+)/admin/add/$', group_add_admin, name='group_add_admin'),
|
||||
|
@@ -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,
|
||||
|
@@ -643,7 +643,7 @@
|
||||
<% if (is_staff) { %>
|
||||
<span class="sf2-icon-cog1 op-icon" title="{% trans "Admin" %}"></span>
|
||||
<% } %>
|
||||
<span class="sf2-icon-user2 op-icon" title="{% trans "Members" %}"></span>
|
||||
<span class="sf2-icon-user2 op-icon" title="{% trans "Members" %}" id="group-members-icon"></span>
|
||||
<% if (!is_pub) { %>
|
||||
<span class="sf2-icon-msgs2 op-icon" title="{% trans "Discussion" %}"></span>
|
||||
<% } %>
|
||||
@@ -905,3 +905,10 @@
|
||||
<p class="empty-tips alc">{% trans "No library is shared to this group" %}</p>
|
||||
<% } %>
|
||||
</script>
|
||||
<script type="text/template" id="group-member-tmpl">
|
||||
<img src="<%= avatar_url %>" alt="" width="32" class="avatar fleft" />
|
||||
<div class="txt">
|
||||
<p class="txt-item ellipsis" title="<%- name %>"><%- name %></p>
|
||||
<p class="txt-item ellipsis" title="<%- contact_email %>"><%- contact_email %></p>
|
||||
</div>
|
||||
</script>
|
||||
|
@@ -130,26 +130,38 @@
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<div id="group-repo-tabs" class="hide">
|
||||
<div id="group" class="hide">
|
||||
<div id="group-top"></div>
|
||||
|
||||
<div id="grp-repos">
|
||||
<div id="group-repos">
|
||||
<table class="hide">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<div class="empty-tips" style="margin-bottom:150px; display:none;">
|
||||
<h2 class="alc">{% trans "No library is shared to this group" %}</h2>
|
||||
<p>{% blocktrans %}You can share libraries by clicking the "New Library" button above or the "Share" icon on your libraries list.{% endblocktrans %}</p>
|
||||
<p>{% trans "Libraries shared as writable can be downloaded and synced by other group members. Read only libraries can only be downloaded, updates by others will not be uploaded." %}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="loading-icon loading-tip"></span>
|
||||
<p class="error error-tip hide"></p>
|
||||
</div>
|
||||
|
||||
<div id="group-members" class="popover hide">
|
||||
<div class="outer-caret up-outer-caret"><div class="inner-caret"></div></div>
|
||||
<div class="popover-hd ovhd">
|
||||
<span class="popover-close close sf2-icon-x1 op-icon fright" title="{% trans "Close" %}"></span>
|
||||
<h3 class="popover-title">{% trans "Members" %}</h3>
|
||||
</div>
|
||||
<div class="popover-con">
|
||||
<span class="loading-icon loading-tip"></span>
|
||||
<ul id="group-member-list" class="hide"></ul>
|
||||
<p class="error hide"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="organization-repos" class="hide">
|
||||
<div class="hd">
|
||||
<h3 class="fleft">{% trans "Organization" %}</h3>
|
||||
|
@@ -1,50 +0,0 @@
|
||||
{% load seahub_tags group_avatar_tags i18n %}<div id="group-repos">
|
||||
{% if group_repos %}
|
||||
<table>
|
||||
<tr>
|
||||
<th width="4%"><!--icon--></th>
|
||||
<th width="13%">{% trans "Group" %}</th>
|
||||
<th width="4%"><!--icon--></th>
|
||||
<th width="20%">{% trans "Name" %}</th>
|
||||
<th width="29%">{% trans "Description" %}</th>
|
||||
<th width="15%">{% trans "Last Update" %}</th>
|
||||
<th width="15%">{% trans "Shared By" %}</th>
|
||||
</tr>
|
||||
|
||||
{% for repo in group_repos %}
|
||||
<tr>
|
||||
{% if repo.show_group_name %}
|
||||
<td>{% grp_avatar repo.group.id 20 %}</td>
|
||||
<td><a href="{% url 'group_info' repo.group.id %}">{{ repo.group.group_name }}</a></td>
|
||||
{% else %}
|
||||
<td></td>
|
||||
<td></td>
|
||||
{% endif %}
|
||||
<td>
|
||||
{% if repo.encrypted %}
|
||||
<img src="{{MEDIA_URL}}img/sync-folder-encrypt-20.png" title="{% trans "Read-Write" %}" alt="{% trans "directory icon" %}" />
|
||||
{% else %}
|
||||
{% if repo.user_perm == 'rw' %}
|
||||
<img src="{{MEDIA_URL}}img/sync-folder-20.png?t=1387267140" title="{% trans "Read-Write" %}" alt="{% trans "directory icon" %}" />
|
||||
{% else %}
|
||||
<img src="{{MEDIA_URL}}img/folder-no-write-20.png?t=1387267140" title="{% trans "Read-Only" %}" alt="{% trans "directory icon" %}" />
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a href="{% url 'repo' repo.repo_id %}">{{ repo.repo_name }}</a></td>
|
||||
<td>{{ repo.repo_desc }}</td>
|
||||
{% if repo.last_modified %}
|
||||
<td>{{ repo.last_modified|translate_seahub_time }}</td>
|
||||
{% else %}
|
||||
<td>--</td>
|
||||
{% endif %}
|
||||
<td>{{ repo.user|email2nickname }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="empty-tips">
|
||||
<h2 class="alc">{% trans "No library is shared to your groups" %}</h2>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
@@ -98,6 +98,7 @@ urlpatterns = patterns(
|
||||
url(r'^lib/(?P<repo_id>[-0-9a-f]{36})/file(?P<path>.*)$', view_lib_file, name='view_lib_file'),
|
||||
url(r'^#common/lib/(?P<repo_id>[-0-9a-f]{36})/(?P<path>.*)$', fake_view, name='view_common_lib_dir'),
|
||||
url(r'^#group/(?P<group_id>\d+)/$', fake_view, name='view_group'),
|
||||
url(r'^#group/(?P<group_id>\d+)/members/$', fake_view, name='group_members'),
|
||||
url(r'^#groups/', fake_view, name='group_list'),
|
||||
# url(r'^home/my/lib/(?P<repo_id>[-0-9a-f]{36})/dir/(?P<path>.*)$', myhome_lib, name='myhome_lib'),
|
||||
|
||||
|
19
static/scripts/app/collections/group-members.js
Normal file
19
static/scripts/app/collections/group-members.js
Normal file
@@ -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;
|
||||
});
|
@@ -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();
|
||||
|
47
static/scripts/app/views/group-member.js
Normal file
47
static/scripts/app/views/group-member.js
Normal file
@@ -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;
|
||||
});
|
110
static/scripts/app/views/group-members.js
Normal file
110
static/scripts/app/views/group-members.js
Normal file
@@ -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;
|
||||
});
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
@@ -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 + '/';
|
||||
}
|
||||
},
|
||||
|
||||
|
Reference in New Issue
Block a user