]> git.proxmox.com Git - pmg-gui.git/blob - js/ConfigPanel.js
quarantines: use a check mark for the dark mode filter
[pmg-gui.git] / js / ConfigPanel.js
1 /*
2 * Base class for all the multitab config panels.
3 * Usage: You'd create a subclass of this, and then define your wanted tabs as items like this:
4 *
5 * items: [{
6 * title: "myTitle",
7 * xytpe: "somextype",
8 * iconCls: 'fa fa-icon',
9 * groups: ['somegroup'],
10 * expandedOnInit: true,
11 * itemId: 'someId'
12 * }]
13 *
14 * this has to be in the declarative syntax, else we cannot save them for later (so no Ext.create
15 * or Ext.apply of an item in the subclass)
16 *
17 * the groups array expects the itemids of the items which are the parents, which have to come
18 * before they are used.
19 *
20 * If you want following the tree:
21 * Option1
22 * Option2
23 * -> SubOption1
24 * -> SubSubOption1
25 *
26 * then the suboption1 group array has to look like this:
27 * groups: ['itemid-of-option2']
28 *
29 * and the subsuboption1 one:
30 * groups: ['itemid-of-option2', 'itemid-of-suboption1']
31 *
32 * setting the expandedOnInit determines if the item/group is expanded initially (false by default)
33 */
34 Ext.define('PMG.panel.Config', {
35 extend: 'Ext.panel.Panel',
36 alias: 'widget.pmgPanelConfig',
37
38 viewFilter: undefined, // a filter to pass to that ressource grid
39
40 dockedItems: [{
41 // this is needed for the overflow handler
42 xtype: 'toolbar',
43 overflowHandler: 'scroller',
44 dock: 'left',
45 style: {
46 backgroundColor: '#f5f5f5',
47 padding: 0,
48 margin: 0,
49 },
50 items: {
51 xtype: 'treelist',
52 itemId: 'menu',
53 ui: 'pve-nav',
54 expanderOnly: true,
55 expanderFirst: false,
56 animation: false,
57 singleExpand: false,
58 listeners: {
59 selectionchange: function(treeList, selection) {
60 let view = this.up('panel');
61 view.suspendLayout = true;
62 view.activateCard(selection.data.id);
63 view.suspendLayout = false;
64 view.updateLayout();
65 },
66 itemclick: function(treelist, info) {
67 var olditem = treelist.getSelection();
68 var newitem = info.node;
69
70 // don't select when clicking on the expand arrow, but still want the original behavior
71 if (info.select === false) {
72 return;
73 }
74
75 // if a different open item is clicked, leave it open, else toggle the clicked item
76 if (olditem.data.id !== newitem.data.id &&
77 newitem.data.expanded === true) {
78 info.toggle = false;
79 } else {
80 info.toggle = true;
81 }
82 },
83 },
84 },
85 }],
86
87 firstItem: '',
88 layout: 'card',
89 border: 0,
90
91 // used for automated test
92 selectById: function(cardid) {
93 var me = this;
94
95 var root = me.store.getRoot();
96 var selection = root.findChild('id', cardid, true);
97
98 if (selection) {
99 selection.expand();
100 var menu = me.down('#menu');
101 menu.setSelection(selection);
102 return cardid;
103 }
104 return null;
105 },
106
107 activateCard: function(cardid) {
108 var me = this;
109 if (me.savedItems[cardid]) {
110 var curcard = me.getLayout().getActiveItem();
111 me.add(me.savedItems[cardid]);
112 if (curcard) {
113 me.setActiveItem(cardid);
114 me.remove(curcard, true);
115
116 // trigger state change
117
118 var ncard = cardid;
119 // Note: '' is alias for first tab. First tab can be 'search' or something else
120 if (cardid === me.firstItem) {
121 ncard = '';
122 }
123 if (me.hstateid) {
124 me.sp.set(me.hstateid, { value: ncard });
125 }
126 }
127 }
128 },
129
130 initComponent: function() {
131 var me = this;
132
133 var stateid = me.hstateid;
134
135 me.sp = Ext.state.Manager.getProvider();
136
137 var activeTab; // leaving this undefined means items[0] will be the default tab
138
139 if (stateid) {
140 var state = me.sp.get(stateid);
141 if (state && state.value) {
142 // if this tab does not exists, it chooses the first
143 activeTab = state.value;
144 }
145 }
146
147 // include search tab
148 me.items = me.items || [];
149
150 me.savedItems = {};
151 if (me.items[0]) {
152 me.firstItem = me.items[0].itemId;
153 }
154
155 me.store = Ext.create('Ext.data.TreeStore', {
156 root: {
157 expanded: true,
158 },
159 });
160 var root = me.store.getRoot();
161 me.items.forEach(function(item) {
162 var treeitem = Ext.create('Ext.data.TreeModel', {
163 id: item.itemId,
164 text: item.title,
165 iconCls: item.iconCls,
166 leaf: true,
167 expanded: item.expandedOnInit,
168 });
169 item.header = false;
170 if (me.savedItems[item.itemId] !== undefined) {
171 throw "itemId already exists, please use another";
172 }
173 me.savedItems[item.itemId] = item;
174
175 var group;
176 var curnode = root;
177
178 // get/create the group items
179 while (Ext.isArray(item.groups) && item.groups.length > 0) {
180 group = item.groups.shift();
181
182 var child = curnode.findChild('id', group);
183 if (child === null) {
184 // did not find the group item so add it where we are
185 break;
186 }
187 curnode = child;
188 }
189
190 // lets see if it already exists
191 var node = curnode.findChild('id', item.itemId);
192
193 if (node === null) {
194 curnode.appendChild(treeitem); // insert the item
195 } else {
196 // should not happen!
197 throw "id already exists";
198 }
199 });
200
201 delete me.items;
202 me.defaults = me.defaults || {};
203 Ext.apply(me.defaults, {
204 viewFilter: me.viewFilter,
205 border: 0,
206 });
207
208 me.callParent();
209
210 var menu = me.down('#menu');
211 var selection = root.findChild('id', activeTab, true) || root.firstChild;
212 var node = selection;
213 while (node !== root) {
214 node.expand();
215 node = node.parentNode;
216 }
217 menu.setStore(me.store);
218 menu.setSelection(selection);
219
220 // on a state change select the new item
221 const statechange = function(sp, key, newState) {
222 // it the state change is for this panel
223 if (stateid && (key === stateid) && newState) {
224 // get active item
225 var acard = me.getLayout().getActiveItem().itemId;
226 // get the itemid of the new value
227 var ncard = newState.value || me.firstItem;
228 if (ncard && (acard !== ncard)) {
229 // select the chosen item
230 menu.setSelection(root.findChild('id', ncard, true) || root.firstChild);
231 }
232 }
233 };
234
235 if (stateid) {
236 me.mon(me.sp, 'statechange', statechange);
237 }
238 },
239 });