]>
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 // overwrite any other class
128 if (info
.hastate
=== 'error') {
129 iconClsAdd
= '-offline';
132 info
.iconCls
= defaults
.iconCls
+ iconClsAdd
;
135 iconClsAdd
= '-template';
136 info
.iconCls
= PVE
.tree
.ResourceTree
.typeDefaults
.template
.iconCls
+ '-' + info
.type
;
143 addChildSorted: function(node
, info
) {
149 if (info
.groupbyid
) {
150 info
.text
= info
.groupbyid
;
151 if (info
.type
=== 'type') {
152 defaults
= PVE
.tree
.ResourceTree
.typeDefaults
[info
.groupbyid
];
153 if (defaults
&& defaults
.text
) {
154 info
.text
= defaults
.text
;
158 var child
= Ext
.create('PVETree', info
);
160 var cs
= node
.childNodes
;
163 pos
= cs
[me
.findInsertIndex(node
, child
, 0, cs
.length
)];
166 node
.insertBefore(child
, pos
);
172 groupChild: function(node
, info
, groups
, level
) {
175 var groupby
= groups
[level
];
176 var v
= info
[groupby
];
179 var group
= node
.findChild('groupbyid', v
);
182 if (info
.type
=== groupby
) {
187 id
: groupby
+ "/" + v
189 if (groupby
!== 'type') {
190 groupinfo
[groupby
] = v
;
193 groupinfo
.leaf
= false;
194 groupinfo
.groupbyid
= v
;
195 group
= me
.addChildSorted(node
, groupinfo
);
196 // fixme: remove when EXTJS has fixed those bugs?!
197 group
.expand(); group
.collapse();
199 if (info
.type
=== groupby
) {
203 return me
.groupChild(group
, info
, groups
, level
+ 1);
207 return me
.addChildSorted(node
, info
);
210 initComponent : function() {
213 var rstore
= PVE
.data
.ResourceStore
;
214 var sp
= Ext
.state
.Manager
.getProvider();
216 if (!me
.viewFilter
) {
225 var store
= Ext
.create('Ext.data.TreeStore', {
230 text
: gettext('Datacenter')
236 var updateTree = function() {
239 // fixme: suspend events ?
241 var rootnode
= me
.store
.getRootNode();
242 me
.setIconCls(rootnode
.data
);
243 // remember selected node (and all parents)
244 var sm
= me
.getSelectionModel();
246 var lastsel
= sm
.getSelection()[0];
249 while (p
&& !!(p
= p
.parentNode
)) {
253 var index
= pdata
.dataIndex
;
255 var groups
= me
.viewFilter
.groups
|| [];
256 var filterfn
= me
.viewFilter
.filterfn
;
258 // remove vanished or moved items
259 // update in place changed items
262 if (index
.hasOwnProperty(key
)) {
263 var olditem
= index
[key
];
265 // getById() use find(), which is slow (ExtJS4 DP5)
266 //var item = rstore.getById(olditem.data.id);
267 var item
= rstore
.data
.get(olditem
.data
.id
);
272 // test if any grouping attributes changed
273 // this will also catch migrated nodes
276 for (i
= 0, len
= groups
.length
; i
< len
; i
++) {
277 var attr
= groups
[i
];
278 if (item
.data
[attr
] != olditem
.data
[attr
]) {
279 //console.log("changed " + attr);
285 // explicitely check for node, since
286 // in some views, node is not a grouping
288 if (!moved
&& item
.data
.node
!== olditem
.data
.node
) {
292 // tree item has been updated
293 if ((item
.data
.text
!== olditem
.data
.text
) ||
294 (item
.data
.running
!== olditem
.data
.running
) ||
295 (item
.data
.template
!== olditem
.data
.template
) ||
296 (item
.data
.status
!== olditem
.data
.status
) ||
297 (item
.data
.hastate
!== olditem
.data
.hastate
)) {
298 //console.log("changed node/text/running " + olditem.data.id);
302 // fixme: also test filterfn()?
307 //console.log("REM UPDATE UID: " + key + " ITEM " + item.data.running);
308 var info
= olditem
.data
;
309 Ext
.apply(info
, item
.data
);
313 if ((!item
|| moved
) && olditem
.isLeaf()) {
314 //console.log("REM UID: " + key + " ITEM " + olditem.data.id);
316 var parentNode
= olditem
.parentNode
;
317 parentNode
.removeChild(olditem
, true);
323 rstore
.each(function(item
) {
324 var olditem
= index
[item
.data
.id
];
329 if (filterfn
&& !filterfn(item
)) {
333 //console.log("ADD UID: " + item.data.id);
335 var info
= Ext
.apply({ leaf
: true }, item
.data
);
337 var child
= me
.groupChild(rootnode
, info
, groups
, 0);
339 index
[item
.data
.id
] = child
;
343 // select parent node is selection vanished
344 if (lastsel
&& !rootnode
.findChild('id', lastsel
.data
.id
, true)) {
346 while (!!(p
= parents
.shift())) {
347 if (!!(tmp
= rootnode
.findChild('id', p
.data
.id
, true))) {
352 me
.selectById(lastsel
.data
.id
);
355 // on first tree load set the selection from the stateful provider
356 if (!pdata
.updateCount
) {
359 me
.applyState(sp
.get(stateid
));
365 var statechange = function(sp
, key
, value
) {
366 if (key
=== stateid
) {
367 me
.applyState(value
);
371 sp
.on('statechange', statechange
);
374 allowSelection
: true,
377 // note: animate cause problems with applyState
381 //rootVisible: false,
382 //title: 'Resource Tree',
384 itemcontextmenu
: PVE
.Utils
.createCmdMenu
,
385 destroy: function() {
386 rstore
.un("load", updateTree
);
388 beforecellmousedown: function (tree
, td
, cellIndex
, record
, tr
, rowIndex
, ev
) {
389 // disable selection when right clicking
390 me
.allowSelection
= (ev
.button
!== 2);
392 beforeselect: function (tree
, record
, index
, eopts
) {
393 var allow
= me
.allowSelection
;
394 me
.allowSelection
= true;
397 itemdblclick
: PVE
.Utils
.openTreeConsole
399 setViewFilter: function(view
) {
400 me
.viewFilter
= view
;
404 clearTree: function() {
405 pdata
.updateCount
= 0;
406 var rootnode
= me
.store
.getRootNode();
408 rootnode
.removeAll();
409 pdata
.dataIndex
= {};
410 me
.getSelectionModel().deselectAll();
412 selectExpand: function(node
) {
413 var sm
= me
.getSelectionModel();
414 if (!sm
.isSelected(node
)) {
417 while (!!(cn
= cn
.parentNode
)) {
418 if (!cn
.isExpanded()) {
422 me
.getView().focusRow(node
);
425 selectById: function(nodeid
) {
426 var rootnode
= me
.store
.getRootNode();
427 var sm
= me
.getSelectionModel();
429 if (nodeid
=== 'root') {
432 node
= rootnode
.findChild('id', nodeid
, true);
435 me
.selectExpand(node
);
438 checkVmMigration: function(record
) {
439 if (!(record
.data
.type
=== 'qemu' || record
.data
.type
=== 'lxc')) {
440 throw "not a vm type";
443 var rootnode
= me
.store
.getRootNode();
444 var node
= rootnode
.findChild('id', record
.data
.id
, true);
446 if (node
&& node
.data
.type
=== record
.data
.type
&&
447 node
.data
.node
!== record
.data
.node
) {
448 // defer select (else we get strange errors)
449 Ext
.defer(function() { me
.selectExpand(node
); }, 100, me
);
452 applyState : function(state
) {
453 var sm
= me
.getSelectionModel();
454 if (state
&& state
.value
) {
455 me
.selectById(state
.value
);
464 var sm
= me
.getSelectionModel();
465 sm
.on('select', function(sm
, n
) {
466 sp
.set(stateid
, { value
: n
.data
.id
});
469 rstore
.on("load", updateTree
);
470 rstore
.startUpdate();
471 //rstore.stopUpdate();