You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@brooklyn.apache.org by GitBox <gi...@apache.org> on 2021/07/08 11:18:29 UTC

[GitHub] [brooklyn-ui] tbouron opened a new pull request #241: Add support for an ancestor quick fix

tbouron opened a new pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241


   This will check if an entity has implicit inherited config keys. If this is the case, then warnings will be created for these config keys. Additionally, a quick fix will be available to automatically set the implicit inherited config key `x` to `$brooklyn:parent().config("x")`
   
   Here it is in action:
   ![quick-fix-ancestor](https://user-images.githubusercontent.com/2082759/124912966-7b5b8680-dfe6-11eb-964b-eccd8480bbb6.gif)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666770161



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -353,7 +398,7 @@ export function getQuickFixProposer(type) {
 export function getQuickFixHintsForIssue(issue, entity) {
     if (issue.group === 'config') {
         let hints = (entity.miscData.get('ui-composer-hints') || {})['config-quick-fixes'] || [];
-        hints = hints.filter(h => h.key === issue.ref);
+        hints = hints.filter(h => new RegExp(h.key).test(issue.ref));

Review comment:
       @algairim `RegExp` can take a regex or a string as regex, this is perfectly valid. The idea is to filter for the specific config key but in the case of implicit use of inherited config key, we want to do the check for ALL config key (see: https://github.com/apache/brooklyn-ui/pull/241/files#diff-b9b9776bc3d54d479c21091094606ac270b807327ee31a93317a3598964e2749R39)
   
   This is merly to be backward compatible with what was there previously. The quick fix API is super obscure and I plan to surface this kind of thing much more when refactoring it




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666364202



##########
File path: ui-modules/blueprint-composer/app/views/main/graphical/graphical.state.html
##########
@@ -19,129 +19,258 @@
 
 <div class="palette-and-or-toolbar">
 
-  <div class="layout">
-    <div class="toolbar">
-        <div class="list-group">
-            <a class="hand list-group-item"
-               ng-repeat="section in vm.sections track by $index"
-               ng-class="{'active': vm.selectedSection === section}"
-               ng-click="vm.selectedSection = section">
-                <i class="fa fa-fw" ng-class="section.icon"></i>
-            </a>
-
-            <div class="spacer"></div>
-            <a class="hand list-group-item errors-square"
-               title="Click to show/hide details of errors"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="allIssues.errors.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
-                <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
-            </a>
-            <a class="hand list-group-item warning-square"
-               title="Click to show/hide details of warnings"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="!allIssues.errors.count && allIssues.warnings.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
-                <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
-            </a>
+    <div class="layout">
+        <div class="toolbar">
+            <div class="list-group">
+                <a class="hand list-group-item"
+                   ng-repeat="section in vm.sections track by $index"
+                   ng-class="{'active': vm.selectedSection === section}"
+                   ng-click="vm.selectedSection = section">
+                    <i class="fa fa-fw" ng-class="section.icon"></i>
+                </a>
+
+                <div class="spacer"></div>
+                <a class="hand list-group-item errors-square"
+                   title="Click to show/hide details of errors"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="allIssues.errors.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
+                    <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
+                </a>
+                <a class="hand list-group-item warning-square"
+                   title="Click to show/hide details of warnings"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="!allIssues.errors.count && allIssues.warnings.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
+                    <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
+                </a>
+            </div>
         </div>
-    </div>
 
-      <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
-          <div class="errors-body">
+        <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
+            <div class="errors-body">
+
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <div ng-if="allIssues.errors.count">
+                    <a class="hand" ng-click="errorsPane.level = 'error-errors'">
+                        <ng-pluralize count="allIssues.errors.count"
+                                      when="{'one': '{} error', 'other': '{} errors'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'error-entities'">
+                        <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="allIssues.warnings.count">
+                    <a class="hand" ng-click="errorsPane.level = 'warning-errors'">
+                        <ng-pluralize count="allIssues.warnings.count"
+                                      when="{'one': '{} warning', 'other': '{} warnings'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'warning-entities'">
+                        <ng-pluralize count="vm.size(allIssues.warnings.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="!allIssues.errors.count && !allIssues.warnings.count">
+                    No errors or warnings.
+                </div>
+
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-entities'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
 
-              <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+                <strong>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
+                </strong>
+
+                with
 
-            <div ng-if="allIssues.errors.count">
                 <a class="hand" ng-click="errorsPane.level = 'error-errors'">
-                {{ allIssues.errors.count }}
-                    <span ng-if="allIssues.errors.count == 1">error</span>
-                    <span ng-if="allIssues.errors.count != 1">errors</span>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
                 </a>
+            </div>
+
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byEntity" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                        {{ vm.entitySummary(allIssues.entities[itemK]) }}:
+                        {{ itemV.length }} {{ itemV.length==1 ? 'error' : 'errors' }}
+                    </div>
+                    <div class="error-line-action">
+                        <a class="hand" ui-sref="main.graphical.edit.entity({entityId: itemK})">
+                            <i class="fa fa-fw fa-external-link"></i>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-errors'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <strong>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
+                </strong>
+
+                <span ng-show="allIssues.errors.count != vm.size(allIssues.errors.byMessage)"> ({{ vm.size(allIssues.errors.byMessage) }} unique)</span>
+
                 in
+
                 <a class="hand" ng-click="errorsPane.level = 'error-entities'">
-                    {{ vm.size(allIssues.errors.byEntity) }}
-                    <span ng-if="vm.size(allIssues.errors.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.errors.byEntity) != 1">entities</span>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
                 </a>
             </div>
 
-            <!-- TODO add links and panels for warnings -->
-            <div ng-if="allIssues.warnings.count">
-                {{ allIssues.warnings.count }}
-                    <span ng-if="allIssues.errors.count == 1">warning</span>
-                    <span ng-if="allIssues.errors.count != 1">warnings</span>
-                in {{ vm.size(allIssues.warnings.byEntity) }}
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) != 1">entities</span>
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byMessage" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                      <span>
+                          <span ng-show="vm.messageNeedsPrefix(itemV)">
+                              {{ itemV.group }} {{ itemV.ref }}<span ng-show="itemV.message">:</span>
+                          </span>
+                          <span ng-show="itemV.message">
+                              <ng-bind-html ng-bind-html="itemV.message"></ng-bind-html>
+                          </span>
+                      </span>
+
+                        (<a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'errors:'+itemK ? null : 'errors:'+itemK)"
+                            ng-class="{active: errorsPane.focus == 'errors:'+itemK }">
+                            <ng-pluralize count="itemV.issues.length"
+                                          when="{'one': '{} entity', 'other': '{} entities'}" />
+                        </a>
+                        <span ng-if="vm.size(itemV.quickFixes)">;
+                          <a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'fixes:'+itemK ? null : 'fixes:'+itemK)"
+                             ng-class="{active: errorsPane.focus == 'fixes:'+itemK }">
+                             <ng-pluralize count="vm.size(itemV.quickFixes)"
+                                           when="{'one': '{} quick fix', 'other': '{} quick fixes'}" />
+                             available
+                          </a>
+                        </span>)
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'errors:'+itemK">
+                            <div ng-repeat="issue in itemV.issues" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-circle"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ vm.entitySummary(issue.issue.entity) }}
+                                    <!-- could offer the issue-specific quick fixes; but clearer to navigate to entity and do there -->
+                                </div>
+                                <div class="error-line-action">
+                                    <a class="hand" ui-sref="main.graphical.edit.entity({entityId: issue.issue.entity._id})">
+                                        <i class="fa fa-fw fa-external-link"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'fixes:'+itemK">
+                            <div ng-repeat="fix in itemV.quickFixes" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-magic"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ fix.text }}
+                                    <a class="hand btn btn-xs btn-primary" style="float: right;" ng-click="vm.applyQuickFix(fix)"
+                                       ng-attr-title="{{ fix.tooltip }}"
+                                    >Apply
+                                        (<ng-pluralize count="vm.size(fix.issues)"

Review comment:
       Or make parentheses at the end visible. It is not displayed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666385550



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -55,6 +55,31 @@ export function computeQuickFixes(blueprintService, allIssues) {
             computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
         });
     });
+
+    allIssues.warnings.byMessage = {};
+    Object.values(allIssues.warnings.byEntity).forEach(list => {
+        list.forEach(issue => {
+            let key = issue.group+":"+issue.ref+":"+issue.message;
+            let v = allIssues.warnings.byMessage[key];
+            if (!v) {
+                v = allIssues.warnings.byMessage[key] = {
+                    group: issue.group,
+                    ref: issue.ref,
+                    message: issue.message,
+                    issues: [],
+                    quickFixes: {},
+                };
+            }
+
+            let issueO = {
+                issue,
+                //quickFixes: {},
+            }
+            v.issues.push(issueO);
+
+            computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
+        });
+    });

Review comment:
       Duplicate code, can be moved into a function like:
   ```
   export function computeQuickFixes(blueprintService, allIssues) {
       if (!allIssues) allIssues = blueprintService.getAllIssues();
       if (!allIssues) allIssues = {};
       if (!allIssues.errors) allIssues.errors = {};
   
       computeQuickFixesForIssues(allIssues.errors, blueprintService);
       computeQuickFixesForIssues(allIssues.warnings, blueprintService);
       
       return allIssues;
   }
   
   function computeQuickFixesForIssues(issuesCollection, blueprintService) {
       issuesCollection.byMessage = {};
       Object.values(issuesCollection.byEntity).forEach(list => {
   
       // etc.
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666757429



##########
File path: ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
##########
@@ -554,6 +564,24 @@ function BlueprintService($log, $q, $sce, paletteApi, iconGenerator, dslService,
         }, []));
     }
 
+    function refreshConfigInherited(entity) {
+        return $q((resolve) => {
+            entity.miscData.get('config')
+                .filter(definition => !entity.config.has(definition.name))
+                .forEach(definition => {
+                    if (entity.hasInheritedConfig(definition.name)) {
+                        entity.addIssue(Issue.builder()
+                            .group('config')
+                            .ref(definition.name)
+                            .level(ISSUE_LEVEL.WARN)
+                            .message(`Implicitly defined from one of it's ancestor`)

Review comment:
       Good catch, I'll update that @algairim 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666759479



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -55,6 +55,31 @@ export function computeQuickFixes(blueprintService, allIssues) {
             computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
         });
     });
+
+    allIssues.warnings.byMessage = {};
+    Object.values(allIssues.warnings.byEntity).forEach(list => {
+        list.forEach(issue => {
+            let key = issue.group+":"+issue.ref+":"+issue.message;
+            let v = allIssues.warnings.byMessage[key];
+            if (!v) {
+                v = allIssues.warnings.byMessage[key] = {
+                    group: issue.group,
+                    ref: issue.ref,
+                    message: issue.message,
+                    issues: [],
+                    quickFixes: {},
+                };
+            }
+
+            let issueO = {
+                issue,
+                //quickFixes: {},
+            }
+            v.issues.push(issueO);
+
+            computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
+        });
+    });

Review comment:
       @algairim Yeah about that. This was the quickest and dirtiest way to make this work (the previous version supported only errors) 
   
   However, the way the quick fixes are implemented doesn't really follow the AngularJS best practices or "way". I plan du refactor that which would make this bit of code go away. That's why I didn't go for a DRY implementation just now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] iuliana merged pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
iuliana merged pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666379029



##########
File path: ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
##########
@@ -554,6 +564,24 @@ function BlueprintService($log, $q, $sce, paletteApi, iconGenerator, dslService,
         }, []));
     }
 
+    function refreshConfigInherited(entity) {
+        return $q((resolve) => {
+            entity.miscData.get('config')
+                .filter(definition => !entity.config.has(definition.name))
+                .forEach(definition => {
+                    if (entity.hasInheritedConfig(definition.name)) {
+                        entity.addIssue(Issue.builder()
+                            .group('config')
+                            .ref(definition.name)
+                            .level(ISSUE_LEVEL.WARN)
+                            .message(`Implicitly defined from one of it's ancestor`)

Review comment:
       typo: _...one of its ancestors_.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666767170



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -353,7 +398,7 @@ export function getQuickFixProposer(type) {
 export function getQuickFixHintsForIssue(issue, entity) {
     if (issue.group === 'config') {
         let hints = (entity.miscData.get('ui-composer-hints') || {})['config-quick-fixes'] || [];
-        hints = hints.filter(h => h.key === issue.ref);
+        hints = hints.filter(h => new RegExp(h.key).test(issue.ref));

Review comment:
       Puzzling myself with this RegExp. It supposed to take regex expression as a parameter, however, `h.key` is a plain string if I understand that correctly. Does it work? What do we filter here?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666371874



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -55,6 +55,31 @@ export function computeQuickFixes(blueprintService, allIssues) {
             computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
         });
     });
+
+    allIssues.warnings.byMessage = {};
+    Object.values(allIssues.warnings.byEntity).forEach(list => {
+        list.forEach(issue => {
+            let key = issue.group+":"+issue.ref+":"+issue.message;
+            let v = allIssues.warnings.byMessage[key];
+            if (!v) {
+                v = allIssues.warnings.byMessage[key] = {
+                    group: issue.group,
+                    ref: issue.ref,
+                    message: issue.message,
+                    issues: [],
+                    quickFixes: {},
+                };
+            }
+
+            let issueO = {

Review comment:
       Is it `issueObject`?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666759479



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -55,6 +55,31 @@ export function computeQuickFixes(blueprintService, allIssues) {
             computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
         });
     });
+
+    allIssues.warnings.byMessage = {};
+    Object.values(allIssues.warnings.byEntity).forEach(list => {
+        list.forEach(issue => {
+            let key = issue.group+":"+issue.ref+":"+issue.message;
+            let v = allIssues.warnings.byMessage[key];
+            if (!v) {
+                v = allIssues.warnings.byMessage[key] = {
+                    group: issue.group,
+                    ref: issue.ref,
+                    message: issue.message,
+                    issues: [],
+                    quickFixes: {},
+                };
+            }
+
+            let issueO = {
+                issue,
+                //quickFixes: {},
+            }
+            v.issues.push(issueO);
+
+            computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
+        });
+    });

Review comment:
       @algairim Yeah about that. This was the quickest and dirtiest way to make this work (the previous version supported only warning) 
   
   However, the way the quick fixes are implemented doesn't really follow the AngularJS best practices or "way". I plan du refactor that which would make this bit of code go away. That's why I didn't go for a DRY implementation just now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#issuecomment-877014529


   Looks good @tbouron 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666770645



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -353,7 +398,7 @@ export function getQuickFixProposer(type) {
 export function getQuickFixHintsForIssue(issue, entity) {
     if (issue.group === 'config') {
         let hints = (entity.miscData.get('ui-composer-hints') || {})['config-quick-fixes'] || [];
-        hints = hints.filter(h => h.key === issue.ref);
+        hints = hints.filter(h => new RegExp(h.key).test(issue.ref));

Review comment:
       I see, thanks for clarifying.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666755869



##########
File path: ui-modules/blueprint-composer/app/views/main/graphical/graphical.state.html
##########
@@ -19,129 +19,258 @@
 
 <div class="palette-and-or-toolbar">
 
-  <div class="layout">
-    <div class="toolbar">
-        <div class="list-group">
-            <a class="hand list-group-item"
-               ng-repeat="section in vm.sections track by $index"
-               ng-class="{'active': vm.selectedSection === section}"
-               ng-click="vm.selectedSection = section">
-                <i class="fa fa-fw" ng-class="section.icon"></i>
-            </a>
-
-            <div class="spacer"></div>
-            <a class="hand list-group-item errors-square"
-               title="Click to show/hide details of errors"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="allIssues.errors.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
-                <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
-            </a>
-            <a class="hand list-group-item warning-square"
-               title="Click to show/hide details of warnings"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="!allIssues.errors.count && allIssues.warnings.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
-                <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
-            </a>
+    <div class="layout">
+        <div class="toolbar">
+            <div class="list-group">
+                <a class="hand list-group-item"
+                   ng-repeat="section in vm.sections track by $index"
+                   ng-class="{'active': vm.selectedSection === section}"
+                   ng-click="vm.selectedSection = section">
+                    <i class="fa fa-fw" ng-class="section.icon"></i>
+                </a>
+
+                <div class="spacer"></div>
+                <a class="hand list-group-item errors-square"
+                   title="Click to show/hide details of errors"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="allIssues.errors.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
+                    <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
+                </a>
+                <a class="hand list-group-item warning-square"
+                   title="Click to show/hide details of warnings"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="!allIssues.errors.count && allIssues.warnings.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
+                    <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
+                </a>
+            </div>
         </div>
-    </div>
 
-      <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
-          <div class="errors-body">
+        <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
+            <div class="errors-body">
+
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <div ng-if="allIssues.errors.count">
+                    <a class="hand" ng-click="errorsPane.level = 'error-errors'">
+                        <ng-pluralize count="allIssues.errors.count"
+                                      when="{'one': '{} error', 'other': '{} errors'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'error-entities'">
+                        <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="allIssues.warnings.count">
+                    <a class="hand" ng-click="errorsPane.level = 'warning-errors'">
+                        <ng-pluralize count="allIssues.warnings.count"
+                                      when="{'one': '{} warning', 'other': '{} warnings'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'warning-entities'">
+                        <ng-pluralize count="vm.size(allIssues.warnings.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="!allIssues.errors.count && !allIssues.warnings.count">
+                    No errors or warnings.
+                </div>
+
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-entities'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
 
-              <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+                <strong>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
+                </strong>
+
+                with
 
-            <div ng-if="allIssues.errors.count">
                 <a class="hand" ng-click="errorsPane.level = 'error-errors'">
-                {{ allIssues.errors.count }}
-                    <span ng-if="allIssues.errors.count == 1">error</span>
-                    <span ng-if="allIssues.errors.count != 1">errors</span>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
                 </a>
+            </div>
+
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byEntity" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                        {{ vm.entitySummary(allIssues.entities[itemK]) }}:
+                        {{ itemV.length }} {{ itemV.length==1 ? 'error' : 'errors' }}
+                    </div>
+                    <div class="error-line-action">
+                        <a class="hand" ui-sref="main.graphical.edit.entity({entityId: itemK})">
+                            <i class="fa fa-fw fa-external-link"></i>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-errors'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <strong>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
+                </strong>
+
+                <span ng-show="allIssues.errors.count != vm.size(allIssues.errors.byMessage)"> ({{ vm.size(allIssues.errors.byMessage) }} unique)</span>
+
                 in
+
                 <a class="hand" ng-click="errorsPane.level = 'error-entities'">
-                    {{ vm.size(allIssues.errors.byEntity) }}
-                    <span ng-if="vm.size(allIssues.errors.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.errors.byEntity) != 1">entities</span>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
                 </a>
             </div>
 
-            <!-- TODO add links and panels for warnings -->
-            <div ng-if="allIssues.warnings.count">
-                {{ allIssues.warnings.count }}
-                    <span ng-if="allIssues.errors.count == 1">warning</span>
-                    <span ng-if="allIssues.errors.count != 1">warnings</span>
-                in {{ vm.size(allIssues.warnings.byEntity) }}
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) != 1">entities</span>
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byMessage" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                      <span>
+                          <span ng-show="vm.messageNeedsPrefix(itemV)">
+                              {{ itemV.group }} {{ itemV.ref }}<span ng-show="itemV.message">:</span>
+                          </span>
+                          <span ng-show="itemV.message">
+                              <ng-bind-html ng-bind-html="itemV.message"></ng-bind-html>
+                          </span>
+                      </span>
+
+                        (<a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'errors:'+itemK ? null : 'errors:'+itemK)"
+                            ng-class="{active: errorsPane.focus == 'errors:'+itemK }">
+                            <ng-pluralize count="itemV.issues.length"
+                                          when="{'one': '{} entity', 'other': '{} entities'}" />
+                        </a>
+                        <span ng-if="vm.size(itemV.quickFixes)">;
+                          <a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'fixes:'+itemK ? null : 'fixes:'+itemK)"
+                             ng-class="{active: errorsPane.focus == 'fixes:'+itemK }">
+                             <ng-pluralize count="vm.size(itemV.quickFixes)"
+                                           when="{'one': '{} quick fix', 'other': '{} quick fixes'}" />
+                             available
+                          </a>
+                        </span>)
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'errors:'+itemK">
+                            <div ng-repeat="issue in itemV.issues" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-circle"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ vm.entitySummary(issue.issue.entity) }}
+                                    <!-- could offer the issue-specific quick fixes; but clearer to navigate to entity and do there -->
+                                </div>
+                                <div class="error-line-action">
+                                    <a class="hand" ui-sref="main.graphical.edit.entity({entityId: issue.issue.entity._id})">
+                                        <i class="fa fa-fw fa-external-link"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'fixes:'+itemK">
+                            <div ng-repeat="fix in itemV.quickFixes" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-magic"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ fix.text }}
+                                    <a class="hand btn btn-xs btn-primary" style="float: right;" ng-click="vm.applyQuickFix(fix)"
+                                       ng-attr-title="{{ fix.tooltip }}"
+                                    >Apply
+                                        (<ng-pluralize count="vm.size(fix.issues)"

Review comment:
       @algairim It is at the end of the `ng-pluralize` directive, on line 197




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666761739



##########
File path: ui-modules/blueprint-composer/app/views/main/graphical/graphical.state.html
##########
@@ -19,129 +19,258 @@
 
 <div class="palette-and-or-toolbar">
 
-  <div class="layout">
-    <div class="toolbar">
-        <div class="list-group">
-            <a class="hand list-group-item"
-               ng-repeat="section in vm.sections track by $index"
-               ng-class="{'active': vm.selectedSection === section}"
-               ng-click="vm.selectedSection = section">
-                <i class="fa fa-fw" ng-class="section.icon"></i>
-            </a>
-
-            <div class="spacer"></div>
-            <a class="hand list-group-item errors-square"
-               title="Click to show/hide details of errors"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="allIssues.errors.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
-                <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
-            </a>
-            <a class="hand list-group-item warning-square"
-               title="Click to show/hide details of warnings"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="!allIssues.errors.count && allIssues.warnings.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
-                <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
-            </a>
+    <div class="layout">
+        <div class="toolbar">
+            <div class="list-group">
+                <a class="hand list-group-item"
+                   ng-repeat="section in vm.sections track by $index"
+                   ng-class="{'active': vm.selectedSection === section}"
+                   ng-click="vm.selectedSection = section">
+                    <i class="fa fa-fw" ng-class="section.icon"></i>
+                </a>
+
+                <div class="spacer"></div>
+                <a class="hand list-group-item errors-square"
+                   title="Click to show/hide details of errors"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="allIssues.errors.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
+                    <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
+                </a>
+                <a class="hand list-group-item warning-square"
+                   title="Click to show/hide details of warnings"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="!allIssues.errors.count && allIssues.warnings.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
+                    <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
+                </a>
+            </div>
         </div>
-    </div>
 
-      <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
-          <div class="errors-body">
+        <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
+            <div class="errors-body">
+
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <div ng-if="allIssues.errors.count">
+                    <a class="hand" ng-click="errorsPane.level = 'error-errors'">
+                        <ng-pluralize count="allIssues.errors.count"
+                                      when="{'one': '{} error', 'other': '{} errors'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'error-entities'">
+                        <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="allIssues.warnings.count">
+                    <a class="hand" ng-click="errorsPane.level = 'warning-errors'">
+                        <ng-pluralize count="allIssues.warnings.count"
+                                      when="{'one': '{} warning', 'other': '{} warnings'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'warning-entities'">
+                        <ng-pluralize count="vm.size(allIssues.warnings.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="!allIssues.errors.count && !allIssues.warnings.count">
+                    No errors or warnings.
+                </div>
+
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-entities'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
 
-              <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+                <strong>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
+                </strong>
+
+                with
 
-            <div ng-if="allIssues.errors.count">
                 <a class="hand" ng-click="errorsPane.level = 'error-errors'">
-                {{ allIssues.errors.count }}
-                    <span ng-if="allIssues.errors.count == 1">error</span>
-                    <span ng-if="allIssues.errors.count != 1">errors</span>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
                 </a>
+            </div>
+
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byEntity" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                        {{ vm.entitySummary(allIssues.entities[itemK]) }}:
+                        {{ itemV.length }} {{ itemV.length==1 ? 'error' : 'errors' }}
+                    </div>
+                    <div class="error-line-action">
+                        <a class="hand" ui-sref="main.graphical.edit.entity({entityId: itemK})">
+                            <i class="fa fa-fw fa-external-link"></i>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-errors'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <strong>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
+                </strong>
+
+                <span ng-show="allIssues.errors.count != vm.size(allIssues.errors.byMessage)"> ({{ vm.size(allIssues.errors.byMessage) }} unique)</span>
+
                 in
+
                 <a class="hand" ng-click="errorsPane.level = 'error-entities'">
-                    {{ vm.size(allIssues.errors.byEntity) }}
-                    <span ng-if="vm.size(allIssues.errors.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.errors.byEntity) != 1">entities</span>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
                 </a>
             </div>
 
-            <!-- TODO add links and panels for warnings -->
-            <div ng-if="allIssues.warnings.count">
-                {{ allIssues.warnings.count }}
-                    <span ng-if="allIssues.errors.count == 1">warning</span>
-                    <span ng-if="allIssues.errors.count != 1">warnings</span>
-                in {{ vm.size(allIssues.warnings.byEntity) }}
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) != 1">entities</span>
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byMessage" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                      <span>
+                          <span ng-show="vm.messageNeedsPrefix(itemV)">
+                              {{ itemV.group }} {{ itemV.ref }}<span ng-show="itemV.message">:</span>
+                          </span>
+                          <span ng-show="itemV.message">
+                              <ng-bind-html ng-bind-html="itemV.message"></ng-bind-html>
+                          </span>
+                      </span>
+
+                        (<a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'errors:'+itemK ? null : 'errors:'+itemK)"
+                            ng-class="{active: errorsPane.focus == 'errors:'+itemK }">
+                            <ng-pluralize count="itemV.issues.length"
+                                          when="{'one': '{} entity', 'other': '{} entities'}" />
+                        </a>
+                        <span ng-if="vm.size(itemV.quickFixes)">;
+                          <a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'fixes:'+itemK ? null : 'fixes:'+itemK)"
+                             ng-class="{active: errorsPane.focus == 'fixes:'+itemK }">
+                             <ng-pluralize count="vm.size(itemV.quickFixes)"
+                                           when="{'one': '{} quick fix', 'other': '{} quick fixes'}" />
+                             available
+                          </a>
+                        </span>)
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'errors:'+itemK">
+                            <div ng-repeat="issue in itemV.issues" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-circle"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ vm.entitySummary(issue.issue.entity) }}
+                                    <!-- could offer the issue-specific quick fixes; but clearer to navigate to entity and do there -->
+                                </div>
+                                <div class="error-line-action">
+                                    <a class="hand" ui-sref="main.graphical.edit.entity({entityId: issue.issue.entity._id})">
+                                        <i class="fa fa-fw fa-external-link"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'fixes:'+itemK">
+                            <div ng-repeat="fix in itemV.quickFixes" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-magic"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ fix.text }}
+                                    <a class="hand btn btn-xs btn-primary" style="float: right;" ng-click="vm.applyQuickFix(fix)"
+                                       ng-attr-title="{{ fix.tooltip }}"
+                                    >Apply
+                                        (<ng-pluralize count="vm.size(fix.issues)"

Review comment:
       <img width="187" alt="Screenshot 2021-07-09 at 09 13 46" src="https://user-images.githubusercontent.com/81319331/125046483-f8920480-e095-11eb-81f8-d91f03c78e39.png">
   parentheses  at 197 is not displayed.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#issuecomment-877014205


   Reminder to myself: @algairim to fix overlapping of multiple labels on relationship arcs:
   <img width="194" alt="Screenshot 2021-07-09 at 09 29 10" src="https://user-images.githubusercontent.com/81319331/125048718-20826780-e098-11eb-8f90-81a96cbf1209.png">
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666768940



##########
File path: ui-modules/blueprint-composer/app/views/main/graphical/graphical.state.html
##########
@@ -19,129 +19,258 @@
 
 <div class="palette-and-or-toolbar">
 
-  <div class="layout">
-    <div class="toolbar">
-        <div class="list-group">
-            <a class="hand list-group-item"
-               ng-repeat="section in vm.sections track by $index"
-               ng-class="{'active': vm.selectedSection === section}"
-               ng-click="vm.selectedSection = section">
-                <i class="fa fa-fw" ng-class="section.icon"></i>
-            </a>
-
-            <div class="spacer"></div>
-            <a class="hand list-group-item errors-square"
-               title="Click to show/hide details of errors"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="allIssues.errors.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
-                <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
-            </a>
-            <a class="hand list-group-item warning-square"
-               title="Click to show/hide details of warnings"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="!allIssues.errors.count && allIssues.warnings.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
-                <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
-            </a>
+    <div class="layout">
+        <div class="toolbar">
+            <div class="list-group">
+                <a class="hand list-group-item"
+                   ng-repeat="section in vm.sections track by $index"
+                   ng-class="{'active': vm.selectedSection === section}"
+                   ng-click="vm.selectedSection = section">
+                    <i class="fa fa-fw" ng-class="section.icon"></i>
+                </a>
+
+                <div class="spacer"></div>
+                <a class="hand list-group-item errors-square"
+                   title="Click to show/hide details of errors"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="allIssues.errors.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
+                    <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
+                </a>
+                <a class="hand list-group-item warning-square"
+                   title="Click to show/hide details of warnings"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="!allIssues.errors.count && allIssues.warnings.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
+                    <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
+                </a>
+            </div>
         </div>
-    </div>
 
-      <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
-          <div class="errors-body">
+        <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
+            <div class="errors-body">
+
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <div ng-if="allIssues.errors.count">
+                    <a class="hand" ng-click="errorsPane.level = 'error-errors'">
+                        <ng-pluralize count="allIssues.errors.count"
+                                      when="{'one': '{} error', 'other': '{} errors'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'error-entities'">
+                        <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="allIssues.warnings.count">
+                    <a class="hand" ng-click="errorsPane.level = 'warning-errors'">
+                        <ng-pluralize count="allIssues.warnings.count"
+                                      when="{'one': '{} warning', 'other': '{} warnings'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'warning-entities'">
+                        <ng-pluralize count="vm.size(allIssues.warnings.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="!allIssues.errors.count && !allIssues.warnings.count">
+                    No errors or warnings.
+                </div>
+
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-entities'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
 
-              <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+                <strong>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
+                </strong>
+
+                with
 
-            <div ng-if="allIssues.errors.count">
                 <a class="hand" ng-click="errorsPane.level = 'error-errors'">
-                {{ allIssues.errors.count }}
-                    <span ng-if="allIssues.errors.count == 1">error</span>
-                    <span ng-if="allIssues.errors.count != 1">errors</span>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
                 </a>
+            </div>
+
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byEntity" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                        {{ vm.entitySummary(allIssues.entities[itemK]) }}:
+                        {{ itemV.length }} {{ itemV.length==1 ? 'error' : 'errors' }}
+                    </div>
+                    <div class="error-line-action">
+                        <a class="hand" ui-sref="main.graphical.edit.entity({entityId: itemK})">
+                            <i class="fa fa-fw fa-external-link"></i>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-errors'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <strong>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
+                </strong>
+
+                <span ng-show="allIssues.errors.count != vm.size(allIssues.errors.byMessage)"> ({{ vm.size(allIssues.errors.byMessage) }} unique)</span>
+
                 in
+
                 <a class="hand" ng-click="errorsPane.level = 'error-entities'">
-                    {{ vm.size(allIssues.errors.byEntity) }}
-                    <span ng-if="vm.size(allIssues.errors.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.errors.byEntity) != 1">entities</span>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
                 </a>
             </div>
 
-            <!-- TODO add links and panels for warnings -->
-            <div ng-if="allIssues.warnings.count">
-                {{ allIssues.warnings.count }}
-                    <span ng-if="allIssues.errors.count == 1">warning</span>
-                    <span ng-if="allIssues.errors.count != 1">warnings</span>
-                in {{ vm.size(allIssues.warnings.byEntity) }}
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) != 1">entities</span>
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byMessage" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                      <span>
+                          <span ng-show="vm.messageNeedsPrefix(itemV)">
+                              {{ itemV.group }} {{ itemV.ref }}<span ng-show="itemV.message">:</span>
+                          </span>
+                          <span ng-show="itemV.message">
+                              <ng-bind-html ng-bind-html="itemV.message"></ng-bind-html>
+                          </span>
+                      </span>
+
+                        (<a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'errors:'+itemK ? null : 'errors:'+itemK)"
+                            ng-class="{active: errorsPane.focus == 'errors:'+itemK }">
+                            <ng-pluralize count="itemV.issues.length"
+                                          when="{'one': '{} entity', 'other': '{} entities'}" />
+                        </a>
+                        <span ng-if="vm.size(itemV.quickFixes)">;
+                          <a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'fixes:'+itemK ? null : 'fixes:'+itemK)"
+                             ng-class="{active: errorsPane.focus == 'fixes:'+itemK }">
+                             <ng-pluralize count="vm.size(itemV.quickFixes)"
+                                           when="{'one': '{} quick fix', 'other': '{} quick fixes'}" />
+                             available
+                          </a>
+                        </span>)
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'errors:'+itemK">
+                            <div ng-repeat="issue in itemV.issues" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-circle"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ vm.entitySummary(issue.issue.entity) }}
+                                    <!-- could offer the issue-specific quick fixes; but clearer to navigate to entity and do there -->
+                                </div>
+                                <div class="error-line-action">
+                                    <a class="hand" ui-sref="main.graphical.edit.entity({entityId: issue.issue.entity._id})">
+                                        <i class="fa fa-fw fa-external-link"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'fixes:'+itemK">
+                            <div ng-repeat="fix in itemV.quickFixes" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-magic"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ fix.text }}
+                                    <a class="hand btn btn-xs btn-primary" style="float: right;" ng-click="vm.applyQuickFix(fix)"
+                                       ng-attr-title="{{ fix.tooltip }}"
+                                    >Apply
+                                        (<ng-pluralize count="vm.size(fix.issues)"

Review comment:
       Now it works, thanks @tbouron 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666767915



##########
File path: ui-modules/blueprint-composer/app/views/main/graphical/graphical.state.html
##########
@@ -19,129 +19,258 @@
 
 <div class="palette-and-or-toolbar">
 
-  <div class="layout">
-    <div class="toolbar">
-        <div class="list-group">
-            <a class="hand list-group-item"
-               ng-repeat="section in vm.sections track by $index"
-               ng-class="{'active': vm.selectedSection === section}"
-               ng-click="vm.selectedSection = section">
-                <i class="fa fa-fw" ng-class="section.icon"></i>
-            </a>
-
-            <div class="spacer"></div>
-            <a class="hand list-group-item errors-square"
-               title="Click to show/hide details of errors"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="allIssues.errors.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
-                <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
-            </a>
-            <a class="hand list-group-item warning-square"
-               title="Click to show/hide details of warnings"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="!allIssues.errors.count && allIssues.warnings.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
-                <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
-            </a>
+    <div class="layout">
+        <div class="toolbar">
+            <div class="list-group">
+                <a class="hand list-group-item"
+                   ng-repeat="section in vm.sections track by $index"
+                   ng-class="{'active': vm.selectedSection === section}"
+                   ng-click="vm.selectedSection = section">
+                    <i class="fa fa-fw" ng-class="section.icon"></i>
+                </a>
+
+                <div class="spacer"></div>
+                <a class="hand list-group-item errors-square"
+                   title="Click to show/hide details of errors"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="allIssues.errors.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
+                    <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
+                </a>
+                <a class="hand list-group-item warning-square"
+                   title="Click to show/hide details of warnings"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="!allIssues.errors.count && allIssues.warnings.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
+                    <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
+                </a>
+            </div>
         </div>
-    </div>
 
-      <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
-          <div class="errors-body">
+        <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
+            <div class="errors-body">
+
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <div ng-if="allIssues.errors.count">
+                    <a class="hand" ng-click="errorsPane.level = 'error-errors'">
+                        <ng-pluralize count="allIssues.errors.count"
+                                      when="{'one': '{} error', 'other': '{} errors'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'error-entities'">
+                        <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="allIssues.warnings.count">
+                    <a class="hand" ng-click="errorsPane.level = 'warning-errors'">
+                        <ng-pluralize count="allIssues.warnings.count"
+                                      when="{'one': '{} warning', 'other': '{} warnings'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'warning-entities'">
+                        <ng-pluralize count="vm.size(allIssues.warnings.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="!allIssues.errors.count && !allIssues.warnings.count">
+                    No errors or warnings.
+                </div>
+
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-entities'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
 
-              <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+                <strong>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
+                </strong>
+
+                with
 
-            <div ng-if="allIssues.errors.count">
                 <a class="hand" ng-click="errorsPane.level = 'error-errors'">
-                {{ allIssues.errors.count }}
-                    <span ng-if="allIssues.errors.count == 1">error</span>
-                    <span ng-if="allIssues.errors.count != 1">errors</span>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
                 </a>
+            </div>
+
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byEntity" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                        {{ vm.entitySummary(allIssues.entities[itemK]) }}:
+                        {{ itemV.length }} {{ itemV.length==1 ? 'error' : 'errors' }}
+                    </div>
+                    <div class="error-line-action">
+                        <a class="hand" ui-sref="main.graphical.edit.entity({entityId: itemK})">
+                            <i class="fa fa-fw fa-external-link"></i>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-errors'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <strong>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
+                </strong>
+
+                <span ng-show="allIssues.errors.count != vm.size(allIssues.errors.byMessage)"> ({{ vm.size(allIssues.errors.byMessage) }} unique)</span>
+
                 in
+
                 <a class="hand" ng-click="errorsPane.level = 'error-entities'">
-                    {{ vm.size(allIssues.errors.byEntity) }}
-                    <span ng-if="vm.size(allIssues.errors.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.errors.byEntity) != 1">entities</span>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
                 </a>
             </div>
 
-            <!-- TODO add links and panels for warnings -->
-            <div ng-if="allIssues.warnings.count">
-                {{ allIssues.warnings.count }}
-                    <span ng-if="allIssues.errors.count == 1">warning</span>
-                    <span ng-if="allIssues.errors.count != 1">warnings</span>
-                in {{ vm.size(allIssues.warnings.byEntity) }}
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) != 1">entities</span>
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byMessage" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                      <span>
+                          <span ng-show="vm.messageNeedsPrefix(itemV)">
+                              {{ itemV.group }} {{ itemV.ref }}<span ng-show="itemV.message">:</span>
+                          </span>
+                          <span ng-show="itemV.message">
+                              <ng-bind-html ng-bind-html="itemV.message"></ng-bind-html>
+                          </span>
+                      </span>
+
+                        (<a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'errors:'+itemK ? null : 'errors:'+itemK)"
+                            ng-class="{active: errorsPane.focus == 'errors:'+itemK }">
+                            <ng-pluralize count="itemV.issues.length"
+                                          when="{'one': '{} entity', 'other': '{} entities'}" />
+                        </a>
+                        <span ng-if="vm.size(itemV.quickFixes)">;
+                          <a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'fixes:'+itemK ? null : 'fixes:'+itemK)"
+                             ng-class="{active: errorsPane.focus == 'fixes:'+itemK }">
+                             <ng-pluralize count="vm.size(itemV.quickFixes)"
+                                           when="{'one': '{} quick fix', 'other': '{} quick fixes'}" />
+                             available
+                          </a>
+                        </span>)
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'errors:'+itemK">
+                            <div ng-repeat="issue in itemV.issues" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-circle"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ vm.entitySummary(issue.issue.entity) }}
+                                    <!-- could offer the issue-specific quick fixes; but clearer to navigate to entity and do there -->
+                                </div>
+                                <div class="error-line-action">
+                                    <a class="hand" ui-sref="main.graphical.edit.entity({entityId: issue.issue.entity._id})">
+                                        <i class="fa fa-fw fa-external-link"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'fixes:'+itemK">
+                            <div ng-repeat="fix in itemV.quickFixes" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-magic"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ fix.text }}
+                                    <a class="hand btn btn-xs btn-primary" style="float: right;" ng-click="vm.applyQuickFix(fix)"
+                                       ng-attr-title="{{ fix.tooltip }}"
+                                    >Apply
+                                        (<ng-pluralize count="vm.size(fix.issues)"

Review comment:
       Urgh, forgot that AngularJS is picky with self-closing tag. It's fixed now




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666769976



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -55,6 +55,31 @@ export function computeQuickFixes(blueprintService, allIssues) {
             computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
         });
     });
+
+    allIssues.warnings.byMessage = {};
+    Object.values(allIssues.warnings.byEntity).forEach(list => {
+        list.forEach(issue => {
+            let key = issue.group+":"+issue.ref+":"+issue.message;
+            let v = allIssues.warnings.byMessage[key];
+            if (!v) {
+                v = allIssues.warnings.byMessage[key] = {
+                    group: issue.group,
+                    ref: issue.ref,
+                    message: issue.message,
+                    issues: [],
+                    quickFixes: {},
+                };
+            }
+
+            let issueO = {
+                issue,
+                //quickFixes: {},
+            }
+            v.issues.push(issueO);
+
+            computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
+        });
+    });

Review comment:
       Ok, a little effort to move this code into function though :) 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] tbouron commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
tbouron commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666756575



##########
File path: ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
##########
@@ -55,6 +55,31 @@ export function computeQuickFixes(blueprintService, allIssues) {
             computeQuickFixesForIssue(issue, issue.entity, blueprintService, v.quickFixes)
         });
     });
+
+    allIssues.warnings.byMessage = {};
+    Object.values(allIssues.warnings.byEntity).forEach(list => {
+        list.forEach(issue => {
+            let key = issue.group+":"+issue.ref+":"+issue.message;
+            let v = allIssues.warnings.byMessage[key];
+            if (!v) {
+                v = allIssues.warnings.byMessage[key] = {
+                    group: issue.group,
+                    ref: issue.ref,
+                    message: issue.message,
+                    issues: [],
+                    quickFixes: {},
+                };
+            }
+
+            let issueO = {

Review comment:
       This is a copy-paste from existing code, see more detailled explanation below @algairim 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [brooklyn-ui] algairim commented on a change in pull request #241: Add support for an ancestor quick fix

Posted by GitBox <gi...@apache.org>.
algairim commented on a change in pull request #241:
URL: https://github.com/apache/brooklyn-ui/pull/241#discussion_r666363431



##########
File path: ui-modules/blueprint-composer/app/views/main/graphical/graphical.state.html
##########
@@ -19,129 +19,258 @@
 
 <div class="palette-and-or-toolbar">
 
-  <div class="layout">
-    <div class="toolbar">
-        <div class="list-group">
-            <a class="hand list-group-item"
-               ng-repeat="section in vm.sections track by $index"
-               ng-class="{'active': vm.selectedSection === section}"
-               ng-click="vm.selectedSection = section">
-                <i class="fa fa-fw" ng-class="section.icon"></i>
-            </a>
-
-            <div class="spacer"></div>
-            <a class="hand list-group-item errors-square"
-               title="Click to show/hide details of errors"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="allIssues.errors.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
-                <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
-            </a>
-            <a class="hand list-group-item warning-square"
-               title="Click to show/hide details of warnings"
-               ng-class="{ errorsActive: errorsPane.level }"
-               ng-show="!allIssues.errors.count && allIssues.warnings.count"
-               ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
-                <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
-            </a>
+    <div class="layout">
+        <div class="toolbar">
+            <div class="list-group">
+                <a class="hand list-group-item"
+                   ng-repeat="section in vm.sections track by $index"
+                   ng-class="{'active': vm.selectedSection === section}"
+                   ng-click="vm.selectedSection = section">
+                    <i class="fa fa-fw" ng-class="section.icon"></i>
+                </a>
+
+                <div class="spacer"></div>
+                <a class="hand list-group-item errors-square"
+                   title="Click to show/hide details of errors"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="allIssues.errors.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'error-errors'">
+                    <i class="fa fa-fw fa-times-circle"></i> {{ allIssues.errors.count }}
+                </a>
+                <a class="hand list-group-item warning-square"
+                   title="Click to show/hide details of warnings"
+                   ng-class="{ errorsActive: errorsPane.level }"
+                   ng-show="!allIssues.errors.count && allIssues.warnings.count"
+                   ng-click="errorsPane.level = errorsPane.level ? null : 'summary'">
+                    <i class="fa fa-fw fa-exclamation-triangle"></i> {{ allIssues.warnings.count }}
+                </a>
+            </div>
         </div>
-    </div>
 
-      <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
-          <div class="errors-body">
+        <div ng-if="errorsPane.level == 'summary'" class="errors-popout">
+            <div class="errors-body">
+
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <div ng-if="allIssues.errors.count">
+                    <a class="hand" ng-click="errorsPane.level = 'error-errors'">
+                        <ng-pluralize count="allIssues.errors.count"
+                                      when="{'one': '{} error', 'other': '{} errors'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'error-entities'">
+                        <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="allIssues.warnings.count">
+                    <a class="hand" ng-click="errorsPane.level = 'warning-errors'">
+                        <ng-pluralize count="allIssues.warnings.count"
+                                      when="{'one': '{} warning', 'other': '{} warnings'}" />
+                    </a>
+                    in
+                    <a class="hand" ng-click="errorsPane.level = 'warning-entities'">
+                        <ng-pluralize count="vm.size(allIssues.warnings.byEntity)"
+                                      when="{'one': '{} entity', 'other': '{} entities'}" />
+                    </a>
+                </div>
+
+                <div ng-if="!allIssues.errors.count && !allIssues.warnings.count">
+                    No errors or warnings.
+                </div>
+
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-entities'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
 
-              <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+                <strong>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
+                </strong>
+
+                with
 
-            <div ng-if="allIssues.errors.count">
                 <a class="hand" ng-click="errorsPane.level = 'error-errors'">
-                {{ allIssues.errors.count }}
-                    <span ng-if="allIssues.errors.count == 1">error</span>
-                    <span ng-if="allIssues.errors.count != 1">errors</span>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
                 </a>
+            </div>
+
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byEntity" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                        {{ vm.entitySummary(allIssues.entities[itemK]) }}:
+                        {{ itemV.length }} {{ itemV.length==1 ? 'error' : 'errors' }}
+                    </div>
+                    <div class="error-line-action">
+                        <a class="hand" ui-sref="main.graphical.edit.entity({entityId: itemK})">
+                            <i class="fa fa-fw fa-external-link"></i>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div ng-if="errorsPane.level == 'error-errors'" class="errors-popout">
+            <div class="errorsHeader">
+                <a ng-click="errorsPane.level = null" class="hand errors-close"><i class="fa fa-fw fa-times"></i></a>
+
+                <strong>
+                    <ng-pluralize count="allIssues.errors.count"
+                                  when="{'one': '{} error', 'other': '{} errors'}" />
+                </strong>
+
+                <span ng-show="allIssues.errors.count != vm.size(allIssues.errors.byMessage)"> ({{ vm.size(allIssues.errors.byMessage) }} unique)</span>
+
                 in
+
                 <a class="hand" ng-click="errorsPane.level = 'error-entities'">
-                    {{ vm.size(allIssues.errors.byEntity) }}
-                    <span ng-if="vm.size(allIssues.errors.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.errors.byEntity) != 1">entities</span>
+                    <ng-pluralize count="vm.size(allIssues.errors.byEntity)"
+                                  when="{'one': '{} entity', 'other': '{} entities'}" />
                 </a>
             </div>
 
-            <!-- TODO add links and panels for warnings -->
-            <div ng-if="allIssues.warnings.count">
-                {{ allIssues.warnings.count }}
-                    <span ng-if="allIssues.errors.count == 1">warning</span>
-                    <span ng-if="allIssues.errors.count != 1">warnings</span>
-                in {{ vm.size(allIssues.warnings.byEntity) }}
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) == 1">entity</span>
-                    <span ng-if="vm.size(allIssues.warnings.byEntity) != 1">entities</span>
+            <div class="errors-body">
+                <div ng-repeat="(itemK,itemV) in allIssues.errors.byMessage" class="error-line">
+                    <div class="error-line-marker">
+                        <i class="fa fa-fw fa-times-circle"></i>
+                    </div>
+                    <div class="error-line-text">
+                      <span>
+                          <span ng-show="vm.messageNeedsPrefix(itemV)">
+                              {{ itemV.group }} {{ itemV.ref }}<span ng-show="itemV.message">:</span>
+                          </span>
+                          <span ng-show="itemV.message">
+                              <ng-bind-html ng-bind-html="itemV.message"></ng-bind-html>
+                          </span>
+                      </span>
+
+                        (<a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'errors:'+itemK ? null : 'errors:'+itemK)"
+                            ng-class="{active: errorsPane.focus == 'errors:'+itemK }">
+                            <ng-pluralize count="itemV.issues.length"
+                                          when="{'one': '{} entity', 'other': '{} entities'}" />
+                        </a>
+                        <span ng-if="vm.size(itemV.quickFixes)">;
+                          <a class="hand" ng-click="errorsPane.focus = (errorsPane.focus == 'fixes:'+itemK ? null : 'fixes:'+itemK)"
+                             ng-class="{active: errorsPane.focus == 'fixes:'+itemK }">
+                             <ng-pluralize count="vm.size(itemV.quickFixes)"
+                                           when="{'one': '{} quick fix', 'other': '{} quick fixes'}" />
+                             available
+                          </a>
+                        </span>)
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'errors:'+itemK">
+                            <div ng-repeat="issue in itemV.issues" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-circle"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ vm.entitySummary(issue.issue.entity) }}
+                                    <!-- could offer the issue-specific quick fixes; but clearer to navigate to entity and do there -->
+                                </div>
+                                <div class="error-line-action">
+                                    <a class="hand" ui-sref="main.graphical.edit.entity({entityId: issue.issue.entity._id})">
+                                        <i class="fa fa-fw fa-external-link"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="error-line-sub" ng-if="errorsPane.focus == 'fixes:'+itemK">
+                            <div ng-repeat="fix in itemV.quickFixes" class="error-line-sub-line">
+                                <div class="error-line-marker">
+                                    <i class="fa fa-fw fa-magic"></i>
+                                </div>
+                                <div class="error-line-text">
+                                    {{ fix.text }}
+                                    <a class="hand btn btn-xs btn-primary" style="float: right;" ng-click="vm.applyQuickFix(fix)"
+                                       ng-attr-title="{{ fix.tooltip }}"
+                                    >Apply
+                                        (<ng-pluralize count="vm.size(fix.issues)"

Review comment:
       Typo: redundant parentheses at the beginning.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@brooklyn.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org