]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/ACMEPluginEdit.js
notification: matcher: move match-severity fields to panel
[proxmox-widget-toolkit.git] / src / window / ACMEPluginEdit.js
1 Ext.define('Proxmox.window.ACMEPluginEdit', {
2 extend: 'Proxmox.window.Edit',
3 xtype: 'pmxACMEPluginEdit',
4 mixins: ['Proxmox.Mixin.CBind'],
5
6 //onlineHelp: 'sysadmin_certs_acme_plugins',
7
8 isAdd: true,
9 isCreate: false,
10
11 width: 550,
12
13 acmeUrl: undefined,
14
15 subject: 'ACME DNS Plugin',
16
17 cbindData: function(config) {
18 let me = this;
19 return {
20 challengeSchemaUrl: `/api2/json/${me.acmeUrl}/challenge-schema`,
21 };
22 },
23
24 items: [
25 {
26 xtype: 'inputpanel',
27 // we dynamically create fields from the given schema
28 // things we have to do here:
29 // * save which fields we created to remove them again
30 // * split the data from the generic 'data' field into the boxes
31 // * on deletion collect those values again
32 // * save the original values of the data field
33 createdFields: {},
34 createdInitially: false,
35 originalValues: {},
36 createSchemaFields: function(schema) {
37 let me = this;
38 // we know where to add because we define it right below
39 let container = me.down('container');
40 let datafield = me.down('field[name=data]');
41 let hintfield = me.down('field[name=hint]');
42 if (!me.createdInitially) {
43 [me.originalValues] = Proxmox.Utils.parseACMEPluginData(datafield.getValue());
44 }
45
46 // collect values from custom fields and add it to 'data'',
47 // then remove the custom fields
48 let data = [];
49 for (const [name, field] of Object.entries(me.createdFields)) {
50 let value = field.getValue();
51 if (value !== undefined && value !== null && value !== '') {
52 data.push(`${name}=${value}`);
53 }
54 container.remove(field);
55 }
56 let datavalue = datafield.getValue();
57 if (datavalue !== undefined && datavalue !== null && datavalue !== '') {
58 data.push(datavalue);
59 }
60 datafield.setValue(data.join('\n'));
61
62 me.createdFields = {};
63
64 if (typeof schema.fields !== 'object') {
65 schema.fields = {};
66 }
67 // create custom fields according to schema
68 let gotSchemaField = false;
69 for (const [name, definition] of Object
70 .entries(schema.fields)
71 .sort((a, b) => a[0].localeCompare(b[0]))
72 ) {
73 let xtype;
74 switch (definition.type) {
75 case 'string':
76 xtype = 'proxmoxtextfield';
77 break;
78 case 'integer':
79 xtype = 'proxmoxintegerfield';
80 break;
81 case 'number':
82 xtype = 'numberfield';
83 break;
84 default:
85 console.warn(`unknown type '${definition.type}'`);
86 xtype = 'proxmoxtextfield';
87 break;
88 }
89
90 let label = name;
91 if (typeof definition.name === "string") {
92 label = definition.name;
93 }
94
95 let field = Ext.create({
96 xtype,
97 name: `custom_${name}`,
98 fieldLabel: label,
99 width: '100%',
100 labelWidth: 150,
101 labelSeparator: '=',
102 emptyText: definition.default || '',
103 autoEl: definition.description ? {
104 tag: 'div',
105 'data-qtip': definition.description,
106 } : undefined,
107 });
108
109 me.createdFields[name] = field;
110 container.add(field);
111 gotSchemaField = true;
112 }
113 datafield.setHidden(gotSchemaField); // prefer schema-fields
114
115 if (schema.description) {
116 hintfield.setValue(schema.description);
117 hintfield.setHidden(false);
118 } else {
119 hintfield.setValue('');
120 hintfield.setHidden(true);
121 }
122
123 // parse data from field and set it to the custom ones
124 let extradata = [];
125 [data, extradata] = Proxmox.Utils.parseACMEPluginData(datafield.getValue());
126 for (const [key, value] of Object.entries(data)) {
127 if (me.createdFields[key]) {
128 me.createdFields[key].setValue(value);
129 me.createdFields[key].originalValue = me.originalValues[key];
130 me.createdFields[key].checkDirty();
131 } else {
132 extradata.push(`${key}=${value}`);
133 }
134 }
135 datafield.setValue(extradata.join('\n'));
136 if (!me.createdInitially) {
137 datafield.resetOriginalValue();
138 me.createdInitially = true; // save that we initially set that
139 }
140 },
141
142 onGetValues: function(values) {
143 let me = this;
144 let win = me.up('pmxACMEPluginEdit');
145 if (win.isCreate) {
146 values.id = values.plugin;
147 values.type = 'dns'; // the only one for now
148 }
149 delete values.plugin;
150
151 Proxmox.Utils.delete_if_default(values, 'validation-delay', '30', win.isCreate);
152
153 let data = '';
154 for (const [name, field] of Object.entries(me.createdFields)) {
155 let value = field.getValue();
156 if (value !== null && value !== undefined && value !== '') {
157 data += `${name}=${value}\n`;
158 }
159 delete values[`custom_${name}`];
160 }
161 values.data = Ext.util.Base64.encode(data + values.data);
162 return values;
163 },
164
165 items: [
166 {
167 xtype: 'pmxDisplayEditField',
168 cbind: {
169 editable: (get) => get('isCreate'),
170 submitValue: (get) => get('isCreate'),
171 },
172 editConfig: {
173 flex: 1,
174 xtype: 'proxmoxtextfield',
175 allowBlank: false,
176 },
177 name: 'plugin',
178 labelWidth: 150,
179 fieldLabel: gettext('Plugin ID'),
180 },
181 {
182 xtype: 'proxmoxintegerfield',
183 name: 'validation-delay',
184 labelWidth: 150,
185 fieldLabel: gettext('Validation Delay'),
186 emptyText: 30,
187 cbind: {
188 deleteEmpty: '{!isCreate}',
189 },
190 minValue: 0,
191 maxValue: 48*60*60,
192 },
193 {
194 xtype: 'pmxACMEApiSelector',
195 name: 'api',
196 labelWidth: 150,
197 cbind: {
198 url: '{challengeSchemaUrl}',
199 },
200 listeners: {
201 change: function(selector) {
202 let schema = selector.getSchema();
203 selector.up('inputpanel').createSchemaFields(schema);
204 },
205 },
206 },
207 {
208 xtype: 'textarea',
209 fieldLabel: gettext('API Data'),
210 labelWidth: 150,
211 name: 'data',
212 },
213 {
214 xtype: 'displayfield',
215 fieldLabel: gettext('Hint'),
216 labelWidth: 150,
217 name: 'hint',
218 hidden: true,
219 },
220 ],
221 },
222 ],
223
224 initComponent: function() {
225 var me = this;
226
227 if (!me.acmeUrl) {
228 throw "no acmeUrl given";
229 }
230
231 me.callParent();
232
233 if (!me.isCreate) {
234 me.load({
235 success: function(response, opts) {
236 me.setValues(response.result.data);
237 },
238 });
239 } else {
240 me.method = 'POST';
241 }
242 },
243 });