mirror of https://github.com/apache/nifi.git
NIFI-12948: (#8564)
- Action is optional. - Removing duplicate check in counter table. - Ensure flow configuration is loaded in route guard. - Only show user/group list when there are users or groups. - Default override policy to copy.
This commit is contained in:
parent
339a06a8c6
commit
0c01dfe585
|
@ -35,7 +35,7 @@ export class OverridePolicyDialog {
|
|||
|
||||
constructor(private formBuilder: FormBuilder) {
|
||||
this.overridePolicyForm = this.formBuilder.group({
|
||||
override: new FormControl()
|
||||
override: new FormControl('copy')
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -74,16 +74,14 @@
|
|||
<ng-container matColumnDef="reset">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let item">
|
||||
@if (canModifyCounters) {
|
||||
<div class="flex items-center gap-x-3">
|
||||
@if (canModifyCounters) {
|
||||
<div
|
||||
class="pointer fa fa-undo"
|
||||
title="Reset Counter"
|
||||
(click)="resetClicked(item, $event)"></div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="flex items-center gap-x-3">
|
||||
@if (canModifyCounters) {
|
||||
<div
|
||||
class="pointer fa fa-undo"
|
||||
title="Reset Counter"
|
||||
(click)="resetClicked(item, $event)"></div>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ export interface ActionEntity {
|
|||
timestamp: string;
|
||||
sourceId: string;
|
||||
canRead: boolean;
|
||||
action: Action;
|
||||
action?: Action;
|
||||
}
|
||||
|
||||
export interface Action {
|
||||
|
|
|
@ -25,164 +25,166 @@
|
|||
<div class="value">{{ actionEntity.sourceId }}</div>
|
||||
</div>
|
||||
|
||||
@if (actionEntity.action.componentDetails) {
|
||||
@if (isRemoteProcessGroup(actionEntity)) {
|
||||
<div>
|
||||
<div>Uri</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: getRemoteProcessGroupDetails(actionEntity)?.uri }
|
||||
"></ng-container>
|
||||
</div>
|
||||
} @else {
|
||||
<div>
|
||||
<div>Type</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: getExtensionDetails(actionEntity)?.type }
|
||||
"></ng-container>
|
||||
</div>
|
||||
@if (actionEntity.action; as action) {
|
||||
@if (action.componentDetails) {
|
||||
@if (isRemoteProcessGroup(action)) {
|
||||
<div>
|
||||
<div>Uri</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: getRemoteProcessGroupDetails(action)?.uri }
|
||||
"></ng-container>
|
||||
</div>
|
||||
} @else {
|
||||
<div>
|
||||
<div>Type</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: getExtensionDetails(action)?.type }
|
||||
"></ng-container>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if (actionEntity.action.actionDetails) {
|
||||
@switch (actionEntity.action.operation) {
|
||||
@case ('Configure') {
|
||||
@if (getConfigureActionDetails(actionEntity); as details) {
|
||||
<div>
|
||||
<div>Name</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.name }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Value</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.value }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Previous Value</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.previousValue }
|
||||
"></ng-container>
|
||||
</div>
|
||||
@if (action.actionDetails) {
|
||||
@switch (action.operation) {
|
||||
@case ('Configure') {
|
||||
@if (getConfigureActionDetails(action); as details) {
|
||||
<div>
|
||||
<div>Name</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.name }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Value</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.value }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Previous Value</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.previousValue }
|
||||
"></ng-container>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
@case ('Connect' || 'Disconnect') {
|
||||
@if (getConnectActionDetails(actionEntity); as details) {
|
||||
<div>
|
||||
<div>Source Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.sourceId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Source Name</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.sourceName }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Source Type</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.sourceType }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Relationship(s)</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.relationship }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Destination Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.destinationId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Destination Name</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.destinationName }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Destination Type</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.destinationType }
|
||||
"></ng-container>
|
||||
</div>
|
||||
@case ('Connect' || 'Disconnect') {
|
||||
@if (getConnectActionDetails(action); as details) {
|
||||
<div>
|
||||
<div>Source Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.sourceId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Source Name</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.sourceName }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Source Type</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.sourceType }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Relationship(s)</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.relationship }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Destination Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.destinationId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Destination Name</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.destinationName }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Destination Type</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.destinationType }
|
||||
"></ng-container>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
@case ('Move') {
|
||||
@if (getMoveActionDetails(actionEntity); as details) {
|
||||
<div>
|
||||
<div>Group</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.group }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Group Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.groupId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Previous Group</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.previousGroup }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Previous Group Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.previousGroupId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
@case ('Move') {
|
||||
@if (getMoveActionDetails(action); as details) {
|
||||
<div>
|
||||
<div>Group</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.group }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Group Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.groupId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Previous Group</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.previousGroup }
|
||||
"></ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div>Previous Group Id</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.previousGroupId }
|
||||
"></ng-container>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
@case ('Purge') {
|
||||
@if (getPurgeActionDetails(actionEntity); as details) {
|
||||
<div>
|
||||
<div>End Date</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.endDate }
|
||||
"></ng-container>
|
||||
</div>
|
||||
@case ('Purge') {
|
||||
@if (getPurgeActionDetails(action); as details) {
|
||||
<div>
|
||||
<div>End Date</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
formatValue;
|
||||
context: { $implicit: details.endDate }
|
||||
"></ng-container>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import { Component, Inject } from '@angular/core';
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||
import {
|
||||
Action,
|
||||
ActionEntity,
|
||||
ConfigureActionDetails,
|
||||
ConnectionActionDetails,
|
||||
|
@ -27,7 +28,6 @@ import {
|
|||
PurgeActionDetails,
|
||||
RemoteProcessGroupDetails
|
||||
} from '../../../state/flow-configuration-history-listing';
|
||||
import { NiFiCommon } from '../../../../../service/nifi-common.service';
|
||||
import { PipesModule } from '../../../../../pipes/pipes.module';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
|
||||
|
@ -39,54 +39,51 @@ import { MatButtonModule } from '@angular/material/button';
|
|||
styleUrls: ['./action-details.component.scss']
|
||||
})
|
||||
export class ActionDetails {
|
||||
constructor(
|
||||
@Inject(MAT_DIALOG_DATA) public actionEntity: ActionEntity,
|
||||
private nifiCommon: NiFiCommon
|
||||
) {}
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public actionEntity: ActionEntity) {}
|
||||
|
||||
isRemoteProcessGroup(actionEntity: ActionEntity): boolean {
|
||||
return actionEntity.action.sourceType === 'RemoteProcessGroup';
|
||||
isRemoteProcessGroup(action: Action): boolean {
|
||||
return action.sourceType === 'RemoteProcessGroup';
|
||||
}
|
||||
|
||||
getRemoteProcessGroupDetails(actionEntity: ActionEntity): RemoteProcessGroupDetails | null {
|
||||
if (!this.isRemoteProcessGroup(actionEntity)) {
|
||||
getRemoteProcessGroupDetails(action: Action): RemoteProcessGroupDetails | null {
|
||||
if (!this.isRemoteProcessGroup(action)) {
|
||||
return null;
|
||||
}
|
||||
return actionEntity.action.componentDetails as RemoteProcessGroupDetails;
|
||||
return action.componentDetails as RemoteProcessGroupDetails;
|
||||
}
|
||||
|
||||
getExtensionDetails(actionEntity: ActionEntity): ExtensionDetails | null {
|
||||
if (this.isRemoteProcessGroup(actionEntity)) {
|
||||
getExtensionDetails(action: Action): ExtensionDetails | null {
|
||||
if (this.isRemoteProcessGroup(action)) {
|
||||
return null;
|
||||
}
|
||||
return actionEntity.action.componentDetails as ExtensionDetails;
|
||||
return action.componentDetails as ExtensionDetails;
|
||||
}
|
||||
|
||||
getConfigureActionDetails(actionEntity: ActionEntity): ConfigureActionDetails | null {
|
||||
if (actionEntity.action.operation !== 'Configure') {
|
||||
getConfigureActionDetails(action: Action): ConfigureActionDetails | null {
|
||||
if (action.operation !== 'Configure') {
|
||||
return null;
|
||||
}
|
||||
return actionEntity.action.actionDetails as ConfigureActionDetails;
|
||||
return action.actionDetails as ConfigureActionDetails;
|
||||
}
|
||||
|
||||
getConnectActionDetails(actionEntity: ActionEntity): ConnectionActionDetails | null {
|
||||
if (!['Connect', 'Disconnect'].includes(actionEntity.action.operation)) {
|
||||
getConnectActionDetails(action: Action): ConnectionActionDetails | null {
|
||||
if (!['Connect', 'Disconnect'].includes(action.operation)) {
|
||||
return null;
|
||||
}
|
||||
return actionEntity.action.actionDetails as ConnectionActionDetails;
|
||||
return action.actionDetails as ConnectionActionDetails;
|
||||
}
|
||||
|
||||
getMoveActionDetails(actionEntity: ActionEntity): MoveActionDetails | null {
|
||||
if (actionEntity.action.operation !== 'Move') {
|
||||
getMoveActionDetails(action: Action): MoveActionDetails | null {
|
||||
if (action.operation !== 'Move') {
|
||||
return null;
|
||||
}
|
||||
return actionEntity.action.actionDetails as MoveActionDetails;
|
||||
return action.actionDetails as MoveActionDetails;
|
||||
}
|
||||
|
||||
getPurgeActionDetails(actionEntity: ActionEntity): PurgeActionDetails | null {
|
||||
if (actionEntity.action.operation !== 'Purge') {
|
||||
getPurgeActionDetails(action: Action): PurgeActionDetails | null {
|
||||
if (action.operation !== 'Purge') {
|
||||
return null;
|
||||
}
|
||||
return actionEntity.action.actionDetails as PurgeActionDetails;
|
||||
return action.actionDetails as PurgeActionDetails;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
||||
import { MatSortModule, Sort } from '@angular/material/sort';
|
||||
import { ActionEntity } from '../../../state/flow-configuration-history-listing';
|
||||
import { NiFiCommon } from '../../../../../service/nifi-common.service';
|
||||
|
||||
@Component({
|
||||
selector: 'flow-configuration-history-table',
|
||||
|
@ -52,7 +51,7 @@ export class FlowConfigurationHistoryTable {
|
|||
displayedColumns: string[] = ['moreDetails', 'timestamp', 'sourceName', 'sourceType', 'operation', 'userIdentity'];
|
||||
dataSource: MatTableDataSource<ActionEntity> = new MatTableDataSource<ActionEntity>();
|
||||
|
||||
constructor(private nifiCommon: NiFiCommon) {}
|
||||
constructor() {}
|
||||
|
||||
sortData(sort: Sort) {
|
||||
this.sortChanged.next(sort);
|
||||
|
@ -63,7 +62,7 @@ export class FlowConfigurationHistoryTable {
|
|||
}
|
||||
|
||||
private format(item: ActionEntity, property: string): string {
|
||||
if (this.canRead(item) && Object.hasOwn(item.action, property)) {
|
||||
if (this.canRead(item) && item.action && Object.hasOwn(item.action, property)) {
|
||||
const value = (item.action as any)[property];
|
||||
if (!value) {
|
||||
return 'Empty String Set';
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
|
||||
import { CanMatchFn, Router } from '@angular/router';
|
||||
import { inject } from '@angular/core';
|
||||
import { map } from 'rxjs';
|
||||
import { catchError, map, of, switchMap, tap } from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { FlowConfiguration, FlowConfigurationState } from '../../state/flow-configuration';
|
||||
import { selectFlowConfiguration } from '../../state/flow-configuration/flow-configuration.selectors';
|
||||
import { FlowConfigurationService } from '../flow-configuration.service';
|
||||
import { loadFlowConfigurationSuccess } from '../../state/flow-configuration/flow-configuration.actions';
|
||||
|
||||
export const checkFlowConfiguration = (
|
||||
flowConfigurationCheck: (flowConfiguration: FlowConfiguration) => boolean
|
||||
|
@ -28,15 +30,35 @@ export const checkFlowConfiguration = (
|
|||
return () => {
|
||||
const router: Router = inject(Router);
|
||||
const store: Store<FlowConfigurationState> = inject(Store<FlowConfigurationState>);
|
||||
const flowConfigurationService: FlowConfigurationService = inject(FlowConfigurationService);
|
||||
|
||||
return store.select(selectFlowConfiguration).pipe(
|
||||
switchMap((flowConfiguration) => {
|
||||
if (flowConfiguration) {
|
||||
return of(flowConfiguration);
|
||||
} else {
|
||||
return flowConfigurationService.getFlowConfiguration().pipe(
|
||||
tap((response) =>
|
||||
store.dispatch(
|
||||
loadFlowConfigurationSuccess({
|
||||
response
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}),
|
||||
map((flowConfiguration) => {
|
||||
if (flowConfiguration && flowConfigurationCheck(flowConfiguration)) {
|
||||
if (flowConfigurationCheck(flowConfiguration)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO - replace with 409 error page
|
||||
// TODO - replace with error page
|
||||
return router.parseUrl('/');
|
||||
}),
|
||||
catchError(() => {
|
||||
// TODO - replace with error page
|
||||
return of(router.parseUrl('/'));
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
<form class="edit-tenant-form" [formGroup]="editTenantForm">
|
||||
<error-banner></error-banner>
|
||||
<mat-dialog-content>
|
||||
<div class="mb-6">
|
||||
<div>
|
||||
<mat-radio-group formControlName="tenantType" (change)="tenantTypeChanged()">
|
||||
<mat-radio-button color="primary" [value]="USER">Individual</mat-radio-button>
|
||||
<mat-radio-button color="primary" [value]="USER_GROUP">Group</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="mt-6">
|
||||
<mat-form-field>
|
||||
<mat-label>Identity</mat-label>
|
||||
<input matInput formControlName="identity" type="text" />
|
||||
|
@ -35,27 +35,31 @@
|
|||
</mat-form-field>
|
||||
</div>
|
||||
@if (isUser) {
|
||||
<div>
|
||||
<mat-label>Member of</mat-label>
|
||||
<mat-selection-list formControlName="userGroups" class="border">
|
||||
@for (userGroup of userGroups; track userGroup) {
|
||||
<mat-list-option togglePosition="before" [value]="userGroup.id"
|
||||
>{{ userGroup.component.identity }}
|
||||
</mat-list-option>
|
||||
}
|
||||
</mat-selection-list>
|
||||
</div>
|
||||
@if (userGroups.length > 0) {
|
||||
<div class="mt-2">
|
||||
<mat-label>Member of</mat-label>
|
||||
<mat-selection-list formControlName="userGroups" class="border">
|
||||
@for (userGroup of userGroups; track userGroup) {
|
||||
<mat-list-option togglePosition="before" [value]="userGroup.id"
|
||||
>{{ userGroup.component.identity }}
|
||||
</mat-list-option>
|
||||
}
|
||||
</mat-selection-list>
|
||||
</div>
|
||||
}
|
||||
} @else {
|
||||
<div>
|
||||
<mat-label>Members</mat-label>
|
||||
<mat-selection-list formControlName="users" class="border">
|
||||
@for (user of users; track user) {
|
||||
<mat-list-option togglePosition="before" [value]="user.id"
|
||||
>{{ user.component.identity }}
|
||||
</mat-list-option>
|
||||
}
|
||||
</mat-selection-list>
|
||||
</div>
|
||||
@if (users.length > 0) {
|
||||
<div class="mt-2">
|
||||
<mat-label>Members</mat-label>
|
||||
<mat-selection-list formControlName="users" class="border">
|
||||
@for (user of users; track user) {
|
||||
<mat-list-option togglePosition="before" [value]="user.id"
|
||||
>{{ user.component.identity }}
|
||||
</mat-list-option>
|
||||
}
|
||||
</mat-selection-list>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</mat-dialog-content>
|
||||
@if ({ value: (saving$ | async)! }; as saving) {
|
||||
|
|
Loading…
Reference in New Issue