scottyaslan commented on code in PR #8974:
URL: https://github.com/apache/nifi/pull/8974#discussion_r1720294792


##########
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html:
##########
@@ -0,0 +1,258 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<div class="flow-analysis-drawer h-full w-96 p-5">
+    <component-context type="ProcessGroup" [name]="processGroupName" 
[id]="currentProcessGroupId"></component-context>
+    <div class="flex items-center w-full">
+        <ng-container *ngIf="isAnalysisPending">
+            <span *nifiSpinner="isAnalysisPending"></span>
+            <div class="ml-1">Rules analysis pending...</div>
+        </ng-container>
+    </div>
+    <div class="mt-5">
+        <div class="flex items-center justify-between">
+            <div>
+                <div>
+                    <mat-checkbox class="text-sm" color="primary" 
[(ngModel)]="showEnforcedViolations">
+                        Show enforced violations
+                    </mat-checkbox>
+                </div>
+                <div>
+                    <mat-checkbox color="primary" 
[(ngModel)]="showWarningViolations">
+                        Show warning violations
+                    </mat-checkbox>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="mt-5 mb-2" [hidden]="showEnforcedViolations() || 
showWarningViolations()">
+        <div class="flex flex-col gap-y-2">
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Enforced Rules ({{ enforcedRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of enforcedRules; track rule.id) {
+                        <div class="mb-2">
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="warn-color-darker text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                @for (violation of violationsMap.get(rule.id); 
track violation.scope) {
+                                    <div class="flex align-center 
justify-between mt-2">
+                                        <div class="flex flex-col items-start 
ml-2">
+                                            <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                {{ 
violation.subjectDisplayName }}
+                                            </div>
+                                            <span class="text-sm">
+                                                {{ violation.subjectId }}
+                                            </span>
+                                        </div>
+
+                                        <ng-template
+                                            
[ngTemplateOutlet]="violationMenuTemplate"
+                                            [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                    </div>
+                                }
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Warning Rules ({{ warningRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of warningRules; track rule.id) {
+                        <div>
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu" class="rule-menu 
w-52 shadow-lg">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="primary-color text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                <ul>
+                                    @for (violation of 
violationsMap.get(rule.id); track violation.scope) {
+                                        <li class="flex align-center 
justify-between mt-2">
+                                            <div class="flex flex-col 
items-start ml-2">
+                                                <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                    {{ 
violation.subjectDisplayName }}
+                                                </div>
+                                                <span class="text-sm">
+                                                    {{ violation.subjectId }}
+                                                </span>
+                                            </div>
+
+                                            <ng-template
+                                                
[ngTemplateOutlet]="violationMenuTemplate"
+                                                [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                        </li>
+                                    }
+                                </ul>
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+        </div>
+    </div>
+
+    <div class="mt-5 mb-2" [hidden]="!showEnforcedViolations()" 
[class.mb-5]="!showWarningViolations()">
+        <div class="border-b pb-2">
+            <div>
+                Enforced Violations
+                <span>({{ enforcedViolations.length }})</span>
+            </div>
+        </div>
+
+        <ul>
+            @for (violation of enforcedViolations; track violation.scope) {
+                <li class="mt-2 pb-2 border-b border-white 
last-of-type:border-0">
+                    <div class="warn-color-darker">{{ 
getRuleName(violation.ruleId) }}</div>
+                    <div class="flex align-center justify-between ml-2">
+                        <div class="flex flex-col items-start">
+                            <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                {{ violation.subjectDisplayName }}
+                            </div>
+                            <span class="text-sm">{{ violation.subjectId 
}}</span>
+                        </div>
+
+                        <ng-template [ngTemplateOutlet]="violationMenuTemplate"
+                                     [ngTemplateOutletContext]="{ violation: 
violation }"></ng-template>
+                    </div>
+                </li>
+            }
+        </ul>
+    </div>
+
+    <div class="mt-5 mb-2" [hidden]="!showWarningViolations()">
+        <div class="border-b pb-2">

Review Comment:
   ```suggestion
           <div class="border-b mb-2">
   ```



##########
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html:
##########
@@ -0,0 +1,258 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<div class="flow-analysis-drawer h-full w-96 p-5">
+    <component-context type="ProcessGroup" [name]="processGroupName" 
[id]="currentProcessGroupId"></component-context>
+    <div class="flex items-center w-full">
+        <ng-container *ngIf="isAnalysisPending">
+            <span *nifiSpinner="isAnalysisPending"></span>
+            <div class="ml-1">Rules analysis pending...</div>
+        </ng-container>
+    </div>
+    <div class="mt-5">
+        <div class="flex items-center justify-between">
+            <div>
+                <div>
+                    <mat-checkbox class="text-sm" color="primary" 
[(ngModel)]="showEnforcedViolations">
+                        Show enforced violations
+                    </mat-checkbox>
+                </div>
+                <div>
+                    <mat-checkbox color="primary" 
[(ngModel)]="showWarningViolations">
+                        Show warning violations
+                    </mat-checkbox>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="mt-5 mb-2" [hidden]="showEnforcedViolations() || 
showWarningViolations()">
+        <div class="flex flex-col gap-y-2">
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Enforced Rules ({{ enforcedRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of enforcedRules; track rule.id) {
+                        <div class="mb-2">
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="warn-color-darker text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                @for (violation of violationsMap.get(rule.id); 
track violation.scope) {
+                                    <div class="flex align-center 
justify-between mt-2">
+                                        <div class="flex flex-col items-start 
ml-2">
+                                            <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                {{ 
violation.subjectDisplayName }}
+                                            </div>
+                                            <span class="text-sm">
+                                                {{ violation.subjectId }}
+                                            </span>
+                                        </div>
+
+                                        <ng-template
+                                            
[ngTemplateOutlet]="violationMenuTemplate"
+                                            [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                    </div>
+                                }
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Warning Rules ({{ warningRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of warningRules; track rule.id) {
+                        <div>
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu" class="rule-menu 
w-52 shadow-lg">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="primary-color text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                <ul>
+                                    @for (violation of 
violationsMap.get(rule.id); track violation.scope) {
+                                        <li class="flex align-center 
justify-between mt-2">
+                                            <div class="flex flex-col 
items-start ml-2">
+                                                <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                    {{ 
violation.subjectDisplayName }}
+                                                </div>
+                                                <span class="text-sm">
+                                                    {{ violation.subjectId }}
+                                                </span>
+                                            </div>
+
+                                            <ng-template
+                                                
[ngTemplateOutlet]="violationMenuTemplate"
+                                                [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                        </li>
+                                    }
+                                </ul>
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+        </div>
+    </div>
+
+    <div class="mt-5 mb-2" [hidden]="!showEnforcedViolations()" 
[class.mb-5]="!showWarningViolations()">
+        <div class="border-b pb-2">
+            <div>
+                Enforced Violations
+                <span>({{ enforcedViolations.length }})</span>
+            </div>
+        </div>
+
+        <ul>
+            @for (violation of enforcedViolations; track violation.scope) {
+                <li class="mt-2 pb-2 border-b border-white 
last-of-type:border-0">
+                    <div class="warn-color-darker">{{ 
getRuleName(violation.ruleId) }}</div>
+                    <div class="flex align-center justify-between ml-2">
+                        <div class="flex flex-col items-start">
+                            <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                {{ violation.subjectDisplayName }}
+                            </div>
+                            <span class="text-sm">{{ violation.subjectId 
}}</span>
+                        </div>
+
+                        <ng-template [ngTemplateOutlet]="violationMenuTemplate"
+                                     [ngTemplateOutletContext]="{ violation: 
violation }"></ng-template>
+                    </div>
+                </li>
+            }
+        </ul>
+    </div>
+
+    <div class="mt-5 mb-2" [hidden]="!showWarningViolations()">
+        <div class="border-b pb-2">
+            <div>
+                Warning Violations
+                <span>({{ warningViolations.length }})</span>
+            </div>
+        </div>
+
+        <ul>
+            @for (violation of warningViolations; track violation.scope) {
+                <li class="mt-2 pb-2 border-b border-white 
last-of-type:border-0">

Review Comment:
   ```suggestion
                   <li class="mt-2 mb-2 border-b border-white 
last-of-type:border-0">
   ```



##########
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html:
##########
@@ -0,0 +1,258 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<div class="flow-analysis-drawer h-full w-96 p-5">
+    <component-context type="ProcessGroup" [name]="processGroupName" 
[id]="currentProcessGroupId"></component-context>
+    <div class="flex items-center w-full">
+        <ng-container *ngIf="isAnalysisPending">
+            <span *nifiSpinner="isAnalysisPending"></span>
+            <div class="ml-1">Rules analysis pending...</div>
+        </ng-container>
+    </div>
+    <div class="mt-5">
+        <div class="flex items-center justify-between">
+            <div>
+                <div>
+                    <mat-checkbox class="text-sm" color="primary" 
[(ngModel)]="showEnforcedViolations">
+                        Show enforced violations
+                    </mat-checkbox>
+                </div>
+                <div>
+                    <mat-checkbox color="primary" 
[(ngModel)]="showWarningViolations">
+                        Show warning violations
+                    </mat-checkbox>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="mt-5 mb-2" [hidden]="showEnforcedViolations() || 
showWarningViolations()">
+        <div class="flex flex-col gap-y-2">
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Enforced Rules ({{ enforcedRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of enforcedRules; track rule.id) {
+                        <div class="mb-2">
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="warn-color-darker text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                @for (violation of violationsMap.get(rule.id); 
track violation.scope) {
+                                    <div class="flex align-center 
justify-between mt-2">
+                                        <div class="flex flex-col items-start 
ml-2">
+                                            <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                {{ 
violation.subjectDisplayName }}
+                                            </div>
+                                            <span class="text-sm">
+                                                {{ violation.subjectId }}
+                                            </span>
+                                        </div>
+
+                                        <ng-template
+                                            
[ngTemplateOutlet]="violationMenuTemplate"
+                                            [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                    </div>
+                                }
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Warning Rules ({{ warningRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of warningRules; track rule.id) {
+                        <div>
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu" class="rule-menu 
w-52 shadow-lg">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="primary-color text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                <ul>
+                                    @for (violation of 
violationsMap.get(rule.id); track violation.scope) {
+                                        <li class="flex align-center 
justify-between mt-2">
+                                            <div class="flex flex-col 
items-start ml-2">
+                                                <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                    {{ 
violation.subjectDisplayName }}
+                                                </div>
+                                                <span class="text-sm">
+                                                    {{ violation.subjectId }}
+                                                </span>
+                                            </div>
+
+                                            <ng-template
+                                                
[ngTemplateOutlet]="violationMenuTemplate"
+                                                [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                        </li>
+                                    }
+                                </ul>
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+        </div>
+    </div>
+
+    <div class="mt-5 mb-2" [hidden]="!showEnforcedViolations()" 
[class.mb-5]="!showWarningViolations()">
+        <div class="border-b pb-2">
+            <div>
+                Enforced Violations
+                <span>({{ enforcedViolations.length }})</span>
+            </div>
+        </div>
+
+        <ul>
+            @for (violation of enforcedViolations; track violation.scope) {
+                <li class="mt-2 pb-2 border-b border-white 
last-of-type:border-0">

Review Comment:
   ```suggestion
                   <li class="mt-2 mb-2 border-b border-white 
last-of-type:border-0">
   ```



##########
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/canvas/header/flow-analysis-drawer/flow-analysis-drawer.component.html:
##########
@@ -0,0 +1,258 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<div class="flow-analysis-drawer h-full w-96 p-5">
+    <component-context type="ProcessGroup" [name]="processGroupName" 
[id]="currentProcessGroupId"></component-context>
+    <div class="flex items-center w-full">
+        <ng-container *ngIf="isAnalysisPending">
+            <span *nifiSpinner="isAnalysisPending"></span>
+            <div class="ml-1">Rules analysis pending...</div>
+        </ng-container>
+    </div>
+    <div class="mt-5">
+        <div class="flex items-center justify-between">
+            <div>
+                <div>
+                    <mat-checkbox class="text-sm" color="primary" 
[(ngModel)]="showEnforcedViolations">
+                        Show enforced violations
+                    </mat-checkbox>
+                </div>
+                <div>
+                    <mat-checkbox color="primary" 
[(ngModel)]="showWarningViolations">
+                        Show warning violations
+                    </mat-checkbox>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="mt-5 mb-2" [hidden]="showEnforcedViolations() || 
showWarningViolations()">
+        <div class="flex flex-col gap-y-2">
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Enforced Rules ({{ enforcedRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of enforcedRules; track rule.id) {
+                        <div class="mb-2">
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="warn-color-darker text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                @for (violation of violationsMap.get(rule.id); 
track violation.scope) {
+                                    <div class="flex align-center 
justify-between mt-2">
+                                        <div class="flex flex-col items-start 
ml-2">
+                                            <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                {{ 
violation.subjectDisplayName }}
+                                            </div>
+                                            <span class="text-sm">
+                                                {{ violation.subjectId }}
+                                            </span>
+                                        </div>
+
+                                        <ng-template
+                                            
[ngTemplateOutlet]="violationMenuTemplate"
+                                            [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                    </div>
+                                }
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+            <mat-expansion-panel hideToggle>
+                <mat-expansion-panel-header>
+                    <mat-panel-title>
+                        <div class="flex flex-1 justify-start">
+                            <div>Warning Rules ({{ warningRules.length 
}})</div>
+                        </div>
+                    </mat-panel-title>
+                </mat-expansion-panel-header>
+
+                @if (rules) {
+                    @for (rule of warningRules; track rule.id) {
+                        <div>
+                            <div class="flex justify-between">
+                                <div class="flex items-center">{{ rule.name 
}}</div>
+                                <button
+                                    mat-icon-button
+                                    type="button"
+                                    [matMenuTriggerFor]="menu"
+                                    class="h-16 w-16 flex items-center 
justify-center">
+                                    <i class="fa fa-ellipsis-v"></i>
+                                </button>
+                                <mat-menu #menu="matMenu" class="rule-menu 
w-52 shadow-lg">
+                                    <button mat-menu-item 
(click)="openDocumentation(rule)">
+                                        <i class="fa fa-book mr-2 
primary-color"></i>
+                                        View Documentation
+                                    </button>
+                                    <button mat-menu-item 
(click)="openRule(rule)">
+                                        <i class="fa fa-cog mr-2 
primary-color"></i>
+                                        Edit Rule
+                                    </button>
+                                </mat-menu>
+                            </div>
+                            @if (violationsMap.size > 0 && 
violationsMap.get(rule.id)) {
+                                <div class="primary-color text-sm">
+                                    <ng-container 
[ngPlural]="violationsMap.get(rule.id).length">
+                                        <ng-template ngPluralCase="=1"
+                                            >{{ 
violationsMap.get(rule.id).length }} violation</ng-template
+                                        >
+                                        <ng-template ngPluralCase="other"
+                                            >{{ 
violationsMap.get(rule.id).length }} violations</ng-template
+                                        >
+                                    </ng-container>
+                                </div>
+                                <ul>
+                                    @for (violation of 
violationsMap.get(rule.id); track violation.scope) {
+                                        <li class="flex align-center 
justify-between mt-2">
+                                            <div class="flex flex-col 
items-start ml-2">
+                                                <div 
*ngIf="violation?.subjectPermissionDto?.canRead; else unauthorized">
+                                                    {{ 
violation.subjectDisplayName }}
+                                                </div>
+                                                <span class="text-sm">
+                                                    {{ violation.subjectId }}
+                                                </span>
+                                            </div>
+
+                                            <ng-template
+                                                
[ngTemplateOutlet]="violationMenuTemplate"
+                                                [ngTemplateOutletContext]="{ 
violation: violation }"></ng-template>
+                                        </li>
+                                    }
+                                </ul>
+                            }
+                        </div>
+                    }
+                }
+            </mat-expansion-panel>
+        </div>
+    </div>
+
+    <div class="mt-5 mb-2" [hidden]="!showEnforcedViolations()" 
[class.mb-5]="!showWarningViolations()">
+        <div class="border-b pb-2">

Review Comment:
   ```suggestion
           <div class="border-b mb-2">
   ```



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to