]>
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
: 'x-tree-node-server',
12 text
: gettext('Nodes')
15 iconCls
: 'x-tree-node-pool',
16 text
: gettext('Resource Pool')
19 iconCls
: 'x-tree-node-harddisk',
20 text
: gettext('Storage')
23 iconCls
: 'x-tree-node-computer',
24 text
: gettext('Virtual Machine')
27 iconCls
: 'x-tree-node-lxc',
28 text
: gettext('LXC Container')
34 nodeSortFn: function(node1
, node2
) {
38 if ((n1
.groupbyid
&& n2
.groupbyid
) ||
39 !(n1
.groupbyid
|| n2
.groupbyid
)) {
46 if ((tcmp
= v1
> v2
? 1 : (v1
< v2
? -1 : 0)) != 0) {
50 // numeric compare for VM IDs
51 // sort templates after regular VMs
52 if (v1
=== 'qemu' || v1
=== 'lxc') {
53 if (n1
.template
&& !n2
.template
) {
55 } else if (n2
.template
&& !n1
.template
) {
60 if ((tcmp
= v1
> v2
? 1 : (v1
< v2
? -1 : 0)) != 0) {
65 return n1
.text
> n2
.text
? 1 : (n1
.text
< n2
.text
? -1 : 0);
66 } else if (n1
.groupbyid
) {
68 } else if (n2
.groupbyid
) {
73 // private: fast binary search
74 findInsertIndex: function(node
, child
, start
, end
) {
77 var diff
= end
- start
;
79 var mid
= start
+ (diff
>>1);
85 var res
= me
.nodeSortFn(child
, node
.childNodes
[mid
]);
87 return me
.findInsertIndex(node
, child
, start
, mid
);
89 return me
.findInsertIndex(node
, child
, mid
+ 1, end
);
93 setIconCls: function(info
) {
96 var defaults
= PVE
.tree
.ResourceTree
.typeDefaults
[info
.type
];
97 if (defaults
&& defaults
.iconCls
) {
98 var running
= info
.running
? '-running' : '';
99 var template
= info
.template
? '-template' : '';
100 info
.iconCls
= defaults
.iconCls
+ running
+ template
;
105 addChildSorted: function(node
, info
) {
111 if (info
.groupbyid
) {
112 info
.text
= info
.groupbyid
;
113 if (info
.type
=== 'type') {
114 defaults
= PVE
.tree
.ResourceTree
.typeDefaults
[info
.groupbyid
];
115 if (defaults
&& defaults
.text
) {
116 info
.text
= defaults
.text
;
120 var child
= Ext
.create('PVETree', info
);
122 var cs
= node
.childNodes
;
125 pos
= cs
[me
.findInsertIndex(node
, child
, 0, cs
.length
)];
128 node
.insertBefore(child
, pos
);
134 groupChild: function(node
, info
, groups
, level
) {
137 var groupby
= groups
[level
];
138 var v
= info
[groupby
];
141 var group
= node
.findChild('groupbyid', v
);
144 if (info
.type
=== groupby
) {
149 id
: groupby
+ "/" + v
151 if (groupby
!== 'type') {
152 groupinfo
[groupby
] = v
;
155 groupinfo
.leaf
= false;
156 groupinfo
.groupbyid
= v
;
157 group
= me
.addChildSorted(node
, groupinfo
);
158 // fixme: remove when EXTJS has fixed those bugs?!
159 group
.expand(); group
.collapse();
161 if (info
.type
=== groupby
) {
165 return me
.groupChild(group
, info
, groups
, level
+ 1);
169 return me
.addChildSorted(node
, info
);
172 initComponent : function() {
175 var rstore
= PVE
.data
.ResourceStore
;
176 var sp
= Ext
.state
.Manager
.getProvider();
178 if (!me
.viewFilter
) {
187 var store
= Ext
.create('Ext.data.TreeStore', {
192 text
: gettext('Datacenter')
198 var updateTree = function() {
201 // fixme: suspend events ?
203 var rootnode
= me
.store
.getRootNode();
205 // remember selected node (and all parents)
206 var sm
= me
.getSelectionModel();
208 var lastsel
= sm
.getSelection()[0];
211 while (p
&& !!(p
= p
.parentNode
)) {
215 var index
= pdata
.dataIndex
;
217 var groups
= me
.viewFilter
.groups
|| [];
218 var filterfn
= me
.viewFilter
.filterfn
;
220 // remove vanished or moved items
221 // update in place changed items
224 if (index
.hasOwnProperty(key
)) {
225 var olditem
= index
[key
];
227 // getById() use find(), which is slow (ExtJS4 DP5)
228 //var item = rstore.getById(olditem.data.id);
229 var item
= rstore
.data
.get(olditem
.data
.id
);
234 // test if any grouping attributes changed
235 // this will also catch migrated nodes
237 for (i
= 0, len
= groups
.length
; i
< len
; i
++) {
238 var attr
= groups
[i
];
239 if (item
.data
[attr
] != olditem
.data
[attr
]) {
240 //console.log("changed " + attr);
246 // tree item has been updated
247 if ((item
.data
.text
!== olditem
.data
.text
) ||
248 (item
.data
.running
!== olditem
.data
.running
) ||
249 (item
.data
.template
!== olditem
.data
.template
)) {
250 //console.log("changed node/text/running " + olditem.data.id);
254 // fixme: also test filterfn()?
259 //console.log("REM UPDATE UID: " + key + " ITEM " + item.data.running);
260 var info
= olditem
.data
;
261 Ext
.apply(info
, item
.data
);
265 if ((!item
|| moved
) && olditem
.isLeaf()) {
266 //console.log("REM UID: " + key + " ITEM " + olditem.data.id);
268 var parentNode
= olditem
.parentNode
;
269 parentNode
.removeChild(olditem
, true);
275 rstore
.each(function(item
) {
276 var olditem
= index
[item
.data
.id
];
281 if (filterfn
&& !filterfn(item
)) {
285 //console.log("ADD UID: " + item.data.id);
287 var info
= Ext
.apply({ leaf
: true }, item
.data
);
289 var child
= me
.groupChild(rootnode
, info
, groups
, 0);
291 index
[item
.data
.id
] = child
;
295 // select parent node is selection vanished
296 if (lastsel
&& !rootnode
.findChild('id', lastsel
.data
.id
, true)) {
298 while (!!(p
= parents
.shift())) {
299 if (!!(tmp
= rootnode
.findChild('id', p
.data
.id
, true))) {
304 me
.selectById(lastsel
.data
.id
);
307 // on first tree load set the selection from the stateful provider
308 if (!pdata
.updateCount
) {
311 me
.applyState(sp
.get(stateid
));
317 var statechange = function(sp
, key
, value
) {
318 if (key
=== stateid
) {
319 me
.applyState(value
);
323 sp
.on('statechange', statechange
);
328 // note: animate cause problems with applyState
332 //rootVisible: false,
333 //title: 'Resource Tree',
335 itemcontextmenu: function(v
, record
, item
, index
, event
) {
340 if (record
.data
.type
=== 'qemu' && !record
.data
.template
) {
341 menu
= Ext
.create('PVE.qemu.CmdMenu', {
344 } else if (record
.data
.type
=== 'qemu' && record
.data
.template
) {
345 menu
= Ext
.create('PVE.qemu.TemplateMenu', {
348 } else if (record
.data
.type
=== 'lxc' && !record
.data
.template
) {
349 menu
= Ext
.create('PVE.lxc.CmdMenu', {
352 } else if (record
.data
.type
=== 'lxc' && record
.data
.template
) {
353 /* since clone does not work reliably, disable for now
354 menu = Ext.create('PVE.lxc.TemplateMenu', {
363 menu
.showAt(event
.getXY());
365 destroy: function() {
366 rstore
.un("load", updateTree
);
369 setViewFilter: function(view
) {
370 me
.viewFilter
= view
;
374 clearTree: function() {
375 pdata
.updateCount
= 0;
376 var rootnode
= me
.store
.getRootNode();
378 rootnode
.removeAll();
379 pdata
.dataIndex
= {};
380 me
.getSelectionModel().deselectAll();
382 selectExpand: function(node
) {
383 var sm
= me
.getSelectionModel();
384 if (!sm
.isSelected(node
)) {
387 while (!!(cn
= cn
.parentNode
)) {
388 if (!cn
.isExpanded()) {
394 selectById: function(nodeid
) {
395 var rootnode
= me
.store
.getRootNode();
396 var sm
= me
.getSelectionModel();
398 if (nodeid
=== 'root') {
401 node
= rootnode
.findChild('id', nodeid
, true);
404 me
.selectExpand(node
);
407 checkVmMigration: function(record
) {
408 if (!(record
.data
.type
=== 'qemu' || record
.data
.type
=== 'lxc')) {
409 throw "not a vm type";
412 var rootnode
= me
.store
.getRootNode();
413 var node
= rootnode
.findChild('id', record
.data
.id
, true);
415 if (node
&& node
.data
.type
=== record
.data
.type
&&
416 node
.data
.node
!== record
.data
.node
) {
417 // defer select (else we get strange errors)
418 Ext
.defer(function() { me
.selectExpand(node
); }, 100, me
);
421 applyState : function(state
) {
422 var sm
= me
.getSelectionModel();
423 if (state
&& state
.value
) {
424 me
.selectById(state
.value
);
433 var sm
= me
.getSelectionModel();
434 sm
.on('select', function(sm
, n
) {
435 sp
.set(stateid
, { value
: n
.data
.id
});
438 rstore
.on("load", updateTree
);
439 rstore
.startUpdate();
440 //rstore.stopUpdate();