mirror of https://github.com/jumpserver/jumpserver
[Update] 支持拖拽更新
parent
5a0068d86a
commit
1018deda96
|
@ -19,7 +19,7 @@ from rest_framework.response import Response
|
||||||
from rest_framework_bulk import BulkModelViewSet
|
from rest_framework_bulk import BulkModelViewSet
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger, get_object_or_none
|
||||||
from ..hands import IsSuperUser
|
from ..hands import IsSuperUser
|
||||||
from ..models import Node
|
from ..models import Node
|
||||||
from .. import serializers
|
from .. import serializers
|
||||||
|
@ -29,6 +29,7 @@ logger = get_logger(__file__)
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'NodeViewSet', 'NodeChildrenApi',
|
'NodeViewSet', 'NodeChildrenApi',
|
||||||
'NodeAddAssetsApi', 'NodeRemoveAssetsApi',
|
'NodeAddAssetsApi', 'NodeRemoveAssetsApi',
|
||||||
|
'NodeAddChildrenApi',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,6 +76,24 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
||||||
return Response(response, status=200)
|
return Response(response, status=200)
|
||||||
|
|
||||||
|
|
||||||
|
class NodeAddChildrenApi(generics.UpdateAPIView):
|
||||||
|
queryset = Node.objects.all()
|
||||||
|
permission_classes = (IsSuperUser,)
|
||||||
|
serializer_class = serializers.NodeAddChildrenSerializer
|
||||||
|
instance = None
|
||||||
|
|
||||||
|
def put(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
nodes_id = request.data.get("nodes")
|
||||||
|
children = [get_object_or_none(Node, id=pk) for pk in nodes_id]
|
||||||
|
for node in children:
|
||||||
|
if not node:
|
||||||
|
continue
|
||||||
|
node.parent = instance
|
||||||
|
node.save()
|
||||||
|
return Response("OK")
|
||||||
|
|
||||||
|
|
||||||
class NodeAddAssetsApi(generics.UpdateAPIView):
|
class NodeAddAssetsApi(generics.UpdateAPIView):
|
||||||
serializer_class = serializers.NodeAssetsSerializer
|
serializer_class = serializers.NodeAssetsSerializer
|
||||||
queryset = Node.objects.all()
|
queryset = Node.objects.all()
|
||||||
|
|
|
@ -94,6 +94,10 @@ class Node(models.Model):
|
||||||
else:
|
else:
|
||||||
return parent
|
return parent
|
||||||
|
|
||||||
|
@parent.setter
|
||||||
|
def parent(self, parent):
|
||||||
|
self.key = parent.get_next_child_key()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ancestor(self):
|
def ancestor(self):
|
||||||
if self.parent == self.__class__.root():
|
if self.parent == self.__class__.root():
|
||||||
|
|
|
@ -65,4 +65,8 @@ class NodeAssetsSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Node
|
model = Node
|
||||||
fields = ['assets']
|
fields = ['assets']
|
||||||
|
|
||||||
|
|
||||||
|
class NodeAddChildrenSerializer(serializers.Serializer):
|
||||||
|
nodes = serializers.ListField()
|
||||||
|
|
|
@ -224,6 +224,7 @@ function editTreeNode() {
|
||||||
if (!current_node){
|
if (!current_node){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
current_node.name = current_node.value;
|
||||||
zTree.editName(current_node);
|
zTree.editName(current_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +309,44 @@ function selectQueryNode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function beforeDrag() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeDrop() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDrag(event, treeId, treeNodes) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDrop(event, treeId, treeNodes, targetNode, moveType) {
|
||||||
|
console.log("DROP");
|
||||||
|
console.log(event);
|
||||||
|
console.log(treeNodes);
|
||||||
|
console.log(targetNode);
|
||||||
|
console.log(moveType);
|
||||||
|
|
||||||
|
var treeNodesNames = [];
|
||||||
|
var treeNodesIds = [];
|
||||||
|
$.each(treeNodes, function (index, value) {
|
||||||
|
treeNodesNames.push(value.value);
|
||||||
|
treeNodesIds.push(value.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
var msg = "你想移动节点: `" + treeNodesNames.join(",") + "` 到 `" + targetNode.value + "` 下吗?";
|
||||||
|
var the_url = "{% url 'api-assets:node-add-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", targetNode.id);
|
||||||
|
var body = {nodes: treeNodesIds};
|
||||||
|
if (confirm(msg)){
|
||||||
|
APIUpdateAttr({
|
||||||
|
url: the_url,
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function initTree() {
|
function initTree() {
|
||||||
var setting = {
|
var setting = {
|
||||||
view: {
|
view: {
|
||||||
|
@ -319,11 +358,24 @@ function initTree() {
|
||||||
enable: true
|
enable: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
edit: {
|
||||||
|
enable: true,
|
||||||
|
showRemoveBtn: false,
|
||||||
|
showRenameBtn: false,
|
||||||
|
drag: {
|
||||||
|
isCopy: true,
|
||||||
|
isMove: true
|
||||||
|
}
|
||||||
|
},
|
||||||
callback: {
|
callback: {
|
||||||
onRightClick: OnRightClick,
|
onRightClick: OnRightClick,
|
||||||
beforeClick: beforeClick,
|
beforeClick: beforeClick,
|
||||||
onRename: onRename,
|
onRename: onRename,
|
||||||
onSelected: onSelected
|
onSelected: onSelected,
|
||||||
|
beforeDrag: beforeDrag,
|
||||||
|
onDrag: onDrag,
|
||||||
|
beforeDrop: beforeDrop,
|
||||||
|
onDrop: onDrop
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -334,7 +386,8 @@ function initTree() {
|
||||||
{#if (value["key"] === "0") {#}
|
{#if (value["key"] === "0") {#}
|
||||||
value["open"] = true;
|
value["open"] = true;
|
||||||
{# }#}
|
{# }#}
|
||||||
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')'
|
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
|
||||||
|
value['value'] = value['value'];
|
||||||
});
|
});
|
||||||
zNodes = data;
|
zNodes = data;
|
||||||
$.fn.zTree.init($("#assetTree"), setting, zNodes);
|
$.fn.zTree.init($("#assetTree"), setting, zNodes);
|
||||||
|
|
|
@ -44,6 +44,7 @@ urlpatterns = [
|
||||||
url(r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$',
|
url(r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$',
|
||||||
api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'),
|
api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'),
|
||||||
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/$', api.NodeChildrenApi.as_view(), name='node-children'),
|
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/$', api.NodeChildrenApi.as_view(), name='node-children'),
|
||||||
|
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'),
|
||||||
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
|
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
|
||||||
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
|
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -215,16 +215,6 @@ $(document).ready(function(){
|
||||||
initTable();
|
initTable();
|
||||||
initTree();
|
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, '_self');
|
|
||||||
})
|
|
||||||
.on('click', '.btn-del', function () {
|
.on('click', '.btn-del', function () {
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
var uid = $this.data('uid');
|
var uid = $this.data('uid');
|
||||||
|
@ -241,7 +231,7 @@ $(document).ready(function(){
|
||||||
current_node = nodes[0];
|
current_node = nodes[0];
|
||||||
url += "?node_id=" + current_node.id;
|
url += "?node_id=" + current_node.id;
|
||||||
}
|
}
|
||||||
window.open(url);
|
window.open(url, '_self');
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
极致的用户使用体验:拥有时尚外观是区别与以往版本和其他软件的铭牌,高雅的气质让你爱不释手;
|
极致的用户使用体验:拥有时尚外观是区别与以往版本和其他软件的铭牌,高雅的气质让你爱不释手;
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
混合云环境下的堡垒机:怎么能容忍传统堡垒机的繁琐步骤,Jumpserver让你极致省力。
|
混合云环境下的堡垒机:怎么能容忍传统堡垒机的繁琐步骤,Jumpserver让你极致省力;
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<small>改变世界,从一点点开始。</small>
|
<small>改变世界,从一点点开始。</small>
|
||||||
|
|
Loading…
Reference in New Issue