1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-20 19:08:21 +00:00

[org] improve org feature

This commit is contained in:
lian
2014-10-22 10:10:58 +08:00
parent a984c86442
commit 10a31ca7e3
13 changed files with 488 additions and 269 deletions

View File

@@ -16,7 +16,11 @@
</tr>
{% for group in groups %}
<tr>
<td><a href="{{ SITE_ROOT }}group/{{ group.props.id }}/">{{ group.props.group_name }}</a></td>
<td><a href="{{ SITE_ROOT }}group/{{ group.props.id }}/">{{ group.props.group_name }}</a>
{% if group.org_name %}
<p style="font-size:11px;"><a href="{% url 'sys_org_info_user' group.org_id %}">({{group.org_name}})</a></p>
{% endif %}
</td>
<td>{{ group.props.creator_name }}</td>
<td>{{ group.props.timestamp|tsstr_sec }}</td>
<td><a href="#" data-url="{% url 'group_remove' group.id %}" data-target="{{ group.props.group_name }}" class="group-remove-btn op vh">{% trans "Delete" %}</a></td>

View File

@@ -39,7 +39,7 @@
</tr>
{% for org in orgs %}
<tr>
<td><a href="{% url 'sys_org_info' org.org_id %}">{{ org.org_name }}</a></td>
<td><a href="{% url 'sys_org_info_user' org.org_id %}">{{ org.org_name }}</a></td>
<td>{{ org.url_prefix }}</td>
<td><a href="{% url 'user_info' org.creator %}">{{ org.creator }}</a></td>
<td>

View File

@@ -1,240 +0,0 @@
{% extends "admin_base.html" %}
{% load i18n avatar_tags seahub_tags group_avatar_tags %}
{% load url from future %}
{% block nav_orgadmin_class %}class="cur"{% endblock %}
{% block extra_style %}
<style type="text/css">
#set-quota-form {
min-width:255px;
}
</style>
{% endblock %}
{% block left_panel %}
<div class="side-info">
<a class="go-back" title="{% trans "Back to organization list" %}" href="{% url 'sys_org_admin' %}"><span class="icon-chevron-left"></span></a>
<h3 class="hd">{{ org.org_name }}</h3>
<dl>
<dt>{% trans "Number of members" %}</dt>
<dd>{{ users_count }}</dd>
<dt>{% trans "Number of groups" %}</dt>
<dd>{{ groups_count }}</dd>
</dl>
<h3 class="hd">{% trans "Space Used" %}</h3>
<p>{{ quota_usage|filesizeformat }} {% if total_quota > 0 %}/ {{ total_quota|filesizeformat }} {% endif %}</p>
<a href="#" id="set-quota">{% trans "Set Quota" %}</a>
</div>
<form id="set-quota-form" method="post" class="hide">{% csrf_token %}
<h3>{% trans "Set org storage limit" %}</h3>
<input type="hidden" name="org_id" value="{{ org.org_id }}" />
<input type="text" name="quota" /> MB
<p class="tip">{% trans "Tip: 0 means default limit" %}</p>
<p class="error hide"></p>
<input type="submit" value="{% trans "Submit" %}" class="submit" />
</form>
{% endblock %}
{% block right_panel %}
<div id="tabs" class="tab-tabs">
<div class="hd ovhd">
<ul class="tab-tabs-nav fleft">
<li class="tab"><a href="#members" class="a">{% trans "Members" %}</a></li>
<li class="tab"><a href="#grps" class="a">{% trans "Groups" %}</a></li>
</ul>
</div>
<div id="members">
<table>
<tr>
<th width="25%">{% trans "Email" %}</th>
<th width="10%">{% trans "Status" %}</th>
<th width="20%">{% trans "Space Used" %}</th>
<th width="25%">{% trans "Create At / Last Login" %}</th>
<th width="20%">{% trans "Operations" %}</th>
</tr>
{% for user in users %}
<tr data-userid="{{user.email}}">
<td><a href="{% url 'user_info' user.email %}">{{ user.email }}</a></td>
<td>
<div class="user-status">
{% if user.is_active %}
<span class="user-status-cur-value">{% trans "Active" %}</span>
{% else %}
<span class="user-status-cur-value">{% trans "Inactive" %}</span>
{% endif %}
<img src="{{MEDIA_URL}}img/edit_12.png" alt="{% trans "Edit"%}" title="{% trans "Edit"%}" class="user-status-edit-icon cspt vh" />
</div>
<select name="permission" class="user-status-select hide">
<option value="1" {%if user.is_active %}selected="selected"{% endif %}>{% trans "Active" %}</option>
<option value="0" {%if not user.is_active %}selected="selected"{% endif %}>{% trans "Inactive"%}</option>
</select>
</td>
<td>
{% if CALC_SHARE_USAGE %}
{{ user.self_usage|filesizeformat }} + {{ user.share_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %}
{% else %}
{{ user.self_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %}
{% endif %}
</td>
<td style="font-size:11px;">
{{ user.ctime|tsstr_sec }} / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %}
</td>
<td>
{% if not user.is_self %}
<a href="#" class="remove-user-btn op vh" data-url="{% url 'user_remove' user.id %}" data-target="{{ user.email }}">{% trans "Delete" %}</a>
<a href="#" class="reset-user-btn op vh" data-url="{% url 'user_reset' user.id %}" data-target="{{ user.email }}">{% trans "ResetPwd" %}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<div id="grps" class="hide">
{% if groups %}
<table>
<tr>
<th width="30%">{% trans "Name" %}</th>
<th width="30%">{% trans "Creator" %}</th>
<th width="25%">{% trans "Create At" %}</th>
<th width="15%">{% trans "Operations" %}</th>
</tr>
{% for group in groups %}
<tr>
<td><a href="{{ SITE_ROOT }}group/{{ group.id }}/">{{ group.group_name }}</a></td>
<td>{{ group.creator_name }}</td>
<td>{{ group.timestamp|tsstr_sec }}</td>
<td><a href="#" data-url="{% url 'group_remove' group.id %}" data-target="{{ group.group_name }}" class="group-remove-btn op vh">{% trans "Delete" %}</a></td>
</tr>
{% endfor %}
</table>
{% else %}
<p>{% trans "None" %}</p>
{% endif %}
</div>
</div>
<div id="activate-msg" class="hide">
<p>{% trans "Activating..., please wait" %}</p>
</div>
{% 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 form = $('#set-quota-form'),
form_id = form.attr('id');
var quota = $('input[name="quota"]', form).val();
if (!$.trim(quota)) {
apply_form_error(form_id, "{% trans "Quota can not be empty" %}");
return false;
}
var sb_btn = $(this);
disable(sb_btn);
$.ajax({
url: '{% url 'sys_org_set_quota' org.org_id %}',
type: 'POST',
dataType: 'json',
cache: 'false',
beforeSend: prepareCSRFToken,
data: {
'quota': quota
},
success: function(data) {
location.reload(true);
},
error: function(xhr, textStatus, errorThrown) {
if (xhr.responseText) {
apply_form_error(form_id, $.parseJSON(xhr.responseText).error);
} else {
apply_form_error(form_id, "{% trans "Failed. Please check the network." %}");
}
enable(sb_btn);
}
});
return false;
});
addConfirmTo($('.group-remove-btn'), {
'title': "{% trans "Delete Group" %}",
'con': "{% trans "Are you sure you want to delete %s ?" %}"
});
addConfirmTo($('.remove-user-btn'), {
'title':"{% trans "Delete User" %}",
'con':"{% trans "Are you sure you want to delete %s ?" %}"
});
addConfirmTo($('.reset-user-btn'), {
'title':"{% trans "Password Reset" %}",
'con':"{% trans "Are you sure you want to reset the password of %s ?" %}"
});
$('tr:gt(0)').hover(
function() {
$(this).find('.user-status-edit-icon').removeClass('vh');
},
function() {
$(this).find('.user-status-edit-icon').addClass('vh');
}
);
$('.user-status-edit-icon').click(function() {
$(this).parent().addClass('hide');
$(this).parent().next().removeClass('hide'); // show 'select'
});
$('.user-status-select').change(function() {
var select = $(this),
select_val = select.val(),
uid = select.parents('tr').attr('data-userid'),
url = "{{ SITE_ROOT }}useradmin/toggle_status/" + uid + "/?s=" + select_val;
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
cache: false,
beforeSend: function() {
if (select_val == 1) {
// show activating popup
$('#activate-msg').modal();
$('#simplemodal-container').css({'height':'auto'});
}
},
success: function(data) {
if (data['email_sent']) {
feedback("{% trans "Edit succeeded, an email has been sent." %}", 'success');
} else if (data['email_sent'] === false) {
feedback("{% trans "Edit succeeded, but failed to send email, please check your email configuration." %}", 'success');
} else {
feedback("{% trans "Edit succeeded" %}", 'success');
}
select.prev().children('span').html(select.children('option[value="' +select.val() + '"]').text());
select.addClass('hide');
select.prev().removeClass('hide');
$.modal.close();
},
error: function() {
feedback("{% trans "Edit failed." %}", 'error');
select.addClass('hide');
select.prev().removeClass('hide');
$.modal.close();
}
});
});
$(document).click(function(e) {
var target = e.target || event.srcElement;
// target can't be edit-icon
if (!$('.user-status-edit-icon, .user-status-select').is(target)) {
$('.user-status').removeClass('hide');
$('.user-status-select').addClass('hide');
}
});
</script>
{% endblock %}

View File

@@ -0,0 +1,39 @@
{% extends "admin_base.html" %}
{% load i18n seahub_tags %}
{% load url from future %}
{% block nav_orgadmin_class %}class="cur"{% endblock %}
{% block extra_style %}
<style type="text/css">
#set-quota-form {
min-width:255px;
}
</style>
{% endblock %}
{% block left_panel %}
<div class="side-info">
<a class="go-back" title="{% trans "Back to organization list" %}" href="{% url 'sys_org_admin' %}"><span class="icon-chevron-left"></span></a>
<h3 class="hd">{{ org.org_name }}</h3>
<dl>
<dt>{% trans "Number of members" %}</dt>
<dd>{{ users_count }}</dd>
<dt>{% trans "Number of groups" %}</dt>
<dd>{{ groups_count }}</dd>
</dl>
<h3 class="hd">{% trans "Space Used" %}</h3>
<p>{{ quota_usage|filesizeformat }} {% if total_quota > 0 %}/ {{ total_quota|filesizeformat }} {% endif %}</p>
<a href="#" id="set-quota">{% trans "Set Quota" %}</a>
</div>
<form id="set-quota-form" method="post" class="hide">{% csrf_token %}
<h3>{% trans "Set org storage limit" %}</h3>
<input type="hidden" name="org_id" value="{{ org.org_id }}" />
<input type="text" name="quota" /> MB
<p class="tip">{% trans "Tip: 0 means default limit" %}</p>
<p class="error hide"></p>
<input type="submit" value="{% trans "Submit" %}" class="submit" />
</form>
{% endblock %}

View File

@@ -0,0 +1,47 @@
{% extends "sysadmin/sys_org_info_base.html" %}
{% load i18n seahub_tags %}
{% load url from future %}
{% block right_panel %}
<div class="tabnav">
<ul class="tabnav-tabs">
<li class="tabnav-tab"><a href="{% url 'sys_org_info_user' org.org_id %}">{% trans "Members" %}</a></li>
<li class="tabnav-tab tabnav-tab-cur"><a href="{% url 'sys_org_info_group' org.org_id %}">{% trans "Groups" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_library' org.org_id %}">{% trans "Libraries" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_setting' org.org_id %}">{% trans "Setting" %}</a></li>
</ul>
</div>
{% if groups %}
<table>
<tr>
<th width="30%">{% trans "Name" %}</th>
<th width="30%">{% trans "Creator" %}</th>
<th width="25%">{% trans "Create At" %}</th>
<th width="15%">{% trans "Operations" %}</th>
</tr>
{% for group in groups %}
<tr>
<td><a href="{{ SITE_ROOT }}group/{{ group.id }}/">{{ group.group_name }}</a></td>
<td>{{ group.creator_name }}</td>
<td>{{ group.timestamp|tsstr_sec }}</td>
<td><a href="#" data-url="{% url 'group_remove' group.id %}" data-target="{{ group.group_name }}" class="group-remove-btn op vh">{% trans "Delete" %}</a></td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="empty-tips">
<h2 class="alc">{% trans "This organization doesn't have any groups" %}</h2>
</div>
{% endif %}
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
{% include 'sysadmin/sys_org_set_quota_js.html' %}
addConfirmTo($('.group-remove-btn'), {
'title': "{% trans "Delete Group" %}",
'con': "{% trans "Are you sure you want to delete %s ?" %}"
});
</script>
{% endblock %}

View File

@@ -0,0 +1,61 @@
{% extends "sysadmin/sys_org_info_base.html" %}
{% load i18n seahub_tags %}
{% load url from future %}
{% block right_panel %}
<div class="tabnav">
<ul class="tabnav-tabs">
<li class="tabnav-tab"><a href="{% url 'sys_org_info_user' org.org_id %}">{% trans "Members" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_group' org.org_id %}">{% trans "Groups" %}</a></li>
<li class="tabnav-tab tabnav-tab-cur"><a href="{% url 'sys_org_info_library' org.org_id %}">{% trans "Libraries" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_setting' org.org_id %}">{% trans "Setting" %}</a></li>
</ul>
</div>
{% if org_repos %}
<table class="repo-list">
<tr>
<th width="15%">{% trans "Name" %}</th>
<th width="25%">ID</th>
<th width="25%">{% trans "Owner" %}</th>
<th width="22%">{% trans "Description" %}</th>
<th width="13%">{% trans "Operations" %}</th>
</tr>
{% for repo in org_repos %}
<tr>
<td>{{ repo.name }}</td>
<td style="font-size:11px;">{{ repo.id }}</td>
<td>
{% if repo.owner %}
<a href="{{ SITE_ROOT }}useradmin/info/{{ repo.owner }}/">{{ repo.owner}}</a>
{% else %}
--
{% endif %}
</td>
<td>{{ repo.desc }}</td>
<td data-id="{{ repo.id }}" data-name="{{ repo.name }}">
<div>
<a href="#" class="repo-delete-btn op vh">{% trans "Delete" %}</a>
</div>
</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="empty-tips">
<h2 class="alc">{% trans "This organization doesn't have any libraries" %}</h2>
</div>
{% endif %}
{% include 'snippets/repo_del_popup.html' %}
{% include 'sysadmin/repo_transfer_form.html' %}
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
{% include 'sysadmin/sys_org_set_quota_js.html' %}
{% include 'snippets/repo_del_js.html' %}
{% include 'sysadmin/repoadmin_js.html' %}
</script>
{% endblock %}

View File

@@ -0,0 +1,30 @@
{% extends "sysadmin/sys_org_info_base.html" %}
{% load i18n seahub_tags %}
{% load url from future %}
{% block right_panel %}
<div class="tabnav">
<ul class="tabnav-tabs">
<li class="tabnav-tab"><a href="{% url 'sys_org_info_user' org.org_id %}">{% trans "Members" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_group' org.org_id %}">{% trans "Groups" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_library' org.org_id %}">{% trans "Libraries" %}</a></li>
<li class="tabnav-tab tabnav-tab-cur"><a href="{% url 'sys_org_info_setting' org.org_id %}">{% trans "Setting" %}</a></li>
</ul>
</div>
<div class="setting-item">
<h3>{% trans "Rename Organization" %}</h3>
<form action="{% url 'sys_org_rename' org.org_id %}" method="post">{% csrf_token %}
<label>{% trans "New Name" %}</label></br>
<input type="text" name="new_name" class="input" /></br>
<input type="submit" value="{% trans "Submit" %}" class="submit" />
</form>
</div>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
{% include 'sysadmin/sys_org_set_quota_js.html' %}
</script>
{% endblock %}

View File

@@ -0,0 +1,138 @@
{% extends "sysadmin/sys_org_info_base.html" %}
{% load i18n seahub_tags %}
{% load url from future %}
{% block right_panel %}
<div class="tabnav">
<ul class="tabnav-tabs">
<li class="tabnav-tab tabnav-tab-cur"><a href="{% url 'sys_org_info_user' org.org_id %}">{% trans "Members" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_group' org.org_id %}">{% trans "Groups" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_library' org.org_id %}">{% trans "Libraries" %}</a></li>
<li class="tabnav-tab"><a href="{% url 'sys_org_info_setting' org.org_id %}">{% trans "Setting" %}</a></li>
</ul>
</div>
<table>
<tr>
<th width="25%">{% trans "Email" %}</th>
<th width="10%">{% trans "Status" %}</th>
<th width="20%">{% trans "Space Used" %}</th>
<th width="25%">{% trans "Create At / Last Login" %}</th>
<th width="20%">{% trans "Operations" %}</th>
</tr>
{% for user in users %}
<tr data-userid="{{user.email}}">
<td><a href="{% url 'user_info' user.email %}">{{ user.email }}</a></td>
<td>
<div class="user-status">
{% if user.is_active %}
<span class="user-status-cur-value">{% trans "Active" %}</span>
{% else %}
<span class="user-status-cur-value">{% trans "Inactive" %}</span>
{% endif %}
<img src="{{MEDIA_URL}}img/edit_12.png" alt="{% trans "Edit"%}" title="{% trans "Edit"%}" class="user-status-edit-icon cspt vh" />
</div>
<select name="permission" class="user-status-select hide">
<option value="1" {%if user.is_active %}selected="selected"{% endif %}>{% trans "Active" %}</option>
<option value="0" {%if not user.is_active %}selected="selected"{% endif %}>{% trans "Inactive"%}</option>
</select>
</td>
<td>
{% if CALC_SHARE_USAGE %}
{{ user.self_usage|filesizeformat }} + {{ user.share_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %}
{% else %}
{{ user.self_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %}
{% endif %}
</td>
<td style="font-size:11px;">
{{ user.ctime|tsstr_sec }} / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %}
</td>
<td>
{% if not user.is_self %}
<a href="#" class="remove-user-btn op vh" data-url="{% url 'user_remove' user.id %}" data-target="{{ user.email }}">{% trans "Delete" %}</a>
<a href="#" class="reset-user-btn op vh" data-url="{% url 'user_reset' user.id %}" data-target="{{ user.email }}">{% trans "ResetPwd" %}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<div id="activate-msg" class="hide">
<p>{% trans "Activating..., please wait" %}</p>
</div>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
{% include 'sysadmin/sys_org_set_quota_js.html' %}
addConfirmTo($('.remove-user-btn'), {
'title':"{% trans "Delete User" %}",
'con':"{% trans "Are you sure you want to delete %s ?" %}"
});
addConfirmTo($('.reset-user-btn'), {
'title':"{% trans "Password Reset" %}",
'con':"{% trans "Are you sure you want to reset the password of %s ?" %}"
});
$('tr:gt(0)').hover(
function() {
$(this).find('.user-status-edit-icon').removeClass('vh');
},
function() {
$(this).find('.user-status-edit-icon').addClass('vh');
}
);
$('.user-status-edit-icon').click(function() {
$(this).parent().addClass('hide');
$(this).parent().next().removeClass('hide'); // show 'select'
});
$('.user-status-select').change(function() {
var select = $(this),
select_val = select.val(),
uid = select.parents('tr').attr('data-userid'),
url = "{{ SITE_ROOT }}useradmin/toggle_status/" + uid + "/?s=" + select_val;
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
cache: false,
beforeSend: function() {
if (select_val == 1) {
// show activating popup
$('#activate-msg').modal();
$('#simplemodal-container').css({'height':'auto'});
}
},
success: function(data) {
if (data['email_sent']) {
feedback("{% trans "Edit succeeded, an email has been sent." %}", 'success');
} else if (data['email_sent'] === false) {
feedback("{% trans "Edit succeeded, but failed to send email, please check your email configuration." %}", 'success');
} else {
feedback("{% trans "Edit succeeded" %}", 'success');
}
select.prev().children('span').html(select.children('option[value="' +select.val() + '"]').text());
select.addClass('hide');
select.prev().removeClass('hide');
$.modal.close();
},
error: function() {
feedback("{% trans "Edit failed." %}", 'error');
select.addClass('hide');
select.prev().removeClass('hide');
$.modal.close();
}
});
});
$(document).click(function(e) {
var target = e.target || event.srcElement;
// target can't be edit-icon
if (!$('.user-status-edit-icon, .user-status-select').is(target)) {
$('.user-status').removeClass('hide');
$('.user-status-select').addClass('hide');
}
});
</script>
{% endblock %}

View File

@@ -0,0 +1,41 @@
{% load i18n%}
$('#set-quota').click(function() {
$("#set-quota-form").modal({appendTo: "#main"});
return false;
});
$('#set-quota-form .submit').click(function() {
var form = $('#set-quota-form'),
form_id = form.attr('id');
var quota = $('input[name="quota"]', form).val();
if (!$.trim(quota)) {
apply_form_error(form_id, "{% trans "Quota can not be empty" %}");
return false;
}
var sb_btn = $(this);
disable(sb_btn);
$.ajax({
url: '{% url 'sys_org_set_quota' org.org_id %}',
type: 'POST',
dataType: 'json',
cache: 'false',
beforeSend: prepareCSRFToken,
data: {
'quota': quota
},
success: function(data) {
location.reload(true);
},
error: function(xhr, textStatus, errorThrown) {
if (xhr.responseText) {
apply_form_error(form_id, $.parseJSON(xhr.responseText).error);
} else {
apply_form_error(form_id, "{% trans "Failed. Please check the network." %}");
}
enable(sb_btn);
}
});
return false;
});

View File

@@ -13,7 +13,7 @@
<tr data-userid="{{user.email}}">
<td><a href="{{ SITE_ROOT }}useradmin/info/{{ user.props.email }}/">{{ user.email }}</a>
{% if user.org %}
<p style="font-size:11px;"><a href="{% url 'sys_org_info' user.org.org_id %}">({{user.org.org_name}})</a></p>
<p style="font-size:11px;"><a href="{% url 'sys_org_info_user' user.org.org_id %}">({{user.org.org_name}})</a></p>
{% endif %}
</td>
<td>

View File

@@ -11,6 +11,11 @@
<dt>{% trans "Email" %}</dt>
<dd>{{ email }}</dd>
{% if org_name %}
<dt>{% trans "Organization" %}</dt>
<dd>{{ org_name }}</dd>
{% endif %}
{% if profile %}
<dt>{% trans "Name" context "true name" %}</dt>
<dd>{{ profile.nickname }}</dd>

View File

@@ -187,8 +187,12 @@ urlpatterns = patterns('',
url(r'^sys/useradmin/admins/$', sys_user_admin_admins, name='sys_useradmin_admins'),
url(r'^sys/groupadmin/$', sys_group_admin, name='sys_group_admin'),
url(r'^sys/orgadmin/$', sys_org_admin, name='sys_org_admin'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/$', sys_org_info, name='sys_org_info'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/set_quota/$', sys_org_set_quota, name='sys_org_set_quota'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/rename/$', sys_org_rename, name='sys_org_rename'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/user/$', sys_org_info_user, name='sys_org_info_user'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/group/$', sys_org_info_group, name='sys_org_info_group'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/library/$', sys_org_info_library, name='sys_org_info_library'),
url(r'^sys/orgadmin/(?P<org_id>\d+)/setting/$', sys_org_info_setting, name='sys_org_info_setting'),
url(r'^sys/publinkadmin/$', sys_publink_admin, name='sys_publink_admin'),
url(r'^sys/notificationadmin/', notification_list, name='notification_list'),
url(r'^useradmin/add/$', user_add, name="user_add"),

View File

@@ -331,6 +331,7 @@ def user_info(request, email):
owned_repos = seafile_api.get_owned_repo_list(email)
org = ccnet_threaded_rpc.get_orgs_by_user(email)
org_name = None
if not org:
my_usage = seafile_api.get_user_self_usage(email)
quota = seafile_api.get_user_quota(email)
@@ -340,6 +341,7 @@ def user_info(request, email):
get_org_user_quota_usage(org_id, email)
quota = seafserv_threaded_rpc. \
get_org_user_quota(org_id, email)
org_name = org[0].org_name
if CALC_SHARE_USAGE:
try:
@@ -371,6 +373,7 @@ def user_info(request, email):
'email': email,
'profile': profile,
'd_profile': d_profile,
'org_name': org_name,
}, context_instance=RequestContext(request))
@login_required_ajax
@@ -394,7 +397,13 @@ def user_set_quota(request, email):
seafile_api.set_user_quota(email, quota)
else:
org_id = org[0].org_id
seafserv_threaded_rpc.set_org_user_quota(org_id, email, quota)
org_quota_mb = seafserv_threaded_rpc.get_org_quota(org_id) / (1 << 20)
if quota_mb > org_quota_mb:
result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \
org_quota_mb)
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
else:
seafserv_threaded_rpc.set_org_user_quota(org_id, email, quota)
except:
result['error'] = _(u'Failed to set quota: internal server error')
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
@@ -444,8 +453,8 @@ def user_remove(request, user_id):
return HttpResponseRedirect(next)
org_id = org[0].org_id
org_repos = seafile_api.get_org_owned_repo_list(org_id, user.email)
for repo in org_repos:
org_user_repos = seafile_api.get_org_owned_repo_list(org_id, user.email)
for repo in org_user_repos:
seafile_api.remove_repo(repo.id)
user.delete()
@@ -735,6 +744,11 @@ def sys_group_admin(request):
per_page +1)
groups = groups_plus_one[:per_page]
for grp in groups:
org_id = ccnet_threaded_rpc.get_org_id_by_group(int(grp.id))
if org_id > 0:
grp.org_id = org_id
grp.org_name = ccnet_threaded_rpc.get_org_by_id(int(org_id)).org_name
if len(groups_plus_one) == per_page + 1:
page_next = True
@@ -784,18 +798,59 @@ def sys_org_admin(request):
@login_required
@sys_staff_required
def sys_org_info(request, org_id):
def sys_org_rename(request, org_id):
if request.method != 'POST':
raise Http404
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_org_admin') if referer is None else referer
new_name = request.POST.get('new_name', None)
if new_name:
try:
ccnet_threaded_rpc.set_org_name(int(org_id), new_name)
messages.success(request, _(u'Success'))
except Exception as e:
logger.error(e)
messages.error(request, _(u'Failed to rename organization'))
return HttpResponseRedirect(next)
def sys_get_org_base_info(org_id):
org_id = int(org_id)
org = ccnet_threaded_rpc.get_org_by_id(org_id)
# users
users = ccnet_threaded_rpc.get_org_emailusers(org.url_prefix, -1, -1)
users_count = len(users)
# groups
groups = ccnet_threaded_rpc.get_org_groups(org_id, -1, -1)
groups_count = len(groups)
# quota
total_quota = seafserv_threaded_rpc.get_org_quota(org_id)
quota_usage = seafserv_threaded_rpc.get_org_quota_usage(org_id)
return {
"org": org,
"users": users,
"users_count": users_count,
"groups": groups,
"groups_count": groups_count,
"total_quota": total_quota,
"quota_usage": quota_usage,
}
@login_required
@sys_staff_required
def sys_org_info_user(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
users = org_basic_info["users"]
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
for user in users:
if user.id == request.user.id:
@@ -803,7 +858,7 @@ def sys_org_info(request, org_id):
try:
user.self_usage =seafserv_threaded_rpc. \
get_org_user_quota_usage(org_id, user.email)
user.share_usage = 0 #seafile_api.get_user_share_usage(user.email)
user.share_usage = 0
user.quota = seafserv_threaded_rpc. \
get_org_user_quota(org_id, user.email)
except SearpcError as e:
@@ -818,20 +873,49 @@ def sys_org_info(request, org_id):
if last_login.username == user.email:
user.last_login = last_login.last_login
# groups
groups = ccnet_threaded_rpc.get_org_groups(org_id, -1, -1)
groups_count = len(groups)
return render_to_response('sysadmin/sys_org_info_user.html',
org_basic_info, context_instance=RequestContext(request))
return render_to_response('sysadmin/sys_org_info.html', {
'org': org,
'users': users,
'users_count': users_count,
'total_quota': total_quota,
'quota_usage': quota_usage,
'groups': groups,
'groups_count': groups_count,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_info_group(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
return render_to_response('sysadmin/sys_org_info_group.html',
org_basic_info, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_info_library(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
# library
org_repos = seafserv_threaded_rpc.get_org_repo_list(org_id, -1, -1)
for repo in org_repos:
try:
repo.owner = seafserv_threaded_rpc.get_org_repo_owner(repo.id)
except:
repo.owner = None
org_basic_info["org_repos"] = org_repos
return render_to_response('sysadmin/sys_org_info_library.html',
org_basic_info, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_info_setting(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
return render_to_response('sysadmin/sys_org_info_setting.html',
org_basic_info, context_instance=RequestContext(request))
@login_required
@sys_staff_required
@@ -930,12 +1014,18 @@ def sys_repo_transfer(request):
new_owner = request.POST.get('email', None)
if repo_id and new_owner:
try:
User.objects.get(email=new_owner)
seafile_api.set_repo_owner(repo_id, new_owner)
messages.success(request, _(u'Successfully transfered.'))
except User.DoesNotExist:
messages.error(request, _(u'Failed to transfer, user %s not found') % new_owner)
if seafserv_threaded_rpc.get_org_id_by_repo_id(repo_id) > 0:
messages.error(request, _(u'Can not transfer organization library'))
else:
try:
User.objects.get(email=new_owner)
if ccnet_threaded_rpc.get_orgs_by_user(new_owner):
messages.error(request, _(u'Can not transfer library to organization user %s') % new_owner)
else:
seafile_api.set_repo_owner(repo_id, new_owner)
messages.success(request, _(u'Successfully transfered.'))
except User.DoesNotExist:
messages.error(request, _(u'Failed to transfer, user %s not found') % new_owner)
else:
messages.error(request, _(u'Failed to transfer, invalid arguments.'))