提交 2d396787 编写于 作者: baltery's avatar baltery

[Feature] 完成资产授权和资产添加

上级 653c328e
...@@ -23,7 +23,7 @@ from django.shortcuts import get_object_or_404 ...@@ -23,7 +23,7 @@ from django.shortcuts import get_object_or_404
from django.db.models import Q, Count from django.db.models import Q, Count
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.mixins import CustomFilterMixin from common.mixins import IDInFilterMixin
from common.utils import get_logger from common.utils import get_logger
from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \ from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \
get_user_granted_assets get_user_granted_assets
...@@ -38,7 +38,7 @@ from .utils import LabelFilter ...@@ -38,7 +38,7 @@ from .utils import LabelFilter
logger = get_logger(__file__) logger = get_logger(__file__)
class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet): class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
""" """
API endpoint that allows Asset to be viewed or edited. API endpoint that allows Asset to be viewed or edited.
""" """
...@@ -56,6 +56,7 @@ class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet): ...@@ -56,6 +56,7 @@ class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet):
asset_group_id = self.request.query_params.get('asset_group_id') asset_group_id = self.request.query_params.get('asset_group_id')
admin_user_id = self.request.query_params.get('admin_user_id') admin_user_id = self.request.query_params.get('admin_user_id')
system_user_id = self.request.query_params.get('system_user_id') system_user_id = self.request.query_params.get('system_user_id')
node_id = self.request.query_params.get("node_id")
if cluster_id: if cluster_id:
queryset = queryset.filter(cluster__id=cluster_id) queryset = queryset.filter(cluster__id=cluster_id)
...@@ -70,6 +71,9 @@ class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet): ...@@ -70,6 +71,9 @@ class AssetViewSet(CustomFilterMixin, LabelFilter, BulkModelViewSet):
system_user = get_object_or_404(SystemUser, id=system_user_id) system_user = get_object_or_404(SystemUser, id=system_user_id)
clusters = system_user.get_clusters() clusters = system_user.get_clusters()
queryset = queryset.filter(cluster__in=clusters) queryset = queryset.filter(cluster__in=clusters)
if node_id:
node = get_object_or_404(Node, id=node_id)
queryset = queryset.filter(nodes__key__startswith=node.key)
return queryset return queryset
...@@ -86,7 +90,7 @@ class UserAssetListView(generics.ListAPIView): ...@@ -86,7 +90,7 @@ class UserAssetListView(generics.ListAPIView):
return queryset return queryset
class AssetGroupViewSet(CustomFilterMixin, BulkModelViewSet): class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet):
""" """
Asset group api set, for add,delete,update,list,retrieve resource Asset group api set, for add,delete,update,list,retrieve resource
""" """
...@@ -120,7 +124,7 @@ class GroupAddAssetsApi(generics.UpdateAPIView): ...@@ -120,7 +124,7 @@ class GroupAddAssetsApi(generics.UpdateAPIView):
return Response({'error': serializer.errors}, status=400) return Response({'error': serializer.errors}, status=400)
class ClusterViewSet(CustomFilterMixin, BulkModelViewSet): class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
""" """
Cluster api set, for add,delete,update,list,retrieve resource Cluster api set, for add,delete,update,list,retrieve resource
""" """
...@@ -161,7 +165,7 @@ class ClusterAddAssetsApi(generics.UpdateAPIView): ...@@ -161,7 +165,7 @@ class ClusterAddAssetsApi(generics.UpdateAPIView):
return Response({'error': serializer.errors}, status=400) return Response({'error': serializer.errors}, status=400)
class AdminUserViewSet(CustomFilterMixin, BulkModelViewSet): class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet):
""" """
Admin user api set, for add,delete,update,list,retrieve resource Admin user api set, for add,delete,update,list,retrieve resource
""" """
...@@ -197,7 +201,7 @@ class SystemUserViewSet(BulkModelViewSet): ...@@ -197,7 +201,7 @@ class SystemUserViewSet(BulkModelViewSet):
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
class AssetListUpdateApi(CustomFilterMixin, ListBulkCreateUpdateDestroyAPIView): class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
""" """
Asset bulk update api Asset bulk update api
""" """
...@@ -318,8 +322,8 @@ class NodeViewSet(BulkModelViewSet): ...@@ -318,8 +322,8 @@ class NodeViewSet(BulkModelViewSet):
serializer_class = serializers.NodeSerializer serializer_class = serializers.NodeSerializer
def perform_create(self, serializer): def perform_create(self, serializer):
child_id = Node.root().get_next_child_id() child_key = Node.root().get_next_child_key()
serializer.validated_data["id"] = child_id serializer.validated_data["key"] = child_key
serializer.save() serializer.save()
...@@ -330,17 +334,20 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): ...@@ -330,17 +334,20 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
instance = None instance = None
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
if not request.data.get("name"): if not request.data.get("value"):
request.data["name"] = _("New node {}").format( request.data["value"] = _("New node {}").format(
Node.root().get_next_child_id().split(":")[-1] Node.root().get_next_child_key().split(":")[-1]
) )
return super().post(request, *args, **kwargs) return super().post(request, *args, **kwargs)
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
instance = self.get_object() instance = self.get_object()
name = request.data.get("name") value = request.data.get("value")
node = instance.create_child(name=name) node = instance.create_child(value=value)
return Response({"id": node.id, "name": node.name}, status=201) return Response(
{"id": node.id, "key": node.key, "value": node.value},
status=201,
)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
instance = self.get_object() instance = self.get_object()
...@@ -348,5 +355,5 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): ...@@ -348,5 +355,5 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
children = instance.get_all_children() children = instance.get_all_children()
else: else:
children = instance.get_children() children = instance.get_children()
response = [{"id": node.id, "name": node.name} for node in children] response = [{"id": node.id, "key": node.key, "value": node.value} for node in children]
return Response(response, status=200) return Response(response, status=200)
...@@ -17,7 +17,14 @@ class Node(models.Model): ...@@ -17,7 +17,14 @@ class Node(models.Model):
date_create = models.DateTimeField(auto_now_add=True) date_create = models.DateTimeField(auto_now_add=True)
def __str__(self): def __str__(self):
return self.value return self.full_value
@property
def full_value(self):
if self == self.__class__.root():
return self.value
else:
return '{}/{}'.format( self.value, self.parent.full_value)
@property @property
def level(self): def level(self):
...@@ -52,6 +59,21 @@ class Node(models.Model): ...@@ -52,6 +59,21 @@ class Node(models.Model):
assets = Asset.objects.filter(nodes__in=children) assets = Asset.objects.filter(nodes__in=children)
return assets return assets
@property
def parent(self):
if self.key == "0":
return self.__class__.root()
elif not self.key.startswith("0"):
return self.__class__.root()
parent_key = ":".join(self.key.split(":")[:-1])
try:
parent = self.__class__.objects.get(key=parent_key)
except Node.DoesNotExist:
return self.__class__.root()
else:
return parent
@classmethod @classmethod
def root(cls): def root(cls):
obj, created = cls.objects.get_or_create( obj, created = cls.objects.get_or_create(
......
...@@ -328,11 +328,7 @@ class NodeSerializer(serializers.ModelSerializer): ...@@ -328,11 +328,7 @@ class NodeSerializer(serializers.ModelSerializer):
@staticmethod @staticmethod
def get_parent(obj): def get_parent(obj):
if obj.key == "0": return obj.parent.id
return "#"
if not obj.key.startswith("0"):
return "0"
return ":".join(obj.key.split(":")[:-1])
def get_fields(self): def get_fields(self):
fields = super().get_fields() fields = super().get_fields()
......
...@@ -64,7 +64,6 @@ ...@@ -64,7 +64,6 @@
</div> </div>
</div> </div>
{% include 'assets/_asset_import_modal.html' %} {% include 'assets/_asset_import_modal.html' %}
{#{% include 'assets/_asset_bulk_update_modal.html' %}#}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
...@@ -126,15 +125,7 @@ $(document).ready(function(){ ...@@ -126,15 +125,7 @@ $(document).ready(function(){
}) })
.on('click', '.labels li', function () { .on('click', '.labels li', function () {
var val = $(this).text(); var val = $(this).text();
{#var origin_val = $("#asset_list_table_filter input").val();#}
{#var new_val;#}
{#if (origin_val === "") {#}
{# new_val = val;#}
{# } else { #}
{# new_val = origin_val + " " + val;#}
{# } #}
$("#asset_list_table_filter input").val(val); $("#asset_list_table_filter input").val(val);
{#$('#asset_list_table').DataTable().search(val).draw();#}
jumpserver.table.search(val).draw(); jumpserver.table.search(val).draw();
}) })
.on('click', '.btn_export', function () { .on('click', '.btn_export', function () {
......
...@@ -5,13 +5,7 @@ ...@@ -5,13 +5,7 @@
{% block custom_head_css_js %} {% block custom_head_css_js %}
<link href="{% static 'css/plugins/jstree/style.min.css' %}" rel="stylesheet"> <link href="{% static 'css/plugins/jstree/style.min.css' %}" rel="stylesheet">
<link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet"> <link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
{# <link href="{% static 'css/plugins/ztree/demo.css' %}" rel="stylesheet">#}
<script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
<script type="text/javascript">
$(document).ready(function(){
});
</script>
<style type="text/css"> <style type="text/css">
div#rMenu { div#rMenu {
position:absolute; position:absolute;
...@@ -45,7 +39,6 @@ ...@@ -45,7 +39,6 @@
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0"> <div class="ibox-content mailbox-content" style="padding-top: 0">
<div class="file-manager "> <div class="file-manager ">
{# <h5>Tree View</h5>#}
<div id="assetTree" class="ztree"> <div id="assetTree" class="ztree">
</div> </div>
...@@ -55,9 +48,18 @@ ...@@ -55,9 +48,18 @@
</div> </div>
</div> </div>
<div class="col-lg-9 animated fadeInRight"> <div class="col-lg-9 animated fadeInRight">
<div class="row">
<div class="mail-box-header"> <div class="mail-box-header">
<div class="uc pull-left m-r-5"><a href="{% url "assets:asset-create" %}" class="btn btn-sm btn-primary"> {% trans "Add asset" %} </a></div> <div class="uc pull-left m-r-5"><a class="btn btn-sm btn-primary btn-create-asset"> {% trans "Create asset" %} </a></div>
<div class="html5buttons">
<div class="dt-buttons btn-group">
<a class="btn btn-default btn_import" data-toggle="modal" data-target="#asset_import_modal" tabindex="0">
<span>{% trans "Import" %}</span>
</a>
<a class="btn btn-default btn_export" tabindex="0">
<span>{% trans "Export" %}</span>
</a>
</div>
</div>
<div class="btn-group" style="float: right"> <div class="btn-group" style="float: right">
<button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button> <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>
<ul class="dropdown-menu labels"> <ul class="dropdown-menu labels">
...@@ -72,8 +74,6 @@ ...@@ -72,8 +74,6 @@
<th class="text-center"><input type="checkbox" class="ipt_check_all"></th> <th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
<th class="text-center">{% trans 'Hostname' %}</th> <th class="text-center">{% trans 'Hostname' %}</th>
<th class="text-center">{% trans 'IP' %}</th> <th class="text-center">{% trans 'IP' %}</th>
<th class="text-center">{% trans 'Port' %}</th>
<th class="text-center">{% trans 'Cluster' %}</th>
<th class="text-center">{% trans 'Hardware' %}</th> <th class="text-center">{% trans 'Hardware' %}</th>
<th class="text-center">{% trans 'Active' %}</th> <th class="text-center">{% trans 'Active' %}</th>
<th class="text-center">{% trans 'Reachable' %}</th> <th class="text-center">{% trans 'Reachable' %}</th>
...@@ -98,9 +98,6 @@ ...@@ -98,9 +98,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<div class="row">
</div> </div>
</div> </div>
</div> </div>
...@@ -108,220 +105,393 @@ ...@@ -108,220 +105,393 @@
<div id="rMenu"> <div id="rMenu">
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>重命名</a></li> <li id="m_add" class="btn-create-asset" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Create asset' %}</a></li>
<li id="m_add" tabindex="-1" onclick="addTreeNode();"><a>添加节点</a></li> <li class="divider"></li>
<li id="m_add" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Add node' %}</a></li>
<li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>{% trans 'Rename node' %}</a></li>
<li class="divider"></li> <li class="divider"></li>
<li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a>删除节点</a></li> <li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a>{% trans 'Delete node' %}</a></li>
</ul> </ul>
</div> </div>
{% include 'assets/_asset_import_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script src="{% static 'js/plugins/jstree/jstree.min.js' %}"></script>
<script> <script>
var zTree, rMenu; var zTree, rMenu, asset_table;
function initTable() { function initTable() {
var options = { var options = {
ele: $('#asset_list_table'), ele: $('#asset_list_table'),
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) { {targets: 1, createdCell: function (td, cellData, rowData) {
{% url 'assets:asset-detail' pk=DEFAULT_PK as the_url %} {% url 'assets:asset-detail' pk=DEFAULT_PK as the_url %}
var detail_btn = '<a href="{{ the_url }}">' + cellData + '</a>'; var detail_btn = '<a href="{{ the_url }}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id)); $(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}}, }},
{targets: 4, createdCell: function (td, cellData, rowData) { {targets: 3, createdCell: function (td, cellData, rowData) {
$(td).html(rowData.cluster_name) $(td).html(rowData.hardware_info)
}}, }},
{targets: 5, createdCell: function (td, cellData, rowData) { {targets: 4, createdCell: function (td, cellData) {
$(td).html(rowData.hardware_info) if (!cellData) {
}}, $(td).html('<i class="fa fa-times text-danger"></i>')
{targets: 6, createdCell: function (td, cellData) { } else {
if (!cellData) { $(td).html('<i class="fa fa-check text-navy"></i>')
$(td).html('<i class="fa fa-times text-danger"></i>') }
} else { }},
$(td).html('<i class="fa fa-check text-navy"></i>') {targets: 5, createdCell: function (td, cellData) {
} if (cellData === 'Unknown'){
}}, $(td).html('<i class="fa fa-circle text-warning"></i>')
{targets: 7, createdCell: function (td, cellData) { } else if (!cellData) {
if (cellData == 'Unknown'){ $(td).html('<i class="fa fa-circle text-danger"></i>')
$(td).html('<i class="fa fa-circle text-warning"></i>') } else {
} else if (!cellData) { $(td).html('<i class="fa fa-circle text-navy"></i>')
$(td).html('<i class="fa fa-circle text-danger"></i>') }
} else { }},
$(td).html('<i class="fa fa-circle text-navy"></i>') {targets: 6, createdCell: function (td, cellData, rowData) {
} var update_btn = '<a href="{% url "assets:asset-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
}}, var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
{targets: 8, createdCell: function (td, cellData, rowData) { $(td).html(update_btn + del_btn)
var update_btn = '<a href="{% url "assets:asset-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData); }}
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); ],
$(td).html(update_btn + del_btn) ajax_url: '{% url "api-assets:asset-list" %}',
}} columns: [
], {data: "id"}, {data: "hostname" }, {data: "ip" },
ajax_url: '{% url "api-assets:asset-list" %}', {data: "cpu_cores"}, {data: "is_active", orderable: false },
columns: [ {data: "is_connective", orderable: false}, {data: "id", orderable: false }
{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, ],
{data: "cluster"}, op_html: $('#actions').html()
{data: "cpu_cores"}, {data: "is_active", orderable: false }, };
{data: "is_connective", orderable: false}, {data: "id", orderable: false } asset_table = jumpserver.initServerSideDataTable(options);
], return asset_table
op_html: $('#actions').html() }
};
return jumpserver.initServerSideDataTable(options);
}
function OnRightClick(event, treeId, treeNode) { function addTreeNode() {
if (!treeNode && event.target.tagName.toLowerCase() !== "button" && $(event.target).parents("a").length == 0) { hideRMenu();
zTree.cancelSelectedNode(); var parentNode = zTree.getSelectedNodes()[0];
showRMenu("root", event.clientX, event.clientY); if (!parentNode){
} else if (treeNode && !treeNode.noR) { return
zTree.selectNode(treeNode);
showRMenu("node", event.clientX, event.clientY);
}
} }
var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.id );
$.post(url, {}, function (data, status){
if (status === "success") {
var newNode = {
name: data["value"],
id: data["id"],
pId: parentNode.id
};
newNode.checked = zTree.getSelectedNodes()[0].checked;
zTree.addNodes(parentNode, 0, newNode);
} else {
alert("{% trans 'Create node failed' %}")
}
});
}
function showRMenu(type, x, y) { function removeTreeNode() {
$("#rMenu ul").show(); hideRMenu();
if (type === "root") { var current_node = zTree.getSelectedNodes()[0];
return if (!current_node){
} else { return
$("#m_del").show(); }
$("#m_check").show();
$("#m_unCheck").show();
}
{#y += $("#page-wrapper")[0].scrollTop;#}
{#x += $("#page-wrapper")[0].scrollLeft;#}
x -= 220;
{#y -= 100;#}
{#y += document.body.scrollTop;#}
{#x += document.body.scrollLeft;#}
rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
$("body").bind("mousedown", onBodyMouseDown); if (current_node.children && current_node.children.length > 0) {
alert("{% trans 'Have child node, cancel' %}")
} else {
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id );
$.ajax({
url: url,
method: "DELETE",
success: function () {
zTree.removeNode(current_node);
}
});
} }
}
function beforeClick(treeId, treeNode, clickFlag) { function editTreeNode() {
return true; hideRMenu();
} var current_node = zTree.getSelectedNodes()[0];
if (!current_node){
function onClick(event, treeId, treeNode, clickFlag) { return
showLog("On click"); }
} zTree.editName(current_node);
}
function showLog(str) {
console.log(str) function OnRightClick(event, treeId, treeNode) {
if (!treeNode && event.target.tagName.toLowerCase() !== "button" && $(event.target).parents("a").length === 0) {
zTree.cancelSelectedNode();
showRMenu("root", event.clientX, event.clientY);
} else if (treeNode && !treeNode.noR) {
zTree.selectNode(treeNode);
showRMenu("node", event.clientX, event.clientY);
} }
}
function hideRMenu() { function showRMenu(type, x, y) {
if (rMenu) rMenu.css({"visibility": "hidden"}); $("#rMenu ul").show();
$("body").unbind("mousedown", onBodyMouseDown); if (type === "root") {
return
} else {
$("#m_del").show();
$("#m_check").show();
$("#m_unCheck").show();
} }
x -= 220;
rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
$("body").bind("mousedown", onBodyMouseDown);
}
function beforeClick(treeId, treeNode, clickFlag) {
return true;
}
function hideRMenu() {
if (rMenu) rMenu.css({"visibility": "hidden"});
$("body").unbind("mousedown", onBodyMouseDown);
}
function onBodyMouseDown(event){ function onBodyMouseDown(event){
if (!(event.target.id === "rMenu" || $(event.target).parents("#rMenu").length>0)) { if (!(event.target.id === "rMenu" || $(event.target).parents("#rMenu").length>0)) {
rMenu.css({"visibility" : "hidden"}); rMenu.css({"visibility" : "hidden"});
}
} }
}
function onRename(event, treeId, treeNode, isCancel){
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.id);
var data = {"value": treeNode.name};
if (isCancel){
return
}
APIUpdateAttr({
url: url,
body: JSON.stringify(data),
method: "PATCH"
})
}
function onSelected(event, treeNode) {
var url = asset_table.ajax.url();
url = setUrlParam(url, "node_id", treeNode.id);
asset_table.ajax.url(url);
asset_table.ajax.reload();
}
function selectQueryNode() {
var node_id = $.getUrlParam("node");
if (node_id !== null) {
var node = zTree.getNodesByParam("id", node_id, null);
if (node){
zTree.selectNode(node[0]);
}
}
}
function addTreeNode() { function initTree() {
hideRMenu(); var setting = {
var parentNode = zTree.getSelectedNodes()[0]; view: {
if (!parentNode){ dblClickExpand: false,
return showLine: true
},
data: {
simpleData: {
enable: true
}
},
callback: {
onRightClick: OnRightClick,
beforeClick: beforeClick,
onRename: onRename,
onSelected: onSelected
} }
var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.id ); };
$.post(url, {}, function (data, status){
if (status === "success") { var zNodes = [];
var newNode = { name:data["name"], id:data["id"], pId: parentNode.id }; $.get("{% url 'api-assets:node-list' %}", function(data, status){
newNode.checked = zTree.getSelectedNodes()[0].checked; $.each(data, function (index, value) {
zTree.addNodes(parentNode, 0, newNode); value["pId"] = value["parent"];
} else { if (value["key"] === "0") {
alert("{% trans 'Create node failed' %}") value["open"] = true;
} }
value["name"] = value["value"]
}); });
} zNodes = data;
$.fn.zTree.init($("#assetTree"), setting, zNodes);
zTree = $.fn.zTree.getZTreeObj("assetTree");
rMenu = $("#rMenu");
selectQueryNode();
});
}
function removeTreeNode() { $(document).ready(function(){
hideRMenu(); initTable();
var current_node = zTree.getSelectedNodes()[0]; initTree();
if (!current_node){ })
return .on('click', '.labels li', function () {
var val = $(this).text();
$("#asset_list_table_filter input").val(val);
jumpserver.table.search(val).draw();
})
.on('click', '.btn_export', function () {
var $data_table = $('#asset_list_table').DataTable();
var rows = $data_table.rows('.selected').data();
var assets = [];
$.each(rows, function (index, obj) {
assets.push(obj.id)
});
$.ajax({
url: "{% url "assets:asset-export" %}",
method: 'POST',
data: JSON.stringify({assets_id: assets}),
dataType: "json",
success: function (data, textStatus) {
window.open(data.redirect)
},
error: function () {
toastr.error('Export failed');
} }
})
})
.on('click', '#btn_asset_import', function () {
var $form = $('#fm_asset_import');
$form.find('.help-block').remove();
function success (data) {
if (data.valid === false) {
$('<span />', {class: 'help-block text-danger'}).html(data.msg).insertAfter($('#id_assets'));
} else {
$('#id_created').html(data.created_info);
$('#id_created_detail').html(data.created.join(', '));
$('#id_updated').html(data.updated_info);
$('#id_updated_detail').html(data.updated.join(', '));
$('#id_failed').html(data.failed_info);
$('#id_failed_detail').html(data.failed.join(', '));
var $data_table = $('#asset_list_table').DataTable();
$data_table.ajax.reload();
}
}
$form.ajaxSubmit({success: success});
})
.on('click', '.btn-create-asset', function () {
var url = "{% url 'assets:asset-create' %}";
var nodes = zTree.getSelectedNodes();
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
url += "?node_id=" + current_node.id;
}
window.open(url);
})
.on('click', '.btn_asset_delete', function () {
var $this = $(this);
var $data_table = $("#asset_list_table").DataTable();
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
var uid = $this.data('uid');
var the_url = '{% url "api-assets:asset-detail" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", uid);
objectDelete($this, name, the_url);
setTimeout( function () {
$data_table.ajax.reload();
}, 3000);
})
.on('click', '#btn_bulk_update', function () {
var action = $('#slct_bulk_update').val();
var $data_table = $('#asset_list_table').DataTable();
var id_list = [];
$data_table.rows({selected: true}).every(function(){
id_list.push(this.data().id);
});
if (id_list.length === 0) {
return false;
}
var the_url = "{% url 'api-assets:asset-list' %}";
if (current_node.children && current_node.children.length > 0) { function doDeactive() {
alert("{% trans 'Have child node, cancel' %}") var data = [];
} else { $.each(id_list, function(index, object_id) {
var url = "{% url 'api-assets:node-detail' pk='0:0' %}".replace("0:0", current_node.id ); var obj = {"pk": object_id, "is_active": false};
$.ajax({ data.push(obj);
url: url, });
method: "DELETE", function success() {
success: function () { asset_table.ajax.reload()
zTree.removeNode(current_node);
}
});
}
}
function onRenameNode(event, treeId, treeNode, isCancel){
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.id);
var data = {"value": treeNode.name};
if (isCancel){
return
} }
APIUpdateAttr({ APIUpdateAttr({
url: url, url: the_url,
method: 'PATCH',
body: JSON.stringify(data), body: JSON.stringify(data),
method: "PATCH" success: success
}) });
} }
function doActive() {
function editTreeNode() { var data = [];
hideRMenu(); $.each(id_list, function(index, object_id) {
var current_node = zTree.getSelectedNodes()[0]; var obj = {"pk": object_id, "is_active": true};
if (!current_node){ data.push(obj);
return });
function success() {
asset_table.ajax.reload()
} }
zTree.editName(current_node); APIUpdateAttr({
url: the_url,
method: 'PATCH',
body: JSON.stringify(data),
success: success
});
} }
function doDelete() {
function initTree() { swal({
var setting = { title: "{% trans 'Are you sure?' %}",
view: { text: "{% trans 'This will delete the selected assets !!!' %}",
dblClickExpand: false, type: "warning",
showLine: true showCancelButton: true,
}, confirmButtonColor: "#DD6B55",
data: { confirmButtonText: "{% trans 'Confirm' %}",
simpleData: { closeOnConfirm: false
enable: true }, function() {
} var success = function() {
}, var msg = "{% trans 'Asset Deleted.' %}";
callback: { swal("{% trans 'Asset Delete' %}", msg, "success");
onRightClick: OnRightClick, $('#asset_list_table').DataTable().ajax.reload();
beforeClick: beforeClick, };
onClick: onClick, var fail = function() {
onRename: onRenameNode var msg = "{% trans 'Asset Deleting failed.' %}";
} swal("{% trans 'Asset Delete' %}", msg, "error");
}; };
var url_delete = the_url + '?id__in=' + JSON.stringify(id_list);
var zNodes = []; APIUpdateAttr({
$.get("{% url 'api-assets:node-list' %}", function(data, status){ url: url_delete,
$.each(data, function (index, value) { method: 'DELETE',
value["pId"] = value["parent"]; success: success,
if (value["key"] === "0") { error: fail
value["open"] = true;
}
value["name"] = value["value"]
}); });
zNodes = data; $data_table.ajax.reload();
$.fn.zTree.init($("#assetTree"), setting, zNodes); jumpserver.checked = false;
zTree = $.fn.zTree.getZTreeObj("assetTree");
rMenu = $("#rMenu");
}); });
} }
$(document).ready(function(){ function doUpdate() {
initTable(); var id_list_string = id_list.join(',');
initTree(); var url = "{% url 'assets:asset-bulk-update' %}?assets_id=" + id_list_string;
}); location.href = url
}
switch(action) {
case 'deactive':
doDeactive();
break;
case 'delete':
doDelete();
break;
case 'update':
doUpdate();
break;
case 'active':
doActive();
break;
default:
break;
}
});
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -27,7 +27,7 @@ from common.mixins import JSONResponseMixin ...@@ -27,7 +27,7 @@ from common.mixins import JSONResponseMixin
from common.utils import get_object_or_none, get_logger, is_uuid from common.utils import get_object_or_none, get_logger, is_uuid
from common.const import create_success_msg, update_success_msg from common.const import create_success_msg, update_success_msg
from .. import forms from .. import forms
from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser, Label from ..models import Asset, AssetGroup, AdminUser, Cluster, SystemUser, Label, Node
from ..hands import AdminUserRequiredMixin from ..hands import AdminUserRequiredMixin
...@@ -41,13 +41,12 @@ logger = get_logger(__file__) ...@@ -41,13 +41,12 @@ logger = get_logger(__file__)
class AssetListView(AdminUserRequiredMixin, TemplateView): class AssetListView(AdminUserRequiredMixin, TemplateView):
template_name = 'assets/asset_list.html' template_name = 'assets/tree.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('Assets'), 'app': _('Assets'),
'action': _('Asset list'), 'action': _('Asset list'),
'system_users': SystemUser.objects.all(),
'labels': Label.objects.all().order_by('name'), 'labels': Label.objects.all().order_by('name'),
} }
kwargs.update(context) kwargs.update(context)
...@@ -81,6 +80,16 @@ class AssetCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): ...@@ -81,6 +80,16 @@ class AssetCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
# asset.save() # asset.save()
# return super().form_valid(form) # return super().form_valid(form)
def get_form(self, form_class=None):
form = super().get_form(form_class=form_class)
node_id = self.request.GET.get("node_id")
if node_id:
node = get_object_or_none(Node, id=node_id)
else:
node = Node.root()
form["nodes"].initial = node
return form
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('Assets'), 'app': _('Assets'),
......
...@@ -5,6 +5,7 @@ from django.views.generic import TemplateView ...@@ -5,6 +5,7 @@ from django.views.generic import TemplateView
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.mixins import AdminUserRequiredMixin from common.mixins import AdminUserRequiredMixin
from ..models import Label
__all__ = ['TreeView'] __all__ = ['TreeView']
...@@ -17,6 +18,7 @@ class TreeView(AdminUserRequiredMixin, TemplateView): ...@@ -17,6 +18,7 @@ class TreeView(AdminUserRequiredMixin, TemplateView):
context = { context = {
'app': _('Assets'), 'app': _('Assets'),
'action': _('Tree view'), 'action': _('Tree view'),
'labels': Label.objects.all(),
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
......
...@@ -47,9 +47,9 @@ class JSONResponseMixin(object): ...@@ -47,9 +47,9 @@ class JSONResponseMixin(object):
return JsonResponse(context) return JsonResponse(context)
class CustomFilterMixin(object): class IDInFilterMixin(object):
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
queryset = super(CustomFilterMixin, self).filter_queryset(queryset) queryset = super(IDInFilterMixin, self).filter_queryset(queryset)
id_list = self.request.query_params.get('id__in') id_list = self.request.query_params.get('id__in')
if id_list: if id_list:
import json import json
......
...@@ -9,10 +9,9 @@ from rest_framework import viewsets ...@@ -9,10 +9,9 @@ from rest_framework import viewsets
from common.utils import get_object_or_none from common.utils import get_object_or_none
from users.permissions import IsValidUser, IsSuperUser, IsAppUser, IsSuperUserOrAppUser from users.permissions import IsValidUser, IsSuperUser, IsAppUser, IsSuperUserOrAppUser
from .utils import get_user_granted_assets, get_user_granted_asset_groups, \ from .utils import get_user_granted_assets, get_user_granted_asset_groups, \
get_user_asset_permissions, get_user_group_asset_permissions, \
get_user_group_granted_assets, get_user_group_granted_asset_groups get_user_group_granted_assets, get_user_group_granted_asset_groups
from .models import AssetPermission, NodePermission from .models import AssetPermission, NodePermission
from .hands import AssetGrantedSerializer, User, UserGroup, AssetGroup, Asset, \ from .hands import AssetGrantedSerializer, User, UserGroup, Node, Asset, \
AssetGroup, AssetGroupGrantedSerializer, SystemUser, MyAssetGroupGrantedSerializer AssetGroup, AssetGroupGrantedSerializer, SystemUser, MyAssetGroupGrantedSerializer
from . import serializers from . import serializers
...@@ -30,24 +29,12 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): ...@@ -30,24 +29,12 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
return serializers.AssetPermissionListSerializer return serializers.AssetPermissionListSerializer
return self.serializer_class return self.serializer_class
# def get_queryset(self): def get_queryset(self):
# queryset = super(AssetPermissionViewSet, self).get_queryset() queryset = super().get_queryset()
# user_id = self.request.query_params.get('user', '') node_id = self.request.query_params.get('node_id')
# user_group_id = self.request.query_params.get('user_group', '') if node_id:
# queryset = queryset.filter(node__id=node_id)
# if user_id and user_id.isdigit(): return queryset
# user = get_object_or_404(User, id=int(user_id))
# queryset = get_user_asset_permissions(user)
#
# if user_group_id:
# user_group = get_object_or_404(UserGroup, id=user_group_id)
# queryset = get_user_group_asset_permissions(user_group)
# return queryset
# def get_serializer_class(self):
# if getattr(self, 'user_id', ''):
# return serializers.UserAssetPermissionCreateUpdateSerializer
# return serializers.AssetPermissionCreateUpdateSerializer
class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView): class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
from users.utils import AdminUserRequiredMixin from users.utils import AdminUserRequiredMixin
from users.models import User, UserGroup from users.models import User, UserGroup
from assets.models import Asset, AssetGroup, SystemUser from assets.models import Asset, AssetGroup, SystemUser, Node
from assets.serializers import AssetGrantedSerializer, AssetGroupGrantedSerializer, MyAssetGroupGrantedSerializer from assets.serializers import AssetGrantedSerializer, AssetGroupGrantedSerializer, MyAssetGroupGrantedSerializer
......
{% extends '_base_list.html' %} {% extends 'base.html' %}
{% load static %}
{% load i18n %} {% load i18n %}
{% block table_search %} {% block custom_head_css_js %}
{% endblock %} <link href="{% static 'css/plugins/jstree/style.min.css' %}" rel="stylesheet">
<link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
<script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
<style type="text/css">
div#rMenu {
position:absolute;
visibility:hidden;
text-align: left;
top: 100%;
left: 0;
z-index: 1000;
float: left;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
background-clip: padding-box;
}
div#rMenu li{
margin: 1px 0;
cursor: pointer;
{#list-style: none outside none;#}
}
.dropdown a:hover {
background-color: #f1f1f1
}
</style>
{% block help_message %}
<div class="alert alert-info help-message">
</div>
{% endblock %} {% endblock %}
{% block table_container %} {% block content %}
<div class="uc pull-left m-r-5"> <div class="wrapper wrapper-content">
<a href="{% url 'perms:asset-permission-create' %}" class="btn btn-sm btn-primary "> <div class="row">
{% trans "Create permission" %} <div class="col-lg-3">
</a> <div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0">
<div class="file-manager ">
<div id="assetTree" class="ztree">
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="col-lg-9 animated fadeInRight">
<div class="mail-box-header">
<div class="uc pull-left m-r-5">
<a class="btn btn-sm btn-primary btn-create-permission">
{% trans "Create permission" %}
</a>
</div>
<table class="table table-striped table-bordered table-hover" id="permission_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Node' %}</th>
<th class="text-center">{% trans 'User group' %}</th>
<th class="text-center">{% trans 'System user' %}</th>
<th class="text-center">{% trans 'Is active' %}</th>
<th class="text-center">{% trans 'Date expired' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div> </div>
<table class="table table-striped table-bordered table-hover" id="permission_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Node' %}</th>
<th class="text-center">{% trans 'User group' %}</th>
<th class="text-center">{% trans 'System user' %}</th>
<th class="text-center">{% trans 'Is active' %}</th>
<th class="text-center">{% trans 'Date expired' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var zTree, rMenu, table;
function initTable() { function initTable() {
var options = { var options = {
ele: $('#permission_list_table'), ele: $('#permission_list_table'),
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData) { {targets: 1, createdCell: function (td, cellData) {
var html = '<a href="">' + cellData.name + '</a>'; var html = '<a href="{% url 'assets:tree-view' %}?node=99899">' + cellData.name + '</a>';
$(td).html(html) $(td).html(html.replace("99899", cellData.pk));
}}, }},
{targets: 2, createdCell: function (td, cellData) { {targets: 2, createdCell: function (td, cellData) {
var html = '<a href="">' + cellData.name + '</a>'; var html = '<a href="{% url "users:user-group-detail" pk=DEFAULT_PK %}">' + cellData.name + '</a>';
$(td).html(html) $(td).html(html.replace("{{ DEFAULT_PK }}", cellData.pk))
}}, }},
{targets: 3, createdCell: function (td, cellData) { {targets: 3, createdCell: function (td, cellData) {
var html = '<a href="">' + cellData.name + '</a>'; var html = '<a href="{% url 'assets:system-user-detail' pk=DEFAULT_PK %}">' + cellData.name + '</a>';
$(td).html(html) $(td).html(html.replace("{{ DEFAULT_PK }}", cellData.pk));
}}, }},
{targets: 4, createdCell: function (td, cellData) { {targets: 4, createdCell: function (td, cellData) {
if (!cellData) { if (!cellData) {
...@@ -59,7 +103,14 @@ function initTable() { ...@@ -59,7 +103,14 @@ function initTable() {
$(td).html('<i class="fa fa-check text-navy"></i>') $(td).html('<i class="fa fa-check text-navy"></i>')
} }
}}, }},
{targets: 5, createdCell: function (td, cellData) {
var date_expired = cellData.split(" ");
if (date_expired && date_expired.length === 3) {
$(td).html(date_expired[0]);
} else {
$(td).html(cellData);
}
}},
{targets: 6, createdCell: function (td, cellData, rowData) { {targets: 6, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); var update_btn = '<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>' var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
...@@ -76,13 +127,75 @@ function initTable() { ...@@ -76,13 +127,75 @@ function initTable() {
], ],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
jumpserver.initDataTable(options) table = jumpserver.initDataTable(options);
return table
}
function onSelected(event, treeNode) {
var url = table.ajax.url();
url = setUrlParam(url, "node_id", treeNode.id);
table.ajax.url(url);
table.ajax.reload();
}
function selectQueryNode() {
var node_id = $.getUrlParam("node");
if (node_id !== null) {
var node = zTree.getNodesByParam("id", node_id, null);
if (node) {
zTree.selectNode(node[0]);
}
}
}
function initTree() {
var setting = {
view: {
dblClickExpand: false,
showLine: true
},
data: {
simpleData: {
enable: true
}
},
callback: {
onSelected: onSelected
}
};
var zNodes = [];
$.get("{% url 'api-assets:node-list' %}", function(data, status){
$.each(data, function (index, value) {
value["pId"] = value["parent"];
if (value["key"] === "0") {
value["open"] = true;
}
value["name"] = value["value"]
});
zNodes = data;
$.fn.zTree.init($("#assetTree"), setting, zNodes);
zTree = $.fn.zTree.getZTreeObj("assetTree");
rMenu = $("#rMenu");
selectQueryNode();
});
} }
$(document).ready(function(){ $(document).ready(function(){
initTable() initTable();
initTree();
})
.on('click', '.btn-create-asset', function () {
var url = "{% url 'assets:asset-create' %}";
var nodes = zTree.getSelectedNodes();
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
url += "?node=" + current_node.id;
}
window.open(url);
}) })
.on('click', '.btn-del', function () { .on('click', '.btn-del', function () {
var $this = $(this); var $this = $(this);
var name = $this.data('name'); var name = $this.data('name');
...@@ -91,5 +204,16 @@ $(document).ready(function(){ ...@@ -91,5 +204,16 @@ $(document).ready(function(){
.replace('{{ DEFAULT_PK }}', uid); .replace('{{ DEFAULT_PK }}', uid);
objectDelete($this, name, the_url); objectDelete($this, name, the_url);
}) })
.on('click', '.btn-create-permission', function () {
var url = "{% url 'perms:asset-permission-create' %}";
var nodes = zTree.getSelectedNodes();
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
url += "?node_id=" + current_node.id;
}
window.open(url);
})
</script> </script>
{% endblock %} {% endblock %}
...@@ -10,9 +10,9 @@ from django.urls import reverse_lazy ...@@ -10,9 +10,9 @@ from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.detail import DetailView, SingleObjectMixin
from common.const import create_success_msg, update_success_msg from common.utils import get_object_or_none
from .hands import AdminUserRequiredMixin, User, UserGroup, SystemUser, \ from .hands import AdminUserRequiredMixin, User, UserGroup, SystemUser, \
Asset, AssetGroup Asset, AssetGroup, Node
from .models import AssetPermission, NodePermission from .models import AssetPermission, NodePermission
from .forms import AssetPermissionForm from .forms import AssetPermissionForm
...@@ -37,6 +37,15 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, CreateView): ...@@ -37,6 +37,15 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, CreateView):
template_name = 'perms/asset_permission_create_update.html' template_name = 'perms/asset_permission_create_update.html'
success_url = reverse_lazy('perms:asset-permission-list') success_url = reverse_lazy('perms:asset-permission-list')
def get_form(self, form_class=None):
form = super().get_form(form_class=form_class)
node_id = self.request.GET.get("node_id")
node = get_object_or_none(Node, id=node_id)
if not node:
node = Node.root()
form['node'].initial = node
return form
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('Perms'), 'app': _('Perms'),
......
...@@ -530,4 +530,44 @@ function createPopover(dataset, title, callback) { ...@@ -530,4 +530,44 @@ function createPopover(dataset, title, callback) {
var html = "<a data-toggle='popover' data-content='" + data_content + "'>" + dataset.length + "</a>"; var html = "<a data-toggle='popover' data-content='" + data_content + "'>" + dataset.length + "</a>";
return html; return html;
} }
\ No newline at end of file
$(function () {
(function ($) {
$.getUrlParam = function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
})(jQuery);
});
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
function setUrlParam(url, name, value) {
var urlArray = url.split("?");
if (urlArray.length===1){
url += "?" + name + "=" + value;
} else {
var oriParam = urlArray[1].split("&");
var oriParamMap = {};
$.each(oriParam, function (index, value) {
var v = value.split("=");
oriParamMap[v[0]] = v[1];
});
oriParamMap[name] = value;
url = urlArray[0] + "?";
var newParam = [];
$.each(oriParamMap, function (index, value) {
console.log(index, value);
newParam.push(index + "=" + value);
});
url += newParam.join("&")
}
return url
}
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li> <li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li>
<li id="asset-group"><a href="{% url 'assets:asset-group-list' %}">{% trans 'Asset group' %}</a></li>
<li id="cluster"><a href="{% url 'assets:cluster-list' %}">{% trans 'Cluster' %}</a></li>
<li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li> <li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li>
<li id="system-user"><a href="{% url 'assets:system-user-list' %}">{% trans 'System user' %}</a></li> <li id="system-user"><a href="{% url 'assets:system-user-list' %}">{% trans 'System user' %}</a></li>
<li id="label"><a href="{% url 'assets:label-list' %}">{% trans 'Labels' %}</a></li> <li id="label"><a href="{% url 'assets:label-list' %}">{% trans 'Labels' %}</a></li>
......
...@@ -17,14 +17,14 @@ from .models import User, UserGroup ...@@ -17,14 +17,14 @@ from .models import User, UserGroup
from .permissions import IsSuperUser, IsValidUser, IsCurrentUserOrReadOnly, \ from .permissions import IsSuperUser, IsValidUser, IsCurrentUserOrReadOnly, \
IsSuperUserOrAppUser IsSuperUserOrAppUser
from .utils import check_user_valid, generate_token from .utils import check_user_valid, generate_token
from common.mixins import CustomFilterMixin from common.mixins import IDInFilterMixin
from common.utils import get_logger from common.utils import get_logger
logger = get_logger(__name__) logger = get_logger(__name__)
class UserViewSet(CustomFilterMixin, BulkModelViewSet): class UserViewSet(IDInFilterMixin, BulkModelViewSet):
queryset = User.objects.exclude(role="App") queryset = User.objects.exclude(role="App")
# queryset = User.objects.all().exclude(role="App").order_by("date_joined") # queryset = User.objects.all().exclude(role="App").order_by("date_joined")
serializer_class = UserSerializer serializer_class = UserSerializer
...@@ -88,7 +88,7 @@ class UserUpdatePKApi(generics.UpdateAPIView): ...@@ -88,7 +88,7 @@ class UserUpdatePKApi(generics.UpdateAPIView):
user.save() user.save()
class UserGroupViewSet(CustomFilterMixin, BulkModelViewSet): class UserGroupViewSet(IDInFilterMixin, BulkModelViewSet):
queryset = UserGroup.objects.all() queryset = UserGroup.objects.all()
serializer_class = UserGroupSerializer serializer_class = UserGroupSerializer
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册