]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/node/ACME.js
fix #5093: ui: acme: expose custom directory option
[pve-manager.git] / www / manager6 / node / ACME.js
CommitLineData
488be4c2
DC
1Ext.define('PVE.node.ACMEAccountCreate', {
2 extend: 'Proxmox.window.Edit',
fc40915c 3 mixins: ['Proxmox.Mixin.CBind'],
488be4c2 4
04a8058e 5 width: 450,
488be4c2
DC
6 title: gettext('Register Account'),
7 isCreate: true,
8 method: 'POST',
9 submitText: gettext('Register'),
10 url: '/cluster/acme/account',
11 showTaskViewer: true,
fc40915c 12 defaultExists: false,
fdc4c229
FG
13 referenceHolder: true,
14 onlineHelp: "sysadmin_certs_acme_account",
15
16 viewModel: {
17 data: {
18 customDirectory: false,
19 },
20 },
488be4c2
DC
21
22 items: [
c0afd5cc
DC
23 {
24 xtype: 'proxmoxtextfield',
e023535e 25 fieldLabel: gettext('Account Name'),
c0afd5cc 26 name: 'name',
fc40915c
DC
27 cbind: {
28 emptyText: (get) => get('defaultExists') ? '' : 'default',
29 allowBlank: (get) => !get('defaultExists'),
30 },
c0afd5cc 31 },
04a8058e
DC
32 {
33 xtype: 'textfield',
34 name: 'contact',
35 vtype: 'email',
36 allowBlank: false,
f6710aac 37 fieldLabel: gettext('E-Mail'),
04a8058e 38 },
488be4c2
DC
39 {
40 xtype: 'proxmoxComboGrid',
fdc4c229
FG
41 notFoundIsValid: true,
42 isFormField: false,
488be4c2
DC
43 allowBlank: false,
44 valueField: 'url',
45 displayField: 'name',
46 fieldLabel: gettext('ACME Directory'),
47 store: {
fdc4c229
FG
48 listeners: {
49 'load': function() {
50 this.add({ name: gettext("Custom"), url: '' });
51 },
52 },
488be4c2
DC
53 autoLoad: true,
54 fields: ['name', 'url'],
55 idProperty: ['name'],
56 proxy: {
57 type: 'proxmox',
f6710aac 58 url: '/api2/json/cluster/acme/directories',
488be4c2 59 },
488be4c2
DC
60 },
61 listConfig: {
62 columns: [
63 {
64 header: gettext('Name'),
65 dataIndex: 'name',
f6710aac 66 flex: 1,
488be4c2
DC
67 },
68 {
69 header: gettext('URL'),
70 dataIndex: 'url',
f6710aac
TL
71 flex: 1,
72 },
73 ],
488be4c2
DC
74 },
75 listeners: {
76 change: function(combogrid, value) {
fdc4c229 77 let me = this;
488be4c2 78
fdc4c229
FG
79 let vm = me.up('window').getViewModel();
80 let dirField = me.up('window').lookupReference('directoryInput');
81 let tosButton = me.up('window').lookupReference('queryTos');
488be4c2 82
fdc4c229
FG
83 let isCustom = combogrid.getSelection().get('name') === gettext("Custom");
84 vm.set('customDirectory', isCustom);
488be4c2 85
fdc4c229
FG
86 dirField.setValue(value);
87
88 if (!isCustom) {
89 tosButton.click();
90 } else {
91 me.up('window').clearToSFields();
92 }
93 },
94 },
95 },
96 {
97 xtype: 'fieldcontainer',
98 layout: 'hbox',
99 fieldLabel: gettext('URL'),
100 bind: {
101 hidden: '{!customDirectory}',
102 },
103 items: [
104 {
105 xtype: 'proxmoxtextfield',
106 name: 'directory',
107 reference: 'directoryInput',
108 flex: 1,
109 allowBlank: false,
110 listeners: {
111 change: function(textbox, value) {
112 let me = this;
113 me.up('window').clearToSFields();
488be4c2 114 },
fdc4c229
FG
115 },
116 },
117 {
118 xtype: 'proxmoxButton',
119 margin: '0 0 0 5',
120 reference: 'queryTos',
121 text: gettext('Query URL'),
122 listeners: {
123 click: function(button) {
124 let me = this;
125
126 let w = me.up('window');
127 let disp = w.down('#tos_url_display');
128 let field = w.down('#tos_url');
129 let checkbox = w.down('#tos_checkbox');
130 let value = w.lookupReference('directoryInput').getValue();
131 w.clearToSFields();
132
133 if (!value) {
134 return;
7fb70c3b 135 } else {
fdc4c229 136 disp.setValue(gettext("Loading"));
7fb70c3b 137 }
fdc4c229
FG
138
139 Proxmox.Utils.API2Request({
140 url: '/cluster/acme/meta',
141 method: 'GET',
142 params: {
143 directory: value,
144 },
145 success: function(response, opt) {
146 if (response.result.data.termsOfService) {
147 field.setValue(response.result.data.termsOfService);
148 disp.setValue(response.result.data.termsOfService);
149 checkbox.setHidden(false);
150 } else {
151 checkbox.setValue(false);
152 disp.setValue("No terms of service agreement required");
153 }
154 },
155 failure: function(response, opt) {
156 disp.setValue(undefined);
157 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
158 },
159 });
488be4c2 160 },
fdc4c229 161 },
f6710aac 162 },
fdc4c229 163 ],
488be4c2
DC
164 },
165 {
166 xtype: 'displayfield',
167 itemId: 'tos_url_display',
488be4c2 168 renderer: PVE.Utils.render_optional_url,
f6710aac 169 name: 'tos_url_display',
488be4c2
DC
170 },
171 {
172 xtype: 'hidden',
173 itemId: 'tos_url',
f6710aac 174 name: 'tos_url',
488be4c2
DC
175 },
176 {
177 xtype: 'proxmoxcheckbox',
178 itemId: 'tos_checkbox',
04a8058e 179 boxLabel: gettext('Accept TOS'),
488be4c2
DC
180 submitValue: false,
181 validateValue: function(value) {
182 if (value && this.checked) {
183 return true;
184 }
185 return false;
f6710aac 186 },
488be4c2 187 },
f6710aac 188 ],
488be4c2 189
fdc4c229
FG
190 clearToSFields: function() {
191 let me = this;
192
193 let disp = me.down('#tos_url_display');
194 let field = me.down('#tos_url');
195 let checkbox = me.down('#tos_checkbox');
196
197 disp.setValue("Terms of service not fetched yet");
198 field.setValue(undefined);
199 checkbox.setValue(undefined);
200 checkbox.setHidden(true);
201 },
202
488be4c2
DC
203});
204
205Ext.define('PVE.node.ACMEAccountView', {
206 extend: 'Proxmox.window.Edit',
207
208 width: 600,
209 fieldDefaults: {
f6710aac 210 labelWidth: 140,
488be4c2
DC
211 },
212
213 title: gettext('Account'),
214
215 items: [
216 {
217 xtype: 'displayfield',
218 fieldLabel: gettext('E-Mail'),
f6710aac 219 name: 'email',
488be4c2
DC
220 },
221 {
222 xtype: 'displayfield',
223 fieldLabel: gettext('Created'),
f6710aac 224 name: 'createdAt',
488be4c2
DC
225 },
226 {
227 xtype: 'displayfield',
228 fieldLabel: gettext('Status'),
f6710aac 229 name: 'status',
488be4c2
DC
230 },
231 {
232 xtype: 'displayfield',
233 fieldLabel: gettext('Directory'),
234 renderer: PVE.Utils.render_optional_url,
f6710aac 235 name: 'directory',
488be4c2
DC
236 },
237 {
238 xtype: 'displayfield',
239 fieldLabel: gettext('Terms of Services'),
240 renderer: PVE.Utils.render_optional_url,
f6710aac
TL
241 name: 'tos',
242 },
488be4c2
DC
243 ],
244
245 initComponent: function() {
246 var me = this;
247
248 if (!me.accountname) {
249 throw "no account name defined";
250 }
251
252 me.url = '/cluster/acme/account/' + me.accountname;
253
254 me.callParent();
255
256 // hide OK/Reset button, because we just want to show data
257 me.down('toolbar[dock=bottom]').setVisible(false);
258
259 me.load({
260 success: function(response) {
261 var data = response.result.data;
262 data.email = data.account.contact[0];
263 data.createdAt = data.account.createdAt;
264 data.status = data.account.status;
265 me.setValues(data);
f6710aac 266 },
488be4c2 267 });
f6710aac 268 },
488be4c2
DC
269});
270
8e49a93f
DC
271Ext.define('PVE.node.ACMEDomainEdit', {
272 extend: 'Proxmox.window.Edit',
273 alias: 'widget.pveACMEDomainEdit',
274
275 subject: gettext('Domain'),
276 isCreate: false,
3c6b4c80 277 width: 450,
eff602d8 278 onlineHelp: 'sysadmin_certificate_management',
8e49a93f
DC
279
280 items: [
281 {
282 xtype: 'inputpanel',
283 onGetValues: function(values) {
284 let me = this;
285 let win = me.up('pveACMEDomainEdit');
286 let nodeconfig = win.nodeconfig;
287 let olddomain = win.domain || {};
288
289 let params = {
290 digest: nodeconfig.digest,
291 };
292
293 let configkey = olddomain.configkey;
6ac64c3a 294 let acmeObj = PVE.Parser.parseACME(nodeconfig.acme);
8e49a93f
DC
295
296 if (values.type === 'dns') {
297 if (!olddomain.configkey || olddomain.configkey === 'acme') {
298 // look for first free slot
299 for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
300 if (nodeconfig[`acmedomain${i}`] === undefined) {
301 configkey = `acmedomain${i}`;
302 break;
303 }
304 }
305 if (olddomain.domain) {
306 // we have to remove the domain from the acme domainlist
307 PVE.Utils.remove_domain_from_acme(acmeObj, olddomain.domain);
308 params.acme = PVE.Parser.printACME(acmeObj);
309 }
310 }
311
312 delete values.type;
313 params[configkey] = PVE.Parser.printPropertyString(values, 'domain');
314 } else {
315 if (olddomain.configkey && olddomain.configkey !== 'acme') {
316 // delete the old dns entry
317 params.delete = [olddomain.configkey];
318 }
319
320 // add new, remove old and make entries unique
321 PVE.Utils.add_domain_to_acme(acmeObj, values.domain);
322 PVE.Utils.remove_domain_from_acme(acmeObj, olddomain.domain);
323 params.acme = PVE.Parser.printACME(acmeObj);
324 }
325
326 return params;
327 },
328 items: [
329 {
330 xtype: 'proxmoxKVComboBox',
331 name: 'type',
3c6b4c80 332 fieldLabel: gettext('Challenge Type'),
8e49a93f 333 allowBlank: false,
3c6b4c80 334 value: 'standalone',
8e49a93f 335 comboItems: [
9c164224 336 ['standalone', 'HTTP'],
8e49a93f
DC
337 ['dns', 'DNS'],
338 ],
339 validator: function(value) {
340 let me = this;
341 let win = me.up('pveACMEDomainEdit');
342 let oldconfigkey = win.domain ? win.domain.configkey : undefined;
343 let val = me.getValue();
344 if (val === 'dns' && (!oldconfigkey || oldconfigkey === 'acme')) {
345 // we have to check if there is a 'acmedomain' slot left
346 let found = false;
347 for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
348 if (!win.nodeconfig[`acmedomain${i}`]) {
349 found = true;
350 }
351 }
352 if (!found) {
353 return gettext('Only 5 Domains with type DNS can be configured');
354 }
355 }
356
357 return true;
358 },
359 listeners: {
360 change: function(cb, value) {
361 let me = this;
362 let view = me.up('pveACMEDomainEdit');
a94b71fb
TL
363 let pluginField = view.down('field[name=plugin]');
364 pluginField.setDisabled(value !== 'dns');
365 pluginField.setHidden(value !== 'dns');
8e49a93f
DC
366 },
367 },
368 },
369 {
370 xtype: 'hidden',
371 name: 'alias',
372 },
8e49a93f
DC
373 {
374 xtype: 'pveACMEPluginSelector',
375 name: 'plugin',
376 disabled: true,
a94b71fb 377 hidden: true,
8e49a93f
DC
378 allowBlank: false,
379 },
a94b71fb
TL
380 {
381 xtype: 'proxmoxtextfield',
382 name: 'domain',
383 allowBlank: false,
384 vtype: 'DnsName',
385 value: '',
386 fieldLabel: gettext('Domain'),
387 },
8e49a93f
DC
388 ],
389 },
390 ],
391
392 initComponent: function() {
393 let me = this;
394
395 if (!me.nodename) {
396 throw 'no nodename given';
397 }
398
399 if (!me.nodeconfig) {
400 throw 'no nodeconfig given';
401 }
402
403 me.isCreate = !me.domain;
8b779b4a
TL
404 if (me.isCreate) {
405 me.domain = `${me.nodename}.`; // TODO: FQDN of node
406 }
8e49a93f
DC
407
408 me.url = `/api2/extjs/nodes/${me.nodename}/config`;
409
410 me.callParent();
411
412 if (!me.isCreate) {
413 me.setValues(me.domain);
8b779b4a
TL
414 } else {
415 me.setValues({ domain: me.domain });
8e49a93f
DC
416 }
417 },
418});
419
fd254233
DC
420Ext.define('pve-acme-domains', {
421 extend: 'Ext.data.Model',
422 fields: ['domain', 'type', 'alias', 'plugin', 'configkey'],
423 idProperty: 'domain',
424});
425
488be4c2 426Ext.define('PVE.node.ACME', {
fd254233
DC
427 extend: 'Ext.grid.Panel',
428 alias: 'widget.pveACMEView',
488be4c2
DC
429
430 margin: '10 0 0 0',
431 title: 'ACME',
432
e666f688
DC
433 emptyText: gettext('No Domains configured'),
434
fd254233
DC
435 viewModel: {
436 data: {
1580b605 437 domaincount: 0,
3071cc5b
DC
438 account: undefined, // the account we display
439 configaccount: undefined, // the account set in the config
fd254233 440 accountEditable: false,
a8b6a80a 441 accountsAvailable: false,
fd254233
DC
442 },
443
444 formulas: {
1580b605 445 canOrder: (get) => !!get('account') && get('domaincount') > 0,
80bd3209 446 editBtnIcon: (get) => 'fa black fa-' + (get('accountEditable') ? 'check' : 'pencil'),
8fc2d938 447 editBtnText: (get) => get('accountEditable') ? gettext('Apply') : gettext('Edit'),
a8b6a80a
TL
448 accountTextHidden: (get) => get('accountEditable') || !get('accountsAvailable'),
449 accountValueHidden: (get) => !get('accountEditable') || !get('accountsAvailable'),
fd254233
DC
450 },
451 },
452
453 controller: {
454 xclass: 'Ext.app.ViewController',
455
a8b6a80a 456 init: function(view) {
a8b6a80a
TL
457 let accountSelector = this.lookup('accountselector');
458 accountSelector.store.on('load', this.onAccountsLoad, this);
459 },
460
461 onAccountsLoad: function(store, records, success) {
80bd3209
DC
462 let me = this;
463 let vm = me.getViewModel();
3071cc5b 464 let configaccount = vm.get('configaccount');
a8b6a80a 465 vm.set('accountsAvailable', records.length > 0);
80bd3209
DC
466 if (me.autoChangeAccount && records.length > 0) {
467 me.changeAccount(records[0].data.name, () => {
31c9edc8 468 vm.set('accountEditable', false);
80bd3209 469 me.reload();
31c9edc8
TL
470 });
471 me.autoChangeAccount = false;
3071cc5b
DC
472 } else if (configaccount) {
473 if (store.findExact('name', configaccount) !== -1) {
474 vm.set('account', configaccount);
475 } else {
476 vm.set('account', null);
477 }
31c9edc8 478 }
a8b6a80a
TL
479 },
480
fd254233
DC
481 addDomain: function() {
482 let me = this;
483 let view = me.getView();
484
485 Ext.create('PVE.node.ACMEDomainEdit', {
486 nodename: view.nodename,
487 nodeconfig: view.nodeconfig,
488 apiCallDone: function() {
489 me.reload();
490 },
491 }).show();
492 },
493
494 editDomain: function() {
495 let me = this;
496 let view = me.getView();
497
498 let selection = view.getSelection();
499 if (selection.length < 1) return;
500
501 Ext.create('PVE.node.ACMEDomainEdit', {
502 nodename: view.nodename,
503 nodeconfig: view.nodeconfig,
504 domain: selection[0].data,
505 apiCallDone: function() {
506 me.reload();
507 },
508 }).show();
509 },
510
511 removeDomain: function() {
512 let me = this;
513 let view = me.getView();
514 let selection = view.getSelection();
515 if (selection.length < 1) return;
516
517 let rec = selection[0].data;
518 let params = {};
519 if (rec.configkey !== 'acme') {
520 params.delete = rec.configkey;
521 } else {
522 let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
523 PVE.Utils.remove_domain_from_acme(acme, rec.domain);
524 params.acme = PVE.Parser.printACME(acme);
525 }
526
527 Proxmox.Utils.API2Request({
528 method: 'PUT',
529 url: `/nodes/${view.nodename}/config`,
530 params,
531 success: function(response, opt) {
532 me.reload();
533 },
534 failure: function(response, opt) {
535 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
536 },
537 });
538 },
539
540 toggleEditAccount: function() {
541 let me = this;
542 let vm = me.getViewModel();
543 let editable = vm.get('accountEditable');
544 if (editable) {
545 me.changeAccount(vm.get('account'), function() {
546 vm.set('accountEditable', false);
547 me.reload();
548 });
549 } else {
550 vm.set('accountEditable', true);
551 }
552 },
553
554 changeAccount: function(account, callback) {
555 let me = this;
556 let view = me.getView();
557 let params = {};
558
559 let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
560 acme.account = account;
561 params.acme = PVE.Parser.printACME(acme);
562
563 Proxmox.Utils.API2Request({
564 method: 'PUT',
565 waitMsgTarget: view,
566 url: `/nodes/${view.nodename}/config`,
567 params,
568 success: function(response, opt) {
569 if (Ext.isFunction(callback)) {
570 callback();
571 }
572 },
573 failure: function(response, opt) {
574 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
575 },
576 });
577 },
578
579 order: function() {
580 let me = this;
581 let view = me.getView();
582
583 Proxmox.Utils.API2Request({
584 method: 'POST',
585 params: {
586 force: 1,
587 },
588 url: `/nodes/${view.nodename}/certificates/acme/certificate`,
589 success: function(response, opt) {
590 Ext.create('Proxmox.window.TaskViewer', {
591 upid: response.result.data,
592 taskDone: function(success) {
593 me.orderFinished(success);
594 },
595 }).show();
596 },
597 failure: function(response, opt) {
598 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
599 },
600 });
601 },
602
603 orderFinished: function(success) {
604 if (!success) return;
72cfb3d4
FS
605 // reload only if the Web UI is open on the same node that the cert was ordered for
606 if (this.getView().nodename !== Proxmox.NodeName) {
607 return;
608 }
fd254233
DC
609 var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
610 Ext.getBody().mask(txt, ['pve-static-mask']);
611 // reload after 10 seconds automatically
612 Ext.defer(function() {
613 window.location.reload(true);
614 }, 10000);
615 },
616
617 reload: function() {
618 let me = this;
619 let view = me.getView();
620 view.rstore.load();
621 },
622
31c9edc8
TL
623 addAccount: function() {
624 let me = this;
625 Ext.create('PVE.node.ACMEAccountCreate', {
626 autoShow: true,
627 taskDone: function() {
628 me.reload();
629 let accountSelector = me.lookup('accountselector');
630 me.autoChangeAccount = true;
631 accountSelector.store.load();
632 },
633 });
fd254233
DC
634 },
635 },
636
488be4c2
DC
637 tbar: [
638 {
fd254233
DC
639 xtype: 'proxmoxButton',
640 text: gettext('Add'),
641 handler: 'addDomain',
642 selModel: false,
643 },
644 {
645 xtype: 'proxmoxButton',
646 text: gettext('Edit'),
647 disabled: true,
648 handler: 'editDomain',
649 },
650 {
651 xtype: 'proxmoxStdRemoveButton',
652 handler: 'removeDomain',
488be4c2 653 },
fd254233 654 '-',
488be4c2
DC
655 {
656 xtype: 'button',
fd254233 657 reference: 'order',
a8b6a80a 658 text: gettext('Order Certificates Now'),
31c9edc8 659 bind: {
1580b605 660 disabled: '{!canOrder}',
31c9edc8 661 },
fd254233
DC
662 handler: 'order',
663 },
664 '-',
665 {
666 xtype: 'displayfield',
a8b6a80a
TL
667 value: gettext('Using Account') + ':',
668 bind: {
669 hidden: '{!accountsAvailable}',
670 },
fd254233
DC
671 },
672 {
673 xtype: 'displayfield',
674 reference: 'accounttext',
3071cc5b 675 renderer: (val) => val || Proxmox.Utils.NoneText,
fd254233
DC
676 bind: {
677 value: '{account}',
a8b6a80a 678 hidden: '{accountTextHidden}',
fd254233
DC
679 },
680 },
681 {
682 xtype: 'pveACMEAccountSelector',
683 hidden: true,
684 reference: 'accountselector',
685 bind: {
686 value: '{account}',
a8b6a80a 687 hidden: '{accountValueHidden}',
fd254233 688 },
488be4c2
DC
689 },
690 {
691 xtype: 'button',
fd254233 692 iconCls: 'fa black fa-pencil',
fd254233 693 bind: {
a8b6a80a 694 iconCls: '{editBtnIcon}',
8fc2d938 695 text: '{editBtnText}',
a8b6a80a 696 hidden: '{!accountsAvailable}',
fd254233
DC
697 },
698 handler: 'toggleEditAccount',
488be4c2 699 },
a8b6a80a
TL
700 {
701 xtype: 'displayfield',
702 value: gettext('No Account available.'),
703 bind: {
704 hidden: '{accountsAvailable}',
705 },
706 },
488be4c2
DC
707 {
708 xtype: 'button',
fd254233
DC
709 hidden: true,
710 reference: 'accountlink',
31c9edc8 711 text: gettext('Add ACME Account'),
a8b6a80a
TL
712 bind: {
713 hidden: '{accountsAvailable}',
714 },
31c9edc8 715 handler: 'addAccount',
80bd3209 716 },
488be4c2
DC
717 ],
718
fd254233
DC
719 updateStore: function(store, records, success) {
720 let me = this;
721 let data = [];
722 let rec;
723 if (success && records.length > 0) {
724 rec = records[0];
725 } else {
726 rec = {
80bd3209 727 data: {},
fd254233 728 };
488be4c2 729 }
488be4c2 730
fd254233 731 me.nodeconfig = rec.data; // save nodeconfig for updates
488be4c2 732
fd254233 733 let account = 'default';
488be4c2 734
fd254233
DC
735 if (rec.data.acme) {
736 let obj = PVE.Parser.parseACME(rec.data.acme);
737 (obj.domains || []).forEach(domain => {
738 if (domain === '') return;
739 let record = {
740 domain,
741 type: 'standalone',
742 configkey: 'acme',
743 };
744 data.push(record);
745 });
488be4c2 746
fd254233
DC
747 if (obj.account) {
748 account = obj.account;
749 }
750 }
488be4c2 751
fd254233
DC
752 let vm = me.getViewModel();
753 let oldaccount = vm.get('account');
754
755 // account changed, and we do not edit currently, load again to verify
756 if (oldaccount !== account && !vm.get('accountEditable')) {
3071cc5b
DC
757 vm.set('configaccount', account);
758 me.lookup('accountselector').store.load();
fd254233 759 }
488be4c2 760
fd254233
DC
761 for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
762 let acmedomain = rec.data[`acmedomain${i}`];
763 if (!acmedomain) continue;
488be4c2 764
fd254233
DC
765 let record = PVE.Parser.parsePropertyString(acmedomain, 'domain');
766 record.type = 'dns';
767 record.configkey = `acmedomain${i}`;
768 data.push(record);
769 }
770
1580b605 771 vm.set('domaincount', data.length);
fd254233 772 me.store.loadData(data, false);
488be4c2
DC
773 },
774
775 listeners: {
fd254233 776 itemdblclick: 'editDomain',
488be4c2
DC
777 },
778
fd254233
DC
779 columns: [
780 {
781 dataIndex: 'domain',
3c6b4c80 782 flex: 5,
fd254233
DC
783 text: gettext('Domain'),
784 },
785 {
786 dataIndex: 'type',
3c6b4c80 787 flex: 1,
fd254233
DC
788 text: gettext('Type'),
789 },
790 {
791 dataIndex: 'plugin',
3c6b4c80 792 flex: 1,
fd254233
DC
793 text: gettext('Plugin'),
794 },
795 ],
488be4c2
DC
796
797 initComponent: function() {
798 var me = this;
799
800 if (!me.nodename) {
801 throw "no nodename given";
802 }
803
fd254233 804 me.rstore = Ext.create('Proxmox.data.UpdateStore', {
1b90cfc6 805 interval: 10 * 1000,
fd254233
DC
806 autoStart: true,
807 storeid: `pve-node-domains-${me.nodename}`,
808 proxy: {
809 type: 'proxmox',
810 url: `/api2/json/nodes/${me.nodename}/config`,
811 },
812 });
813
814 me.store = Ext.create('Ext.data.Store', {
815 model: 'pve-acme-domains',
816 sorters: 'domain',
817 });
488be4c2
DC
818
819 me.callParent();
fd254233
DC
820 me.mon(me.rstore, 'load', 'updateStore', me);
821 Proxmox.Utils.monStoreErrors(me, me.rstore);
1f249769 822 me.on('destroy', me.rstore.stopUpdate, me.rstore);
fd254233 823 },
488be4c2 824});