Commit d8e64334 authored by ibuler's avatar ibuler

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

parents d0ba1737 7f09b486
.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
}
}
\ No newline at end of file
...@@ -151,4 +151,25 @@ function getIDall() { ...@@ -151,4 +151,25 @@ function getIDall() {
check_array.push(id); check_array.push(id);
}); });
return check_array.join(","); return check_array.join(",");
} }
\ No newline at end of file
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;
}
!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
\ No newline at end of file
...@@ -3,54 +3,54 @@ ...@@ -3,54 +3,54 @@
<script src="{% static "js/plugins/metisMenu/jquery.metisMenu.js" %}"></script> <script src="{% static "js/plugins/metisMenu/jquery.metisMenu.js" %}"></script>
<!-- Custom and plugin javascript --> <!-- 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/inspinia.js" %}"></script>
<script src="{% static "js/jumpserver.js" %}"></script>
<script> <script>
<!-- active menu --> // active menu
var url_array = document.location.pathname.split("/"); var url_array = document.location.pathname.split("/");
app = url_array[1]; app = url_array[1];
resource = url_array[2]; resource = url_array[2];
if (app == ''){ if (app == ''){
$('#index').addClass('active') $('#index').addClass('active')
} else { } else {
$("#"+app).addClass('active'); $("#"+app).addClass('active');
$('#'+app+' #'+resource).addClass('active'); $('#'+app+' #'+resource).addClass('active');
} }
<!-- ajax set cookie --> // ajax set cookie
function getCookie(name) { function getCookie(name) {
var cookieValue = null; var cookieValue = null;
if (document.cookie && document.cookie !== '') { if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';'); var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) { for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]); var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want? // Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) { if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break; break;
}
} }
} }
return cookieValue;
} }
return cookieValue;
}
var csrftoken = getCookie('csrftoken'); var csrftoken = getCookie('csrftoken');
var sessionid = getCookie('sessionid'); var sessionid = getCookie('sessionid');
function csrfSafeMethod(method) { function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection // these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
} }
$.ajaxSetup({ $.ajaxSetup({
beforeSend: function(xhr, settings) { beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken); xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
} }
}); }
});
<!-- textarea rows --> // textarea rows
$('textarea').attr('rows', 5) $('textarea').attr('rows', 5)
</script> </script>
\ No newline at end of file <script src="{% static "js/jumpserver.js" %}"></script>
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<!-- css file --> <!-- css file -->
<link href="{% static "css/bootstrap.min.css" %}" rel="stylesheet"> <link href="{% static "css/bootstrap.min.css" %}" rel="stylesheet">
<link href="{% static "css/font-awesome.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/style.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/vaildator/jquery.validator.css" %}" rel="stylesheet"> <link href="{% static "css/plugins/vaildator/jquery.validator.css" %}" rel="stylesheet">
......
This diff is collapsed.
...@@ -3,11 +3,9 @@ ...@@ -3,11 +3,9 @@
import logging import logging
from rest_framework import generics, mixins, status, permissions from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import UserSerializer, UserGroupSerializer, UserActiveSerializer from .serializers import UserSerializer, UserGroupSerializer, UserAttributeSerializer, UserGroupEditSerializer
from .models import User, UserGroup from .models import User, UserGroup
...@@ -33,16 +31,6 @@ class UserDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView): ...@@ -33,16 +31,6 @@ class UserDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView):
# return super(UserDetailDeleteUpdateApi, self).get(request, *args, **kwargs) # 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): class UserGroupListAddApi(generics.ListCreateAPIView):
queryset = UserGroup.objects.all() queryset = UserGroup.objects.all()
serializer_class = UserGroupSerializer serializer_class = UserGroupSerializer
...@@ -52,3 +40,12 @@ class UserGroupDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView): ...@@ -52,3 +40,12 @@ class UserGroupDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView):
queryset = UserGroup.objects.all() queryset = UserGroup.objects.all()
serializer_class = UserGroupSerializer 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): ...@@ -17,15 +17,24 @@ class UserSerializer(serializers.ModelSerializer):
] ]
class UserActiveSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['is_active']
class UserGroupSerializer(serializers.ModelSerializer): class UserGroupSerializer(serializers.ModelSerializer):
users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api') users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api')
class Meta: class Meta:
model = UserGroup model = UserGroup
fields = '__all__' 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 @@ ...@@ -25,7 +25,7 @@
<div class="col-sm-7" style="padding-left: 0px;"> <div class="col-sm-7" style="padding-left: 0px;">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <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"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -49,56 +49,56 @@ ...@@ -49,56 +49,56 @@
<tbody> <tbody>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <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> </td>
</tr> </tr>
<tr> <tr>
<td width="20%">{% trans 'Name' %}:</td> <td width="20%">{% trans 'Name' %}:</td>
<td><b>{{ user.name }}</b></td> <td><b>{{ user_object.name }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Username' %}:</td> <td>{% trans 'Username' %}:</td>
<td><b>{{ user.username }}</b></td> <td><b>{{ user_object.username }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Email' %}:</td> <td>{% trans 'Email' %}:</td>
<td><b>{{ user.email }}</b></td> <td><b>{{ user_object.email }}</b></td>
</tr> </tr>
{% if user.phone %} {% if user_object.phone %}
<tr> <tr>
<td>{% trans 'Phone' %}:</td> <td>{% trans 'Phone' %}:</td>
<td><b>{{ user.phone }}</b></td> <td><b>{{ user_object.phone }}</b></td>
</tr> </tr>
{% endif %} {% endif %}
{% if user.wechat %} {% if user_object.wechat %}
<tr> <tr>
<td>{% trans 'Wechat' %}:</td> <td>{% trans 'Wechat' %}:</td>
<td><b>{{ user.wechat }}</b></td> <td><b>{{ user_object.wechat }}</b></td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<td>{% trans 'Role' %}:</td> <td>{% trans 'Role' %}:</td>
<td><b>{{ user.get_role_display }}</b></td> <td><b>{{ user_object.get_role_display }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Date expired' %}:</td> <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>
<tr> <tr>
<td>{% trans 'Created by' %}:</td> <td>{% trans 'Created by' %}:</td>
<td><b>{{ user.created_by }}</b></td> <td><b>{{ user_object.created_by }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Date joined' %}:</td> <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>
<tr> <tr>
<td>{% trans 'Last login' %}:</td> <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>
<tr> <tr>
<td>{% trans 'Comment' %}:</td> <td>{% trans 'Comment' %}:</td>
<td><b>{{ user.comment }}</b></td> <td><b>{{ user_object.comment }}</b></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
<td><span style="float: right"> <td><span style="float: right">
<div class="switch"> <div class="switch">
<div class="onoffswitch"> <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"> <label class="onoffswitch-label" for="is_active">
<span class="onoffswitch-inner"></span> <span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span> <span class="onoffswitch-switch"></span>
...@@ -132,9 +132,9 @@ ...@@ -132,9 +132,9 @@
<td><span style="float: right"> <td><span style="float: right">
<div class="switch"> <div class="switch">
<div class="onoffswitch"> <div class="onoffswitch">
<input type="checkbox" class="onoffswitch-checkbox" <input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
id="example2"> id="enable_otp">
<label class="onoffswitch-label" for="example2"> <label class="onoffswitch-label" for="enable_otp">
<span class="onoffswitch-inner"></span> <span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span> <span class="onoffswitch-switch"></span>
</label> </label>
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
</tr> </tr>
</form> </form>
{% for group in user.groups.all %} {% for group in user_object.groups.all %}
<tr> <tr>
<td ><b>{{ group.name }}</b></td> <td ><b>{{ group.name }}</b></td>
<td> <td>
...@@ -209,26 +209,26 @@ ...@@ -209,26 +209,26 @@
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
function switch_user_status(obj) { $(document).ready(function () {
var status = $(obj).prop('checked'); $('.select2').select2();
});
$.ajax({ $(document).on('click', '#is_active', function(){
url: "{% url 'users:user-active-api' pk=user.id %}", var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
type: "PUT", var checked = !$(this).prop('checked');
data: { var body = {'is_active': checked };
'is_active': status var success = function(data) {
}, toastr.success('{% trans "Update success!" %}')
success: function (data, status) { }
console.log(data) APIUpdateAttr(the_url, body, success);
}, }).on('click', '#enable_otp', function(){
error: function () { var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
console.log('error') var checked = !$(this).prop('checked');
} var body = {'enable_otp': checked };
}) var success = function(data) {
} toastr.success('{% trans "Update success!" %}')
$(document).ready(function () { }
$('.select2').select2(); APIUpdateAttr(the_url, body, success);
}) });
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -32,8 +32,11 @@ urlpatterns += [ ...@@ -32,8 +32,11 @@ urlpatterns += [
url(r'^v1/users$', api.UserListAddApi.as_view(), name='user-list-api'), url(r'^v1/users$', api.UserListAddApi.as_view(), name='user-list-api'),
url(r'^v1/users/(?P<pk>[0-9]+)$', url(r'^v1/users/(?P<pk>[0-9]+)$',
api.UserDetailDeleteUpdateApi.as_view(), name='user-detail-api'), 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$', api.UserGroupListAddApi.as_view(), name='user-group-list-api'),
url(r'^v1/user-groups/(?P<pk>[0-9]+)$', url(r'^v1/user-groups/(?P<pk>[0-9]+)$',
api.UserGroupDetailDeleteUpdateApi.as_view(), name='user-group-detail-api'), 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): ...@@ -155,10 +155,10 @@ class UserDeleteView(AdminUserRequiredMixin, DeleteView):
class UserDetailView(AdminUserRequiredMixin, DetailView): class UserDetailView(AdminUserRequiredMixin, DetailView):
model = User model = User
template_name = 'users/user_detail.html' template_name = 'users/user_detail.html'
context_object_name = "user" context_object_name = "user_object"
def get_context_data(self, **kwargs): 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} context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups}
kwargs.update(context) kwargs.update(context)
return super(UserDetailView, self).get_context_data(**kwargs) return super(UserDetailView, self).get_context_data(**kwargs)
......
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