mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 17:02:47 +00:00
Add quota and quota usage information.
Changed pages: * myhome * user info admin * org personal page * org admin page
This commit is contained in:
8
forms.py
8
forms.py
@@ -215,3 +215,11 @@ class RepoPassowrdForm(forms.Form):
|
||||
else:
|
||||
raise forms.ValidationError(u'未知错误')
|
||||
|
||||
class SetUserQuotaForm(forms.Form):
|
||||
"""
|
||||
Form for setting user quota.
|
||||
"""
|
||||
email = forms.CharField(error_messages={'required': '参数错误'})
|
||||
quota = forms.IntegerField(min_value=0,
|
||||
error_messages={'required': '容量不能为空',
|
||||
'min_value': '容量不能小于0'})
|
||||
|
@@ -3,18 +3,33 @@
|
||||
|
||||
{% block nav_useradmin_class %}class="cur"{% endblock %}
|
||||
|
||||
{% block left_panel %}
|
||||
|
||||
<div class="info-item">
|
||||
<h3 class="info-item-top">团体已用总空间</h3>
|
||||
<p class="info-item-bottom">{{ org_quota_usage|filesizeformat }} {% if org_quota > 0 %} / {{ org_quota|filesizeformat }} {% endif %}</p>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block right_panel %}
|
||||
<h3>所有用户</h3>
|
||||
<button id="org-user-add">添加用户</button>
|
||||
<h3>所有成员</h3>
|
||||
<button id="org-user-add">添加成员</button>
|
||||
<table>
|
||||
<tr>
|
||||
<th width="80%">邮箱</th>
|
||||
<th width="60%">邮箱</th>
|
||||
<th width="20%">已用空间</th>
|
||||
<th width="20%">操作</th>
|
||||
</tr>
|
||||
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td><a href="{% url 'user_profile' user.email %}" target="_blank">{{ user.props.email }}</a></td>
|
||||
<td>
|
||||
{% if user.quota_usage >= 0 %}
|
||||
{{ user.quota_usage|filesizeformat }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if not user.is_self %}
|
||||
<a href="#" class="remove-user-btn op" data="{% url 'org_user_remove' request.user.org.url_prefix user.email %}">删除</a>
|
@@ -21,6 +21,12 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<h3 class="info-item-top">我已用的团体空间</h3>
|
||||
<p class="info-item-bottom">{{ quota_usage|filesizeformat }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 我的群组 -->
|
||||
{% include "snippets/my_groups.html" %}
|
||||
{% endblock %}
|
||||
|
@@ -27,7 +27,7 @@ urlpatterns = patterns('',
|
||||
|
||||
### Org admin ###
|
||||
url(r'^(?P<url_prefix>[^/]+)/seafadmin/$', org_seafadmin, name='org_seafadmin'),
|
||||
url(r'^(?P<url_prefix>[^/]+)/useradmin/$', org_useradmin, name='org_useradmin'),
|
||||
url(r'^(?P<url_prefix>[^/]+)/orgadmin/$', org_admin, name='org_admin'),
|
||||
url(r'^(?P<url_prefix>[^/]+)/useradmin/remove/(?P<user>[^/]+)/$', org_user_remove, name='org_user_remove'),
|
||||
url(r'^(?P<url_prefix>[^/]+)/groupadmin/$', org_group_admin, name='org_groupadmin'),
|
||||
url(r'^(?P<url_prefix>[^/]+)/group/remove/(?P<group_id>[\d]+)/$', org_group_remove, name='org_group_remove'),
|
||||
|
@@ -140,6 +140,8 @@ def org_personal(request, url_prefix):
|
||||
else:
|
||||
events = None
|
||||
|
||||
quota_usage = seafserv_threaded_rpc.get_org_user_quota_usage(org.org_id, user)
|
||||
|
||||
return render_to_response('organizations/personal.html', {
|
||||
'owned_repos': owned_repos,
|
||||
"in_repos": in_repos,
|
||||
@@ -151,6 +153,7 @@ def org_personal(request, url_prefix):
|
||||
'allow_public_share': True,
|
||||
'nickname': nickname,
|
||||
'events': events,
|
||||
'quota_usage': quota_usage,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
@login_required
|
||||
@@ -281,7 +284,7 @@ def send_org_user_add_mail(request, email, password, org_name):
|
||||
|
||||
@login_required
|
||||
@org_staff_required
|
||||
def org_useradmin(request, url_prefix):
|
||||
def org_admin(request, url_prefix):
|
||||
"""
|
||||
List and add org users.
|
||||
"""
|
||||
@@ -334,16 +337,27 @@ def org_useradmin(request, url_prefix):
|
||||
else:
|
||||
page_next = False
|
||||
|
||||
org = get_user_current_org(request.user.username, url_prefix)
|
||||
if not org:
|
||||
return HttpResponseRedirect(reverse(myhome))
|
||||
|
||||
users = users_plus_one[:per_page]
|
||||
for user in users:
|
||||
if user.props.id == request.user.id:
|
||||
user.is_self = True
|
||||
try:
|
||||
user.quota_usage = seafserv_threaded_rpc.get_org_user_quota_usage(org.org_id, user.email)
|
||||
except:
|
||||
user.quota_usage = -1
|
||||
|
||||
# My contacts
|
||||
contacts = Contact.objects.filter(user_email=request.user.username)
|
||||
|
||||
org_quota_usage = seafserv_threaded_rpc.get_org_quota_usage(org.org_id)
|
||||
org_quota = seafserv_threaded_rpc.get_org_quota(org.org_id)
|
||||
|
||||
return render_to_response(
|
||||
'organizations/org_useradmin.html', {
|
||||
'organizations/org_admin.html', {
|
||||
'users': users,
|
||||
'contacts': contacts,
|
||||
'current_page': current_page,
|
||||
@@ -351,6 +365,8 @@ def org_useradmin(request, url_prefix):
|
||||
'next_page': current_page+1,
|
||||
'per_page': per_page,
|
||||
'page_next': page_next,
|
||||
'org_quota_usage': org_quota_usage,
|
||||
'org_quota': org_quota,
|
||||
},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
@@ -49,7 +49,7 @@
|
||||
{% endif %}
|
||||
|
||||
{% if org.is_staff %}
|
||||
<a href="{% url 'org_useradmin' org.url_prefix %}"{% block top_bar_org_manager_class %}{% endblock %}>管理员工作台</a>
|
||||
<a href="{% url 'org_admin' org.url_prefix %}"{% block top_bar_org_manager_class %}{% endblock %}>管理员工作台</a>
|
||||
<a href="{% url 'org_personal' org.url_prefix %}"{% block top_bar_org_myaccount_class %}{% endblock %}>个人工作台</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@@ -42,7 +42,7 @@
|
||||
|
||||
<div class="info-item">
|
||||
<h3 class="info-item-top">已用空间</h3>
|
||||
<p class="info-item-bottom">{{ quota_usage|filesizeformat }} {% if cloud_mode %}/ 2 GB {% endif %}</p>
|
||||
<p class="info-item-bottom">{{ quota_usage|filesizeformat }} {% if quota > 0 %}/ {{ quota|filesizeformat }} {% endif %}</p>
|
||||
</div>
|
||||
|
||||
<!-- 我的群组 -->
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<ul class="nav">
|
||||
{% if request.user.org.is_staff %}
|
||||
<li>
|
||||
<a href="{% url org_useradmin request.user.org.url_prefix %}" {% block nav_useradmin_class %}{% endblock %}>用户管理</a>
|
||||
<a href="{% url org_admin request.user.org.url_prefix %}" {% block nav_useradmin_class %}{% endblock %}>团体概况</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url org_seafadmin request.user.org.url_prefix %}" {% block nav_seafadmin_class %}{% endblock %}>资料库管理</a>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
{% block nav_orgadmin_class %}class="cur"{% endblock %}
|
||||
|
||||
{% block right_panel %}
|
||||
<h3>所有企业</h3>
|
||||
<h3>所有团体</h3>
|
||||
{% if orgs %}
|
||||
<table>
|
||||
<tr>
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
{% block extra_script %}
|
||||
<script type="text/javascript">
|
||||
addConfirmTo($('.org-remove-btn'), '确定要删除该企业?');
|
||||
addConfirmTo($('.org-remove-btn'), '确定要删除该团体?');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
{% extends "admin_base.html" %}
|
||||
|
||||
{% load url from future %}
|
||||
|
||||
{% block nav_useradmin_class %}class="cur"{% endblock %}
|
||||
{% block left_panel %}
|
||||
<!--
|
||||
@@ -7,8 +9,13 @@
|
||||
<li><a href="{{ SITE_ROOT }}useradmin/add/">添加用户</a></li>
|
||||
</ul>
|
||||
-->
|
||||
<h3>已用空间</h3>
|
||||
<p>{{ quota_usage|filesizeformat }} / 2 GB</p>
|
||||
<div class="info-item">
|
||||
<div class="info-item-top">
|
||||
<h3 class="inbl">已用空间</h3>
|
||||
<a href="#" class="set-quota op">设置容量</a>
|
||||
</div>
|
||||
<p class="info-item-bottom">{{ quota_usage|filesizeformat }} {% if quota > 0 %} / {{ quota|filesizeformat }} {% endif %}</p>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -29,7 +36,7 @@
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/">{{ repo.props.name }}</a></td>
|
||||
<td>{{ repo.props.desc }}</td>
|
||||
<td>
|
||||
<button data="{{ SITE_ROOT }}repo/remove/{{ repo.props.id }}/?next={{ request.path }}" class="repo-delete-btn">删除</button>
|
||||
<a href="#" data="{{ SITE_ROOT }}repo/remove/{{ repo.props.id }}/?next={{ request.path }}" class="remove-user-repo op">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -61,33 +68,59 @@
|
||||
<p>暂无</p>
|
||||
{% endif %}
|
||||
|
||||
<!--
|
||||
<h3>{{ email }} 的计算机</h3>
|
||||
<table class="user-list">
|
||||
<tr>
|
||||
<th width="60%">计算机名</th>
|
||||
<th width="20%">角色</th>
|
||||
<th width="20%">状态</th>
|
||||
</tr>
|
||||
<form id="set-quota-form" method="post" class="hide">{% csrf_token %}
|
||||
<label>设置该用户的存储容量上限</label><br />
|
||||
<input type="hidden" name="email" value="{{ email }}" />
|
||||
<input type="text" name="quota" /> MB <br />
|
||||
<p class="tip">Tip: 设置为0表示重置为默认上限</p>
|
||||
<p class="error hide"></p>
|
||||
<input type="submit" value="提交" class="submit" />
|
||||
</form>
|
||||
|
||||
{% for username, roles in user_dict.items %}
|
||||
<tr>
|
||||
{% if username %}
|
||||
<td>{{ username }}</td>
|
||||
{% else %}
|
||||
<td>未知</td>
|
||||
{% endif %}
|
||||
|
||||
{% if roles %}
|
||||
<td>{{ roles }}</td>
|
||||
<td>已验证</td>
|
||||
{% else %}
|
||||
<td>无</td>
|
||||
<td>未验证</td>
|
||||
{% endif %}
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
-->
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block extra_script %}
|
||||
<script type="text/javascript">
|
||||
|
||||
$('.set-quota').click(function() {
|
||||
$("#set-quota-form").modal({appendTo: "#main"});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#set-quota-form .submit').click(function() {
|
||||
var self = $(this);
|
||||
self.attr('disabled', 'disabled');
|
||||
$.ajax({
|
||||
url: '{% url 'views.user_info' email %}',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
cache: 'false',
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {
|
||||
'email': $('#set-quota-form input[name="email"]').val(),
|
||||
'quota': $('#set-quota-form input[name="quota"]').val()
|
||||
},
|
||||
success: function(data) {
|
||||
if (data['success']) {
|
||||
location.reload(true);
|
||||
} else {
|
||||
apply_form_error('set-quota-form', data['error']);
|
||||
self.removeAttr('disabled');
|
||||
}
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
var errors = $.parseJSON(data.responseText);
|
||||
$.each(errors, function(index, value) {
|
||||
apply_form_error('set-quota-form', value[0]);
|
||||
});
|
||||
self.removeAttr('disabled');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
addConfirmTo($('.remove-user-repo'), '确定要删除该资料库?');
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
29
views.py
29
views.py
@@ -60,7 +60,7 @@ from notifications.models import UserNotification
|
||||
from profile.models import Profile
|
||||
from forms import AddUserForm, FileLinkShareForm, RepoCreateForm, \
|
||||
RepoNewDirForm, RepoNewFileForm, FileCommentForm, RepoRenameFileForm, \
|
||||
RepoPassowrdForm, SharedRepoCreateForm
|
||||
RepoPassowrdForm, SharedRepoCreateForm, SetUserQuotaForm
|
||||
from utils import render_permission_error, render_error, list_to_string, \
|
||||
get_httpserver_root, get_ccnetapplet_root, gen_token, \
|
||||
calculate_repo_last_modify, valid_previewed_file, \
|
||||
@@ -858,6 +858,7 @@ def myhome(request):
|
||||
quota_usage = 0
|
||||
|
||||
email = request.user.username
|
||||
quota = seafserv_threaded_rpc.get_user_quota(email)
|
||||
quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email)
|
||||
|
||||
# Personal repos that I own
|
||||
@@ -921,6 +922,7 @@ def myhome(request):
|
||||
return render_to_response('myhome.html', {
|
||||
"nickname": nickname,
|
||||
"owned_repos": owned_repos,
|
||||
"quota": quota,
|
||||
"quota_usage": quota_usage,
|
||||
"in_repos": in_repos,
|
||||
"contacts": contacts,
|
||||
@@ -1825,10 +1827,32 @@ def sys_useradmin(request):
|
||||
@login_required
|
||||
@sys_staff_required
|
||||
def user_info(request, email):
|
||||
if request.method == 'POST':
|
||||
result = {}
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
f = SetUserQuotaForm(request.POST)
|
||||
if f.is_valid():
|
||||
email = f.cleaned_data['email']
|
||||
quota_mb = f.cleaned_data['quota']
|
||||
quota = quota_mb * (1 << 20)
|
||||
|
||||
try:
|
||||
seafserv_threaded_rpc.set_user_quota(email, quota)
|
||||
except:
|
||||
result['error'] = u'内部错误,设置失败'
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
|
||||
result['success'] = True
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
else:
|
||||
result['error'] = str(f.errors.values()[0])
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
|
||||
owned_repos = []
|
||||
quota_usage = 0
|
||||
|
||||
owned_repos = seafserv_threaded_rpc.list_owned_repos(email)
|
||||
quota = seafserv_threaded_rpc.get_user_quota(email)
|
||||
quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email)
|
||||
|
||||
# Repos that are share to user
|
||||
@@ -1838,6 +1862,7 @@ def user_info(request, email):
|
||||
return render_to_response(
|
||||
'userinfo.html', {
|
||||
'owned_repos': owned_repos,
|
||||
'quota': quota,
|
||||
'quota_usage': quota_usage,
|
||||
"in_repos": in_repos,
|
||||
'email': email
|
||||
|
Reference in New Issue
Block a user