Skip to content

Commit

Permalink
Merge branch 'master' of code.simcu.com:jumpserver/jumpserver
Browse files Browse the repository at this point in the history
"assets-group"
  • Loading branch information
jiangshifeng committed Sep 22, 2016
2 parents d2e9894 + af71367 commit 1834171
Show file tree
Hide file tree
Showing 15 changed files with 1,109 additions and 284 deletions.
26 changes: 22 additions & 4 deletions apps/static/css/plugins/dataTables/datatables.min.css

Large diffs are not rendered by default.

Binary file not shown.
288 changes: 288 additions & 0 deletions apps/static/fonts/glyphicons-halflings-regular.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
701 changes: 450 additions & 251 deletions apps/static/js/plugins/dataTables/datatables.min.js

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions apps/static/js/plugins/dataTables/i18n/English.lang
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* 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"
}
}
24 changes: 24 additions & 0 deletions apps/static/js/plugins/dataTables/i18n/zh-hans.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"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": ": 以降序排列此列"
}
}
14 changes: 11 additions & 3 deletions apps/templates/_base_list.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{% 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">
Expand All @@ -19,10 +24,10 @@ <h5> {{ action }} </h5>
</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 }}">
Expand All @@ -33,8 +38,9 @@ <h5> {{ action }} </h5>
</div>
</div>
</form>
{% endblock %}
</div>

{% block table_container %}
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
Expand All @@ -45,17 +51,19 @@ <h5> {{ action }} </h5>
{% 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 %}
8 changes: 7 additions & 1 deletion apps/users/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import logging

from rest_framework import generics
from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView

from .serializers import UserSerializer, UserGroupSerializer, UserAttributeSerializer, UserGroupEditSerializer, \
GroupEditSerializer, UserPKUpdateSerializer
GroupEditSerializer, UserPKUpdateSerializer, UserBulkUpdateSerializer
from .models import User, UserGroup


Expand Down Expand Up @@ -92,3 +93,8 @@ def perform_update(self, serializer):
class GroupDeleteApi(generics.DestroyAPIView):
queryset = UserGroup.objects.all()
serializer_class = GroupEditSerializer


class UserBulkUpdateApi(ListBulkCreateUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserBulkUpdateSerializer
20 changes: 20 additions & 0 deletions apps/users/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.utils.translation import ugettext_lazy as _

from rest_framework import serializers
from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin

from .models import User, UserGroup

Expand Down Expand Up @@ -67,3 +68,22 @@ def validate__public_key(self, value):
print e
raise serializers.ValidationError(_('Not a valid ssh public key'))
return value


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', '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)
168 changes: 143 additions & 25 deletions apps/users/templates/users/user_list.html
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
{% 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 %}
{% for user in object_list %}
<tr class="gradeX">
<td class="text-center">
<input type="checkbox" name="checked" value="{{ user.id }}">
<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 %}">
Expand Down Expand Up @@ -50,23 +57,134 @@
{% endblock %}

{% block content_bottom_left %}
<form id="" method="get" action="" class=" mail-search">
<div class="input-group">
<select class="form-control m-b" style="width: auto">
<option>{% trans 'Delete selected' %}</option>
<option>{% trans 'Update selected' %}</option>
<option>{% trans 'Deactive selected' %}</option>
<option>{% trans 'Export selected' %}</option>
<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='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary">
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Submit' %}
</button>
</div>

</div>
</form>
{% endblock %}

{% block custom_foot_js %}
<script>
$(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 $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 %}

Loading

0 comments on commit 1834171

Please sign in to comment.