diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts index b3161d8318185..eb3493356293a 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts @@ -36,12 +36,13 @@ import { } from '../../../../state/shared'; import { Router } from '@angular/router'; import { - selectProcessGroupFlow, + selectChildProcessGroupOptions, selectCurrentProcessGroupId, selectParameterContext, selectSaving, selectStatus, - selectServices + selectServices, + selectBreadcrumb } from './controller-services.selectors'; import { ControllerServiceService } from '../../service/controller-service.service'; import { EnableControllerService } from '../../../../ui/common/controller-service/enable-controller-service/enable-controller-service.component'; @@ -52,7 +53,6 @@ import * as ErrorActions from '../../../../state/error/error.actions'; import { ErrorHelper } from '../../../../service/error-helper.service'; import { HttpErrorResponse } from '@angular/common/http'; import { ParameterHelperService } from '../../service/parameter-helper.service'; -import { ComponentType, LARGE_DIALOG, SMALL_DIALOG, XL_DIALOG } from 'libs/shared/src'; import { ExtensionTypesService } from '../../../../service/extension-types.service'; import { ChangeComponentVersionDialog } from '../../../../ui/common/change-component-version-dialog/change-component-version-dialog'; import { FlowService } from '../../service/flow.service'; @@ -66,7 +66,8 @@ import { } from '../../../../state/property-verification/property-verification.selectors'; import { VerifyPropertiesRequestContext } from '../../../../state/property-verification'; import { BackNavigation } from '../../../../state/navigation'; -import { NiFiCommon, Storage } from '@nifi/shared'; +import { NiFiCommon, Storage, SelectOption, ComponentType, LARGE_DIALOG, SMALL_DIALOG, XL_DIALOG } from '@nifi/shared'; +import { ComponentEntity } from './../flow/index'; @Injectable() export class ControllerServicesEffects { @@ -95,18 +96,28 @@ export class ControllerServicesEffects { this.controllerServiceService.getControllerServices(request.processGroupId), this.controllerServiceService.getFlow(request.processGroupId) ]).pipe( - map(([controllerServicesResponse, flowResponse]) => - ControllerServicesActions.loadControllerServicesSuccess({ + map(([controllerServicesResponse, flowResponse]) => { + const childProcessGroupOptions: SelectOption[] = []; + flowResponse.processGroupFlow.flow.processGroups.forEach((child: ComponentEntity) => { + if (child.permissions.canRead && child.permissions.canWrite) { + childProcessGroupOptions.push({ + text: child.component.name, + value: child.component.id + }); + } + }); + + return ControllerServicesActions.loadControllerServicesSuccess({ response: { processGroupId: flowResponse.processGroupFlow.id, controllerServices: controllerServicesResponse.controllerServices, loadedTimestamp: controllerServicesResponse.currentTime, breadcrumb: flowResponse.processGroupFlow.breadcrumb, parameterContext: flowResponse.processGroupFlow.parameterContext ?? null, - processGroupFlow: flowResponse.processGroupFlow + childProcessGroupOptions: childProcessGroupOptions } - }) - ), + }); + }), catchError((errorResponse: HttpErrorResponse) => of(this.errorHelper.handleLoadingError(status, errorResponse)) ) @@ -644,27 +655,31 @@ export class ControllerServicesEffects { map((action) => action.request), concatLatestFrom(() => [ this.store.select(selectCurrentProcessGroupId), - this.store.select(selectProcessGroupFlow), - this.store.select(selectServices) + this.store.select(selectChildProcessGroupOptions), + this.store.select(selectServices), + this.store.select(selectBreadcrumb) ]), - concatMap(([request, currentProcessGroupId, processGroupFlow, controllerServices]) => - combineLatest([this.flowService.getProcessGroupWithContent(currentProcessGroupId)]).pipe( - map(([processGroupEntity]) => { - return { - request, - currentProcessGroupId, - processGroupFlow, - processGroupEntity, - controllerServices - }; - }) - ) + concatMap( + ([request, currentProcessGroupId, childProcessGroupOptions, controllerServices, breadcrumb]) => + combineLatest([this.flowService.getProcessGroupWithContent(currentProcessGroupId)]).pipe( + map(([processGroupEntity]) => { + return { + request, + currentProcessGroupId, + childProcessGroupOptions, + processGroupEntity, + controllerServices, + breadcrumb + }; + }) + ) ), tap((request) => { const clone = Object.assign({}, request.request); clone.processGroupEntity = request.processGroupEntity; - clone.processGroupFlow = request.processGroupFlow; + clone.childProcessGroupOptions = request.childProcessGroupOptions; clone.parentControllerServices = request.controllerServices; + clone.breadcrumb = request.breadcrumb; const serviceId: string = request.request.id; const moveDialogReference = this.dialog.open(MoveControllerService, { ...LARGE_DIALOG, diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts index 2c8e80fde992a..46329e5aadcdf 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts @@ -35,6 +35,7 @@ import { ControllerServicesState } from './index'; export const initialState: ControllerServicesState = { processGroupId: 'root', + childProcessGroupOptions: [], controllerServices: [], breadcrumb: { id: '', @@ -70,7 +71,7 @@ export const controllerServicesReducer = createReducer( breadcrumb: response.breadcrumb, parameterContext: response.parameterContext, loadedTimestamp: response.loadedTimestamp, - processGroupFlow: response.processGroupFlow, + childProcessGroupOptions: response.childProcessGroupOptions, status: 'success' as const })), on(controllerServicesBannerApiError, (state) => ({ diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts index da66609a224c9..b7cad8339c4f2 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.selectors.ts @@ -41,9 +41,14 @@ export const selectCurrentProcessGroupId = createSelector( (state: ControllerServicesState) => state.processGroupId ); -export const selectProcessGroupFlow = createSelector( +export const selectChildProcessGroupOptions = createSelector( selectControllerServicesState, - (state: ControllerServicesState) => state.processGroupFlow + (state: ControllerServicesState) => state.childProcessGroupOptions +); + +export const selectBreadcrumb = createSelector( + selectControllerServicesState, + (state: ControllerServicesState) => state.breadcrumb ); export const selectParameterContext = createSelector( diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/index.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/index.ts index 90e27d795512b..5a1448a15b1bb 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/index.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/index.ts @@ -15,8 +15,8 @@ * limitations under the License. */ +import { SelectOption } from '@nifi/shared'; import { ControllerServiceEntity, ParameterContextReferenceEntity } from '../../../../state/shared'; -import { ProcessGroupFlow } from '../flow'; import { BreadcrumbEntity } from '../shared'; import { Revision } from './../../../../state/shared/index'; @@ -32,7 +32,7 @@ export interface LoadControllerServicesResponse { controllerServices: ControllerServiceEntity[]; parameterContext: ParameterContextReferenceEntity | null; loadedTimestamp: string; - processGroupFlow: ProcessGroupFlow; + childProcessGroupOptions: SelectOption[]; } export interface CreateControllerServiceSuccess { @@ -57,9 +57,10 @@ export interface ConfigureControllerServiceSuccess { export interface MoveControllerServiceDialogRequest { id: string; controllerService: ControllerServiceEntity; - processGroupFlow?: ProcessGroupFlow; + childProcessGroupOptions: SelectOption[]; processGroupEntity?: any; parentControllerServices: ControllerServiceEntity[]; + breadcrumb?: BreadcrumbEntity; } export interface MoveControllerServiceRequest { @@ -91,7 +92,7 @@ export interface SelectControllerServiceRequest { export interface ControllerServicesState { processGroupId: string; - processGroupFlow?: ProcessGroupFlow; + childProcessGroupOptions: SelectOption[]; breadcrumb: BreadcrumbEntity; controllerServices: ControllerServiceEntity[]; parameterContext: ParameterContextReferenceEntity | null; diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html index 5a32963ad65c4..f5376c38df846 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.html @@ -42,7 +42,7 @@

Controller Services

[selectedServiceId]="selectedServiceId$ | async" [controllerServices]="serviceState.controllerServices" [formatScope]="formatScope(serviceState.breadcrumb)" - [isManagementControllerService]="isManagementControllerService" + [showMoveOption]="true" [definedByCurrentGroup]="definedByCurrentGroup(serviceState.breadcrumb)" [currentUser]="(currentUser$ | async)!" [flowConfiguration]="flowConfiguration" diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts index 47d6c5d411c76..c4e60acb44433 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.ts @@ -245,7 +245,8 @@ export class ControllerServices implements OnDestroy { request: { id: entity.id, controllerService: entity, - parentControllerServices: [] + parentControllerServices: [], + childProcessGroupOptions: [] } }) ); @@ -334,10 +335,6 @@ export class ControllerServices implements OnDestroy { ); } - isManagementControllerService(): boolean { - return false; - } - ngOnDestroy(): void { this.store.dispatch(resetControllerServicesState()); } diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html index bf9d06b517233..b902edc88ea51 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html @@ -16,11 +16,11 @@ -->

Move Controller Service

-
+ -
+
-
+
Service
{ let component: MoveControllerService; let fixture: ComponentFixture; - const flow: ProcessGroupFlow = { + const breadrumb: BreadcrumbEntity = { id: 'cc4eefda-018d-1000-35ee-194d439257e4', - parameterContext: null, - uri: 'http://localhost/nifi-api/flow/process-groups/cc4eefda-018d-1000-35ee-194d439257e4', - parentGroupId: '96456bc3-018b-1000-05d8-51720bebae4b', + permissions: { + canRead: true, + canWrite: true + }, breadcrumb: { id: 'cc4eefda-018d-1000-35ee-194d439257e4', + name: 'pg1' + }, + parentBreadcrumb: { + id: '96456bc3-018b-1000-05d8-51720bebae4b', permissions: { canRead: true, canWrite: true }, breadcrumb: { - id: 'cc4eefda-018d-1000-35ee-194d439257e4', - name: 'pg1' - }, - parentBreadcrumb: { id: '96456bc3-018b-1000-05d8-51720bebae4b', - permissions: { - canRead: true, - canWrite: true - }, - breadcrumb: { - id: '96456bc3-018b-1000-05d8-51720bebae4b', - name: 'NiFi Flow' - }, - versionedFlowState: '' + name: 'NiFi Flow' }, versionedFlowState: '' }, - flow: { - processGroups: [ - { - revision: { - version: 0 - }, - id: 'cc4f110c-018d-1000-d4b6-d933a69c9d53', - position: { - x: 450.00000073872457, - y: 89.00000213800337 - }, - permissions: { - canRead: true, - canWrite: true - }, - component: { - id: 'cc4f110c-018d-1000-d4b6-d933a69c9d53', - versionedComponentId: '11610e12-1853-3179-9e6b-714a77c470e2', - parentGroupId: 'cc4eefda-018d-1000-35ee-194d439257e4', - position: { - x: 450.00000073872457, - y: 89.00000213800337 - }, - name: 'pg2', - comments: '', - flowfileConcurrency: 'UNBOUNDED', - flowfileOutboundPolicy: 'STREAM_WHEN_AVAILABLE', - defaultFlowFileExpiration: '0 sec', - defaultBackPressureObjectThreshold: 10000, - defaultBackPressureDataSizeThreshold: '1 GB', - executionEngine: 'INHERITED', - maxConcurrentTasks: 1, - statelessFlowTimeout: '1 min', - runningCount: 0, - stoppedCount: 0, - invalidCount: 0, - disabledCount: 0, - activeRemotePortCount: 0, - inactiveRemotePortCount: 0, - upToDateCount: 0, - locallyModifiedCount: 0, - staleCount: 0, - locallyModifiedAndStaleCount: 0, - syncFailureCount: 0, - localInputPortCount: 0, - localOutputPortCount: 0, - publicInputPortCount: 0, - publicOutputPortCount: 0, - statelessGroupScheduledState: 'STOPPED', - inputPortCount: 0, - outputPortCount: 0 - } - } - ], - remoteProcessGroups: [], - processors: [ - { - revision: { - version: 0 - }, - id: '018e1000-93c7-1b09-09f3-8e5a070f0381', - position: { - x: 760, - y: 272 - }, - permissions: { - canRead: true, - canWrite: true - }, - component: { - id: '018e1000-93c7-1b09-09f3-8e5a070f0381', - versionedComponentId: '401e9313-5c31-3bb8-ac48-c34af331b2af', - parentGroupId: 'cc4eefda-018d-1000-35ee-194d439257e4', - position: { - x: 760, - y: 272 - }, - name: 'ConsumeKafkaRecord_2_6 t1', - type: 'org.apache.nifi.processors.kafka.pubsub.ConsumeKafkaRecord_2_6', - bundle: { - group: 'org.apache.nifi', - artifact: 'nifi-kafka-2-6-nar', - version: '2.0.0-SNAPSHOT' - }, - state: 'STOPPED', - style: {}, - relationships: [ - { - name: 'parse.failure', - description: - 'If a message from Kafka cannot be parsed using the configured Record Reader, the contents of the message will be routed to this Relationship as its own individual FlowFile.', - autoTerminate: true, - retry: false - }, - { - name: 'success', - description: - 'FlowFiles received from Kafka. Depending on demarcation strategy it is a flow file per message or a bundle of messages grouped by topic and partition.', - autoTerminate: true, - retry: false - } - ], - supportsParallelProcessing: true, - supportsBatching: false, - supportsSensitiveDynamicProperties: false, - persistsState: false, - restricted: false, - deprecated: false, - executionNodeRestricted: false, - multipleVersionsAvailable: false, - inputRequirement: 'INPUT_FORBIDDEN', - config: { - schedulingPeriod: '0 sec', - schedulingStrategy: 'TIMER_DRIVEN', - executionNode: 'ALL', - penaltyDuration: '30 sec', - yieldDuration: '1 sec', - bulletinLevel: 'WARN', - runDurationMillis: 0, - concurrentlySchedulableTaskCount: 1, - autoTerminatedRelationships: ['parse.failure', 'success'], - comments: '', - lossTolerant: false, - retryCount: 10, - retriedRelationships: [], - backoffMechanism: 'PENALIZE_FLOWFILE', - maxBackoffPeriod: '10 mins' - }, - validationStatus: 'VALID', - extensionMissing: false - } - }, - { - revision: { - version: 0 - }, - id: '018e1002-93c7-1b09-913c-8102bce39edb', - position: { - x: 855, - y: 655 - }, - permissions: { - canRead: true, - canWrite: true - }, - component: { - id: '018e1002-93c7-1b09-913c-8102bce39edb', - versionedComponentId: '1bd9430e-e943-33bd-9eca-40fc4187c17c', - parentGroupId: 'cc4eefda-018d-1000-35ee-194d439257e4', - position: { - x: 855, - y: 655 - }, - name: 'Budokai', - type: 'org.apache.nifi.processors.kafka.pubsub.ConsumeKafkaRecord_2_6', - bundle: { - group: 'org.apache.nifi', - artifact: 'nifi-kafka-2-6-nar', - version: '2.0.0-SNAPSHOT' - }, - state: 'STOPPED', - style: {}, - relationships: [ - { - name: 'parse.failure', - description: - 'If a message from Kafka cannot be parsed using the configured Record Reader, the contents of the message will be routed to this Relationship as its own individual FlowFile.', - autoTerminate: true, - retry: false - }, - { - name: 'success', - description: - 'FlowFiles received from Kafka. Depending on demarcation strategy it is a flow file per message or a bundle of messages grouped by topic and partition.', - autoTerminate: true, - retry: false - } - ], - supportsParallelProcessing: true, - supportsBatching: false, - supportsSensitiveDynamicProperties: false, - persistsState: false, - restricted: false, - deprecated: false, - executionNodeRestricted: false, - multipleVersionsAvailable: false, - inputRequirement: 'INPUT_FORBIDDEN', - config: { - schedulingPeriod: '0 sec', - schedulingStrategy: 'TIMER_DRIVEN', - executionNode: 'ALL', - penaltyDuration: '30 sec', - yieldDuration: '1 sec', - bulletinLevel: 'WARN', - runDurationMillis: 0, - concurrentlySchedulableTaskCount: 1, - autoTerminatedRelationships: ['parse.failure', 'success'], - comments: '', - lossTolerant: false, - retryCount: 10, - retriedRelationships: [], - backoffMechanism: 'PENALIZE_FLOWFILE', - maxBackoffPeriod: '10 mins' - }, - validationStatus: 'VALID', - extensionMissing: false - } - }, - { - revision: { - version: 0 - }, - id: '0b0993c7-018e-1000-34f0-eac5126a49d7', - position: { - x: 480, - y: 408 - }, - permissions: { - canRead: true, - canWrite: true - }, - component: { - id: '0b0993c7-018e-1000-34f0-eac5126a49d7', - versionedComponentId: '2f6b8ff4-218e-3a5c-8abc-8a8146852732', - parentGroupId: 'cc4eefda-018d-1000-35ee-194d439257e4', - position: { - x: 480, - y: 408 - }, - name: 'ConsumeKafkaRecord_2_6', - type: 'org.apache.nifi.processors.kafka.pubsub.ConsumeKafkaRecord_2_6', - bundle: { - group: 'org.apache.nifi', - artifact: 'nifi-kafka-2-6-nar', - version: '2.0.0-SNAPSHOT' - }, - state: 'RUNNING', - style: {}, - relationships: [ - { - name: 'parse.failure', - description: - 'If a message from Kafka cannot be parsed using the configured Record Reader, the contents of the message will be routed to this Relationship as its own individual FlowFile.', - autoTerminate: true, - retry: false - }, - { - name: 'success', - description: - 'FlowFiles received from Kafka. Depending on demarcation strategy it is a flow file per message or a bundle of messages grouped by topic and partition.', - autoTerminate: true, - retry: false - } - ], - supportsParallelProcessing: true, - supportsBatching: false, - supportsSensitiveDynamicProperties: false, - persistsState: false, - restricted: false, - deprecated: false, - executionNodeRestricted: false, - multipleVersionsAvailable: false, - inputRequirement: 'INPUT_FORBIDDEN', - config: { - schedulingPeriod: '0 sec', - schedulingStrategy: 'TIMER_DRIVEN', - executionNode: 'ALL', - penaltyDuration: '30 sec', - yieldDuration: '1 sec', - bulletinLevel: 'WARN', - runDurationMillis: 0, - concurrentlySchedulableTaskCount: 1, - autoTerminatedRelationships: ['parse.failure', 'success'], - comments: '', - lossTolerant: false, - retryCount: 10, - retriedRelationships: [], - backoffMechanism: 'PENALIZE_FLOWFILE', - maxBackoffPeriod: '10 mins' - }, - validationStatus: 'VALID', - extensionMissing: false - } - } - ], - inputPorts: [], - outputPorts: [], - connections: [], - labels: [], - funnels: [] - }, - lastRefreshed: '13:19:03 UTC' + versionedFlowState: '' }; + const chldren: SelectOption[] = [ + { + text: 'pg2', + value: 'cc4f110c-018d-1000-d4b6-d933a69c9d53' + }, + { + text: 'pg2', + value: 'cc4f110c-018d-1000-d4b6-d933a69c9d53' + } + ]; + const processGroupEntity = { revision: { version: 0 @@ -3719,7 +3432,8 @@ describe('MoveControllerService', () => { const data: MoveControllerServiceDialogRequest = { id: '92db6ee4-018c-1000-1061-e3476c3f4e9f', - processGroupFlow: flow, + breadcrumb: breadrumb, + childProcessGroupOptions: chldren, processGroupEntity: processGroupEntity, parentControllerServices: parentControllerServices, controllerService: controllerService diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts index 79caab9f12030..493a8686aa566 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts @@ -33,16 +33,14 @@ import { MatSelectModule } from '@angular/material/select'; import { ControllerServiceApi } from '../../../../ui/common/controller-service/controller-service-api/controller-service-api.component'; import { ControllerServiceReferences } from '../../../../ui/common/controller-service/controller-service-references/controller-service-references.component'; import { NifiSpinnerDirective } from '../../../../ui/common/spinner/nifi-spinner.directive'; -import { TextTip } from '../../../../ui/common/tooltips/text-tip/text-tip.component'; -import { NifiTooltipDirective } from '../../../../ui/common/tooltips/nifi-tooltip.directive'; +import { TextTip, NifiTooltipDirective, SelectOption } from '@nifi/shared'; import { Store } from '@ngrx/store'; import { CloseOnEscapeDialog } from '../../../../ui/common/close-on-escape-dialog/close-on-escape-dialog.component'; import { moveControllerService } from '../../state/controller-services/controller-services.actions'; -import { SelectOption } from '../../../../state/shared/index'; import { NiFiState } from 'apps/nifi/src/app/state'; import { MoveControllerServiceDialogRequest } from '../../state/controller-services'; -import { ComponentEntity, ProcessGroupFlow } from '../../state/flow'; import { NgIf } from '@angular/common'; +import { BreadcrumbEntity } from '../../state/shared'; @Component({ selector: 'move-controller-service', @@ -94,96 +92,91 @@ export class MoveControllerService extends CloseOnEscapeDialog { (cs) => cs.parentGroupId != request.controllerService.parentGroupId ); - if (request.processGroupFlow != null) { - const processGroups: SelectOption[] = []; - this.loadParentOption(request.processGroupFlow, parentControllerServices, processGroups); - this.loadChildOptions(request.processGroupFlow, request.processGroupEntity, processGroups); - this.controllerServiceActionProcessGroups = processGroups; + const processGroups: SelectOption[] = []; + if (request.breadcrumb != undefined) { + this.loadParentOption(request.breadcrumb, parentControllerServices, processGroups); + } + this.loadChildOptions(request.childProcessGroupOptions, request.processGroupEntity, processGroups); + this.controllerServiceActionProcessGroups = processGroups; - const firstEnabled = processGroups.findIndex((pg) => !pg.disabled); - if (firstEnabled != -1) { - this.moveControllerServiceForm.controls['processGroups'].setValue(processGroups[firstEnabled].value); - } + const firstEnabled = processGroups.findIndex((pg) => !pg.disabled); + if (firstEnabled != -1) { + this.moveControllerServiceForm.controls['processGroups'].setValue(processGroups[firstEnabled].value); } } loadParentOption( - processGroupFlow: ProcessGroupFlow, + breadcrumb: BreadcrumbEntity, parentControllerServices: ControllerServiceEntity[], processGroups: SelectOption[] ) { - if (processGroupFlow.breadcrumb.parentBreadcrumb != undefined) { - if (processGroupFlow.breadcrumb.parentBreadcrumb != undefined) { - const parentBreadcrumb = processGroupFlow.breadcrumb.parentBreadcrumb; - if (parentBreadcrumb.permissions.canRead && parentBreadcrumb.permissions.canWrite) { - const option: SelectOption = { - text: parentBreadcrumb.breadcrumb.name + ' (Parent)', - value: parentBreadcrumb.breadcrumb.id - }; - - let errorMsg = ''; - const descriptors = this.controllerService.component.descriptors; - for (const descriptor in descriptors) { - if (descriptors[descriptor].identifiesControllerService != undefined) { - const controllerId = - this.controllerService.component.properties[descriptors[descriptor].name]; - if ( - controllerId != null && - !parentControllerServices.some((service) => service.id == controllerId) - ) { - errorMsg += '[' + descriptors[descriptor].name + ']'; - } - } - } + if (breadcrumb.parentBreadcrumb != undefined) { + const parentBreadcrumb = breadcrumb.parentBreadcrumb; + if (parentBreadcrumb.permissions.canRead && parentBreadcrumb.permissions.canWrite) { + const option: SelectOption = { + text: parentBreadcrumb.breadcrumb.name + ' (Parent)', + value: parentBreadcrumb.breadcrumb.id + }; - if (errorMsg != '') { - option.description = - 'The following properties reference controller services that would be out of scope for this ' + - 'process group: ' + - errorMsg; - option.disabled = true; - } else { - option.disabled = false; + let errorMsg = ''; + const descriptors = this.controllerService.component.descriptors; + for (const descriptor in descriptors) { + if (descriptors[descriptor].identifiesControllerService != undefined) { + const controllerId = this.controllerService.component.properties[descriptors[descriptor].name]; + if ( + controllerId != null && + !parentControllerServices.some((service) => service.id == controllerId) + ) { + errorMsg += '[' + descriptors[descriptor].name + ']'; + } } + } - processGroups.push(option); + if (errorMsg != '') { + option.description = + 'The following properties reference controller services that would be out of scope for this ' + + 'process group: ' + + errorMsg; + option.disabled = true; + } else { + option.disabled = false; } + + processGroups.push(option); } } } loadChildOptions( - processGroupFlow: ProcessGroupFlow, + childProcessGroupOptions: SelectOption[], currentProcessGroupEntity: any, processGroups: SelectOption[] ) { const referencingComponents: ControllerServiceReferencingComponentEntity[] = this.controllerService.component.referencingComponents; - processGroupFlow.flow.processGroups.forEach((child: ComponentEntity) => { - if (child.permissions.canRead && child.permissions.canWrite) { - const option: SelectOption = { - text: child.component.name, - value: child.component.id - }; - - const root = this.getProcessGroupById(currentProcessGroupEntity.component, child.component.id); - let errorMsg = ''; - for (const component of referencingComponents) { - if (!this.processGroupContainsComponent(root, component.component.groupId)) { - errorMsg += '[' + component.component.name + ']'; - } - } - - if (errorMsg != '') { - option.description = - 'The following components would be out of scope for this ' + 'process group: ' + errorMsg; - option.disabled = true; - } else { - option.disabled = false; + childProcessGroupOptions.forEach((child: SelectOption) => { + const option: SelectOption = { + text: child.text, + value: child.value + }; + + const root = this.getProcessGroupById(currentProcessGroupEntity.component, child.value ?? ''); + let errorMsg = ''; + for (const component of referencingComponents) { + if (!this.processGroupContainsComponent(root, component.component.groupId)) { + errorMsg += '[' + component.component.name + ']'; } + } - processGroups.push(option); + if (errorMsg != '') { + option.description = + 'The following components would be out of scope for this ' + 'process group: ' + errorMsg; + option.disabled = true; + } else { + option.disabled = false; } + + processGroups.push(option); }); } diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html index e0a6ba7ceee6d..2a0b491d19756 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.html @@ -35,7 +35,7 @@ [selectedServiceId]="selectedServiceId$ | async" [controllerServices]="serviceState.controllerServices" [formatScope]="formatScope" - [isManagementControllerService]="isManagementControllerService" + [showMoveOption]="false" [definedByCurrentGroup]="definedByCurrentGroup" [currentUser]="currentUser" [canModifyParent]="canModifyParent(currentUser)" diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts index 6f99e429bb150..a79d364b46489 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/ui/management-controller-services/management-controller-services.component.ts @@ -228,10 +228,6 @@ export class ManagementControllerServices implements OnInit, OnDestroy { ); } - isManagementControllerService(): boolean { - return true; - } - ngOnDestroy(): void { this.store.dispatch(resetManagementControllerServicesState()); } diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts index 397131cc9f0c8..2eb2697e9c223 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts @@ -62,7 +62,7 @@ export class ControllerServiceTable { @Input() selectedServiceId!: string; @Input() formatScope!: (entity: ControllerServiceEntity) => string; - @Input() isManagementControllerService!: () => boolean; + @Input() showMoveOption!: boolean; @Input() definedByCurrentGroup!: (entity: ControllerServiceEntity) => boolean; @Input() flowConfiguration!: FlowConfiguration; @Input() currentUser!: CurrentUser; @@ -232,7 +232,7 @@ export class ControllerServiceTable { } canMove(entity: ControllerServiceEntity): boolean { - return !this.isManagementControllerService() && this.canRead(entity) && this.canWrite(entity); + return this.showMoveOption && this.canRead(entity) && this.canWrite(entity); } moveClicked(entity: ControllerServiceEntity): void {