mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-16 15:19:06 +00:00
[address book] add 'show/set group quota', 'list/create/delete group libraries' functions
This commit is contained in:
@@ -1024,7 +1024,7 @@
|
||||
{# address book #}
|
||||
<script type="text/template" id="address-book-tmpl">
|
||||
<div class="hd ovhd">
|
||||
<h3 class="fleft">{% trans "Address Book" %}</h3>
|
||||
<h3 class="fleft">{% trans "Organization" %}</h3>
|
||||
<div class="fright">
|
||||
<button class="btn-white js-add-group">{% trans "New Group" %}</button>
|
||||
</div>
|
||||
@@ -1033,9 +1033,10 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">{% trans "Name" %}</th>
|
||||
<th width="30%">{% trans "Created At" %}</th>
|
||||
<th width="20%"><!--Operations--></th>
|
||||
<th width="40%">{% trans "Name" %}</th>
|
||||
<th width="25%">{% trans "Created At" %}</th>
|
||||
<th width="20%">{% trans "Quota" %}</th>
|
||||
<th width="15%"><!--Operations--></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -1052,6 +1053,7 @@
|
||||
<div class="fright">
|
||||
<button class="btn-white js-add-group">{% trans "New Group" %}</button>
|
||||
<button class="btn-white js-add-member">{% trans "Add Member" %}</button>
|
||||
<button class="btn-white js-add-library">{% trans "New Library" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="loading-icon loading-tip"></span>
|
||||
@@ -1060,9 +1062,10 @@
|
||||
<table class="hide">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">{% trans "Name" %}</th>
|
||||
<th width="30%">{% trans "Created At" %}</th>
|
||||
<th width="20%"><!--Operations--></th>
|
||||
<th width="40%">{% trans "Name" %}</th>
|
||||
<th width="25%">{% trans "Created At" %}</th>
|
||||
<th width="20%">{% trans "Quota" %}</th>
|
||||
<th width="15%"><!--Operations--></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -1085,11 +1088,28 @@
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="empty-tip hide">{% trans "No members" %}</p>
|
||||
</div>
|
||||
<div class="libraries">
|
||||
<h4 class="small-hd">{% trans "Libraries" %}</h4>
|
||||
<table class="hide">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th width="55%">{% trans "Name" %}</th>
|
||||
<th width="35%">{% trans "Size" %}</th>
|
||||
<th width="10%"><!--Operations--></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="empty-tip hide">{% trans "No libraries" %}</p>
|
||||
</div>
|
||||
<p class="error error-tip hide"></p>
|
||||
</script>
|
||||
<script type="text/template" id="address-book-group-path-tmpl">
|
||||
<a href="#address-book/" class="normal">{% trans "Address Book" %}</a>
|
||||
<a href="#address-book/" class="normal">{% trans "Organization" %}</a>
|
||||
<span class="path-split">/</span>
|
||||
<% for (var i = 0,len = ancestor_groups.length; i < len; i++) { %>
|
||||
<a href="#address-book/groups/<%= ancestor_groups[i].id %>/" class="normal"><%- ancestor_groups[i].name %></a>
|
||||
@@ -1100,7 +1120,48 @@
|
||||
<script type="text/template" id="address-book-group-item-tmpl">
|
||||
<td><a href="{{ SITE_ROOT }}sysadmin/#address-book/groups/<%= id %>/"><%- name %></a></td>
|
||||
<td><time title="<%= time %>"><%= time_from_now %></time></td>
|
||||
<td>
|
||||
<span class="group-quota"><%= quota_shown %></span>
|
||||
<span title="{% trans "Edit Quota" %}" class="quota-edit-icon sf2-icon-edit op-icon vh"></span>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="sf2-icon-delete sf2-x group-delete-btn op-icon vh" title="{% trans "Delete" %}" aria-label="{% trans "Delete" %}"></a>
|
||||
</td>
|
||||
</script>
|
||||
<script type="text/template" id="address-book-group-quota-set-form-tmpl">
|
||||
<form id="set-quota-form" method="post" action="" class="hide">{% csrf_token %}
|
||||
<h3>{% trans "Set group quota" %}</h3>
|
||||
<input type="text" name="quota" class="input" /> MB
|
||||
<p class="tip">
|
||||
<span>{% trans "An integer that is greater than 0 or equal to -2." %}</span><br />
|
||||
<span>{% trans "Tip: -2 means no limit" %}</span>
|
||||
</p>
|
||||
<p class="error hide"></p>
|
||||
<input type="submit" value="{% trans "Submit" %}" class="submit" />
|
||||
</form>
|
||||
</script>
|
||||
<script type="text/template" id="address-book-group-library-item-tmpl">
|
||||
<td>
|
||||
<img src="<%= icon_url %>" title="<%= icon_title %>" alt="<%= icon_title %>" width="24" />
|
||||
</td>
|
||||
<td>
|
||||
<% if (enable_sys_admin_view_repo && is_pro && !encrypted) { %>
|
||||
<a href="#libs/<%= repo_id %>/"><%- name %></a>
|
||||
<% } else { %>
|
||||
<%- name %>
|
||||
<% } %>
|
||||
</td>
|
||||
<td><%- formatted_size %></td>
|
||||
<td>
|
||||
<a href="#" class="sf2-icon-delete sf2-x repo-delete-btn op-icon vh" title="{% trans "Delete" %}" aria-label="{% trans "Delete" %}"></a>
|
||||
</td>
|
||||
</script>
|
||||
<script type="text/template" id="address-book-library-add-form-tmpl">
|
||||
<form id="library-add-form" action="" method="post" class="hide">{% csrf_token %}
|
||||
<h3 id="dialogTitle">{% trans "New Library" %}</h3>
|
||||
<label for="library-name">{% trans "Name" %}</label><br />
|
||||
<input type="text" name="library_name" value="" class="input" id="library-name" /><br />
|
||||
<p class="error hide"></p>
|
||||
<input type="submit" class="submit" value="{% trans "Submit" %}" />
|
||||
</form>
|
||||
</script>
|
||||
|
@@ -149,6 +149,10 @@ define([
|
||||
case 'group_members': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/members/';
|
||||
case 'group_member': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/members/' + options.email + '/';
|
||||
case 'group_member_bulk': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/members/bulk/';
|
||||
|
||||
case 'group_owned_libraries': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/group-owned-libraries/';
|
||||
case 'group_owned_library': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/group-owned-libraries/' + options.repo_id + '/';
|
||||
|
||||
case 'group_import_members': return siteRoot + 'ajax/group/' + options.group_id + '/members/import/';
|
||||
case 'group_repos': return siteRoot + 'api2/groups/' + options.group_id + '/repos/';
|
||||
case 'group_discussions': return siteRoot + 'api2/groups/' + options.group_id + '/discussions/';
|
||||
|
@@ -4,21 +4,26 @@ define([
|
||||
'backbone',
|
||||
'common',
|
||||
'moment',
|
||||
'simplemodal',
|
||||
'app/views/widgets/hl-item-view'
|
||||
], function($, _, Backbone, Common, Moment, HLItemView) {
|
||||
], function($, _, Backbone, Common, Moment, Simplemodal, HLItemView) {
|
||||
'use strict';
|
||||
|
||||
var GroupView = HLItemView.extend({
|
||||
tagName: 'tr',
|
||||
|
||||
template: _.template($('#address-book-group-item-tmpl').html()),
|
||||
setQuotaFormTemplate: _.template($('#address-book-group-quota-set-form-tmpl').html()),
|
||||
|
||||
events: {
|
||||
'click .group-delete-btn': 'deleteGroup'
|
||||
'click .group-delete-btn': 'deleteGroup',
|
||||
'click .quota-edit-icon': 'setQuota'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
HLItemView.prototype.initialize.call(this);
|
||||
|
||||
this.listenTo(this.model, "change", this.render);
|
||||
},
|
||||
|
||||
deleteGroup: function() {
|
||||
@@ -52,6 +57,54 @@ define([
|
||||
return false;
|
||||
},
|
||||
|
||||
setQuota: function() {
|
||||
var model = this.model;
|
||||
|
||||
var $form = $(this.setQuotaFormTemplate());
|
||||
$form.modal();
|
||||
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||
|
||||
$form.on('submit', function() {
|
||||
var $error = $('.error', $form);
|
||||
var $submitBtn = $('[type="submit"]', $form);
|
||||
var quota = $.trim($('[name="quota"]', $form).val());
|
||||
|
||||
if (!quota) {
|
||||
$error.html(gettext("It is required.")).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
Common.disableButton($submitBtn);
|
||||
$.ajax({
|
||||
url: Common.getUrl({
|
||||
'name':'admin-address-book-group',
|
||||
'group_id': model.get('id')
|
||||
}),
|
||||
type: 'PUT',
|
||||
cache: false,
|
||||
beforeSend: Common.prepareCSRFToken,
|
||||
data: {'quota': quota == -2 ? -2 : quota * 1000000},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
model.set({'quota': data.quota});
|
||||
$.modal.close();
|
||||
},
|
||||
error: function(xhr) {
|
||||
var err_msg;
|
||||
if (xhr.responseText) {
|
||||
err_msg = $.parseJSON(xhr.responseText).error_msg;
|
||||
} else {
|
||||
err_msg = gettext("Failed. Please check the network.");
|
||||
}
|
||||
$error.html(err_msg).show();
|
||||
Common.enableButton($submitBtn);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var data = this.model.toJSON(),
|
||||
created_at = Moment(data['created_at']);
|
||||
@@ -59,6 +112,8 @@ define([
|
||||
data['time'] = created_at.format('LLLL');
|
||||
data['time_from_now'] = Common.getRelativeTimeStr(created_at);
|
||||
|
||||
data['quota_shown'] = data['quota'] == -2 ? '--' : Common.quotaSizeFormat(data['quota']);
|
||||
|
||||
this.$el.html(this.template(data));
|
||||
|
||||
return this;
|
||||
|
@@ -0,0 +1,78 @@
|
||||
define([
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common',
|
||||
'app/views/widgets/hl-item-view'
|
||||
], function($, _, Backbone, Common, HLItemView) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var GroupRepoView = HLItemView.extend({
|
||||
|
||||
tagName: 'tr',
|
||||
|
||||
template: _.template($('#address-book-group-library-item-tmpl').html()),
|
||||
|
||||
events: {
|
||||
'click .repo-delete-btn': 'del'
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
HLItemView.prototype.initialize.call(this);
|
||||
|
||||
this.group_id = options.group_id;
|
||||
},
|
||||
|
||||
del: function() {
|
||||
var _this = this;
|
||||
var repo_name = this.model.get('repo_name');
|
||||
var popupTitle = gettext("Delete Library");
|
||||
var popupContent = gettext("Are you sure you want to delete %s ?").replace('%s', '<span class="op-target ellipsis ellipsis-op-target" title="' + Common.HTMLescape(repo_name) + '">' + Common.HTMLescape(repo_name) + '</span>');
|
||||
var yesCallback = function() {
|
||||
$.ajax({
|
||||
url: Common.getUrl({
|
||||
'name': 'group_owned_library',
|
||||
'group_id': _this.group_id,
|
||||
'repo_id': _this.model.get('repo_id')
|
||||
}),
|
||||
type: 'DELETE',
|
||||
beforeSend: Common.prepareCSRFToken,
|
||||
dataType: 'json',
|
||||
success: function() {
|
||||
_this.$el.remove();
|
||||
var msg = gettext("Successfully deleted library {placeholder}").replace('{placeholder}', repo_name);
|
||||
Common.feedback(msg, 'success');
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
Common.ajaxErrorHandler(xhr, textStatus, errorThrown);
|
||||
},
|
||||
complete: function() {
|
||||
$.modal.close();
|
||||
}
|
||||
});
|
||||
};
|
||||
Common.showConfirm(popupTitle, popupContent, yesCallback);
|
||||
return false;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var data = this.model.toJSON(),
|
||||
icon_size = Common.isHiDPI() ? 48 : 24,
|
||||
icon_url = this.model.getIconUrl(icon_size);
|
||||
|
||||
data['icon_url'] = icon_url;
|
||||
data['icon_title'] = this.model.getIconTitle();
|
||||
data['name'] = data.name || data.repo_name;
|
||||
data['formatted_size'] = Common.fileSizeFormat(data['size'], 1),
|
||||
data['enable_sys_admin_view_repo'] = app.pageOptions.enable_sys_admin_view_repo;
|
||||
data['is_pro'] = app.pageOptions.is_pro;
|
||||
this.$el.html(this.template(data));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return GroupRepoView;
|
||||
});
|
@@ -5,8 +5,11 @@ define([
|
||||
'common',
|
||||
'sysadmin-app/views/address-book-group-item',
|
||||
'sysadmin-app/views/group-member',
|
||||
'sysadmin-app/collection/address-book-group'
|
||||
], function($, _, Backbone, Common, GroupItemView, MemberItemView, GroupCollection) {
|
||||
'sysadmin-app/views/address-book-group-library',
|
||||
'sysadmin-app/collection/address-book-group',
|
||||
'sysadmin-app/collection/group-repos'
|
||||
], function($, _, Backbone, Common, GroupItemView, MemberItemView,
|
||||
LibItemView, GroupCollection, GroupRepoCollection) {
|
||||
'use strict';
|
||||
|
||||
var view = Backbone.View.extend({
|
||||
@@ -17,6 +20,7 @@ define([
|
||||
pathTemplate: _.template($("#address-book-group-path-tmpl").html()),
|
||||
groupAddFormTemplate: _.template($("#address-book-group-add-form-tmpl").html()),
|
||||
addMemberFormTemplate: _.template($('#add-group-member-form-tmpl').html()),
|
||||
addLibFormTemplate: _.template($("#address-book-library-add-form-tmpl").html()),
|
||||
|
||||
initialize: function() {
|
||||
this.groupCollection = new GroupCollection();
|
||||
@@ -27,6 +31,11 @@ define([
|
||||
this.memberCollection = new Backbone.Collection();
|
||||
this.listenTo(this.memberCollection, 'add', this.addMember);
|
||||
|
||||
// libraries
|
||||
this.groupRepoCollection = new GroupRepoCollection();
|
||||
this.listenTo(this.groupRepoCollection, 'reset', this.resetLibraries);
|
||||
this.listenTo(this.groupRepoCollection, 'add', this.addLibrary);
|
||||
|
||||
this.render();
|
||||
},
|
||||
|
||||
@@ -43,6 +52,12 @@ define([
|
||||
this.$members = this.$('.members');
|
||||
this.$membersTable = $('table', this.$members);
|
||||
this.$membersTableBody = $('tbody', this.$membersTable);
|
||||
this.$membersEmptyTip = $('.empty-tip', this.$members);
|
||||
|
||||
this.$libs = this.$('.libraries');
|
||||
this.$libsTable = $('table', this.$libs);
|
||||
this.$libsTableBody = $('tbody', this.$libsTable);
|
||||
this.$libsEmptyTip = $('.empty-tip', this.$libs);
|
||||
|
||||
this.$loadingTip = this.$('.loading-tip');
|
||||
this.$error = this.$('.error');
|
||||
@@ -50,7 +65,8 @@ define([
|
||||
|
||||
events: {
|
||||
'click .js-add-group': 'addGroup',
|
||||
'click .js-add-member': 'newMember'
|
||||
'click .js-add-member': 'newMember',
|
||||
'click .js-add-library': 'newLibrary'
|
||||
},
|
||||
|
||||
initPage: function() {
|
||||
@@ -66,6 +82,12 @@ define([
|
||||
this.$members.hide();
|
||||
this.$membersTable.hide();
|
||||
this.$membersTableBody.empty();
|
||||
this.$membersEmptyTip.hide();
|
||||
|
||||
this.$libs.hide();
|
||||
this.$libsTable.hide();
|
||||
this.$libsTableBody.empty();
|
||||
this.$libsEmptyTip.hide();
|
||||
|
||||
this.$error.hide();
|
||||
},
|
||||
@@ -167,6 +189,10 @@ define([
|
||||
success: function(data) {
|
||||
if (data.success.length > 0) {
|
||||
_this.memberCollection.add(data.success, {prepend: true});
|
||||
if (_this.memberCollection.length == 1) {
|
||||
_this.$membersEmptyTip.hide();
|
||||
_this.$membersTable.show();
|
||||
}
|
||||
}
|
||||
|
||||
var err_str = '';
|
||||
@@ -197,6 +223,60 @@ define([
|
||||
return false;
|
||||
},
|
||||
|
||||
newLibrary: function() {
|
||||
var _this = this;
|
||||
|
||||
var $form = $(this.addLibFormTemplate());
|
||||
$form.modal();
|
||||
$('#simplemodal-container').css({'height':'auto', 'width':'auto'});
|
||||
|
||||
$form.submit(function() {
|
||||
var name = $.trim($('[name="library_name"]', $form).val());
|
||||
var $error = $('.error', $form);
|
||||
var $submitBtn = $('[type="submit"]', $form);
|
||||
|
||||
if (!name) {
|
||||
$error.html(gettext("It is required.")).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
$error.hide();
|
||||
Common.disableButton($submitBtn);
|
||||
|
||||
$.ajax({
|
||||
url: Common.getUrl({
|
||||
'name': 'group_owned_libraries',
|
||||
'group_id': _this.options.group_id
|
||||
}),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: {'repo_name': name},
|
||||
traditional: true,
|
||||
beforeSend: Common.prepareCSRFToken,
|
||||
success: function(data) {
|
||||
_this.groupRepoCollection.add(data, {prepend: true});
|
||||
if (_this.groupRepoCollection.length == 1) {
|
||||
_this.$libsEmptyTip.hide();
|
||||
_this.$libsTable.show();
|
||||
}
|
||||
Common.closeModal();
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown){
|
||||
var err_msg;
|
||||
if (jqXHR.responseText) {
|
||||
err_msg = jqXHR.responseJSON.error_msg;
|
||||
} else {
|
||||
err_msg = gettext('Please check the network.');
|
||||
}
|
||||
$error.html(err_msg).show();
|
||||
Common.enableButton($submitBtn);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.$el.detach();
|
||||
this.attached = false;
|
||||
@@ -219,6 +299,9 @@ define([
|
||||
data: {'return_ancestors': true},
|
||||
cache: false,
|
||||
reset: true,
|
||||
success: function() {
|
||||
_this.getLibs();
|
||||
},
|
||||
error: function(collection, response, opts) {
|
||||
var err_msg;
|
||||
if (response.responseText) {
|
||||
@@ -238,6 +321,47 @@ define([
|
||||
});
|
||||
},
|
||||
|
||||
getLibs: function() {
|
||||
var _this = this;
|
||||
this.groupRepoCollection.setGroupId(this.options.group_id);
|
||||
this.groupRepoCollection.fetch({
|
||||
cache: false,
|
||||
reset: true,
|
||||
error: function(collection, response, opts) {
|
||||
var err_msg;
|
||||
if (response.responseText) {
|
||||
if (response['status'] == 401 || response['status'] == 403) {
|
||||
err_msg = gettext("Permission error");
|
||||
} else {
|
||||
err_msg = $.parseJSON(response.responseText).error_msg;
|
||||
}
|
||||
} else {
|
||||
err_msg = gettext("Failed. Please check the network.");
|
||||
}
|
||||
_this.$error.html(err_msg).show();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
resetLibraries: function() {
|
||||
if (this.groupRepoCollection.length > 0) {
|
||||
this.groupRepoCollection.each(this.addLibrary, this);
|
||||
this.$libsTable.show();
|
||||
} else {
|
||||
this.$libsEmptyTip.show();
|
||||
}
|
||||
this.$libs.show();
|
||||
},
|
||||
|
||||
addLibrary: function(item, collection, options) {
|
||||
var view = new LibItemView({model: item, group_id: this.options.group_id});
|
||||
if (options.prepend) {
|
||||
this.$libsTableBody.prepend(view.render().el);
|
||||
} else {
|
||||
this.$libsTableBody.append(view.render().el);
|
||||
}
|
||||
},
|
||||
|
||||
renderPath: function() {
|
||||
this.$path.html(this.pathTemplate({
|
||||
ancestor_groups: this.groupCollection.data.ancestor_groups,
|
||||
@@ -258,10 +382,13 @@ define([
|
||||
}
|
||||
this.$groups.show();
|
||||
|
||||
// There is at least 1 member, the owner.
|
||||
this.memberCollection.reset(this.groupCollection.data.members);
|
||||
if (this.memberCollection.length > 0) {
|
||||
this.memberCollection.each(this.addMember, this);
|
||||
this.$membersTable.show();
|
||||
} else {
|
||||
this.$membersEmptyTip.show();
|
||||
}
|
||||
this.$members.show();
|
||||
},
|
||||
|
||||
|
Reference in New Issue
Block a user