]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/tree/ResourceTree.js
2 * Left Treepanel, containing all the ressources we manage in this datacenter: server nodes, server storages, VMs and Containers
4 Ext
.define('PVE.tree.ResourceTree', {
5 extend
: 'Ext.tree.TreePanel',
6 alias
: ['widget.pveResourceTree'],
11 iconCls
: 'fa fa-building x-fa-tree',
12 text
: gettext('Nodes')
15 iconCls
: 'fa fa-tags fa-dark x-fa-tree',
16 text
: gettext('Resource Pool')
19 iconCls
: 'fa fa-database fa-dark x-fa-tree',
20 text
: gettext('Storage')
23 iconCls
: 'fa fa-desktop x-fa-tree',
24 text
: gettext('Virtual Machine')
27 //iconCls: 'x-tree-node-lxc',
28 iconCls
: 'fa fa-cube x-fa-tree',
29 text
: gettext('LXC Container')
32 iconCls
: 'fa fa-file-o fa-dark x-fa-tree-template'
35 iconCls
: 'fa fa-server x-fa-tree-datacenter',
43 nodeSortFn: function(node1
, node2
) {
47 if ((n1
.groupbyid
&& n2
.groupbyid
) ||
48 !(n1
.groupbyid
|| n2
.groupbyid
)) {
55 if ((tcmp
= v1
> v2
? 1 : (v1
< v2
? -1 : 0)) != 0) {
59 // numeric compare for VM IDs
60 // sort templates after regular VMs
61 if (v1
=== 'qemu' || v1
=== 'lxc') {
62 if (n1
.template
&& !n2
.template
) {
64 } else if (n2
.template
&& !n1
.template
) {
69 if ((tcmp
= v1
> v2
? 1 : (v1
< v2
? -1 : 0)) != 0) {
74 return n1
.text
> n2
.text
? 1 : (n1
.text
< n2
.text
? -1 : 0);
75 } else if (n1
.groupbyid
) {
77 } else if (n2
.groupbyid
) {
82 // private: fast binary search
83 findInsertIndex: function(node
, child
, start
, end
) {
86 var diff
= end
- start
;
88 var mid
= start
+ (diff
>>1);
94 var res
= me
.nodeSortFn(child
, node
.childNodes
[mid
]);
96 return me
.findInsertIndex(node
, child
, start
, mid
);
98 return me
.findInsertIndex(node
, child
, mid
+ 1, end
);
102 setIconCls: function(info
) {
105 var defaults
= PVE
.tree
.ResourceTree
.typeDefaults
[info
.type
];
106 if (info
.id
=== 'root') {
107 defaults
= PVE
.tree
.ResourceTree
.typeDefaults
['datacenter'];
108 } else if (info
.type
=== 'type') {
109 defaults
= PVE
.tree
.ResourceTree
.typeDefaults
[info
.groupbyid
];
111 if (defaults
&& defaults
.iconCls
) {
114 if (info
.running
&& info
.type
=== 'node') {
115 iconClsAdd
= '-online';
116 } else if (info
.running
) {
117 iconClsAdd
= '-running';
118 if (info
.status
=== 'paused') {
119 iconClsAdd
= '-paused';
121 } else if (info
.type
=== 'lxc' || info
.type
=== 'qemu') {
122 iconClsAdd
= '-stopped';
123 } else if (info
.type
=== 'node') {
124 iconClsAdd
= '-offline';
127 info
.iconCls
= defaults
.iconCls
+ iconClsAdd
;
130 iconClsAdd
= '-template';
131 info
.iconCls
= PVE
.tree
.ResourceTree
.typeDefaults
['template'].iconCls
+ '-' + info
.type
;
138 addChildSorted: function(node
, info
) {
144 if (info
.groupbyid
) {
145 info
.text
= info
.groupbyid
;
146 if (info
.type
=== 'type') {
147 defaults
= PVE
.tree
.ResourceTree
.typeDefaults
[info
.groupbyid
];
148 if (defaults
&& defaults
.text
) {
149 info
.text
= defaults
.text
;
153 var child
= Ext
.create('PVETree', info
);
155 var cs
= node
.childNodes
;
158 pos
= cs
[me
.findInsertIndex(node
, child
, 0, cs
.length
)];
161 node
.insertBefore(child
, pos
);
167 groupChild: function(node
, info
, groups
, level
) {
170 var groupby
= groups
[level
];
171 var v
= info
[groupby
];
174 var group
= node
.findChild('groupbyid', v
);
177 if (info
.type
=== groupby
) {
182 id
: groupby
+ "/" + v
184 if (groupby
!== 'type') {
185 groupinfo
[groupby
] = v
;
188 groupinfo
.leaf
= false;
189 groupinfo
.groupbyid
= v
;
190 group
= me
.addChildSorted(node
, groupinfo
);
191 // fixme: remove when EXTJS has fixed those bugs?!
192 group
.expand(); group
.collapse();
194 if (info
.type
=== groupby
) {
198 return me
.groupChild(group
, info
, groups
, level
+ 1);
202 return me
.addChildSorted(node
, info
);
205 initComponent : function() {
208 var rstore
= PVE
.data
.ResourceStore
;
209 var sp
= Ext
.state
.Manager
.getProvider();
211 if (!me
.viewFilter
) {
220 var store
= Ext
.create('Ext.data.TreeStore', {
225 text
: gettext('Datacenter')
231 var updateTree = function() {
234 // fixme: suspend events ?
236 var rootnode
= me
.store
.getRootNode();
237 me
.setIconCls(rootnode
.data
);
238 // remember selected node (and all parents)
239 var sm
= me
.getSelectionModel();
241 var lastsel
= sm
.getSelection()[0];
244 while (p
&& !!(p
= p
.parentNode
)) {
248 var index
= pdata
.dataIndex
;
250 var groups
= me
.viewFilter
.groups
|| [];
251 var filterfn
= me
.viewFilter
.filterfn
;
253 // remove vanished or moved items
254 // update in place changed items
257 if (index
.hasOwnProperty(key
)) {
258 var olditem
= index
[key
];
260 // getById() use find(), which is slow (ExtJS4 DP5)
261 //var item = rstore.getById(olditem.data.id);
262 var item
= rstore
.data
.get(olditem
.data
.id
);
267 // test if any grouping attributes changed
268 // this will also catch migrated nodes
270 for (i
= 0, len
= groups
.length
; i
< len
; i
++) {
271 var attr
= groups
[i
];
272 if (item
.data
[attr
] != olditem
.data
[attr
]) {
273 //console.log("changed " + attr);
279 // tree item has been updated
280 if ((item
.data
.text
!== olditem
.data
.text
) ||
281 (item
.data
.running
!== olditem
.data
.running
) ||
282 (item
.data
.template
!== olditem
.data
.template
)) {
283 //console.log("changed node/text/running " + olditem.data.id);
287 // fixme: also test filterfn()?
292 //console.log("REM UPDATE UID: " + key + " ITEM " + item.data.running);
293 var info
= olditem
.data
;
294 Ext
.apply(info
, item
.data
);
298 if ((!item
|| moved
) && olditem
.isLeaf()) {
299 //console.log("REM UID: " + key + " ITEM " + olditem.data.id);
301 var parentNode
= olditem
.parentNode
;
302 parentNode
.removeChild(olditem
, true);
308 rstore
.each(function(item
) {
309 var olditem
= index
[item
.data
.id
];
314 if (filterfn
&& !filterfn(item
)) {
318 //console.log("ADD UID: " + item.data.id);
320 var info
= Ext
.apply({ leaf
: true }, item
.data
);
322 var child
= me
.groupChild(rootnode
, info
, groups
, 0);
324 index
[item
.data
.id
] = child
;
328 // select parent node is selection vanished
329 if (lastsel
&& !rootnode
.findChild('id', lastsel
.data
.id
, true)) {
331 while (!!(p
= parents
.shift())) {
332 if (!!(tmp
= rootnode
.findChild('id', p
.data
.id
, true))) {
337 me
.selectById(lastsel
.data
.id
);
340 // on first tree load set the selection from the stateful provider
341 if (!pdata
.updateCount
) {
344 me
.applyState(sp
.get(stateid
));
350 var statechange = function(sp
, key
, value
) {
351 if (key
=== stateid
) {
352 me
.applyState(value
);
356 sp
.on('statechange', statechange
);
361 // note: animate cause problems with applyState
365 //rootVisible: false,
366 //title: 'Resource Tree',
368 itemcontextmenu: function(v
, record
, item
, index
, event
) {
373 if (record
.data
.type
=== 'qemu' && !record
.data
.template
) {
374 menu
= Ext
.create('PVE.qemu.CmdMenu', {
377 } else if (record
.data
.type
=== 'qemu' && record
.data
.template
) {
378 menu
= Ext
.create('PVE.qemu.TemplateMenu', {
381 } else if (record
.data
.type
=== 'lxc' && !record
.data
.template
) {
382 menu
= Ext
.create('PVE.lxc.CmdMenu', {
385 } else if (record
.data
.type
=== 'lxc' && record
.data
.template
) {
386 /* since clone does not work reliably, disable for now
387 menu = Ext.create('PVE.lxc.TemplateMenu', {
396 menu
.showAt(event
.getXY());
398 destroy: function() {
399 rstore
.un("load", updateTree
);
402 setViewFilter: function(view
) {
403 me
.viewFilter
= view
;
407 clearTree: function() {
408 pdata
.updateCount
= 0;
409 var rootnode
= me
.store
.getRootNode();
411 rootnode
.removeAll();
412 pdata
.dataIndex
= {};
413 me
.getSelectionModel().deselectAll();
415 selectExpand: function(node
) {
416 var sm
= me
.getSelectionModel();
417 if (!sm
.isSelected(node
)) {
420 while (!!(cn
= cn
.parentNode
)) {
421 if (!cn
.isExpanded()) {
427 selectById: function(nodeid
) {
428 var rootnode
= me
.store
.getRootNode();
429 var sm
= me
.getSelectionModel();
431 if (nodeid
=== 'root') {
434 node
= rootnode
.findChild('id', nodeid
, true);
437 me
.selectExpand(node
);
440 checkVmMigration: function(record
) {
441 if (!(record
.data
.type
=== 'qemu' || record
.data
.type
=== 'lxc')) {
442 throw "not a vm type";
445 var rootnode
= me
.store
.getRootNode();
446 var node
= rootnode
.findChild('id', record
.data
.id
, true);
448 if (node
&& node
.data
.type
=== record
.data
.type
&&
449 node
.data
.node
!== record
.data
.node
) {
450 // defer select (else we get strange errors)
451 Ext
.defer(function() { me
.selectExpand(node
); }, 100, me
);
454 applyState : function(state
) {
455 var sm
= me
.getSelectionModel();
456 if (state
&& state
.value
) {
457 me
.selectById(state
.value
);
466 var sm
= me
.getSelectionModel();
467 sm
.on('select', function(sm
, n
) {
468 sp
.set(stateid
, { value
: n
.data
.id
});
471 rstore
.on("load", updateTree
);
472 rstore
.startUpdate();
473 //rstore.stopUpdate();