You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2021/04/27 23:45:55 UTC

[brooklyn-ui] 04/05: add quick fix for proposing from a template

This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-ui.git

commit e67cc9331111c83d2f12aeb0b6c97026d00073b9
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Wed Apr 28 00:29:55 2021 +0100

    add quick fix for proposing from a template
---
 docs/basic-with-constraint.bom                     |   8 ++
 .../app/components/quick-fix/quick-fix.js          | 117 +++++++++++++++++++--
 2 files changed, 118 insertions(+), 7 deletions(-)

diff --git a/docs/basic-with-constraint.bom b/docs/basic-with-constraint.bom
index a3297b1..5457a2a 100644
--- a/docs/basic-with-constraint.bom
+++ b/docs/basic-with-constraint.bom
@@ -65,3 +65,11 @@ brooklyn.catalog:
         source-key: post_code                     # will match the key
         source-hierarchy: anywhere                # anywhere
         source-types: [ basic-with-constraint ]   # of this type
+
+      - key: post_code
+        fix: set_from_template
+        message-regex: required
+
+        template: ${application}-${entity}  # required, the template, supporting vars application, application.id, entity, entity.name, entity._id
+        preview: "Set ${entity.type} post_code '${application}-<entity_name_or_id>'"         # optional, summary for button, grouping fixes, and filtering (template rules applied to this, skipped if not applicable)
+        sanitize: _                         # optional, sanitize as specified, eg _ or - or '.' to replace non-alphanumeric chars with that
diff --git a/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js b/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
index 1ee28cb..87ae979 100644
--- a/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
+++ b/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
@@ -91,12 +91,13 @@ const QUICK_FIX_PROPOSERS = {
         },
     },
     set_from_key: {
-        propose: proposeSetFrom()
+        propose: proposeSetFromKey()
         // - key: post_code
         //   fix: set_from_key
         //   message-regex: required
         //
-        //   source-key: postal_code    # required, custom
+        //   source-key: postal_code    # one of these is required
+        //   source-key-regex: ^postal_code($|_.*)
         //
         //   source-hierarchy: root     # optional, root|anywhere|ancestors -- default is root if no source-types given, anywhere if source-types are given
         //   source-types: [ org.apache.brooklyn.api.entity.Application ]     # types to filter by
@@ -105,13 +106,19 @@ const QUICK_FIX_PROPOSERS = {
         //   source-key-parameter-definition:    # if createable and did not exist, extra things to add to definition
         //     constraints:
         //     - required
-
-        //   source-mode: suggested | enforced   # (enhancement, not supported) could allow user to pick the type and/or key/param name
-
     },
+    set_from_template: {
+        propose: proposeSetFromTemplate(),
+        // - key: post_code
+        //   fix: set_from_template
+        //   message-regex: required
+        //   template: ${application}-${entity}  # required, the template, supporting vars application, application.id, entity, entity.name, entity._id
+        //   preview: "Set post_code '${application}_<entity_name_or_id>'"         # optional, summary for button, grouping fixes, and filtering (template rules applied to this, skipped if not applicable)
+        //   sanitize: _                         # optional, sanitize as specified, eg _ or - or '.' to replace non-alphanumeric chars with that
+    }
 };
 
-function proposeSetFrom() {
+function proposeSetFromKey() {
     return function (qfdef, issue, entity, blueprintService, proposals) {
         if (!issue.ref) return;
 
@@ -187,7 +194,7 @@ function proposeSetFrom() {
                     return;
                 }
 
-                let pkey = 'set_from_' + sourceNode.id + '_' + ckey;
+                let pkey = 'set_from_key_' + sourceNode.id + '_' + ckey;
                 if (!proposals[pkey]) {
                     if (create) {
                         proposals[pkey] = {
@@ -243,6 +250,102 @@ function proposeSetFrom() {
     };
 }
 
+function proposeSetFromTemplate() {
+    return function (qfdef, issue, entity, blueprintService, proposals) {
+        if (!issue.ref) return;
+
+        let template = qfdef['template'];
+        if (!template) {
+            console.warn("Missing 'template' on hint", qfdef);
+            return;
+        }
+
+        let sanitize = qfdef['sanitize'];
+        let sanitizeFn = s => {
+            if (!sanitize) return s;
+            return s.replace(/\W+/g, sanitize);
+        }
+
+        if (!proposals) proposals = {};
+
+        function replace(s, keyword, fn, skipSanitize) {
+            if (!s) return null;
+            let p = "${"+keyword+"}";
+            if (s.includes(p)) {
+                let v = fn();
+                if (v) {
+                    if (!skipSanitize) v = sanitizeFn(v);
+                    do {
+                        s = s.replace(p, v);
+                    } while (s.includes(p));
+                } else {
+                    return null;
+                }
+            }
+            return s;
+        }
+
+        function replaceTemplate(result, s, x, idFn, isPreview) {
+            let idLastFn = () => {
+                let last = x.id;
+                let takeLast = last || !isPreview;
+                last = last || idFn(s,x);
+                if (takeLast) last = last.replace(/^.*\W+(\w+\W*)/, '$1');
+                return last;
+            };
+            result = replace(result, s, () => x.name || idLastFn(), isPreview && !x.name && !x.id);
+            result = replace(result, s+".name", () => x.name);
+            result = replace(result, s+".nameOrType", () => x.name || x.miscData.get('typeName') || x.type);
+            result = replace(result, s+".typeName", () => x.miscData.get('typeName') || x.type);
+            result = replace(result, s+".type", () => x.type || x.miscData.get('typeName'));
+            result = replace(result, s+".id", () => x.id || idFn(s,x));
+            // takes the last word of the ID
+            result = replace(result, s+".idLast", idLastFn, isPreview);
+            result = replace(result, s+"._id", () => x._id);
+            return result;
+        }
+
+        let idFnForPreview = (s,x) => "<"+s+" ID, changed from "+x._id+">";
+        let preview = qfdef['preview'] || "Set '"+template+"'";
+        preview = replaceTemplate(preview, "entity", entity, idFnForPreview, true);
+        preview = replaceTemplate(preview, "application", entity.getApplication(), idFnForPreview, true);
+
+        if (preview) {
+            let pkey = 'set_from_template_' + preview;
+            if (!proposals[pkey]) {
+                proposals[pkey] = {
+                    text: preview,
+                    tooltip: "This will fix the error by setting the value here based on a template." +
+                        (sanitize ? " The result will be sanitized using '" + sanitize + "'." : ""),
+                };
+
+                Object.assign(proposals[pkey], {
+                    issues: [],
+                    apply: (issue, entity) => {
+                        entity = (entity || issue.entity);
+                        let result = template;
+                        let idFnForActual = (s, x) => {
+                            blueprintService.populateId(x);
+                            return x.id;
+                        };
+                        result = replaceTemplate(result, "entity", entity, idFnForActual);
+                        result = replaceTemplate(result, "application", entity.getApplication(), idFnForActual);
+                        if (!result) {
+                            console.warn("Could not apply quick fix: template '"+template+"' not valid at entity", entity);
+                        } else {
+                            entity.addConfig(issue.ref, result);
+                        }
+                    }
+                });
+            }
+            if (proposals[pkey]) {
+                proposals[pkey].issues.push(issue);
+            }
+        }
+
+    };
+}
+
 export function getQuickFixProposer(type) {
     return QUICK_FIX_PROPOSERS[type];
 }