[NIFI-12615] - fix ExpressionChanged error on Counters page. (#8252)

* [NIFI-12615] - fix ExpressionChanged error on Counters page.

* * refactor sorting for extension-creation.component
* refactor sorting for controller-service-table.component
* refactor sorting for reporting-task--table.component
* refactor sorting for parameter-context-table.component

This closes #8252
This commit is contained in:
Rob Fellows 2024-01-16 15:46:08 -05:00 committed by GitHub
parent c6f5f534cb
commit b47ca20f56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 266 additions and 162 deletions

View File

@ -44,6 +44,7 @@
[dataSource]="dataSource"
matSort
matSortDisableClear
(matSortChange)="sortData($event)"
[matSortActive]="initialSortColumn"
[matSortDirection]="initialSortDirection">
<!-- Context column -->

View File

@ -15,10 +15,10 @@
* limitations under the License.
*/
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core';
import { CounterEntity } from '../../../state/counter-listing';
import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { Sort } from '@angular/material/sort';
import { FormBuilder, FormGroup } from '@angular/forms';
import { debounceTime } from 'rxjs';
import { NiFiCommon } from '../../../../../service/nifi-common.service';
@ -39,24 +39,14 @@ export class CounterTable implements AfterViewInit {
dataSource: MatTableDataSource<CounterEntity> = new MatTableDataSource<CounterEntity>();
filterForm: FormGroup;
@Input() initialSortColumn: 'context' | 'name' = 'context';
@Input() initialSortColumn: 'context' | 'name' | 'value' = 'context';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
@Input() set counters(counterEntities: CounterEntity[]) {
this.dataSource = new MatTableDataSource<CounterEntity>(counterEntities);
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (data: CounterEntity, displayColumn: string) => {
switch (displayColumn) {
case 'context':
return this.formatContext(data);
case 'name':
return this.formatName(data);
case 'value':
return data.valueCount;
default:
return '';
}
};
this.dataSource.data = this.sortEntities(counterEntities, {
active: this.initialSortColumn,
direction: this.initialSortDirection
});
this.dataSource.filterPredicate = (data: CounterEntity, filter: string) => {
const { filterTerm, filterColumn } = JSON.parse(filter);
@ -93,8 +83,6 @@ export class CounterTable implements AfterViewInit {
@Output() resetCounter: EventEmitter<CounterEntity> = new EventEmitter<CounterEntity>();
@ViewChild(MatSort) sort!: MatSort;
constructor(
private formBuilder: FormBuilder,
private nifiCommon: NiFiCommon
@ -103,8 +91,6 @@ export class CounterTable implements AfterViewInit {
}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
this.filterForm
.get('filterTerm')
?.valueChanges.pipe(debounceTime(500))
@ -140,4 +126,32 @@ export class CounterTable implements AfterViewInit {
event.stopPropagation();
this.resetCounter.next(counter);
}
sortData(sort: Sort) {
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
private sortEntities(data: CounterEntity[], sort: Sort): CounterEntity[] {
if (!data) {
return [];
}
return data.slice().sort((a, b) => {
const isAsc = sort.direction === 'asc';
let retVal = 0;
switch (sort.active) {
case 'name':
retVal = this.nifiCommon.compareString(this.formatName(a), this.formatName(b));
break;
case 'value':
retVal = this.nifiCommon.compareNumber(a.valueCount, b.valueCount);
break;
case 'context':
retVal = this.nifiCommon.compareString(this.formatContext(a), this.formatContext(b));
break;
default:
return 0;
}
return retVal * (isAsc ? 1 : -1);
});
}
}

View File

@ -17,7 +17,14 @@
<div class="relative h-full border">
<div class="listing-table absolute inset-0 overflow-y-auto">
<table mat-table [dataSource]="dataSource" matSort matSortDisableClear>
<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>
@ -35,12 +42,7 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item); else nameNoPermissions">
{{ formatName(item) }}
</ng-container>
<ng-template #nameNoPermissions>
<div class="unset">{{ item.id }}</div>
</ng-template>
<div [ngClass]="{ unset: !canRead(item) }">{{ formatName(item) }}</div>
</td>
</ng-container>
@ -48,9 +50,7 @@
<ng-container matColumnDef="provider">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Provider</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item)">
{{ formatProvider(item) }}
</ng-container>
{{ formatProvider(item) }}
</td>
</ng-container>
@ -58,9 +58,7 @@
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item)">
{{ formatDescription(item) }}
</ng-container>
{{ formatDescription(item) }}
</td>
</ng-container>

View File

@ -19,6 +19,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ParameterContextTable } from './parameter-context-table.component';
import { MatTableModule } from '@angular/material/table';
import { MatSortModule } from '@angular/material/sort';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
describe('ParameterContextTable', () => {
let component: ParameterContextTable;
@ -27,7 +29,7 @@ describe('ParameterContextTable', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ParameterContextTable],
imports: [MatTableModule]
imports: [MatTableModule, MatSortModule, NoopAnimationsModule]
});
fixture = TestBed.createComponent(ParameterContextTable);
component = fixture.componentInstance;

View File

@ -15,9 +15,9 @@
* limitations under the License.
*/
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { Sort } from '@angular/material/sort';
import { NiFiCommon } from '../../../../../service/nifi-common.service';
import { ParameterContextEntity } from '../../../state/parameter-context-listing';
import { FlowConfiguration } from '../../../../../state/flow-configuration';
@ -28,22 +28,15 @@ import { CurrentUser } from '../../../../../state/current-user';
templateUrl: './parameter-context-table.component.html',
styleUrls: ['./parameter-context-table.component.scss', '../../../../../../assets/styles/listing-table.scss']
})
export class ParameterContextTable implements AfterViewInit {
export class ParameterContextTable {
@Input() initialSortColumn: 'name' | 'provider' | 'description' = 'name';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
@Input() set parameterContexts(parameterContextEntities: ParameterContextEntity[]) {
this.dataSource = new MatTableDataSource<ParameterContextEntity>(parameterContextEntities);
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (data: ParameterContextEntity, displayColumn: string) => {
if (this.canRead(data)) {
if (displayColumn === 'name') {
return this.formatName(data);
} else if (displayColumn === 'type') {
return this.formatProvider(data);
} else if (displayColumn === 'bundle') {
return this.formatDescription(data);
}
}
return '';
};
this.dataSource.data = this.sortEntities(parameterContextEntities, {
active: this.initialSortColumn,
direction: this.initialSortDirection
});
}
@Input() selectedParameterContextId!: string;
@ -57,14 +50,8 @@ export class ParameterContextTable implements AfterViewInit {
displayedColumns: string[] = ['moreDetails', 'name', 'provider', 'description', 'actions'];
dataSource: MatTableDataSource<ParameterContextEntity> = new MatTableDataSource<ParameterContextEntity>();
@ViewChild(MatSort) sort!: MatSort;
constructor(private nifiCommon: NiFiCommon) {}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
}
canRead(entity: ParameterContextEntity): boolean {
return entity.permissions.canRead;
}
@ -74,7 +61,7 @@ export class ParameterContextTable implements AfterViewInit {
}
formatName(entity: ParameterContextEntity): string {
return entity.component.name;
return this.canRead(entity) ? entity.component.name : entity.id;
}
formatProvider(entity: ParameterContextEntity): string {
@ -82,7 +69,7 @@ export class ParameterContextTable implements AfterViewInit {
}
formatDescription(entity: ParameterContextEntity): string {
return entity.component.description;
return this.canRead(entity) ? entity.component.description : '';
}
editClicked(entity: ParameterContextEntity, event: MouseEvent): void {
@ -120,4 +107,33 @@ export class ParameterContextTable implements AfterViewInit {
}
return false;
}
sortData(sort: Sort) {
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
private sortEntities(data: ParameterContextEntity[], sort: Sort): ParameterContextEntity[] {
if (!data) {
return [];
}
return data.slice().sort((a, b) => {
const isAsc = sort.direction === 'asc';
let retVal = 0;
switch (sort.active) {
case 'name':
retVal = this.nifiCommon.compareString(this.formatName(a), this.formatName(b));
break;
case 'provider':
retVal = this.nifiCommon.compareString(this.formatProvider(a), this.formatProvider(b));
break;
case 'description':
retVal = this.nifiCommon.compareString(this.formatDescription(a), this.formatDescription(b));
break;
default:
return 0;
}
return retVal * (isAsc ? 1 : -1);
});
}
}

View File

@ -17,7 +17,14 @@
<div class="relative h-full border">
<div class="reporting-task-table listing-table absolute inset-0 overflow-y-auto">
<table mat-table [dataSource]="dataSource" matSort matSortDisableClear>
<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>
@ -59,12 +66,7 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item); else nameNoPermissions">
{{ item.component.name }}
</ng-container>
<ng-template #nameNoPermissions>
<div class="unset">{{ item.id }}</div>
</ng-template>
<div [ngClass]="{ unset: !canRead(item) }">{{ formatName(item) }}</div>
</td>
</ng-container>
@ -72,9 +74,7 @@
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item)">
{{ formatType(item) }}
</ng-container>
{{ formatType(item) }}
</td>
</ng-container>
@ -82,9 +82,7 @@
<ng-container matColumnDef="bundle">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Bundle</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item)">
{{ formatBundle(item) }}
</ng-container>
{{ formatBundle(item) }}
</td>
</ng-container>

View File

@ -19,6 +19,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReportingTaskTable } from './reporting-task-table.component';
import { MatTableModule } from '@angular/material/table';
import { MatSortModule } from '@angular/material/sort';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
describe('ReportingTaskTable', () => {
let component: ReportingTaskTable;
@ -27,7 +29,7 @@ describe('ReportingTaskTable', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ReportingTaskTable],
imports: [MatTableModule]
imports: [MatTableModule, MatSortModule, NoopAnimationsModule]
});
fixture = TestBed.createComponent(ReportingTaskTable);
component = fixture.componentInstance;

View File

@ -15,9 +15,9 @@
* limitations under the License.
*/
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { Sort } from '@angular/material/sort';
import { ReportingTaskEntity } from '../../../state/reporting-tasks';
import { TextTip } from '../../../../../ui/common/tooltips/text-tip/text-tip.component';
import { BulletinsTip } from '../../../../../ui/common/tooltips/bulletins-tip/bulletins-tip.component';
@ -32,23 +32,17 @@ import { CurrentUser } from '../../../../../state/current-user';
templateUrl: './reporting-task-table.component.html',
styleUrls: ['./reporting-task-table.component.scss', '../../../../../../assets/styles/listing-table.scss']
})
export class ReportingTaskTable implements AfterViewInit {
export class ReportingTaskTable {
@Input() initialSortColumn: 'name' | 'type' | 'bundle' | 'state' = 'name';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
@Input() set reportingTasks(reportingTaskEntities: ReportingTaskEntity[]) {
this.dataSource = new MatTableDataSource<ReportingTaskEntity>(reportingTaskEntities);
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (data: ReportingTaskEntity, displayColumn: string) => {
if (displayColumn === 'name') {
return this.formatType(data);
} else if (displayColumn === 'type') {
return this.formatType(data);
} else if (displayColumn === 'bundle') {
return this.formatBundle(data);
} else if (displayColumn === 'state') {
return this.formatState(data);
}
return '';
};
this.dataSource.data = this.sortEntities(reportingTaskEntities, {
active: this.initialSortColumn,
direction: this.initialSortDirection
});
}
@Input() selectedReportingTaskId!: string;
@Input() flowConfiguration!: FlowConfiguration;
@Input() currentUser!: CurrentUser;
@ -66,14 +60,8 @@ export class ReportingTaskTable implements AfterViewInit {
displayedColumns: string[] = ['moreDetails', 'name', 'type', 'bundle', 'state', 'actions'];
dataSource: MatTableDataSource<ReportingTaskEntity> = new MatTableDataSource<ReportingTaskEntity>();
@ViewChild(MatSort) sort!: MatSort;
constructor(private nifiCommon: NiFiCommon) {}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
}
canRead(entity: ReportingTaskEntity): boolean {
return entity.permissions.canRead;
}
@ -156,12 +144,16 @@ export class ReportingTaskTable implements AfterViewInit {
return entity.status?.activeThreadCount > 0;
}
formatName(entity: ReportingTaskEntity): string {
return this.canRead(entity) ? entity.component.name : entity.id;
}
formatType(entity: ReportingTaskEntity): string {
return this.nifiCommon.formatType(entity.component);
return this.canRead(entity) ? this.nifiCommon.formatType(entity.component) : '';
}
formatBundle(entity: ReportingTaskEntity): string {
return this.nifiCommon.formatBundle(entity.component.bundle);
return this.canRead(entity) ? this.nifiCommon.formatBundle(entity.component.bundle) : '';
}
isDisabled(entity: ReportingTaskEntity): boolean {
@ -259,4 +251,36 @@ export class ReportingTaskTable implements AfterViewInit {
}
return false;
}
sortData(sort: Sort) {
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
private sortEntities(data: ReportingTaskEntity[], sort: Sort): ReportingTaskEntity[] {
if (!data) {
return [];
}
return data.slice().sort((a, b) => {
const isAsc = sort.direction === 'asc';
let retVal = 0;
switch (sort.active) {
case 'name':
retVal = this.nifiCommon.compareString(this.formatName(a), this.formatName(b));
break;
case 'type':
retVal = this.nifiCommon.compareString(this.formatType(a), this.formatType(b));
break;
case 'bundle':
retVal = this.nifiCommon.compareString(this.formatBundle(a), this.formatBundle(b));
break;
case 'state':
retVal = this.nifiCommon.compareString(this.formatState(a), this.formatState(b));
break;
default:
return 0;
}
return retVal * (isAsc ? 1 : -1);
});
}
}

View File

@ -17,7 +17,14 @@
<div class="relative h-full border">
<div class="controller-service-table listing-table absolute inset-0 overflow-y-auto">
<table mat-table [dataSource]="dataSource" matSort matSortDisableClear>
<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>
@ -64,12 +71,7 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item); else nameNoPermissions">
{{ item.component.name }}
</ng-container>
<ng-template #nameNoPermissions>
<div class="unset">{{ item.id }}</div>
</ng-template>
<div [ngClass]="{ unset: !canRead(item) }">{{ formatName(item) }}</div>
</td>
</ng-container>
@ -77,9 +79,7 @@
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item)">
{{ formatType(item) }}
</ng-container>
{{ formatType(item) }}
</td>
</ng-container>
@ -87,9 +87,7 @@
<ng-container matColumnDef="bundle">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Bundle</th>
<td mat-cell *matCellDef="let item">
<ng-container *ngIf="canRead(item)">
{{ formatBundle(item) }}
</ng-container>
{{ formatBundle(item) }}
</td>
</ng-container>

View File

@ -15,12 +15,12 @@
* limitations under the License.
*/
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { NiFiCommon } from '../../../../service/nifi-common.service';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatSortModule, Sort } from '@angular/material/sort';
import { NgClass, NgIf } from '@angular/common';
import {
BulletinsTipInput,
@ -52,25 +52,17 @@ import { CurrentUser } from '../../../../state/current-user';
],
styleUrls: ['./controller-service-table.component.scss', '../../../../../assets/styles/listing-table.scss']
})
export class ControllerServiceTable implements AfterViewInit {
export class ControllerServiceTable {
@Input() initialSortColumn: 'name' | 'type' | 'bundle' | 'state' | 'scope' = 'name';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
@Input() set controllerServices(controllerServiceEntities: ControllerServiceEntity[]) {
this.dataSource = new MatTableDataSource<ControllerServiceEntity>(controllerServiceEntities);
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (data: ControllerServiceEntity, displayColumn: string) => {
if (displayColumn == 'name') {
return this.formatType(data);
} else if (displayColumn == 'type') {
return this.formatType(data);
} else if (displayColumn == 'bundle') {
return this.formatBundle(data);
} else if (displayColumn == 'state') {
return this.formatState(data);
} else if (displayColumn == 'scope') {
return this.formatScope(data);
}
return '';
};
this.dataSource.data = this.sortEntities(controllerServiceEntities, {
active: this.initialSortColumn,
direction: this.initialSortDirection
});
}
@Input() selectedServiceId!: string;
@Input() formatScope!: (entity: ControllerServiceEntity) => string;
@Input() definedByCurrentGroup!: (entity: ControllerServiceEntity) => boolean;
@ -96,14 +88,8 @@ export class ControllerServiceTable implements AfterViewInit {
displayedColumns: string[] = ['moreDetails', 'name', 'type', 'bundle', 'state', 'scope', 'actions'];
dataSource: MatTableDataSource<ControllerServiceEntity> = new MatTableDataSource<ControllerServiceEntity>();
@ViewChild(MatSort) sort!: MatSort;
constructor(private nifiCommon: NiFiCommon) {}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
}
canRead(entity: ControllerServiceEntity): boolean {
return entity.permissions.canRead;
}
@ -188,12 +174,16 @@ export class ControllerServiceTable implements AfterViewInit {
return '';
}
formatName(entity: ControllerServiceEntity): string {
return this.canRead(entity) ? entity.component.name : entity.id;
}
formatType(entity: ControllerServiceEntity): string {
return this.nifiCommon.formatType(entity.component);
return this.canRead(entity) ? this.nifiCommon.formatType(entity.component) : '';
}
formatBundle(entity: ControllerServiceEntity): string {
return this.nifiCommon.formatBundle(entity.component.bundle);
return this.canRead(entity) ? this.nifiCommon.formatBundle(entity.component.bundle) : '';
}
getServiceLink(entity: ControllerServiceEntity): string[] {
@ -279,4 +269,39 @@ export class ControllerServiceTable implements AfterViewInit {
}
return false;
}
sortData(sort: Sort) {
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
private sortEntities(data: ControllerServiceEntity[], sort: Sort): ControllerServiceEntity[] {
if (!data) {
return [];
}
return data.slice().sort((a, b) => {
const isAsc = sort.direction === 'asc';
let retVal = 0;
switch (sort.active) {
case 'name':
retVal = this.nifiCommon.compareString(this.formatName(a), this.formatName(b));
break;
case 'type':
retVal = this.nifiCommon.compareString(this.formatType(a), this.formatType(b));
break;
case 'bundle':
retVal = this.nifiCommon.compareString(this.formatBundle(a), this.formatBundle(b));
break;
case 'state':
retVal = this.nifiCommon.compareString(this.formatState(a), this.formatState(b));
break;
case 'scope':
retVal = this.nifiCommon.compareString(this.formatScope(a), this.formatScope(b));
break;
default:
return 0;
}
return retVal * (isAsc ? 1 : -1);
});
}
}

View File

@ -29,7 +29,14 @@
</div>
<div class="type-table">
<div class="h-96 overflow-y-auto overflow-x-hidden border">
<table mat-table [dataSource]="dataSource" matSort matSortDisableClear>
<table
mat-table
[dataSource]="dataSource"
matSort
matSortDisableClear
(matSortChange)="sortData($event)"
[matSortActive]="initialSortColumn"
[matSortDirection]="initialSortDirection">
<!-- Type Column -->
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Type</th>

View File

@ -15,12 +15,12 @@
* limitations under the License.
*/
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { NiFiCommon } from '../../../service/nifi-common.service';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatSortModule, Sort } from '@angular/material/sort';
import { NgIf } from '@angular/common';
import { ControllerServiceApiTipInput, DocumentedType, RestrictionsTipInput } from '../../../state/shared';
import { NifiTooltipDirective } from '../tooltips/nifi-tooltip.directive';
@ -43,27 +43,23 @@ import { NifiSpinnerDirective } from '../spinner/nifi-spinner.directive';
],
styleUrls: ['./extension-creation.component.scss']
})
export class ExtensionCreation implements AfterViewInit {
export class ExtensionCreation {
@Input() set documentedTypes(documentedTypes: DocumentedType[]) {
if (this.selectedType == null && documentedTypes.length > 0) {
this.selectedType = documentedTypes[0];
}
this.dataSource = new MatTableDataSource<DocumentedType>(documentedTypes);
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (data: DocumentedType, displayColumn: string) => {
if (displayColumn == 'type') {
return this.formatType(data);
} else if (displayColumn == 'version') {
return this.formatVersion(data);
} else if (displayColumn == 'tags') {
return this.formatTags(data);
}
return '';
};
this.dataSource.data = this.sortEntities(documentedTypes, {
active: this.initialSortColumn,
direction: this.initialSortDirection
});
}
@Input() componentType!: string;
@Input() saving!: boolean;
@Input() initialSortColumn: 'type' | 'version' | 'tags' = 'type';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
@Output() extensionTypeSelected: EventEmitter<DocumentedType> = new EventEmitter<DocumentedType>();
protected readonly RestrictionsTip = RestrictionsTip;
@ -73,14 +69,8 @@ export class ExtensionCreation implements AfterViewInit {
dataSource: MatTableDataSource<DocumentedType> = new MatTableDataSource<DocumentedType>();
selectedType: DocumentedType | null = null;
@ViewChild(MatSort) sort!: MatSort;
constructor(private nifiCommon: NiFiCommon) {}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
}
formatType(documentedType: DocumentedType): string {
if (documentedType) {
return this.nifiCommon.substringAfterLast(documentedType.type, '.');
@ -115,7 +105,10 @@ export class ExtensionCreation implements AfterViewInit {
formatTags(documentedType: DocumentedType): string {
if (documentedType?.tags) {
return documentedType.tags.join(', ');
return documentedType.tags
.slice()
.sort((a, b) => this.nifiCommon.compareString(a, b))
.join(', ');
}
return '';
}
@ -156,4 +149,30 @@ export class ExtensionCreation implements AfterViewInit {
this.extensionTypeSelected.next(documentedType);
}
}
sortData(sort: Sort) {
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
sortEntities(data: DocumentedType[], sort: Sort): DocumentedType[] {
if (!data) {
return [];
}
return data.slice().sort((a, b) => {
const isAsc = sort.direction === 'asc';
let retVal = 0;
switch (sort.active) {
case 'type':
retVal = this.nifiCommon.compareString(this.formatType(a), this.formatType(b));
break;
case 'version':
retVal = this.nifiCommon.compareString(this.formatVersion(a), this.formatVersion(b));
break;
case 'tags':
retVal = this.nifiCommon.compareString(this.formatTags(a), this.formatTags(b));
break;
}
return retVal * (isAsc ? 1 : -1);
});
}
}