Merge branch 'master' of code.simcu.com:jumpserver/jumpserver

pull/530/head
ibuler 8 years ago
commit d8e6433404

@ -0,0 +1,222 @@
.toast-title {
font-weight: 700
}
.toast-message {
-ms-word-wrap: break-word;
word-wrap: break-word
}
.toast-message a, .toast-message label {
color: #fff
}
.toast-message a:hover {
color: #ccc;
text-decoration: none
}
.toast-close-button {
position: relative;
right: -.3em;
top: -.3em;
float: right;
font-size: 20px;
font-weight: 700;
color: #fff;
-webkit-text-shadow: 0 1px 0 #fff;
text-shadow: 0 1px 0 #fff;
opacity: .8;
-ms-filter: alpha(Opacity=80);
filter: alpha(opacity=80)
}
.toast-close-button:focus, .toast-close-button:hover {
color: #000;
text-decoration: none;
cursor: pointer;
opacity: .4;
-ms-filter: alpha(Opacity=40);
filter: alpha(opacity=40)
}
button.toast-close-button {
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
-webkit-appearance: none
}
.toast-top-center {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-center {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-left {
top: 12px;
left: 12px
}
.toast-top-right {
top: 12px;
right: 12px
}
.toast-bottom-right {
right: 12px;
bottom: 12px
}
.toast-bottom-left {
bottom: 12px;
left: 12px
}
#toast-container {
position: fixed;
z-index: 999999
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box
}
#toast-container > div {
position: relative;
overflow: hidden;
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999;
-webkit-box-shadow: 0 0 12px #999;
box-shadow: 0 0 12px #999;
color: #fff;
opacity: .8;
-ms-filter: alpha(Opacity=80);
filter: alpha(opacity=80)
}
#toast-container > :hover {
-moz-box-shadow: 0 0 12px #000;
-webkit-box-shadow: 0 0 12px #000;
box-shadow: 0 0 12px #000;
opacity: 1;
-ms-filter: alpha(Opacity=100);
filter: alpha(opacity=100);
cursor: pointer
}
#toast-container > .toast-info {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-error {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-success {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==) !important
}
#toast-container > .toast-warning {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=) !important
}
#toast-container.toast-bottom-center > div, #toast-container.toast-top-center > div {
width: 300px;
margin: auto
}
#toast-container.toast-bottom-full-width > div, #toast-container.toast-top-full-width > div {
width: 96%;
margin: auto
}
.toast {
background-color: #030303
}
.toast-success {
background-color: #51a351
}
.toast-error {
background-color: #bd362f
}
.toast-info {
background-color: #2f96b4
}
.toast-warning {
background-color: #f89406
}
.toast-progress {
position: absolute;
left: 0;
bottom: 0;
height: 4px;
background-color: #000;
opacity: .4;
-ms-filter: alpha(Opacity=40);
filter: alpha(opacity=40)
}
@media all and (max-width: 240px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 11em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 241px) and (max-width: 480px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 18em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 481px) and (max-width: 768px) {
#toast-container > div {
padding: 15px 15px 15px 50px;
width: 25em
}
}

@ -151,4 +151,25 @@ function getIDall() {
check_array.push(id);
});
return check_array.join(",");
}
}
function APIUpdateAttr(url, body, success, error, method) {
$.ajax({
url: url,
type: method || "PATCH",
data: body
}).done(function(data, textStatue, jqXHR) {
if (typeof success === 'function') {
return success(data)
} else {
toastr.success('Update Success!')
}
}).fail(function(jqXHR, textStatue, errorThrown) {
if (typeof error === 'function') {
return error(errorThrown)
} else {
toastr.error('Error occurred while updating.')
}
})
return true;
}

@ -0,0 +1,2 @@
!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:'<button type="button">&times;</button>',newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if("undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),r.preventDuplicates){if(t.message===C)return;C=t.message}T++,v=n(r,!0);var u=null,l=e("<div/>"),c=e("<div/>"),p=e("<div/>"),f=e("<div/>"),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),C=void 0))}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
//# sourceMappingURL=/toastr.js.map

@ -3,54 +3,54 @@
<script src="{% static "js/plugins/metisMenu/jquery.metisMenu.js" %}"></script>
<!-- Custom and plugin javascript -->
<script src="{% static "js/plugins/toastr/toastr.min.js" %}"></script>
<script src="{% static "js/inspinia.js" %}"></script>
<script src="{% static "js/jumpserver.js" %}"></script>
<script>
<!-- active menu -->
var url_array = document.location.pathname.split("/");
app = url_array[1];
resource = url_array[2];
if (app == ''){
$('#index').addClass('active')
} else {
$("#"+app).addClass('active');
$('#'+app+' #'+resource).addClass('active');
}
// active menu
var url_array = document.location.pathname.split("/");
app = url_array[1];
resource = url_array[2];
if (app == ''){
$('#index').addClass('active')
} else {
$("#"+app).addClass('active');
$('#'+app+' #'+resource).addClass('active');
}
<!-- ajax set cookie -->
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
// ajax set cookie
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
return cookieValue;
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
var sessionid = getCookie('sessionid');
var csrftoken = getCookie('csrftoken');
var sessionid = getCookie('sessionid');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
});
}
});
<!-- textarea rows -->
$('textarea').attr('rows', 5)
</script>
// textarea rows
$('textarea').attr('rows', 5)
</script>
<script src="{% static "js/jumpserver.js" %}"></script>

@ -3,6 +3,7 @@
<!-- css file -->
<link href="{% static "css/bootstrap.min.css" %}" rel="stylesheet">
<link href="{% static "css/font-awesome.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/toastr/toastr.min.css" %}" rel="stylesheet">
<link href="{% static "css/style.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/vaildator/jquery.validator.css" %}" rel="stylesheet">

@ -0,0 +1,285 @@
{% load staticfiles %}
{% load i18n %}
{% load rest_framework %}
<!DOCTYPE html>
<html>
<head>
{% block head %}
{% block meta %}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="robots" content="NONE,NOARCHIVE" />
{% endblock %}
<title>{% block title %}{% if name %}{{ name }} {% endif %}Django REST framework{% endblock %}</title>
{% block style %}
{% block bootstrap_theme %}
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap.min.css" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap-tweaks.css" %}"/>
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/prettify.css" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/default.css" %}"/>
{% endblock %}
{% endblock %}
</head>
{% block body %}
<body class="{% block bodyclass %}{% endblock %}">
<div class="wrapper">
{% block navbar %}
<div class="navbar navbar-static-top {% block bootstrap_navbar_variant %}navbar-inverse{% endblock %}">
<div class="container">
<span>
{% block branding %}
<a class='navbar-brand' rel="nofollow" href='http://www.django-rest-framework.org'>
Django REST framework
</a>
{% endblock %}
</span>
<ul class="nav navbar-nav pull-right">
{% block userlinks %}
{% if user.is_authenticated %}
{% optional_logout request user %}
{% else %}
{% optional_login request %}
{% endif %}
{% endblock %}
</ul>
</div>
</div>
{% endblock %}
<div class="container">
{% block breadcrumbs %}
<ul class="breadcrumb">
{% for breadcrumb_name, breadcrumb_url in breadcrumblist %}
{% if forloop.last %}
<li class="active"><a href="{{ breadcrumb_url }}">{{ breadcrumb_name }}</a></li>
{% else %}
<li><a href="{{ breadcrumb_url }}">{{ breadcrumb_name }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endblock %}
<!-- Content -->
<div id="content">
{% if 'GET' in allowed_methods %}
<form id="get-form" class="pull-right">
<fieldset>
{% if api_settings.URL_FORMAT_OVERRIDE %}
<div class="btn-group format-selection">
<a class="btn btn-primary js-tooltip" href="{{ request.get_full_path }}" rel="nofollow" title="Make a GET request on the {{ name }} resource">GET</a>
<button class="btn btn-primary dropdown-toggle js-tooltip" data-toggle="dropdown" title="Specify a format for the GET request">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% for format in available_formats %}
<li>
<a class="js-tooltip format-option" href="{% add_query_param request api_settings.URL_FORMAT_OVERRIDE format %}" rel="nofollow" title="Make a GET request on the {{ name }} resource with the format set to `{{ format }}`">{{ format }}</a>
</li>
{% endfor %}
</ul>
</div>
{% else %}
<a class="btn btn-primary js-tooltip" href="{{ request.get_full_path }}" rel="nofollow" title="Make a GET request on the {{ name }} resource">GET</a>
{% endif %}
</fieldset>
</form>
{% endif %}
{% if options_form %}
<form class="button-form" action="{{ request.get_full_path }}" data-method="OPTIONS">
<button class="btn btn-primary js-tooltip" title="Make an OPTIONS request on the {{ name }} resource">OPTIONS</button>
</form>
{% endif %}
{% if delete_form %}
<button class="btn btn-danger button-form js-tooltip" title="Make a DELETE request on the {{ name }} resource" data-toggle="modal" data-target="#deleteModal">DELETE</button>
<!-- Delete Modal -->
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<h4 class="text-center">Are you sure you want to delete this {{ name }}?</h4>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<form class="button-form" action="{{ request.get_full_path }}" data-method="DELETE">
<button class="btn btn-danger">Delete</button>
</form>
</div>
</div>
</div>
</div>
{% endif %}
{% if filter_form %}
<button style="float: right; margin-right: 10px" data-toggle="modal" data-target="#filtersModal" class="btn btn-default">
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span>
{% trans "Filters" %}
</button>
{% endif %}
<div class="content-main">
<div class="page-header">
<h1>{{ name }}</h1>
</div>
<div style="float:left">
{% block description %}
{{ description }}
{% endblock %}
</div>
{% if paginator %}
<nav style="float: right">
{% get_pagination_html paginator %}
</nav>
{% endif %}
<div class="request-info" style="clear: both" >
<pre class="prettyprint"><b>{{ request.method }}</b> {{ request.get_full_path }}</pre>
</div>
<div class="response-info">
<pre class="prettyprint"><span class="meta nocode"><b>HTTP {{ response.status_code }} {{ response.status_text }}</b>{% autoescape off %}
{% for key, val in response_headers.items %}<b>{{ key }}:</b> <span class="lit">{{ val|break_long_headers|urlize_quoted_links }}</span>
{% endfor %}
</span>{{ content|urlize_quoted_links }}</pre>{% endautoescape %}
</div>
</div>
{% if display_edit_forms %}
{% if post_form or raw_data_post_form %}
<div {% if post_form %}class="tabbable"{% endif %}>
{% if post_form %}
<ul class="nav nav-tabs form-switcher">
<li>
<a name='html-tab' href="#post-object-form" data-toggle="tab">HTML form</a>
</li>
<li>
<a name='raw-tab' href="#post-generic-content-form" data-toggle="tab">Raw data</a>
</li>
</ul>
{% endif %}
<div class="well tab-content">
{% if post_form %}
<div class="tab-pane" id="post-object-form">
{% with form=post_form %}
<form action="{{ request.get_full_path }}" method="POST" enctype="multipart/form-data" class="form-horizontal" novalidate>
<fieldset>
{% csrf_token %}
{{ post_form }}
<div class="form-actions">
<button class="btn btn-primary" title="Make a POST request on the {{ name }} resource">POST</button>
</div>
</fieldset>
</form>
{% endwith %}
</div>
{% endif %}
<div {% if post_form %}class="tab-pane"{% endif %} id="post-generic-content-form">
{% with form=raw_data_post_form %}
<form action="{{ request.get_full_path }}" method="POST" class="form-horizontal">
<fieldset>
{% include "rest_framework/raw_data_form.html" %}
<div class="form-actions">
<button class="btn btn-primary" title="Make a POST request on the {{ name }} resource">POST</button>
</div>
</fieldset>
</form>
{% endwith %}
</div>
</div>
</div>
{% endif %}
{% if put_form or raw_data_put_form or raw_data_patch_form %}
<div {% if put_form %}class="tabbable"{% endif %}>
{% if put_form %}
<ul class="nav nav-tabs form-switcher">
<li>
<a name='html-tab' href="#put-object-form" data-toggle="tab">HTML form</a>
</li>
<li>
<a name='raw-tab' href="#put-generic-content-form" data-toggle="tab">Raw data</a>
</li>
</ul>
{% endif %}
<div class="well tab-content">
{% if put_form %}
<div class="tab-pane" id="put-object-form">
<form action="{{ request.get_full_path }}" data-method="PUT" enctype="multipart/form-data" class="form-horizontal" novalidate>
<fieldset>
{{ put_form }}
<div class="form-actions">
<button class="btn btn-primary js-tooltip" title="Make a PUT request on the {{ name }} resource">PUT</button>
</div>
</fieldset>
</form>
</div>
{% endif %}
<div {% if put_form %}class="tab-pane"{% endif %} id="put-generic-content-form">
{% with form=raw_data_put_or_patch_form %}
<form action="{{ request.get_full_path }}" data-method="PUT" class="form-horizontal">
<fieldset>
{% include "rest_framework/raw_data_form.html" %}
<div class="form-actions">
{% if raw_data_put_form %}
<button class="btn btn-primary js-tooltip" title="Make a PUT request on the {{ name }} resource">PUT</button>
{% endif %}
{% if raw_data_patch_form %}
<button data-method="PATCH" class="btn btn-primary js-tooltip" title="Make a PATCH request on the {{ name }} resource">PATCH</button>
{% endif %}
</div>
</fieldset>
</form>
{% endwith %}
</div>
</div>
</div>
{% endif %}
{% endif %}
</div><!-- /.content -->
</div><!-- /.container -->
</div><!-- ./wrapper -->
{% if filter_form %}
{{ filter_form }}
{% endif %}
{% block script %}
<script>
window.drf = {
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
csrfCookieName: "{{ csrf_cookie_name|default:'csrftoken' }}"
};
</script>
<script src="{% static "rest_framework/js/jquery-1.12.4.min.js" %}"></script>
<script src="{% static "rest_framework/js/ajax-form.js" %}"></script>
<script src="{% static "rest_framework/js/csrf.js" %}"></script>
<script src="{% static "rest_framework/js/bootstrap.min.js" %}"></script>
<script src="{% static "rest_framework/js/prettify-min.js" %}"></script>
<script src="{% static "rest_framework/js/default.js" %}"></script>
<script>
$(document).ready(function() {
$('form').ajaxForm();
});
</script>
{% endblock %}
</body>
{% endblock %}
</html>

@ -3,11 +3,9 @@
import logging
from rest_framework import generics, mixins, status, permissions
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import generics
from .serializers import UserSerializer, UserGroupSerializer, UserActiveSerializer
from .serializers import UserSerializer, UserGroupSerializer, UserAttributeSerializer, UserGroupEditSerializer
from .models import User, UserGroup
@ -33,16 +31,6 @@ class UserDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView):
# return super(UserDetailDeleteUpdateApi, self).get(request, *args, **kwargs)
class UserActiveApi(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserActiveSerializer
# def put(self, request, *args, **kwargs):
# for k, v in request.META.items():
# logger.debug("%s --> %s" % (k, v))
# return super(UserActiveApi, self).put(request, *args, **kwargs)
class UserGroupListAddApi(generics.ListCreateAPIView):
queryset = UserGroup.objects.all()
serializer_class = UserGroupSerializer
@ -52,3 +40,12 @@ class UserGroupDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView):
queryset = UserGroup.objects.all()
serializer_class = UserGroupSerializer
class UserAttributeApi(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserAttributeSerializer
class UserGroupEditApi(generics.RetrieveUpdateAPIView):
queryset = User.objects.all()
serializer_class = UserGroupEditSerializer

@ -17,15 +17,24 @@ class UserSerializer(serializers.ModelSerializer):
]
class UserActiveSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['is_active']
class UserGroupSerializer(serializers.ModelSerializer):
users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api')
class Meta:
model = UserGroup
fields = '__all__'
class UserAttributeSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['avatar', 'wechat', 'phone', 'enable_otp', 'comment', 'is_active', 'name']
class UserGroupEditSerializer(serializers.ModelSerializer):
groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
class Meta:
model = User
fields = ['id', 'groups']

@ -25,7 +25,7 @@
<div class="col-sm-7" style="padding-left: 0px;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label"><b>{{ user.name }}</b></span>
<span class="label"><b>{{ user_object.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
@ -49,56 +49,56 @@
<tbody>
<tr class="no-borders-tr">
<td colspan="2">
<img src="{{ user | user_avatar_url }}" class="img-circle" width="64" height="64">
<img src="{{ user_object | user_avatar_url }}" class="img-circle" width="64" height="64">
</td>
</tr>
<tr>
<td width="20%">{% trans 'Name' %}:</td>
<td><b>{{ user.name }}</b></td>
<td><b>{{ user_object.name }}</b></td>
</tr>
<tr>
<td>{% trans 'Username' %}:</td>
<td><b>{{ user.username }}</b></td>
<td><b>{{ user_object.username }}</b></td>
</tr>
<tr>
<td>{% trans 'Email' %}:</td>
<td><b>{{ user.email }}</b></td>
<td><b>{{ user_object.email }}</b></td>
</tr>
{% if user.phone %}
{% if user_object.phone %}
<tr>
<td>{% trans 'Phone' %}:</td>
<td><b>{{ user.phone }}</b></td>
<td><b>{{ user_object.phone }}</b></td>
</tr>
{% endif %}
{% if user.wechat %}
{% if user_object.wechat %}
<tr>
<td>{% trans 'Wechat' %}:</td>
<td><b>{{ user.wechat }}</b></td>
<td><b>{{ user_object.wechat }}</b></td>
</tr>
{% endif %}
<tr>
<td>{% trans 'Role' %}:</td>
<td><b>{{ user.get_role_display }}</b></td>
<td><b>{{ user_object.get_role_display }}</b></td>
</tr>
<tr>
<td>{% trans 'Date expired' %}:</td>
<td><b>{{ user.date_expired|date:"Y-m-j H:i:s" }}</b></td>
<td><b>{{ user_object.date_expired|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ user.created_by }}</b></td>
<td><b>{{ user_object.created_by }}</b></td>
</tr>
<tr>
<td>{% trans 'Date joined' %}:</td>
<td><b>{{ user.date_joined|date:"Y-m-j H:i:s" }}</b></td>
<td><b>{{ user_object.date_joined|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Last login' %}:</td>
<td><b>{{ user.last_login|date:"Y-m-j H:i:s" }}</b></td>
<td><b>{{ user_object.last_login|date:"Y-m-j H:i:s" }}</b></td>
</tr>
<tr>
<td>{% trans 'Comment' %}:</td>
<td><b>{{ user.comment }}</b></td>
<td><b>{{ user_object.comment }}</b></td>
</tr>
</tbody>
</table>
@ -118,7 +118,7 @@
<td><span style="float: right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" {% if user.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active" onchange="switch_user_status(this)">
<input type="checkbox" {% if user_object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
<label class="onoffswitch-label" for="is_active">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
@ -132,9 +132,9 @@
<td><span style="float: right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" class="onoffswitch-checkbox"
id="example2">
<label class="onoffswitch-label" for="example2">
<input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
id="enable_otp">
<label class="onoffswitch-label" for="enable_otp">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
@ -187,7 +187,7 @@
</tr>
</form>
{% for group in user.groups.all %}
{% for group in user_object.groups.all %}
<tr>
<td ><b>{{ group.name }}</b></td>
<td>
@ -209,26 +209,26 @@
{% endblock %}
{% block custom_foot_js %}
<script>
function switch_user_status(obj) {
var status = $(obj).prop('checked');
$.ajax({
url: "{% url 'users:user-active-api' pk=user.id %}",
type: "PUT",
data: {
'is_active': status
},
success: function (data, status) {
console.log(data)
},
error: function () {
console.log('error')
}
})
}
$(document).ready(function () {
$('.select2').select2();
})
</script>
{% endblock %}
<script>
$(document).ready(function () {
$('.select2').select2();
});
$(document).on('click', '#is_active', function(){
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {'is_active': checked };
var success = function(data) {
toastr.success('{% trans "Update success!" %}')
}
APIUpdateAttr(the_url, body, success);
}).on('click', '#enable_otp', function(){
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {'enable_otp': checked };
var success = function(data) {
toastr.success('{% trans "Update success!" %}')
}
APIUpdateAttr(the_url, body, success);
});
</script>
{% endblock %}

@ -32,8 +32,11 @@ urlpatterns += [
url(r'^v1/users$', api.UserListAddApi.as_view(), name='user-list-api'),
url(r'^v1/users/(?P<pk>[0-9]+)$',
api.UserDetailDeleteUpdateApi.as_view(), name='user-detail-api'),
url(r'^v1/users/(?P<pk>[0-9]+)/active$', api.UserActiveApi.as_view(), name='user-active-api'),
url(r'^v1/users/(?P<pk>[0-9]+)/patch$',
api.UserAttributeApi.as_view(), name='user-patch-api'),
url(r'^v1/user-groups$', api.UserGroupListAddApi.as_view(), name='user-group-list-api'),
url(r'^v1/user-groups/(?P<pk>[0-9]+)$',
api.UserGroupDetailDeleteUpdateApi.as_view(), name='user-group-detail-api'),
url(r'^v1/user-groups/(?P<pk>[0-9]+)/edit$',
api.UserGroupEditApi.as_view(), name='user-group-edit-api'),
]

@ -155,10 +155,10 @@ class UserDeleteView(AdminUserRequiredMixin, DeleteView):
class UserDetailView(AdminUserRequiredMixin, DetailView):
model = User
template_name = 'users/user_detail.html'
context_object_name = "user"
context_object_name = "user_object"
def get_context_data(self, **kwargs):
groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
groups = UserGroup.objects.exclude(id__in=self.object.groups.all())
context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups}
kwargs.update(context)
return super(UserDetailView, self).get_context_data(**kwargs)

Loading…
Cancel
Save