From 4fbc5bb6bc4265e5c91d2c58eb45d282b4d4f789 Mon Sep 17 00:00:00 2001 From: nh758 <7259@pm.me> Date: Thu, 24 Apr 2025 13:51:24 +0700 Subject: [PATCH 1/6] add properties for api process task --- .../Designer/properties/PropertyManager.js | 1 + .../process/ABProcessTaskService.js | 5 + .../process/ABProcessTaskServiceApi.js | 244 ++++++++++++++++++ styles/Designer.css | 8 +- 4 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js diff --git a/src/rootPages/Designer/properties/PropertyManager.js b/src/rootPages/Designer/properties/PropertyManager.js index 8527be89..f59651b7 100644 --- a/src/rootPages/Designer/properties/PropertyManager.js +++ b/src/rootPages/Designer/properties/PropertyManager.js @@ -50,6 +50,7 @@ export default function (AB) { require("./process/ABProcessTaskServiceAccountingFPClose.js"), require("./process/ABProcessTaskServiceAccountingFPYearClose.js"), require("./process/ABProcessTaskServiceAccountingJEArchive.js"), + require("./process/ABProcessTaskServiceApi.js"), require("./process/ABProcessTaskServiceCalculate.js"), require("./process/ABProcessTaskServiceGetResetPasswordUrl.js"), require("./process/ABProcessTaskServiceInsertRecord.js"), diff --git a/src/rootPages/Designer/properties/process/ABProcessTaskService.js b/src/rootPages/Designer/properties/process/ABProcessTaskService.js index 39b38905..9d0eefc0 100644 --- a/src/rootPages/Designer/properties/process/ABProcessTaskService.js +++ b/src/rootPages/Designer/properties/process/ABProcessTaskService.js @@ -73,6 +73,11 @@ export default function (AB) { this.switchTo("AccountingJEArchive"); }, }, + { + view: "button", + label: L("Api Request"), + click: () => this.switchTo("Api"), + }, { view: "button", label: L("Query Task"), diff --git a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js new file mode 100644 index 00000000..7cae8eeb --- /dev/null +++ b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js @@ -0,0 +1,244 @@ +/* + * UIProcessTaskServiceApi + * + * Display the form for entering the properties for a new + * ServiceApi Task + * + * @return {ClassUI} The Class Definition for this UI widget. + */ +import UI_Class from "../../ui_class"; + +export default function(AB) { + const UIClass = UI_Class(AB); + const L = UIClass.L(); + const uiConfig = AB.Config.uiSettings(); + + class UIProcessServiceApi extends UIClass { + constructor() { + super("properties_process_service_api", { + form: "", + headers: "", + suggest: "", + }); + + this.element = null; + // A webix datacollection - used to load process data into our mention suggest + this.suggestData = new AB.Webix.DataCollection({}); + } + + static get key() { + return "Api"; + } + + ui() { + const ids = this.ids; + return { + rows: [ + { + id: ids.form, + view: "form", + elementsConfig: { + labelWidth: uiConfig.labelWidthLarge, + }, + elements: [ + { + view: "text", + name: "name", + label: L("Name"), + }, + { + view: "text", + name: "url", + label: L("Url"), + }, + { + view: "combo", + name: "method", + label: L("Method"), + options: ["GET", "POST", "PUT", "DELETE"], + }, + { + cols: [ + { + view: "label", + label: L("Headers"), + autowidth: true, + }, + { + view: "icon", + icon: "fa fa-plus", + width: 50, + on: { onItemClick: () => this.addHeader() }, + }, + {}, + ], + }, + { id: ids.headers, rows: [] }, + { + view: "texthighlight", + name: "body", + height: 200, + label: L("Request Body"), + labelPosition: "top", + type: "textarea", + placeholder: "use ${...} to add process data", + css: "monospace", + highlight: (text) => { + text = text.replaceAll( + " ", + `·` + ); + text = text.replace(/\${([^}]*)}/g, (m, c) => { + const data = this.suggestData.find( + { key: c }, + true + ); + const centerPad = (str, target, pad, right) => { + if (str.length === target) return str; + if (right) + return centerPad( + `${str}${pad}`, + target, + pad + ); + else + return centerPad( + `${pad}${str}`, + target, + pad, + true + ); + }; + if (data) { + // We save the key in the text, but display the + // label. Need to keep the length the same or + // the cursor get's messed up. + const { key, value } = data; + const diff = key.length - value.length; + let val = data.value; + if (diff > 0) { + val = centerPad(val, key.length, "─", true); + } else if (diff < 0) { + val = `...${val.slice(diff + 3)}`; + } + return `\${${val}}`; + } + return `${m}`; + }); + return text; + }, + suggest: { + id: ids.suggest, + view: "mentionsuggest", + symbol: "$", + template: "{#key#}", + data: this.suggestData, + }, + }, + { + view: "switch", + name: "responseJson", + value: 1, + label: L("Response as"), + onLabel: L("JSON"), + offLabel: L("Text"), + }, + ], + }, + ], + }; + } + + populate(element) { + const { name, url, method, body, responseJson } = element; + $$(this.ids.form).setValues({ name, url, method, body, responseJson }); + element.headers?.forEach?.((header) => { + this.addHeader(header); + }); + const processData = element.process.processDataFields(element) ?? []; + this.suggestData.parse( + processData + .filter((i) => !!i) + .map?.((i) => ({ value: i.label, key: i.key })) + ); + } + + values() { + const values = {}; + let form = {}; + try { + form = $$(this.ids.form).getValues(); + } catch (e) { + console.log("caught", e); + } + Object.keys(form).forEach((key) => { + key.includes("headers") + ? nestValue(key, form[key], values) + : (values[key] = form[key]); + }); + // Convert headers to an array + if (values.headers) { + const headers = []; + Object.keys(values.headers).forEach((key) => + headers.push(values.headers[key]) + ); + values.headers = headers; + } + return values; + } + + addHeader(header = {}) { + const uid = AB.Webix.uid(); //this is unique to the page + const row = { + id: uid, + cols: [ + { + view: "text", + name: `headers.${uid}.key`, + placeholder: "header", + value: header.key, + }, + { + view: "text", + name: `headers.${uid}.value`, + placeholder: "value", + value: header.value, + gravity: 2, + }, + { + view: "icon", + icon: "wxi-trash", + width: "50", + on: { + onItemClick: () => $$(this.ids.headers).removeView(uid), + }, + }, + ], + }; + $$(this.ids.headers).addView(row); + } + } + + return UIProcessServiceApi; +} + +/** + * Recursively nests a value within an object based on a dot-separated key. + * + * @param {string} key - The dot-separated key specifying the nested path. + * @param {*} value - The value to assign at the final nested level. + * @param {object} [obj={}] - The object to modify (or a new object if not provided). + * @returns {object} The modified object with the nested value. + */ +function nestValue(key, value, obj = {}) { + const [firstKey, ...remainingKeys] = key.split("."); + + if (remainingKeys.length === 0) { + obj[firstKey] = value; + } else { + obj[firstKey] = obj[firstKey] ?? {}; + nestValue(remainingKeys.join("."), value, obj[firstKey]); + } + + return obj; +} diff --git a/styles/Designer.css b/styles/Designer.css index b6ebbd80..581d1ffc 100644 --- a/styles/Designer.css +++ b/styles/Designer.css @@ -264,4 +264,10 @@ .webix_tree_leaves { display: block !important; -} \ No newline at end of file +} + +.monospace > div > textarea, +.monospace > div > div > .webix_text_highlight_value { + word-break: break-all; + font-family: monospace; +} From 428e17724a49914c5c3d3848e167ef4770bf9404 Mon Sep 17 00:00:00 2001 From: nh758 <7259@pm.me> Date: Thu, 24 Apr 2025 13:52:05 +0700 Subject: [PATCH 2/6] fix saving process task name --- src/rootPages/Designer/ui_work_process_workspace_model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rootPages/Designer/ui_work_process_workspace_model.js b/src/rootPages/Designer/ui_work_process_workspace_model.js index 77c3c0ba..1f3b598a 100644 --- a/src/rootPages/Designer/ui_work_process_workspace_model.js +++ b/src/rootPages/Designer/ui_work_process_workspace_model.js @@ -882,7 +882,7 @@ export default function (AB) { Object.keys(values).forEach((k) => { objVals[k] = values[k]; }); - if (!thisObj.name) objVals.name = values.label; + if (!objVals.name) objVals.name = values.label; thisObj.fromValues(objVals); thisObj.warningsEval(); // resets the warnings From 2dd58c86384b7c696f8363779ffd0ae92204fdd1 Mon Sep 17 00:00:00 2001 From: nh758 <7259@pm.me> Date: Wed, 14 May 2025 09:49:40 +0700 Subject: [PATCH 3/6] add secrets and improve templating --- .../process/ABProcessTaskServiceApi.js | 246 +++++++++++++----- styles/Designer.css | 3 +- 2 files changed, 184 insertions(+), 65 deletions(-) diff --git a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js index 7cae8eeb..4a16946c 100644 --- a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js +++ b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js @@ -18,12 +18,14 @@ export default function(AB) { super("properties_process_service_api", { form: "", headers: "", + secrets: "", suggest: "", }); this.element = null; // A webix datacollection - used to load process data into our mention suggest this.suggestData = new AB.Webix.DataCollection({}); + this.templateRgx = /<%= (.+?) %>/g; } static get key() { @@ -32,6 +34,13 @@ export default function(AB) { ui() { const ids = this.ids; + this.AB.Webix.ui({ + id: ids.suggest, + view: "mentionsuggest", + symbol: "<", + template: "%= #value# %>", + data: this.suggestData, + }); return { rows: [ { @@ -47,9 +56,12 @@ export default function(AB) { label: L("Name"), }, { - view: "text", + view: "texthighlight", name: "url", label: L("Url"), + highlight: (t) => this.highlight(t), + suggest: this.ids.suggest, + css: "monospace", }, { view: "combo", @@ -83,58 +95,26 @@ export default function(AB) { type: "textarea", placeholder: "use ${...} to add process data", css: "monospace", - highlight: (text) => { - text = text.replaceAll( - " ", - `·` - ); - text = text.replace(/\${([^}]*)}/g, (m, c) => { - const data = this.suggestData.find( - { key: c }, - true - ); - const centerPad = (str, target, pad, right) => { - if (str.length === target) return str; - if (right) - return centerPad( - `${str}${pad}`, - target, - pad - ); - else - return centerPad( - `${pad}${str}`, - target, - pad, - true - ); - }; - if (data) { - // We save the key in the text, but display the - // label. Need to keep the length the same or - // the cursor get's messed up. - const { key, value } = data; - const diff = key.length - value.length; - let val = data.value; - if (diff > 0) { - val = centerPad(val, key.length, "─", true); - } else if (diff < 0) { - val = `...${val.slice(diff + 3)}`; - } - return `\${${val}}`; - } - return `${m}`; - }); - return text; - }, - suggest: { - id: ids.suggest, - view: "mentionsuggest", - symbol: "$", - template: "{#key#}", - data: this.suggestData, - }, + highlight: (t) => this.highlight(t), + suggest: this.ids.suggest, + }, + { + cols: [ + { + view: "label", + label: L("Secrets"), + autowidth: true, + }, + { + view: "icon", + icon: "fa fa-plus", + width: 50, + on: { onItemClick: () => this.addSecret() }, + }, + {}, + ], }, + { id: ids.secrets, rows: [] }, { view: "switch", name: "responseJson", @@ -150,29 +130,41 @@ export default function(AB) { } populate(element) { - const { name, url, method, body, responseJson } = element; - $$(this.ids.form).setValues({ name, url, method, body, responseJson }); - element.headers?.forEach?.((header) => { - this.addHeader(header); - }); + // Reset our suggest data + this.suggestData.clearAll(); + this.suggestData.parse( + element.storedSecrets?.map((s) => ({ + value: `Secret: ${s}`, + key: `Secret: ${s}`, + })) + ); const processData = element.process.processDataFields(element) ?? []; this.suggestData.parse( processData .filter((i) => !!i) .map?.((i) => ({ value: i.label, key: i.key })) ); + let { name, url, method, body, responseJson } = element; + // These might have process value placeholders, display the label + // instead of ids + body = this.convertIDToLabel(body); + url = this.convertIDToLabel(url); + + $$(this.ids.form).setValues({ name, url, method, body, responseJson }); + + element.headers?.forEach?.((header) => { + header.value = this.convertIDToLabel(header.value); + this.addHeader(header); + }); + element.storedSecrets?.forEach?.((secret) => this.addSecret(secret)); } values() { const values = {}; let form = {}; - try { - form = $$(this.ids.form).getValues(); - } catch (e) { - console.log("caught", e); - } + form = $$(this.ids.form).getValues(); Object.keys(form).forEach((key) => { - key.includes("headers") + key.includes("headers") || key.includes("secrets") ? nestValue(key, form[key], values) : (values[key] = form[key]); }); @@ -184,9 +176,36 @@ export default function(AB) { ); values.headers = headers; } + // These might contain process value placeholders, convert the label to + // actuall ids before saving + values.body = this.convertLabelToID(values.body); + values.url = this.convertLabelToID(values.url); + values.headers?.forEach( + (h) => (h.value = this.convertLabelToID(h.value)) + ); + // Convert secrets to an array + if (values.secrets) { + const secrets = []; + Object.keys(values.secrets).forEach((secret) => + secrets.push(values.secrets[secret]) + ); + values.secrets = secrets; + } + if (this.deleteSecrets) { + values.deleteSecrets = this.deleteSecrets; + delete this.deleteSecrets; + } + console.log("VALUES", values); + return values; } + /** + * Add fields to the form for a header + * @param {object} [header={}] + * @param {string} [header.key] + * @param {string} [header.value] + */ addHeader(header = {}) { const uid = AB.Webix.uid(); //this is unique to the page const row = { @@ -199,11 +218,14 @@ export default function(AB) { value: header.key, }, { - view: "text", + view: "texthighlight", name: `headers.${uid}.value`, placeholder: "value", value: header.value, gravity: 2, + highlight: (t) => this.highlight(t), + suggest: this.ids.suggest, + css: "monospace", }, { view: "icon", @@ -217,6 +239,102 @@ export default function(AB) { }; $$(this.ids.headers).addView(row); } + + /** + * Add fields to the form for a secret + * @param {string} secret name of an existing secret + */ + addSecret(secret) { + const alreadySaved = !!secret; + // If the secret is already saved in the db we only allow deleting. + // We also don't need it in the from values. + const uid = secret ?? AB.Webix.uid(); //this is unique to the page + const row = { + id: uid, + cols: [ + { + view: "text", + name: alreadySaved ? undefined : `secrets.${uid}.name`, + placeholder: "Name", + disabled: alreadySaved, + value: secret, + }, + { + view: "text", + type: "password", + name: alreadySaved ? undefined : `secrets.${uid}.value`, + placeholder: "Value", + disabled: alreadySaved, + // We don't actually get the existing secret values so we'll + // just mock a value. + value: alreadySaved ? ".........." : undefined, + gravity: 2, + }, + { + view: "icon", + icon: "wxi-trash", + width: "50", + on: { + onItemClick: () => { + $$(this.ids.secret).removeView(uid); + if (alreadySaved) { + this.deleteSecrets = this.deleteSecrets ?? []; + this.deleteSecrets.push(secret); + } + }, + }, + }, + ], + }; + $$(this.ids.secrets).addView(row); + } + + /** + * Highlight function webix texthighlight elements. Highlights secret and + * process data in the text. + */ + highlight(text) { + // text = text.replaceAll(" ", `·`); + text = text.replace(this.templateRgx, (match, value) => { + const data = this.suggestData.find({ value }, true); + let color = "#FF8C00"; //Not matched - highlight orange + let background = "#FFE0B2"; + if (data) { + if (/^Secret:/.test(value)) { + color = "#008C8C"; // Matches secret - highlight cyan + background = "#A0D7D7"; + } else { + color = "#388E3C"; // Matches process value - highlight green + background = "#C4EDC6"; + } + } + return `${match}`; + }); + return text; + } + + /** + * Replace process value labels with ids. Used before saving templates. + */ + convertLabelToID(template) { + return template.replace(this.templateRgx, (match, value) => { + const data = this.suggestData.find({ value }, true); + if (!data) return match; + return `<%= ${data.key} %>`; + }); + } + + /** + * Replace process value ids with labels. Used before displaying + * templates. + */ + convertIDToLabel(template) { + return template.replace(this.templateRgx, (match, key) => { + const data = this.suggestData.find({ key }, true); + if (!data) return match; + return `<%= ${data.value} %>`; + }); + } } return UIProcessServiceApi; diff --git a/styles/Designer.css b/styles/Designer.css index 581d1ffc..bfca69da 100644 --- a/styles/Designer.css +++ b/styles/Designer.css @@ -267,7 +267,8 @@ } .monospace > div > textarea, -.monospace > div > div > .webix_text_highlight_value { +.monospace input, +.monospace .webix_text_highlight_value { word-break: break-all; font-family: monospace; } From 395f0e193f4192440a2011ae0fd293fc808c6d6e Mon Sep 17 00:00:00 2001 From: nh758 <7259@pm.me> Date: Wed, 14 May 2025 09:51:04 +0700 Subject: [PATCH 4/6] fix error loading api object response form --- .../ui_work_object_list_newObject_api_read_response.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rootPages/Designer/ui_work_object_list_newObject_api_read_response.js b/src/rootPages/Designer/ui_work_object_list_newObject_api_read_response.js index 147f9e85..d2e91791 100644 --- a/src/rootPages/Designer/ui_work_object_list_newObject_api_read_response.js +++ b/src/rootPages/Designer/ui_work_object_list_newObject_api_read_response.js @@ -261,12 +261,13 @@ export default function (AB) { _addFieldItem(key, type) { const uiItem = this._fieldItem(key, type); - $$(this.ids.connections).addView(uiItem); + $$(this.ids.fields).addView(uiItem); } _clearFieldItems() { - const $connections = $$(this.ids.connections); - AB.Webix.ui([], $connections); + const $fields = $$(this.ids.connections); + if (!$fields) return; + AB.Webix.ui([], $fields); } _populateDataKeys() { From bc411f749c5a0ce7b96e382130c0547b5baa9632 Mon Sep 17 00:00:00 2001 From: nh758 <7259@pm.me> Date: Thu, 5 Jun 2025 13:06:03 +0700 Subject: [PATCH 5/6] ui/ux improvements --- .../process/ABProcessTaskServiceApi.js | 57 ++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js index 4a16946c..6229c637 100644 --- a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js +++ b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js @@ -16,6 +16,7 @@ export default function(AB) { class UIProcessServiceApi extends UIClass { constructor() { super("properties_process_service_api", { + body: "", form: "", headers: "", secrets: "", @@ -26,6 +27,7 @@ export default function(AB) { // A webix datacollection - used to load process data into our mention suggest this.suggestData = new AB.Webix.DataCollection({}); this.templateRgx = /<%= (.+?) %>/g; + this.hint = L("Use <%= ... %> to add process data / secrets"); } static get key() { @@ -61,6 +63,7 @@ export default function(AB) { label: L("Url"), highlight: (t) => this.highlight(t), suggest: this.ids.suggest, + placeholder: this.hint, css: "monospace", }, { @@ -68,6 +71,13 @@ export default function(AB) { name: "method", label: L("Method"), options: ["GET", "POST", "PUT", "DELETE"], + on: { + onChange: (val) => { + val == "GET" + ? $$(ids.body).disable() + : $$(ids.body).enable(); + }, + }, }, { cols: [ @@ -89,11 +99,12 @@ export default function(AB) { { view: "texthighlight", name: "body", + id: ids.body, height: 200, label: L("Request Body"), labelPosition: "top", type: "textarea", - placeholder: "use ${...} to add process data", + placeholder: this.hint, css: "monospace", highlight: (t) => this.highlight(t), suggest: this.ids.suggest, @@ -115,6 +126,9 @@ export default function(AB) { ], }, { id: ids.secrets, rows: [] }, + /** + * TODO: Allow the response to be decoded and saved for + * future process tasks { view: "switch", name: "responseJson", @@ -123,6 +137,7 @@ export default function(AB) { onLabel: L("JSON"), offLabel: L("Text"), }, + */ ], }, ], @@ -214,13 +229,13 @@ export default function(AB) { { view: "text", name: `headers.${uid}.key`, - placeholder: "header", + placeholder: L("header"), value: header.key, }, { view: "texthighlight", name: `headers.${uid}.value`, - placeholder: "value", + placeholder: `${L("value")} (${this.hint})`, value: header.value, gravity: 2, highlight: (t) => this.highlight(t), @@ -247,17 +262,41 @@ export default function(AB) { addSecret(secret) { const alreadySaved = !!secret; // If the secret is already saved in the db we only allow deleting. - // We also don't need it in the from values. + // Since secrets aren't saved in the definition, we don't need to send + // existing secrets to the server. New one will get encrypted and saved const uid = secret ?? AB.Webix.uid(); //this is unique to the page + const self = this; const row = { id: uid, cols: [ { view: "text", name: alreadySaved ? undefined : `secrets.${uid}.name`, - placeholder: "Name", + placeholder: L("Name"), disabled: alreadySaved, value: secret, + invalidMessage: L("Secret names must be unique!"), + validate: (val) => { + // Check that the secret name is unique + const opts = this.suggestData.find({ + key: `Secret: ${val}`, + }); + return opts.length === 1; + }, + on: { + onChange: function(n, o) { + if (n == o) return; + // Add the secret to the suggest data + const suggest = { + id: uid, + key: `Secret: ${n}`, + value: `Secret: ${n}`, + }; + if (o == "") self.suggestData.parse(suggest); + else self.suggestData.updateItem(uid, suggest); + this.validate(); + }, + }, }, { view: "text", @@ -265,8 +304,8 @@ export default function(AB) { name: alreadySaved ? undefined : `secrets.${uid}.value`, placeholder: "Value", disabled: alreadySaved, - // We don't actually get the existing secret values so we'll - // just mock a value. + // We don't actually get the existing secret values back + // so we'll just mock a value. value: alreadySaved ? ".........." : undefined, gravity: 2, }, @@ -290,7 +329,7 @@ export default function(AB) { } /** - * Highlight function webix texthighlight elements. Highlights secret and + * Highlight function for webix texthighlight elements. Highlights secret and * process data in the text. */ highlight(text) { @@ -317,6 +356,7 @@ export default function(AB) { * Replace process value labels with ids. Used before saving templates. */ convertLabelToID(template) { + if (!template) return; return template.replace(this.templateRgx, (match, value) => { const data = this.suggestData.find({ value }, true); if (!data) return match; @@ -329,6 +369,7 @@ export default function(AB) { * templates. */ convertIDToLabel(template) { + if (!template) return; return template.replace(this.templateRgx, (match, key) => { const data = this.suggestData.find({ key }, true); if (!data) return match; From d184c0d758a7f65f988e94cb6e277db51efa6c9d Mon Sep 17 00:00:00 2001 From: Nate <10155226+nh758@users.noreply.github.com> Date: Mon, 30 Jun 2025 16:02:09 +0700 Subject: [PATCH 6/6] remove debug log --- .../Designer/properties/process/ABProcessTaskServiceApi.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js index 6229c637..cfbddf37 100644 --- a/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js +++ b/src/rootPages/Designer/properties/process/ABProcessTaskServiceApi.js @@ -210,8 +210,7 @@ export default function(AB) { values.deleteSecrets = this.deleteSecrets; delete this.deleteSecrets; } - console.log("VALUES", values); - + return values; }