Commit af713672 authored by xiaoyu's avatar xiaoyu

user list page bulk action

parent 515406c0
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* English - this is the default DataTables ships with
* @name English
* @anchor English
* @author <a href="http://www.sprymedia.co.uk/">Allan Jardine</a>
*/
{
"sEmptyTable": "No data available in table",
"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
"sInfoEmpty": "Showing 0 to 0 of 0 entries",
"sInfoFiltered": "(filtered from _MAX_ total entries)",
"sInfoPostFix": "",
"sInfoThousands": ",",
"sLengthMenu": "Show _MENU_ entries",
"sLoadingRecords": "Loading...",
"sProcessing": "Processing...",
"sSearch": "Search:",
"sZeroRecords": "No matching records found",
"oPaginate": {
"sFirst": "First",
"sLast": "Last",
"sNext": "Next",
"sPrevious": "Previous"
},
"oAria": {
"sSortAscending": ": activate to sort column ascending",
"sSortDescending": ": activate to sort column descending"
}
}
\ No newline at end of file
{
"sProcessing": "处理中...",
"sLengthMenu": "显示 _MENU_ 项结果",
"sZeroRecords": "没有匹配结果",
"sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
"sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
}
}
{% extends 'base.html' %}
{% load static %}
{% load common_tags %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/dataTables/dataTables.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/dataTables/dataTables.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
......@@ -19,10 +24,10 @@
</a>
</div>
</div>
<div class="ibox-content">
<div class="">
{% block content_left_head %} {% endblock %}
{% block table_search %}
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" name="keyword" placeholder="Search" value="{{ keyword }}">
......@@ -33,8 +38,9 @@
</div>
</div>
</form>
{% endblock %}
</div>
{% block table_container %}
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
......@@ -45,17 +51,19 @@
{% block table_body %} {% endblock %}
</tbody>
</table>
{% endblock %}
<div class="row">
<div class="col-sm-4">
{# Update batch #}
{% block content_bottom_left %} {% endblock %}
</div>
{% block table_pagination %}
{% include '_pagination.html' %}
{% endblock %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
......@@ -71,9 +71,19 @@ class UserPKUpdateSerializer(serializers.ModelSerializer):
class UserBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
group_display = serializers.SerializerMethodField()
active_display = serializers.SerializerMethodField()
class Meta(object):
model = User
list_serializer_class = BulkListSerializer
fields = ['id', 'is_active', 'username', 'name', 'email', 'role', 'avatar',
'enable_otp', 'comment', 'groups']
'enable_otp', 'comment', 'groups', 'get_role_display',
'group_display', 'active_display']
def get_group_display(self, obj):
return " ".join([group.name for group in obj.groups.all()])
def get_active_display(self, obj):
# TODO: user ative state
return not (obj.is_expired and obj.is_active)
{% extends '_base_list.html' %}
{% load i18n %}
{% load i18n static %}
{% get_current_language as LANGUAGE_CODE %}
{% load common_tags %}
{% block content_left_head %}
<a href="{% url 'users:user-create' %}" class="btn btn-sm btn-primary "> {% trans "Create user" %} </a>
{% endblock %}
{% block table_head %}
<th class="text-center">
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
</th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=username">{% trans 'Username' %}</a></th>
<th class="text-center">{% trans 'Role' %}</th>
<th class="text-center">{% trans 'User group' %}</th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">{% trans 'Active' %}</a></th>
<th class="text-center"></th>
{% block table_search %}{% endblock %}
{% block table_container %}
<table class="table table-striped table-bordered table-hover " id="user_list_table" >
<thead>
<tr>
<th></th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=username">{% trans 'Username' %}</a></th>
<th class="text-center">{% trans 'Role' %}</th>
<th class="text-center">{% trans 'User group' %}</th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">{% trans 'Active' %}</a></th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
{% block table_body %}
......@@ -66,23 +73,117 @@
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).on('click', '#btn_bulk_update', function(){
$(document).ready(function(){
$('#user_list_table').DataTable({
dom: '<"html5buttons"B>lftip',
language: {
url: "{% static 'js/plugins/dataTables/i18n/language_code.json' %}".replace('language_code', '{{ LANGUAGE_CODE }}')
},
buttons: [
{extend: 'excel',
exportOptions: {
modifier: {
selected: true
}
}
},
{extend: 'pdf',
exportOptions: {
modifier: {
selected: true
}
}
},
{extend: 'print',
customize: function (win){
$(win.document.body).addClass('white-bg');
$(win.document.body).css('font-size', '10px');
$(win.document.body).find('table')
.addClass('compact')
.css('font-size', 'inherit');
}
}
],
columnDefs: [
{orderable: false, className: 'select-checkbox', targets: 0},
{className: 'text-center', targets: [1, 2, 3, 4, 5, 6, 7]},
{targets: 7,
createdCell: function (td, cellData) {
$(td).html('<a href="#" class="btn btn-xs btn-info">{% trans "Update" %}</a><a class="btn btn-xs btn-danger del">{% trans "Delete" %}</a>')
}
},
{targets: 6,
createdCell: function (td, cellData) {
if (!cellData) {
$(td).html('<i class="fa fa-times text-danger"></i>')
} else {
$(td).html('<i class="fa fa-check text-navy"></i>')
}
}}
],
select: {style: 'multi'},
ajax: {
url: '{% url "users:user-bulk-update-api" %}',
dataSrc: ""
},
columns: [
{data: function(){return ""} },
{data: "name" },
{data: "username" },
{data: "get_role_display" },
{data: "group_display" },
{data: function(){return 999} },
{data: "active_display" },
{data: "id" }
]
});
}).on('click', '#btn_bulk_update', function(){
var action = $('#slct_bulk_update').val();
var id_list = $('.ipt_bulk_update:checked').map(function(){return {'id': parseInt($(this).val())}}).get();
var $data_table = $('#user_list_table').DataTable()
var id_list = [];
$data_table.rows({selected: true}).every(function(){
id_list.push({id: this.data().id})
});
var the_url = "{% url 'users:user-bulk-update-api' %}";
function doDeactive() {
var body = $.each(id_list, function(index, user_object) {
user_object['is_active'] = false;
});
APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)});
};
$data_table.ajax.reload();
}
function doDelete() {
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will delete the selected users !!!' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
APIUpdateAttr({url: the_url, method: 'DELETE', body: JSON.stringify(id_list)});
$data_table.ajax.reload();
});
}
function doExport() {}
function doUpdate() {}
switch(action) {
case 'deactive':
doDeactive();
break;
case 'delete':
doDelete();
break;
case 'update':
doUpdate();
break;
case 'export':
doExport();
break;
default:
break;
};
}
})
</script>
{% endblock %}
......
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a href="{% url 'users:user-create' %}" class="btn btn-sm btn-primary "> {% trans "Create user" %} </a>
{% endblock %}
{% block table_head %}
<th class="text-center">
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
</th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=username">{% trans 'Username' %}</a></th>
<th class="text-center">{% trans 'Role' %}</th>
<th class="text-center">{% trans 'User group' %}</th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">{% trans 'Active' %}</a></th>
<th class="text-center"></th>
{% endblock %}
{% block table_body %}
{% for user in object_list %}
<tr class="gradeX">
<td class="text-center">
<input type="checkbox" name="checked" value="{{ user.id }}" class="ipt_bulk_update">
</td>
<td class="text-center">
<a href="{% url 'users:user-detail' pk=user.id %}">
{{ user.name }}
</a>
</td>
<td class="text-center">{{ user.username }}</td>
<td class="text-center">{{ user.get_role_display }}</td>
<td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.groups.all|join_queryset_attr:"name" }} </td>
<th class="text-center">{{ user.name }}</th>
<td class="text-center">
{% if user.is_expired and user.is_active %}
<i class="fa fa-times text-danger"></i>
{% else %}
<i class="fa fa-check text-navy"></i>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'users:user-update' pk=user.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<!--<a href="{% url 'users:user-delete' pk=user.id %}" class="btn btn-xs btn-danger del {% if user.id == request.user.id or user.username == 'admin' %} disabled {% endif %}">{% trans 'Delete' %}</a>-->
<a onclick="obj_del(this,'{{ user.name }}','{% url 'users:user-delete' user.id %}')" class="btn btn-xs btn-danger del {% if user.id == request.user.id or user.username == 'admin' %} disabled {% endif %}">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
{% endblock %}
{% block content_bottom_left %}
<div class="input-group">
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
<option value="delete">{% trans 'Delete selected' %}</option>
<option value="update">{% trans 'Update selected' %}</option>
<option value="deactive">{% trans 'Deactive selected' %}</option>
<option value="export">{% trans 'Export selected' %}</option>
</select>
<div class="input-group-btn pull-left" style="padding-left: 5px;">
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Submit' %}
</button>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).on('click', '#btn_bulk_update', function(){
var action = $('#slct_bulk_update').val();
var id_list = $('.ipt_bulk_update:checked').map(function(){return {'id': parseInt($(this).val())}}).get();
var the_url = "{% url 'users:user-bulk-update-api' %}";
function doDeactive() {
var body = $.each(id_list, function(index, user_object) {
user_object['is_active'] = false;
});
APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)});
};
function doDelete() {
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will delete the selected users !!!' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function() {
APIUpdateAttr({url: the_url, method: 'DELETE', body: JSON.stringify(id_list)});
});
};
function doExport() {};
function doUpdate() {};
switch(action) {
case 'deactive':
doDeactive();
break;
case 'delete':
doDelete();
break;
case 'update':
doUpdate();
break;
case 'export':
doExport();
break;
default:
break;
};
})
</script>
{% endblock %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment