mcgilman commented on code in PR #8143:
URL: https://github.com/apache/nifi/pull/8143#discussion_r1427086417


##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/status-history/status-history.component.html:
##########
@@ -0,0 +1,157 @@
+<!--
+  ~  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 resizable (resized)="resized($event)" [minHeight]="630" [minWidth]="830" 
class="flex flex-col">
+    <ng-container *ngIf="statusHistoryState$ | async; let statusHistoryState">
+        <h2 mat-dialog-title>Status History</h2>
+        <div class="status-history flex flex-col grow">
+            <mat-dialog-content class="grow flex flex-1">
+                <form [formGroup]="statusHistoryForm" class="flex flex-1 
h-full">
+                    <div class="dialog-content flex w-full flex-1">
+                        <div *ngIf="isInitialLoading(statusHistoryState); else 
loaded" class="flex-1">
+                            <ngx-skeleton-loader 
count="3"></ngx-skeleton-loader>
+                        </div>
+                        <ng-template #loaded>
+                            <ng-container *ngIf="instances.length > 0; else 
insufficientHistory">
+                                <div
+                                    *ngIf="componentDetails$ | async; let 
componentDetails"
+                                    class="flex flex-1 w-full gap-x-4">
+                                    <div class="component-details flex 
flex-col gap-y-3">
+                                        <div
+                                            *ngFor="let entry of 
Object.entries(componentDetails)"
+                                            class="flex flex-col">
+                                            <div>{{ entry[0] }}</div>
+                                            <div class="value">{{ entry[1] 
}}</div>
+                                        </div>
+                                        <div class="flex flex-col">
+                                            <div>Start</div>
+                                            <div class="value">{{ minDate 
}}</div>
+                                        </div>
+                                        <div class="flex flex-col">
+                                            <div>End</div>
+                                            <div class="value">{{ maxDate 
}}</div>
+                                        </div>
+                                        <div class="flex flex-col">
+                                            <div class="font-bold">NiFi</div>
+                                            <div class="detail-item">
+                                                <div>Min / Max / Mean</div>
+                                                <div class="value">
+                                                    {{ clusterStats.min }} / 
{{ clusterStats.max }} /
+                                                    {{ clusterStats.mean }}
+                                                </div>
+                                            </div>
+                                            <div class="legend-entry">
+                                                <mat-checkbox
+                                                    value="nifi-instance-id"
+                                                    
(change)="selectNode($event)"
+                                                    
[checked]="!!instanceVisibility['nifi-instance-id']"></mat-checkbox>
+                                                <mat-label>NiFi</mat-label>
+                                            </div>
+                                        </div>
+                                        <div class="flex flex-col" 
*ngIf="!!nodes && nodes.length > 0">
+                                            <div>Nodes</div>
+                                            <div>
+                                                <div>Min / Max / Mean</div>
+                                                <div class="value">
+                                                    {{ nodeStats.min }} / {{ 
nodeStats.max }} / {{ nodeStats.mean }}
+                                                </div>
+                                            </div>
+                                            <!-- TODO display nodes to select 
from-->
+                                            <div class="legend-entry">
+                                                <ng-container *ngFor="let node 
of nodes">
+                                                    <mat-checkbox
+                                                        [value]="node.id"
+                                                        
(change)="selectNode($event)"
+                                                        [checked]="
+                                                            
!!instanceVisibility['nifi-instance-id']
+                                                        "></mat-checkbox>
+                                                    <mat-label>{{ node.label 
}}</mat-label>
+                                                </ng-container>
+                                            </div>
+                                        </div>
+                                    </div>
+                                    <div class="chart-panel grow flex 
flex-col">
+                                        <div *ngIf="fieldDescriptors$ | async">
+                                            <mat-form-field>
+                                                <mat-select 
formControlName="fieldDescriptor">
+                                                    <ng-container *ngFor="let 
descriptor of fieldDescriptors">
+                                                        <ng-container
+                                                            
*ngIf="descriptor.description; else noDescription">
+                                                            <mat-option
+                                                                
[value]="descriptor"
+                                                                nifiTooltip
+                                                                
[tooltipComponentType]="TextTip"
+                                                                
[tooltipInputData]="getSelectOptionTipData(descriptor)"
+                                                                
[delayClose]="false">
+                                                                <span 
class="option-text">{{ descriptor.label }}</span>
+                                                            </mat-option>
+                                                        </ng-container>
+                                                        <ng-template 
#noDescription>
+                                                            <mat-option 
[value]="descriptor">
+                                                                <span 
class="option-text">{{ descriptor.label }}</span>
+                                                            </mat-option>
+                                                        </ng-template>
+                                                    </ng-container>
+                                                </mat-select>
+                                            </mat-form-field>
+                                        </div>
+                                        <status-history-chart
+                                            [instances]="instances"
+                                            
[visibleInstances]="instanceVisibility"
+                                            
[selectedFieldDescriptor]="selectedDescriptor"
+                                            
(nodeStats)="nodeStatsChanged($event)"
+                                            
(clusterStats)="clusterStatsChanged($event)"
+                                            class="flex flex-1 flex-col">
+                                        </status-history-chart>
+
+                                        <!--                                   
     <div id="status-history-container" class="flex-1 flex flex-col">-->
+                                        <!--                                   
         <div id="status-history-chart-container" class="grow">chart goes 
here</div>-->
+                                        <!--                                   
         <div id="status-history-chart-control-container">control goes 
here</div>-->
+                                        <!--                                   
     </div>-->

Review Comment:
   Are these still needed?



##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/nifi-common.service.ts:
##########
@@ -316,4 +327,65 @@ export class NiFiCommon {
             return time;
         }
     }
+
+    /**
+     * Formats the specified number of bytes into a human readable string.
+     *
+     * @param {number} dataSize
+     * @returns {string}
+     */
+    public formatDataSize(dataSize: number): string {
+        let dataSizeToFormat: number = parseFloat(`${dataSize / 
NiFiCommon.BYTES_IN_TERABYTE}`);
+        if (dataSizeToFormat > 1) {
+            return dataSizeToFormat.toFixed(2) + ' TB';
+        }
+
+        // check gigabytes
+        dataSizeToFormat = parseFloat(`${dataSize / 
NiFiCommon.BYTES_IN_GIGABYTE}`);
+        if (dataSizeToFormat > 1) {
+            return dataSizeToFormat.toFixed(2) + ' GB';
+        }
+
+        // check megabytes
+        dataSizeToFormat = parseFloat(`${dataSize / 
NiFiCommon.BYTES_IN_MEGABYTE}`);
+        if (dataSizeToFormat > 1) {
+            return dataSizeToFormat.toFixed(2) + ' MB';
+        }
+
+        // check kilobytes
+        dataSizeToFormat = parseFloat(`${dataSize / 
NiFiCommon.BYTES_IN_KILOBYTE}`);
+        if (dataSizeToFormat > 1) {
+            return dataSizeToFormat.toFixed(2) + ' KB';
+        }
+
+        // default to bytes
+        return parseFloat(`${dataSize}`).toFixed(2) + ' bytes';
+    }
+
+    /**
+     * Formats the specified integer as a string (adding commas). At this
+     * point this does not take into account any locales.
+     *
+     * @param {integer} integer
+     */
+    public formatInteger(integer: number): string {
+        let string: string = String(integer);
+        const regex: RegExp = /(\d+)(\d{3})/;
+        while (regex.test(string)) {
+            string = string.replace(regex, '$1' + ',' + '$2');
+        }
+        return string;

Review Comment:
   Thanks for updating here. I realize this came over from the existing 
`nf-common` that now I'm wondering if we an opportunity to improve here over 
what was written years ago. Maybe we consider using `toLocaleString()` or 
`NumberFormat`.
   
   [1] https://stackoverflow.com/a/32154217



##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/summary/ui/processor-status-listing/processor-status-table/processor-status-table.component.html:
##########
@@ -0,0 +1,231 @@
+<!--
+  ~  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="counter-table h-full flex flex-col">
+    <!-- allow filtering of the table -->
+    <summary-table-filter
+        [filteredCount]="filteredCount"
+        [totalCount]="totalCount"
+        [filterableColumns]="filterableColumns"
+        [includeStatusFilter]="true"
+        [includePrimaryNodeOnlyFilter]="true"
+        (filterChanged)="applyFilter($event)"></summary-table-filter>
+
+    <div class="flex-1 relative">
+        <div class="listing-table overflow-y-auto border absolute inset-0">
+            <table
+                mat-table
+                [dataSource]="dataSource"
+                matSort
+                matSortDisableClear
+                (matSortChange)="sortData($event)"
+                [matSortActive]="initialSortColumn"
+                [matSortDirection]="initialSortDirection">
+                <!-- More Details Column -->
+                <ng-container matColumnDef="moreDetails">
+                    <th mat-header-cell *matHeaderCellDef></th>
+                    <td mat-cell *matCellDef="let item">
+                        <ng-container *ngIf="canRead(item)">
+                            <div class="flex items-center gap-x-3">
+                                <!-- TODO - handle read only in configure 
component? -->
+                                <div
+                                    class="pointer fa fa-info-circle"
+                                    *ngIf="canRead(item)"
+                                    title="View Processor Details"></div>
+                            </div>
+                        </ng-container>
+                    </td>
+                </ng-container>
+
+                <!-- Name Column -->
+                <ng-container matColumnDef="name">
+                    <th mat-header-cell *matHeaderCellDef 
mat-sort-header>Name</th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatName(item) }}
+                    </td>
+                </ng-container>
+
+                <!-- Type column -->
+                <ng-container matColumnDef="type">
+                    <th mat-header-cell *matHeaderCellDef 
mat-sort-header>Type</th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatType(item) }}
+                    </td>
+                </ng-container>
+
+                <!-- Process Group column -->
+                <ng-container matColumnDef="processGroup">
+                    <th mat-header-cell *matHeaderCellDef 
mat-sort-header>Process Group</th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatProcessGroup(item) }}
+                    </td>
+                </ng-container>
+
+                <!-- Run Status column -->
+                <ng-container matColumnDef="runStatus">
+                    <th mat-header-cell *matHeaderCellDef mat-sort-header>Run 
Status</th>
+                    <td mat-cell *matCellDef="let item">
+                        <div class="flex items-center gap-x-2">
+                            <div [ngClass]="getRunStatusIcon(item)"></div>
+                            <div>{{ formatRunStatus(item) }}</div>
+
+                            <ng-container *ngIf="item.processorStatusSnapshot 
as pg">
+                                <div
+                                    *ngIf="pg.terminatedThreadCount > 0; else 
activeThreads"
+                                    title="Threads: (Active / Terminated)">
+                                    ({{ pg.activeThreadCount }}/{{ 
pg.terminatedThreadCount }})
+                                </div>
+                                <ng-template #activeThreads>
+                                    <div *ngIf="pg.activeThreadCount > 0" 
title="Active Threads">
+                                        ({{ pg.activeThreadCount }})
+                                    </div>
+                                </ng-template>
+                            </ng-container>
+                        </div>
+                    </td>
+                </ng-container>
+
+                <!-- Input column -->
+                <ng-container matColumnDef="in">
+                    <th
+                        mat-header-cell
+                        *matHeaderCellDef
+                        mat-sort-header
+                        title="Count / data size in the last 5 minutes">
+                        <div class="flex items-center gap-x-1">
+                            <div [ngClass]="{ underline: multiSort.active === 
'in' && multiSort.sortValueIndex === 0 }">
+                                In
+                            </div>
+                            <div [ngClass]="{ underline: multiSort.active === 
'in' && multiSort.sortValueIndex === 1 }">
+                                (Size)
+                            </div>
+                            <div class="font-light">5 min</div>
+                        </div>
+                    </th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatIn(item) }}
+                    </td>
+                </ng-container>
+
+                <!-- Read Write column -->
+                <ng-container matColumnDef="readWrite">
+                    <th mat-header-cell *matHeaderCellDef mat-sort-header 
title="Data size in the last 5 minutes">
+                        <div class="flex items-center gap-x-1">
+                            <div
+                                [ngClass]="{
+                                    underline: multiSort.active === 
'readWrite' && multiSort.sortValueIndex === 0
+                                }">
+                                Read
+                            </div>
+                            <div>|</div>
+                            <div
+                                [ngClass]="{
+                                    underline: multiSort.active === 
'readWrite' && multiSort.sortValueIndex === 1
+                                }">
+                                Write
+                            </div>
+                            <div class="font-light">5 min</div>
+                        </div>
+                    </th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatReadWrite(item) }}
+                    </td>
+                </ng-container>
+
+                <!-- Output column -->
+                <ng-container matColumnDef="out">
+                    <th
+                        mat-header-cell
+                        *matHeaderCellDef
+                        mat-sort-header
+                        title="Count / data size in the last 5 minutes">
+                        <div class="flex items-center gap-x-1">
+                            <div
+                                [ngClass]="{ underline: multiSort.active === 
'out' && multiSort.sortValueIndex === 0 }">
+                                Out
+                            </div>
+                            <div
+                                [ngClass]="{ underline: multiSort.active === 
'out' && multiSort.sortValueIndex === 1 }">
+                                (Size)
+                            </div>
+                            <div class="font-light">5 min</div>
+                        </div>
+                    </th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatOut(item) }}
+                    </td>
+                </ng-container>
+
+                <!-- Tasks column -->
+                <ng-container matColumnDef="tasks">
+                    <th
+                        mat-header-cell
+                        *matHeaderCellDef
+                        mat-sort-header
+                        title="Count / duration in the last 5 minutes">
+                        <div class="flex items-center gap-x-1">
+                            <div
+                                [ngClass]="{
+                                    underline: multiSort.active === 'tasks' && 
multiSort.sortValueIndex === 0
+                                }">
+                                Tasks
+                            </div>
+                            <div>|</div>
+                            <div
+                                [ngClass]="{
+                                    underline: multiSort.active === 'tasks' && 
multiSort.sortValueIndex === 1
+                                }">
+                                Time
+                            </div>
+                            <div class="font-light">5 min</div>
+                        </div>
+                    </th>
+                    <td mat-cell *matCellDef="let item">
+                        {{ formatTasks(item) }}
+                    </td>
+                </ng-container>
+
+                <ng-container matColumnDef="actions">
+                    <th mat-header-cell *matHeaderCellDef></th>
+                    <td mat-cell *matCellDef="let item">
+                        <div class="flex items-center gap-x-3">
+                            <div
+                                class="pointer fa fa-long-arrow-right"
+                                [routerLink]="getProcessorLink(item)"
+                                (click)="gotoProcessor.next(item)"

Review Comment:
   Sorry if I worded it poorly above but I was suggesting that we use 
`routerLink` when possible. With the update you removed it in favor or the 
`click` handler.



-- 
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: issues-unsubscr...@nifi.apache.org

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

Reply via email to