1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-05 00:43:53 +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:
killing
2012-10-26 14:27:54 +08:00
parent 0106d08911
commit 1d8ae030c2
11 changed files with 147 additions and 44 deletions

View File

@@ -215,3 +215,11 @@ class RepoPassowrdForm(forms.Form):
else: else:
raise forms.ValidationError(u'未知错误') 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'})

View File

@@ -3,18 +3,33 @@
{% block nav_useradmin_class %}class="cur"{% endblock %} {% 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 %} {% block right_panel %}
<h3>所有用户</h3> <h3>所有成员</h3>
<button id="org-user-add">添加用户</button> <button id="org-user-add">添加成员</button>
<table> <table>
<tr> <tr>
<th width="80%">邮箱</th> <th width="60%">邮箱</th>
<th width="20%">已用空间</th>
<th width="20%">操作</th> <th width="20%">操作</th>
</tr> </tr>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td><a href="{% url 'user_profile' user.email %}" target="_blank">{{ user.props.email }}</a></td> <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> <td>
{% if not user.is_self %} {% 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> <a href="#" class="remove-user-btn op" data="{% url 'org_user_remove' request.user.org.url_prefix user.email %}">删除</a>

View File

@@ -21,6 +21,12 @@
{% endif %} {% endif %}
</div> </div>
</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" %} {% include "snippets/my_groups.html" %}
{% endblock %} {% endblock %}

View File

@@ -27,7 +27,7 @@ urlpatterns = patterns('',
### Org admin ### ### Org admin ###
url(r'^(?P<url_prefix>[^/]+)/seafadmin/$', org_seafadmin, name='org_seafadmin'), 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>[^/]+)/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>[^/]+)/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'), url(r'^(?P<url_prefix>[^/]+)/group/remove/(?P<group_id>[\d]+)/$', org_group_remove, name='org_group_remove'),

View File

@@ -139,6 +139,8 @@ def org_personal(request, url_prefix):
events = get_org_user_events(org.org_id, user) events = get_org_user_events(org.org_id, user)
else: else:
events = None events = None
quota_usage = seafserv_threaded_rpc.get_org_user_quota_usage(org.org_id, user)
return render_to_response('organizations/personal.html', { return render_to_response('organizations/personal.html', {
'owned_repos': owned_repos, 'owned_repos': owned_repos,
@@ -151,6 +153,7 @@ def org_personal(request, url_prefix):
'allow_public_share': True, 'allow_public_share': True,
'nickname': nickname, 'nickname': nickname,
'events': events, 'events': events,
'quota_usage': quota_usage,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
@login_required @login_required
@@ -281,7 +284,7 @@ def send_org_user_add_mail(request, email, password, org_name):
@login_required @login_required
@org_staff_required @org_staff_required
def org_useradmin(request, url_prefix): def org_admin(request, url_prefix):
""" """
List and add org users. List and add org users.
""" """
@@ -333,17 +336,28 @@ def org_useradmin(request, url_prefix):
page_next = True page_next = True
else: else:
page_next = False 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] users = users_plus_one[:per_page]
for user in users: for user in users:
if user.props.id == request.user.id: if user.props.id == request.user.id:
user.is_self = True 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 # My contacts
contacts = Contact.objects.filter(user_email=request.user.username) 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( return render_to_response(
'organizations/org_useradmin.html', { 'organizations/org_admin.html', {
'users': users, 'users': users,
'contacts': contacts, 'contacts': contacts,
'current_page': current_page, 'current_page': current_page,
@@ -351,6 +365,8 @@ def org_useradmin(request, url_prefix):
'next_page': current_page+1, 'next_page': current_page+1,
'per_page': per_page, 'per_page': per_page,
'page_next': page_next, 'page_next': page_next,
'org_quota_usage': org_quota_usage,
'org_quota': org_quota,
}, },
context_instance=RequestContext(request)) context_instance=RequestContext(request))

View File

@@ -49,7 +49,7 @@
{% endif %} {% endif %}
{% if org.is_staff %} {% 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> <a href="{% url 'org_personal' org.url_prefix %}"{% block top_bar_org_myaccount_class %}{% endblock %}>个人工作台</a>
{% endif %} {% endif %}
</div> </div>

View File

@@ -42,7 +42,7 @@
<div class="info-item"> <div class="info-item">
<h3 class="info-item-top">已用空间</h3> <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> </div>
<!-- 我的群组 --> <!-- 我的群组 -->

View File

@@ -4,7 +4,7 @@
<ul class="nav"> <ul class="nav">
{% if request.user.org.is_staff %} {% if request.user.org.is_staff %}
<li> <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>
<li> <li>
<a href="{% url org_seafadmin request.user.org.url_prefix %}" {% block nav_seafadmin_class %}{% endblock %}>资料库管理</a> <a href="{% url org_seafadmin request.user.org.url_prefix %}" {% block nav_seafadmin_class %}{% endblock %}>资料库管理</a>

View File

@@ -4,7 +4,7 @@
{% block nav_orgadmin_class %}class="cur"{% endblock %} {% block nav_orgadmin_class %}class="cur"{% endblock %}
{% block right_panel %} {% block right_panel %}
<h3>所有企业</h3> <h3>所有团体</h3>
{% if orgs %} {% if orgs %}
<table> <table>
<tr> <tr>
@@ -58,7 +58,7 @@
{% block extra_script %} {% block extra_script %}
<script type="text/javascript"> <script type="text/javascript">
addConfirmTo($('.org-remove-btn'), '确定要删除该企业'); addConfirmTo($('.org-remove-btn'), '确定要删除该团体');
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -1,5 +1,7 @@
{% extends "admin_base.html" %} {% extends "admin_base.html" %}
{% load url from future %}
{% block nav_useradmin_class %}class="cur"{% endblock %} {% block nav_useradmin_class %}class="cur"{% endblock %}
{% block left_panel %} {% block left_panel %}
<!-- <!--
@@ -7,8 +9,13 @@
<li><a href="{{ SITE_ROOT }}useradmin/add/">添加用户</a></li> <li><a href="{{ SITE_ROOT }}useradmin/add/">添加用户</a></li>
</ul> </ul>
--> -->
<h3>已用空间</h3> <div class="info-item">
<p>{{ quota_usage|filesizeformat }} / 2 GB</p> <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 %} {% endblock %}
@@ -29,7 +36,7 @@
<td><a href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/">{{ repo.props.name }}</a></td> <td><a href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/">{{ repo.props.name }}</a></td>
<td>{{ repo.props.desc }}</td> <td>{{ repo.props.desc }}</td>
<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> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@@ -61,33 +68,59 @@
<p>暂无</p> <p>暂无</p>
{% endif %} {% endif %}
<!-- <form id="set-quota-form" method="post" class="hide">{% csrf_token %}
<h3>{{ email }} 的计算机</h3> <label>设置该用户的存储容量上限</label><br />
<table class="user-list"> <input type="hidden" name="email" value="{{ email }}" />
<tr> <input type="text" name="quota" /> MB <br />
<th width="60%">计算机名</th> <p class="tip">Tip: 设置为0表示重置为默认上限</p>
<th width="20%">角色</th> <p class="error hide"></p>
<th width="20%">状态</th> <input type="submit" value="提交" class="submit" />
</tr> </form>
{% for username, roles in user_dict.items %} {% endblock %}
<tr>
{% if username %}
<td>{{ username }}</td> {% block extra_script %}
{% else %} <script type="text/javascript">
<td>未知</td>
{% endif %} $('.set-quota').click(function() {
$("#set-quota-form").modal({appendTo: "#main"});
{% if roles %} return false;
<td>{{ roles }}</td> });
<td>已验证</td>
{% else %} $('#set-quota-form .submit').click(function() {
<td>无</td> var self = $(this);
<td>未验证</td> self.attr('disabled', 'disabled');
{% endif %} $.ajax({
url: '{% url 'views.user_info' email %}',
</tr> type: 'POST',
{% endfor %} dataType: 'json',
</table> 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 %} {% endblock %}

View File

@@ -60,7 +60,7 @@ from notifications.models import UserNotification
from profile.models import Profile from profile.models import Profile
from forms import AddUserForm, FileLinkShareForm, RepoCreateForm, \ from forms import AddUserForm, FileLinkShareForm, RepoCreateForm, \
RepoNewDirForm, RepoNewFileForm, FileCommentForm, RepoRenameFileForm, \ RepoNewDirForm, RepoNewFileForm, FileCommentForm, RepoRenameFileForm, \
RepoPassowrdForm, SharedRepoCreateForm RepoPassowrdForm, SharedRepoCreateForm, SetUserQuotaForm
from utils import render_permission_error, render_error, list_to_string, \ from utils import render_permission_error, render_error, list_to_string, \
get_httpserver_root, get_ccnetapplet_root, gen_token, \ get_httpserver_root, get_ccnetapplet_root, gen_token, \
calculate_repo_last_modify, valid_previewed_file, \ calculate_repo_last_modify, valid_previewed_file, \
@@ -858,6 +858,7 @@ def myhome(request):
quota_usage = 0 quota_usage = 0
email = request.user.username email = request.user.username
quota = seafserv_threaded_rpc.get_user_quota(email)
quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email) quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email)
# Personal repos that I own # Personal repos that I own
@@ -921,6 +922,7 @@ def myhome(request):
return render_to_response('myhome.html', { return render_to_response('myhome.html', {
"nickname": nickname, "nickname": nickname,
"owned_repos": owned_repos, "owned_repos": owned_repos,
"quota": quota,
"quota_usage": quota_usage, "quota_usage": quota_usage,
"in_repos": in_repos, "in_repos": in_repos,
"contacts": contacts, "contacts": contacts,
@@ -1825,10 +1827,32 @@ def sys_useradmin(request):
@login_required @login_required
@sys_staff_required @sys_staff_required
def user_info(request, email): 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 = [] owned_repos = []
quota_usage = 0
owned_repos = seafserv_threaded_rpc.list_owned_repos(email) 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) quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email)
# Repos that are share to user # Repos that are share to user
@@ -1838,6 +1862,7 @@ def user_info(request, email):
return render_to_response( return render_to_response(
'userinfo.html', { 'userinfo.html', {
'owned_repos': owned_repos, 'owned_repos': owned_repos,
'quota': quota,
'quota_usage': quota_usage, 'quota_usage': quota_usage,
"in_repos": in_repos, "in_repos": in_repos,
'email': email 'email': email