]> git.proxmox.com Git - pve-manager-legacy.git/commitdiff
ui: add ACMEPluginEdit window
authorDominik Csapak <d.csapak@proxmox.com>
Tue, 5 May 2020 12:38:17 +0000 (14:38 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 5 May 2020 17:23:04 +0000 (19:23 +0200)
this is a rather complex edit window, because we dynamically create form
fields according to the schema we get from the api

to do this properly we have to handle a few things:
* we have to properly set the values on edit
* we have to properly track the original values
* we have to merge and split with/from the generic 'data' field
  (so that if a plugin has some extra fields that we did not include in
  the schema the user can still enter them)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
www/manager6/Makefile
www/manager6/Parser.js
www/manager6/dc/ACMEPluginEdit.js [new file with mode: 0644]

index 4be22b973ab4eb2d4c4c82d5c170eb399598add6..cca823ea3f39ed62bcb0c823543d5edd2ea54c44 100644 (file)
@@ -217,6 +217,7 @@ JSSRC=                                                      \
        ha/GroupEdit.js                                 \
        ha/Groups.js                                    \
        ha/Fencing.js                                   \
+       dc/ACMEPluginEdit.js                            \
        dc/Summary.js                                   \
        grid/Replication.js                             \
        dc/Health.js                                    \
index 43cc4f5f9c77cffd09e86ad09dc2a977c500e3d2..4cecb3e1d64325eb7ecdf191d2f74287b8a40d31 100644 (file)
@@ -696,5 +696,20 @@ Ext.define('PVE.Parser', { statics: {
            };
        }
        return null;
-    }
+    },
+
+    parseACMEPluginData: function(data) {
+       let res = {};
+       let extradata = [];
+       data.split('\n').forEach((line) => {
+           // capture everything after the first = as value
+           let [key, value] = line.split(/=(.+)/);
+           if (value !== undefined) {
+               res[key] = value;
+           } else {
+               extradata.push(line);
+           }
+       });
+       return [res, extradata];
+    },
 }});
diff --git a/www/manager6/dc/ACMEPluginEdit.js b/www/manager6/dc/ACMEPluginEdit.js
new file mode 100644 (file)
index 0000000..fd07017
--- /dev/null
@@ -0,0 +1,190 @@
+Ext.define('PVE.dc.ACMEPluginEditor', {
+    extend: 'Proxmox.window.Edit',
+    xtype: 'pveACMEPluginEditor',
+    mixins: ['Proxmox.Mixin.CBind'],
+
+    isAdd: true,
+    isCreate: false,
+
+    width: 400,
+    url: '/cluster/acme/plugins/',
+
+    subject: gettext('Plugin'),
+    items: [
+       {
+           xtype: 'inputpanel',
+           // we dynamically create fields from the given schema
+           // things we have to do here:
+           // * save which fields we created to remove them again
+           // * split the data from the generic 'data' field into the boxes
+           // * on deletion collect those values again
+           // * save the original values of the data field
+           createdFields: {},
+           createdInitially: false,
+           originalValues: {},
+           createSchemaFields: function(schema) {
+               let me = this;
+               // we know where to add because we define it right below
+               let container = me.down('container');
+               let datafield = me.down('field[name=data]');
+               if (!me.createdInitially) {
+                   [me.originalValues] = PVE.Parser.parseACMEPluginData(datafield.getValue());
+               }
+
+               // collect values from custom fields and add it to 'data'',
+               // then remove the custom fields
+               let data = [];
+               for (const [name, field] of Object.entries(me.createdFields)) {
+                   let value = field.getValue();
+                   if (value !== undefined && value !== null && value !== '') {
+                       data.push(`${name}=${value}`);
+                   }
+                   container.remove(field);
+               }
+               let datavalue = datafield.getValue();
+               if (datavalue !== undefined && datavalue !== null && datavalue !== '') {
+                   data.push(datavalue);
+               }
+               datafield.setValue(data.join('\n'));
+
+               me.createdFields = {};
+
+               // create custom fields according to schema
+               for (const [name, definition] of Object.entries(schema)) {
+                   let xtype;
+                   switch (definition.type) {
+                       case 'string':
+                           xtype = 'proxmoxtextfield';
+                           break;
+                       case 'integer':
+                           xtype = 'proxmoxintegerfield';
+                           break;
+                       case 'number':
+                           xtype = 'numberfield';
+                           break;
+                       default:
+                           console.warn(`unknown type '${definition.type}'`);
+                           xtype = 'proxmoxtextfield';
+                           break;
+                   }
+
+                   let field = Ext.create({
+                       xtype,
+                       name: `custom_${name}`,
+                       fieldLabel: name,
+                       width: '100%',
+                       labelWidth: 120,
+                       autoEl: definition.description ? {
+                           tag: 'div',
+                           'data-qtip': definition.description,
+                       } : undefined,
+                   });
+
+                   me.createdFields[name] = field;
+                   container.add(field);
+               }
+
+               // parse data from field and set it to the custom ones
+               let extradata = [];
+               [data, extradata] = PVE.Parser.parseACMEPluginData(datafield.getValue());
+               for (const [key, value] of Object.entries(data)) {
+                   if (me.createdFields[key]) {
+                       me.createdFields[key].setValue(value);
+                       me.createdFields[key].originalValue = me.originalValues[key];
+                   } else {
+                       extradata.push(`${key}=${value}`);
+                   }
+               }
+               datafield.setValue(extradata.join('\n'));
+               if (!me.createdInitially) {
+                   datafield.resetOriginalValue();
+                   me.createdInitially = true; // save that we initally set that
+               }
+           },
+           onGetValues: function(values) {
+               let me = this;
+               let win = me.up('pveACMEPluginEditor');
+               if (win.isCreate) {
+                   values.id = values.plugin;
+                   values.type = 'dns'; // the only one for now
+               }
+               delete values.plugin;
+
+               PVE.Utils.delete_if_default(values, 'validation-delay', '30', win.isCreate);
+
+               let data = '';
+               for (const [name, field] of Object.entries(me.createdFields)) {
+                   let value = field.getValue();
+                   if (value !== null && value !== undefined && value !== '') {
+                       data += `${name}=${value}\n`;
+                   }
+                   delete values[`custom_${name}`];
+               }
+               values.data = Ext.util.Base64.encode(data + values.data);
+               return values;
+           },
+           items: [
+               {
+                   xtype: 'pmxDisplayEditField',
+                   cbind: {
+                       editable: (get) => get('isCreate'),
+                       submitValue: (get) => get('isCreate'),
+                   },
+                   editConfig: {
+                       flex: 1,
+                       xtype: 'proxmoxtextfield',
+                       allowBlank: false,
+                   },
+                   name: 'plugin',
+                   labelWidth: 120,
+                   fieldLabel: gettext('Plugin'),
+               },
+               {
+                   xtype: 'proxmoxintegerfield',
+                   name: 'validation-delay',
+                   labelWidth: 120,
+                   fieldLabel: gettext('Validation Delay'),
+                   emptyText: 30,
+                   cbind: {
+                       deleteEmpty: '{!isCreate}',
+                   },
+                   minValue: 0,
+                   maxValue: 172800,
+               },
+               {
+                   xtype: 'pveACMEApiSelector',
+                   name: 'api',
+                   labelWidth: 120,
+                   listeners: {
+                       change: function(selector) {
+                           let schema = selector.getSchema();
+                           selector.up('inputpanel').createSchemaFields(schema);
+                       },
+                   },
+               },
+               {
+                   fieldLabel: gettext('API Data'),
+                   labelWidth: 120,
+                   xtype: 'textarea',
+                   name: 'data',
+               },
+           ],
+       },
+    ],
+
+    initComponent: function() {
+       var me = this;
+
+       me.callParent();
+
+       if (!me.isCreate) {
+           me.load({
+               success: function(response, opts) {
+                   me.setValues(response.result.data);
+               },
+           });
+       } else {
+           me.method = 'POST';
+       }
+    },
+});