]>
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
271 for (i
= 0, len
= groups
.length
; i
< len
; i
++) {
272 var attr
= groups
[i
];
273 if (item
.data
[attr
] != olditem
.data
[attr
]) {
274 //console.log("changed " + attr);
280 // explicitely check for node, since
281 // in some views, node is not a grouping
283 if (!moved
&& item
.data
.node
!== olditem
.data
.node
) {
287 // tree item has been updated
288 if ((item
.data
.text
!== olditem
.data
.text
) ||
289 (item
.data
.running
!== olditem
.data
.running
) ||
290 (item
.data
.template
!== olditem
.data
.template
) ||
291 (item
.data
.status
!== olditem
.data
.status
)) {
292 //console.log("changed node/text/running " + olditem.data.id);
296 // fixme: also test filterfn()?
301 //console.log("REM UPDATE UID: " + key + " ITEM " + item.data.running);
302 var info
= olditem
.data
;
303 Ext
.apply(info
, item
.data
);
307 if ((!item
|| moved
) && olditem
.isLeaf()) {
308 //console.log("REM UID: " + key + " ITEM " + olditem.data.id);
310 var parentNode
= olditem
.parentNode
;
311 parentNode
.removeChild(olditem
, true);
317 rstore
.each(function(item
) {
318 var olditem
= index
[item
.data
.id
];
323 if (filterfn
&& !filterfn(item
)) {
327 //console.log("ADD UID: " + item.data.id);
329 var info
= Ext
.apply({ leaf
: true }, item
.data
);
331 var child
= me
.groupChild(rootnode
, info
, groups
, 0);
333 index
[item
.data
.id
] = child
;
337 // select parent node is selection vanished
338 if (lastsel
&& !rootnode
.findChild('id', lastsel
.data
.id
, true)) {
340 while (!!(p
= parents
.shift())) {
341 if (!!(tmp
= rootnode
.findChild('id', p
.data
.id
, true))) {
346 me
.selectById(lastsel
.data
.id
);
349 // on first tree load set the selection from the stateful provider
350 if (!pdata
.updateCount
) {
353 me
.applyState(sp
.get(stateid
));
359 var statechange = function(sp
, key
, value
) {
360 if (key
=== stateid
) {
361 me
.applyState(value
);
365 sp
.on('statechange', statechange
);
368 allowSelection
: true,
371 // note: animate cause problems with applyState
375 //rootVisible: false,
376 //title: 'Resource Tree',
378 itemcontextmenu: function(v
, record
, item
, index
, event
) {
383 if (record
.data
.type
=== 'qemu' && !record
.data
.template
) {
384 menu
= Ext
.create('PVE.qemu.CmdMenu', {
387 } else if (record
.data
.type
=== 'qemu' && record
.data
.template
) {
388 menu
= Ext
.create('PVE.qemu.TemplateMenu', {
391 } else if (record
.data
.type
=== 'lxc' && !record
.data
.template
) {
392 menu
= Ext
.create('PVE.lxc.CmdMenu', {
395 } else if (record
.data
.type
=== 'lxc' && record
.data
.template
) {
396 /* since clone does not work reliably, disable for now
397 menu = Ext.create('PVE.lxc.TemplateMenu', {
406 menu
.showAt(event
.getXY());
408 destroy: function() {
409 rstore
.un("load", updateTree
);
411 beforecellmousedown: function (tree
, record
,item
,index
,ev
) {
412 // disable selection when right clicking
413 me
.allowSelection
= (event
.button
!== 2);
415 beforeselect: function (tree
, record
, index
, eopts
) {
416 var allow
= me
.allowSelection
;
417 me
.allowSelection
= true;
421 setViewFilter: function(view
) {
422 me
.viewFilter
= view
;
426 clearTree: function() {
427 pdata
.updateCount
= 0;
428 var rootnode
= me
.store
.getRootNode();
430 rootnode
.removeAll();
431 pdata
.dataIndex
= {};
432 me
.getSelectionModel().deselectAll();
434 selectExpand: function(node
) {
435 var sm
= me
.getSelectionModel();
436 if (!sm
.isSelected(node
)) {
439 while (!!(cn
= cn
.parentNode
)) {
440 if (!cn
.isExpanded()) {
446 selectById: function(nodeid
) {
447 var rootnode
= me
.store
.getRootNode();
448 var sm
= me
.getSelectionModel();
450 if (nodeid
=== 'root') {
453 node
= rootnode
.findChild('id', nodeid
, true);
456 me
.selectExpand(node
);
459 checkVmMigration: function(record
) {
460 if (!(record
.data
.type
=== 'qemu' || record
.data
.type
=== 'lxc')) {
461 throw "not a vm type";
464 var rootnode
= me
.store
.getRootNode();
465 var node
= rootnode
.findChild('id', record
.data
.id
, true);
467 if (node
&& node
.data
.type
=== record
.data
.type
&&
468 node
.data
.node
!== record
.data
.node
) {
469 // defer select (else we get strange errors)
470 Ext
.defer(function() { me
.selectExpand(node
); }, 100, me
);
473 applyState : function(state
) {
474 var sm
= me
.getSelectionModel();
475 if (state
&& state
.value
) {
476 me
.selectById(state
.value
);
485 var sm
= me
.getSelectionModel();
486 sm
.on('select', function(sm
, n
) {
487 sp
.set(stateid
, { value
: n
.data
.id
});
490 rstore
.on("load", updateTree
);
491 rstore
.startUpdate();
492 //rstore.stopUpdate();