You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2024/01/26 17:58:39 UTC
(nifi) branch main updated: [NIFI-12622] - Parameter Providers - listing table (#8298)
This is an automated email from the ASF dual-hosted git repository.
mcgilman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 0e87032ef3 [NIFI-12622] - Parameter Providers - listing table (#8298)
0e87032ef3 is described below
commit 0e87032ef3e2b74c1451f5859e277e6d9787b4d8
Author: Rob Fellows <ro...@gmail.com>
AuthorDate: Fri Jan 26 12:58:33 2024 -0500
[NIFI-12622] - Parameter Providers - listing table (#8298)
* [NIFI-12622] - Parameter Providers - listing table
* Add a new Parameter Provider
* Delete parameter provider
* refactor to reduce duplicate code when creating new properties
* support editing parameter providers
* refactored inline service creation into PropertyTableHelperService
* added parameter provider linking to access policies.
* fix bugs in flow reducer not setting state properly when starting/stopping components and run once.
* address review feedback
* refactored nifiCommon to provide stripProtocol method that was implemented in loads of places. replaced all occurrences to the nifiCommon implementation.
This closes #8298
---
.../web/api/entity/ParameterProvidersEntity.java | 21 ++
.../ParameterProvidersEndpointMerger.java | 2 +
.../java/org/apache/nifi/web/api/FlowResource.java | 1 +
.../service/access-policy.service.ts | 17 +-
.../component-access-policies.component.ts | 3 +
.../counter-table/counter-table.component.ts | 11 +-
.../service/controller-service.service.ts | 53 ++-
.../pages/flow-designer/service/flow.service.ts | 27 +-
.../flow-designer/service/parameter.service.ts | 17 +-
.../pages/flow-designer/service/queue.service.ts | 17 +-
.../controller-services.actions.ts | 2 +-
.../controller-services.effects.ts | 152 ++-------
.../state/controller-services/index.ts | 7 -
.../pages/flow-designer/state/flow/flow.effects.ts | 123 +------
.../pages/flow-designer/state/flow/flow.reducer.ts | 15 +-
.../controller-services.component.spec.ts | 4 +-
.../service/parameter-contexts.service.ts | 17 +-
.../parameter-context-listing.module.ts | 2 +-
.../parameter-context-table.component.ts | 10 +-
.../pages/provenance/service/provenance.service.ts | 15 +-
.../src/app/pages/queue/service/queue.service.ts | 23 +-
.../settings/feature/settings-routing.module.ts | 21 +-
.../app/pages/settings/feature/settings.module.ts | 4 +-
.../settings/service/flow-analysis-rule.service.ts | 22 +-
.../management-controller-service.service.ts | 29 +-
.../settings/service/parameter-provider.service.ts | 78 +++++
.../settings/service/registry-client.service.ts | 20 +-
.../settings/service/reporting-task.service.ts | 27 +-
.../flow-analysis-rules.effects.ts | 123 +------
.../nifi/src/app/pages/settings/state/index.ts | 6 +-
.../state/management-controller-services/index.ts | 6 -
.../management-controller-services.actions.ts | 2 +-
.../management-controller-services.effects.ts | 134 ++------
.../settings/state/parameter-providers/index.ts | 117 +++++++
.../parameter-providers.actions.ts | 99 ++++++
.../parameter-providers.effects.ts | 359 +++++++++++++++++++++
.../parameter-providers.reducer.ts | 106 ++++++
.../parameter-providers.selectors.ts | 56 ++++
.../registry-clients/registry-clients.effects.ts | 129 +-------
.../reporting-tasks/reporting-tasks.effects.ts | 109 +------
.../create-parameter-provider.component.html} | 8 +-
.../create-parameter-provider.component.scss} | 13 +-
.../create-parameter-provider.component.spec.ts | 81 +++++
.../create-parameter-provider.component.ts} | 33 +-
.../edit-parameter-provider.component.html | 91 ++++++
.../edit-parameter-provider.component.scss} | 29 +-
.../edit-parameter-provider.component.spec.ts | 170 ++++++++++
.../edit-parameter-provider.component.ts | 141 ++++++++
...arameter-provider-references.component.spec.ts} | 14 +-
.../parameter-provider-references.component.ts | 50 +++
.../parameter-providers-references.component.html | 76 +++++
.../parameter-providers-references.component.scss} | 19 +-
.../parameter-providers-table.component.html | 121 +++++++
.../parameter-providers-table.component.scss} | 17 +-
.../parameter-providers-table.component.spec.ts} | 15 +-
.../parameter-providers-table.component.ts | 176 ++++++++++
.../parameter-providers.component.html | 37 ++-
.../parameter-providers.component.spec.ts | 9 +-
.../parameter-providers.component.ts | 98 +++++-
.../parameter-providers.module.ts | 5 +-
.../reporting-task-table.component.ts | 10 +-
.../src/app/pages/users/service/users.service.ts | 21 +-
.../src/app/service/component-state.service.ts | 17 +-
.../service/controller-service-state.service.ts | 19 +-
.../nifi/src/app/service/nifi-common.service.ts | 13 +
.../app/service/property-table-helper.service.ts | 177 ++++++++++
.../extension-types/extension-types.selectors.ts | 5 +
.../src/main/nifi/src/app/state/shared/index.ts | 22 +-
.../controller-service-table.component.ts | 10 +-
.../create-controller-service.component.spec.ts | 4 +-
.../create-controller-service.component.ts | 4 +-
.../extension-creation.component.ts | 10 +-
72 files changed, 2430 insertions(+), 1071 deletions(-)
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ParameterProvidersEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ParameterProvidersEntity.java
index 900bdfb4c3..88972d4d2f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ParameterProvidersEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ParameterProvidersEntity.java
@@ -16,7 +16,12 @@
*/
package org.apache.nifi.web.api.entity;
+import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import org.apache.nifi.web.api.dto.util.TimeAdapter;
+
+import java.util.Date;
import java.util.Set;
/**
@@ -27,6 +32,8 @@ public class ParameterProvidersEntity extends Entity {
private Set<ParameterProviderEntity> parameterProviders;
+ private Date currentTime;
+
/**
* @return list of parameter providers that are being serialized
*/
@@ -38,4 +45,18 @@ public class ParameterProvidersEntity extends Entity {
this.parameterProviders = parameterProviders;
}
+ /**
+ * @return current time on the server
+ */
+ @XmlJavaTypeAdapter(TimeAdapter.class)
+ @Schema(description = "The current time on the system.",
+ type = "string"
+ )
+ public Date getCurrentTime() {
+ return currentTime;
+ }
+
+ public void setCurrentTime(Date currentTime) {
+ this.currentTime = currentTime;
+ }
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterProvidersEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterProvidersEndpointMerger.java
index 079922f5d2..1b3e6807c6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterProvidersEndpointMerger.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterProvidersEndpointMerger.java
@@ -23,6 +23,7 @@ import org.apache.nifi.web.api.entity.ParameterProviderEntity;
import org.apache.nifi.web.api.entity.ParameterProvidersEntity;
import java.net.URI;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -60,6 +61,7 @@ public class ParameterProvidersEndpointMerger extends AbstractSingleEntityEndpoi
}
clientEntity.setParameterProviders(new HashSet<>(providerEntities.values()));
+ clientEntity.setCurrentTime(new Date());
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
index fd9bb8c5d4..6ed92d1d73 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
@@ -672,6 +672,7 @@ public class FlowResource extends ApplicationResource {
// create the response entity
final ParameterProvidersEntity entity = new ParameterProvidersEntity();
entity.setParameterProviders(parameterProviders);
+ entity.setCurrentTime(new Date());
// generate the response
return generateOkResponse(entity).build();
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/service/access-policy.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/service/access-policy.service.ts
index 34ab4bf959..8fb0800b80 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/service/access-policy.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/service/access-policy.service.ts
@@ -33,19 +33,6 @@ export class AccessPolicyService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
createAccessPolicy(resourceAction: ResourceAction): Observable<any> {
let resource: string = `/${resourceAction.resource}`;
if (resourceAction.resourceIdentifier) {
@@ -92,12 +79,12 @@ export class AccessPolicyService {
}
};
- return this.httpClient.put(this.stripProtocol(accessPolicy.uri), payload);
+ return this.httpClient.put(this.nifiCommon.stripProtocol(accessPolicy.uri), payload);
}
deleteAccessPolicy(accessPolicy: AccessPolicyEntity): Observable<any> {
const revision: any = this.client.getRevision(accessPolicy);
- return this.httpClient.delete(this.stripProtocol(accessPolicy.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(accessPolicy.uri), { params: revision });
}
getUsers(): Observable<any> {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts
index b22bdeb566..5d52f50df3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/access-policies/ui/component-access-policies/component-access-policies.component.ts
@@ -306,6 +306,7 @@ export class ComponentAccessPolicies implements OnInit, OnDestroy {
return 'icon-label';
case 'remote-process-groups':
return 'icon-group-remote';
+ case 'parameter-providers':
case 'parameter-contexts':
return 'icon-drop';
}
@@ -329,6 +330,8 @@ export class ComponentAccessPolicies implements OnInit, OnDestroy {
return 'Remote Process Group';
case 'parameter-contexts':
return 'Parameter Contexts';
+ case 'parameter-providers':
+ return 'Parameter Provider';
}
return 'Process Group';
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/counters/ui/counter-listing/counter-table/counter-table.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/counters/ui/counter-listing/counter-table/counter-table.component.ts
index 2ae859dfce..666aa21833 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/counters/ui/counter-listing/counter-table/counter-table.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/counters/ui/counter-listing/counter-table/counter-table.component.ts
@@ -42,11 +42,13 @@ export class CounterTable implements AfterViewInit {
@Input() initialSortColumn: 'context' | 'name' | 'value' = 'context';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
+ activeSort: Sort = {
+ active: this.initialSortColumn,
+ direction: this.initialSortDirection
+ };
+
@Input() set counters(counterEntities: CounterEntity[]) {
- this.dataSource.data = this.sortEntities(counterEntities, {
- active: this.initialSortColumn,
- direction: this.initialSortDirection
- });
+ this.dataSource.data = this.sortEntities(counterEntities, this.activeSort);
this.dataSource.filterPredicate = (data: CounterEntity, filter: string) => {
const { filterTerm, filterColumn } = JSON.parse(filter);
@@ -128,6 +130,7 @@ export class CounterTable implements AfterViewInit {
}
sortData(sort: Sort) {
+ this.activeSort = sort;
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/controller-service.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/controller-service.service.ts
index c354935607..cb3ffe42a6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/controller-service.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/controller-service.service.ts
@@ -16,34 +16,22 @@
*/
import { Injectable } from '@angular/core';
-import { Observable, throwError } from 'rxjs';
+import { EMPTY, Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Client } from '../../../service/client.service';
import { NiFiCommon } from '../../../service/nifi-common.service';
-import { ControllerServiceEntity } from '../../../state/shared';
import {
- ConfigureControllerServiceRequest,
+ ControllerServiceCreator,
+ ControllerServiceEntity,
CreateControllerServiceRequest,
- DeleteControllerServiceRequest
-} from '../state/controller-services';
+ PropertyDescriptorRetriever
+} from '../../../state/shared';
+import { ConfigureControllerServiceRequest, DeleteControllerServiceRequest } from '../state/controller-services';
@Injectable({ providedIn: 'root' })
-export class ControllerServiceService {
+export class ControllerServiceService implements ControllerServiceCreator, PropertyDescriptorRetriever {
private static readonly API: string = '../nifi-api';
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
constructor(
private httpClient: HttpClient,
private client: Client,
@@ -69,17 +57,20 @@ export class ControllerServiceService {
}
createControllerService(createControllerService: CreateControllerServiceRequest): Observable<any> {
- const processGroupId: string = createControllerService.processGroupId;
- return this.httpClient.post(
- `${ControllerServiceService.API}/process-groups/${processGroupId}/controller-services`,
- {
- revision: createControllerService.revision,
- component: {
- bundle: createControllerService.controllerServiceBundle,
- type: createControllerService.controllerServiceType
+ if (createControllerService.processGroupId) {
+ const processGroupId: string = createControllerService.processGroupId;
+ return this.httpClient.post(
+ `${ControllerServiceService.API}/process-groups/${processGroupId}/controller-services`,
+ {
+ revision: createControllerService.revision,
+ component: {
+ bundle: createControllerService.controllerServiceBundle,
+ type: createControllerService.controllerServiceType
+ }
}
- }
- );
+ );
+ }
+ return EMPTY;
}
getPropertyDescriptor(id: string, propertyName: string, sensitive: boolean): Observable<any> {
@@ -94,7 +85,7 @@ export class ControllerServiceService {
updateControllerService(configureControllerService: ConfigureControllerServiceRequest): Observable<any> {
return this.httpClient.put(
- this.stripProtocol(configureControllerService.uri),
+ this.nifiCommon.stripProtocol(configureControllerService.uri),
configureControllerService.payload
);
}
@@ -102,6 +93,6 @@ export class ControllerServiceService {
deleteControllerService(deleteControllerService: DeleteControllerServiceRequest): Observable<any> {
const entity: ControllerServiceEntity = deleteControllerService.controllerService;
const revision: any = this.client.getRevision(entity);
- return this.httpClient.delete(this.stripProtocol(entity.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(entity.uri), { params: revision });
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
index b2acac8580..8d841d986c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/flow.service.ts
@@ -38,12 +38,12 @@ import {
UpdateComponentRequest,
UploadProcessGroupRequest
} from '../state/flow';
-import { ComponentType } from '../../../state/shared';
+import { ComponentType, PropertyDescriptorRetriever } from '../../../state/shared';
import { Client } from '../../../service/client.service';
import { NiFiCommon } from '../../../service/nifi-common.service';
@Injectable({ providedIn: 'root' })
-export class FlowService {
+export class FlowService implements PropertyDescriptorRetriever {
private static readonly API: string = '../nifi-api';
constructor(
@@ -53,19 +53,6 @@ export class FlowService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getFlow(processGroupId = 'root'): Observable<any> {
// TODO - support uiOnly... this would mean that we need to load the entire resource prior to editing
return this.httpClient.get(`${FlowService.API}/flow/process-groups/${processGroupId}`);
@@ -212,13 +199,13 @@ export class FlowService {
updateComponent(updateComponent: UpdateComponentRequest): Observable<any> {
// return throwError('API Error');
- return this.httpClient.put(this.stripProtocol(updateComponent.uri), updateComponent.payload);
+ return this.httpClient.put(this.nifiCommon.stripProtocol(updateComponent.uri), updateComponent.payload);
}
deleteComponent(deleteComponent: DeleteComponentRequest): Observable<any> {
// return throwError('API Error');
const revision: any = this.client.getRevision(deleteComponent.entity);
- return this.httpClient.delete(this.stripProtocol(deleteComponent.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(deleteComponent.uri), { params: revision });
}
createSnippet(snippet: Snippet): Observable<any> {
@@ -250,7 +237,7 @@ export class FlowService {
disconnectedNodeAcknowledged: false,
state: 'RUN_ONCE'
};
- return this.httpClient.put(`${this.stripProtocol(request.uri)}/run-status`, startRequest);
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(request.uri)}/run-status`, startRequest);
}
startComponent(request: StartComponentRequest): Observable<any> {
@@ -259,7 +246,7 @@ export class FlowService {
disconnectedNodeAcknowledged: false,
state: request.type === ComponentType.RemoteProcessGroup ? 'TRANSMITTING' : 'RUNNING'
};
- return this.httpClient.put(`${this.stripProtocol(request.uri)}/run-status`, startRequest);
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(request.uri)}/run-status`, startRequest);
}
stopComponent(request: StopComponentRequest): Observable<any> {
@@ -268,7 +255,7 @@ export class FlowService {
disconnectedNodeAcknowledged: false,
state: 'STOPPED'
};
- return this.httpClient.put(`${this.stripProtocol(request.uri)}/run-status`, stopRequest);
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(request.uri)}/run-status`, stopRequest);
}
startProcessGroup(request: StartProcessGroupRequest): Observable<any> {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/parameter.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/parameter.service.ts
index d8e1731c68..009a01c4ca 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/parameter.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/parameter.service.ts
@@ -30,19 +30,6 @@ export class ParameterService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getParameterContext(id: string, includeInheritedParameters: boolean): Observable<any> {
return this.httpClient.get(`${ParameterService.API}/parameter-contexts/${id}`, {
params: {
@@ -59,10 +46,10 @@ export class ParameterService {
}
pollParameterContextUpdate(updateRequest: ParameterContextUpdateRequest): Observable<any> {
- return this.httpClient.get(this.stripProtocol(updateRequest.uri));
+ return this.httpClient.get(this.nifiCommon.stripProtocol(updateRequest.uri));
}
deleteParameterContextUpdate(updateRequest: ParameterContextUpdateRequest): Observable<any> {
- return this.httpClient.delete(this.stripProtocol(updateRequest.uri));
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(updateRequest.uri));
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/queue.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/queue.service.ts
index df242809f3..f6c657bc53 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/queue.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/service/queue.service.ts
@@ -30,19 +30,6 @@ export class QueueService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
submitEmptyQueueRequest(emptyQueueRequest: SubmitEmptyQueueRequest): Observable<any> {
return this.httpClient.post(
`${QueueService.API}/flowfile-queues/${emptyQueueRequest.connectionId}/drop-requests`,
@@ -58,10 +45,10 @@ export class QueueService {
}
pollEmptyQueueRequest(dropRequest: DropRequest): Observable<any> {
- return this.httpClient.get(this.stripProtocol(dropRequest.uri));
+ return this.httpClient.get(this.nifiCommon.stripProtocol(dropRequest.uri));
}
deleteEmptyQueueRequest(dropRequest: DropRequest): Observable<any> {
- return this.httpClient.delete(this.stripProtocol(dropRequest.uri));
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(dropRequest.uri));
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts
index 401f0da757..7dd7c9ff59 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.actions.ts
@@ -19,7 +19,6 @@ import { createAction, props } from '@ngrx/store';
import {
ConfigureControllerServiceRequest,
ConfigureControllerServiceSuccess,
- CreateControllerServiceRequest,
CreateControllerServiceSuccess,
DeleteControllerServiceRequest,
DeleteControllerServiceSuccess,
@@ -28,6 +27,7 @@ import {
SelectControllerServiceRequest
} from './index';
import {
+ CreateControllerServiceRequest,
DisableControllerServiceDialogRequest,
EditControllerServiceDialogRequest,
SetEnableControllerServiceDialogRequest
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
index 4efe9641be..7997d62ca7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
@@ -18,20 +18,7 @@
import { Injectable } from '@angular/core';
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
import * as ControllerServicesActions from './controller-services.actions';
-import {
- catchError,
- combineLatest,
- filter,
- from,
- map,
- NEVER,
- Observable,
- of,
- switchMap,
- take,
- takeUntil,
- tap
-} from 'rxjs';
+import { catchError, combineLatest, filter, from, map, NEVER, of, switchMap, take, takeUntil, tap } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { NiFiState } from '../../../../state';
@@ -45,17 +32,10 @@ import {
ControllerServiceReferencingComponent,
EditParameterRequest,
EditParameterResponse,
- InlineServiceCreationRequest,
- InlineServiceCreationResponse,
- NewPropertyDialogRequest,
- NewPropertyDialogResponse,
Parameter,
ParameterEntity,
- Property,
- PropertyDescriptor,
UpdateControllerServiceRequest
} from '../../../../state/shared';
-import { NewPropertyDialog } from '../../../../ui/common/new-property-dialog/new-property-dialog.component';
import { Router } from '@angular/router';
import { ExtensionTypesService } from '../../../../service/extension-types.service';
import { selectCurrentProcessGroupId, selectSaving } from './controller-services.selectors';
@@ -68,6 +48,7 @@ import * as ParameterActions from '../parameter/parameter.actions';
import { ParameterService } from '../../service/parameter.service';
import { EnableControllerService } from '../../../../ui/common/controller-service/enable-controller-service/enable-controller-service.component';
import { DisableControllerService } from '../../../../ui/common/controller-service/disable-controller-service/disable-controller-service.component';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
@Injectable()
export class ControllerServicesEffects {
@@ -80,7 +61,8 @@ export class ControllerServicesEffects {
private parameterService: ParameterService,
private extensionTypesService: ExtensionTypesService,
private dialog: MatDialog,
- private router: Router
+ private router: Router,
+ private propertyTableHelperService: PropertyTableHelperService
) {}
loadControllerServices$ = createEffect(() =>
@@ -225,36 +207,8 @@ export class ControllerServicesEffects {
editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
- editDialogReference.componentInstance.createNewProperty = (
- existingProperties: string[],
- allowsSensitive: boolean
- ): Observable<Property> => {
- const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
- const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
- data: dialogRequest,
- panelClass: 'small-dialog'
- });
-
- return newPropertyDialogReference.componentInstance.newProperty.pipe(
- take(1),
- switchMap((dialogResponse: NewPropertyDialogResponse) => {
- return this.controllerServiceService
- .getPropertyDescriptor(request.id, dialogResponse.name, dialogResponse.sensitive)
- .pipe(
- take(1),
- map((response) => {
- newPropertyDialogReference.close();
-
- return {
- property: dialogResponse.name,
- value: null,
- descriptor: response.propertyDescriptor
- };
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(request.id, this.controllerServiceService);
const goTo = (commands: string[], destination: string): void => {
if (editDialogReference.componentInstance.editControllerServiceForm.dirty) {
@@ -393,85 +347,21 @@ export class ControllerServicesEffects {
});
};
- editDialogReference.componentInstance.createNewService = (
- serviceRequest: InlineServiceCreationRequest
- ): Observable<InlineServiceCreationResponse> => {
- const descriptor: PropertyDescriptor = serviceRequest.descriptor;
-
- // fetch all services that implement the requested service api
- return this.extensionTypesService
- .getImplementingControllerServiceTypes(
- // @ts-ignore
- descriptor.identifiesControllerService,
- descriptor.identifiesControllerServiceBundle
- )
- .pipe(
- take(1),
- switchMap((implementingTypesResponse) => {
- // show the create controller service dialog with the types that implemented the interface
- const createServiceDialogReference = this.dialog.open(CreateControllerService, {
- data: {
- controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
- },
- panelClass: 'medium-dialog'
- });
-
- return createServiceDialogReference.componentInstance.createControllerService.pipe(
- take(1),
- switchMap((controllerServiceType) => {
- // typically this sequence would be implemented with ngrx actions, however we are
- // currently in an edit session and we need to return both the value (new service id)
- // and updated property descriptor so the table renders correctly
- return this.controllerServiceService
- .createControllerService({
- revision: {
- clientId: this.client.getClientId(),
- version: 0
- },
- processGroupId,
- controllerServiceType: controllerServiceType.type,
- controllerServiceBundle: controllerServiceType.bundle
- })
- .pipe(
- take(1),
- switchMap((createResponse) => {
- // dispatch an inline create service success action so the new service is in the state
- this.store.dispatch(
- ControllerServicesActions.inlineCreateControllerServiceSuccess(
- {
- response: {
- controllerService: createResponse
- }
- }
- )
- );
-
- // fetch an updated property descriptor
- return this.controllerServiceService
- .getPropertyDescriptor(serviceId, descriptor.name, false)
- .pipe(
- take(1),
- map((descriptorResponse) => {
- createServiceDialogReference.close();
-
- return {
- value: createResponse.id,
- descriptor:
- descriptorResponse.propertyDescriptor
- };
- })
- );
- }),
- catchError((error) => {
- // TODO - show error
- return NEVER;
- })
- );
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ request.id,
+ this.controllerServiceService,
+ this.controllerServiceService,
+ processGroupId,
+ (createResponse) =>
+ this.store.dispatch(
+ ControllerServicesActions.inlineCreateControllerServiceSuccess({
+ response: {
+ controllerService: createResponse
+ }
+ })
+ )
+ );
editDialogReference.componentInstance.editControllerService
.pipe(takeUntil(editDialogReference.afterClosed()))
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts
index b9551f7784..4cafd6f50e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/controller-services/index.ts
@@ -31,13 +31,6 @@ export interface LoadControllerServicesResponse {
loadedTimestamp: string;
}
-export interface CreateControllerServiceRequest {
- processGroupId: string;
- controllerServiceType: string;
- controllerServiceBundle: Bundle;
- revision: Revision;
-}
-
export interface CreateControllerServiceSuccess {
controllerService: ControllerServiceEntity;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
index bb2208c6db..1af9e879cf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts
@@ -69,14 +69,8 @@ import {
ComponentType,
EditParameterRequest,
EditParameterResponse,
- InlineServiceCreationRequest,
- InlineServiceCreationResponse,
- NewPropertyDialogRequest,
- NewPropertyDialogResponse,
Parameter,
- ParameterEntity,
- Property,
- PropertyDescriptor
+ ParameterEntity
} from '../../../../state/shared';
import { Router } from '@angular/router';
import { Client } from '../../../../service/client.service';
@@ -86,7 +80,6 @@ import { selectProcessorTypes } from '../../../../state/extension-types/extensio
import { NiFiState } from '../../../../state';
import { CreateProcessor } from '../../ui/canvas/items/processor/create-processor/create-processor.component';
import { EditProcessor } from '../../ui/canvas/items/processor/edit-processor/edit-processor.component';
-import { NewPropertyDialog } from '../../../../ui/common/new-property-dialog/new-property-dialog.component';
import { BirdseyeView } from '../../service/birdseye-view.service';
import { CreateProcessGroup } from '../../ui/canvas/items/process-group/create-process-group/create-process-group.component';
import { CreateConnection } from '../../ui/canvas/items/connection/create-connection/create-connection.component';
@@ -94,13 +87,13 @@ import { EditConnectionComponent } from '../../ui/canvas/items/connection/edit-c
import { OkDialog } from '../../../../ui/common/ok-dialog/ok-dialog.component';
import { GroupComponents } from '../../ui/canvas/items/process-group/group-components/group-components.component';
import { EditProcessGroup } from '../../ui/canvas/items/process-group/edit-process-group/edit-process-group.component';
-import { CreateControllerService } from '../../../../ui/common/controller-service/create-controller-service/create-controller-service.component';
import { ExtensionTypesService } from '../../../../service/extension-types.service';
import { ControllerServiceService } from '../../service/controller-service.service';
import { YesNoDialog } from '../../../../ui/common/yes-no-dialog/yes-no-dialog.component';
import { EditParameterDialog } from '../../../../ui/common/edit-parameter-dialog/edit-parameter-dialog.component';
import { selectParameterSaving } from '../parameter/parameter.selectors';
import { ParameterService } from '../../service/parameter.service';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
@Injectable()
export class FlowEffects {
@@ -117,7 +110,8 @@ export class FlowEffects {
private birdseyeView: BirdseyeView,
private connectionManager: ConnectionManager,
private router: Router,
- private dialog: MatDialog
+ private dialog: MatDialog,
+ private propertyTableHelperService: PropertyTableHelperService
) {}
reloadFlow$ = createEffect(() =>
@@ -852,36 +846,8 @@ export class FlowEffects {
editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
- editDialogReference.componentInstance.createNewProperty = (
- existingProperties: string[],
- allowsSensitive: boolean
- ): Observable<Property> => {
- const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
- const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
- data: dialogRequest,
- panelClass: 'small-dialog'
- });
-
- return newPropertyDialogReference.componentInstance.newProperty.pipe(
- take(1),
- switchMap((dialogResponse: NewPropertyDialogResponse) => {
- return this.flowService
- .getPropertyDescriptor(processorId, dialogResponse.name, dialogResponse.sensitive)
- .pipe(
- take(1),
- map((response) => {
- newPropertyDialogReference.close();
-
- return {
- property: dialogResponse.name,
- value: null,
- descriptor: response.propertyDescriptor
- };
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(processorId, this.flowService);
const goTo = (commands: string[], destination: string): void => {
if (editDialogReference.componentInstance.editProcessorForm.dirty) {
@@ -1013,74 +979,13 @@ export class FlowEffects {
});
};
- editDialogReference.componentInstance.createNewService = (
- serviceRequest: InlineServiceCreationRequest
- ): Observable<InlineServiceCreationResponse> => {
- const descriptor: PropertyDescriptor = serviceRequest.descriptor;
-
- // fetch all services that implement the requested service api
- return this.extensionTypesService
- .getImplementingControllerServiceTypes(
- // @ts-ignore
- descriptor.identifiesControllerService,
- descriptor.identifiesControllerServiceBundle
- )
- .pipe(
- take(1),
- switchMap((implementingTypesResponse) => {
- // show the create controller service dialog with the types that implemented the interface
- const createServiceDialogReference = this.dialog.open(CreateControllerService, {
- data: {
- controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
- },
- panelClass: 'medium-dialog'
- });
-
- return createServiceDialogReference.componentInstance.createControllerService.pipe(
- take(1),
- switchMap((controllerServiceType) => {
- // typically this sequence would be implemented with ngrx actions, however we are
- // currently in an edit session and we need to return both the value (new service id)
- // and updated property descriptor so the table renders correctly
- return this.controllerServiceService
- .createControllerService({
- revision: {
- clientId: this.client.getClientId(),
- version: 0
- },
- processGroupId,
- controllerServiceType: controllerServiceType.type,
- controllerServiceBundle: controllerServiceType.bundle
- })
- .pipe(
- take(1),
- switchMap((createReponse) => {
- // fetch an updated property descriptor
- return this.flowService
- .getPropertyDescriptor(processorId, descriptor.name, false)
- .pipe(
- take(1),
- map((descriptorResponse) => {
- createServiceDialogReference.close();
-
- return {
- value: createReponse.id,
- descriptor:
- descriptorResponse.propertyDescriptor
- };
- })
- );
- }),
- catchError((error) => {
- // TODO - show error
- return NEVER;
- })
- );
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ processorId,
+ this.controllerServiceService,
+ this.flowService,
+ processGroupId
+ );
editDialogReference.componentInstance.editProcessor
.pipe(takeUntil(editDialogReference.afterClosed()))
@@ -2331,7 +2236,7 @@ export class FlowEffects {
return from(this.flowService.getProcessGroup(request.id)).pipe(
map((response) =>
FlowActions.loadChildProcessGroupSuccess({
- response: response.component
+ response
})
),
catchError((error) => of(FlowActions.flowApiError({ error: error.error })))
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts
index 8a1af18d27..87e48cb1f5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/state/flow/flow.reducer.ts
@@ -326,10 +326,7 @@ export const flowReducer = createReducer(
if (collection) {
const componentIndex: number = collection.findIndex((f: any) => response.component.id === f.id);
if (componentIndex > -1) {
- collection[componentIndex] = {
- ...collection[componentIndex],
- ...response.component
- };
+ collection[componentIndex] = response.component;
}
}
@@ -343,10 +340,7 @@ export const flowReducer = createReducer(
if (collection) {
const componentIndex: number = collection.findIndex((f: any) => response.component.id === f.id);
if (componentIndex > -1) {
- collection[componentIndex] = {
- ...collection[componentIndex],
- ...response.component
- };
+ collection[componentIndex] = response.component;
}
}
@@ -361,10 +355,7 @@ export const flowReducer = createReducer(
if (collection) {
const componentIndex: number = collection.findIndex((f: any) => response.id === f.id);
if (componentIndex > -1) {
- collection[componentIndex] = {
- ...collection[componentIndex],
- ...response.component
- };
+ collection[componentIndex] = response;
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.spec.ts
index 34cf6502be..fccb8a6661 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.spec.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/flow-designer/ui/controller-service/controller-services.component.spec.ts
@@ -22,6 +22,8 @@ import { provideMockStore } from '@ngrx/store/testing';
import { initialState } from '../../state/controller-services/controller-services.reducer';
import { RouterTestingModule } from '@angular/router/testing';
import { Component } from '@angular/core';
+import { ControllerServicesModule } from './controller-services.module';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('ControllerServices', () => {
let component: ControllerServices;
@@ -37,7 +39,7 @@ describe('ControllerServices', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ControllerServices],
- imports: [RouterTestingModule, MockNavigation],
+ imports: [RouterTestingModule, MockNavigation, ControllerServicesModule, HttpClientTestingModule],
providers: [
provideMockStore({
initialState
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts
index d013707af0..ae6b5cc2ae 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts
@@ -37,19 +37,6 @@ export class ParameterContextService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getParameterContexts(): Observable<any> {
return this.httpClient.get(`${ParameterContextService.API}/flow/parameter-contexts`);
}
@@ -77,11 +64,11 @@ export class ParameterContextService {
}
pollParameterContextUpdate(updateRequest: ParameterContextUpdateRequest): Observable<any> {
- return this.httpClient.get(this.stripProtocol(updateRequest.uri));
+ return this.httpClient.get(this.nifiCommon.stripProtocol(updateRequest.uri));
}
deleteParameterContextUpdate(updateRequest: ParameterContextUpdateRequest): Observable<any> {
- return this.httpClient.delete(this.stripProtocol(updateRequest.uri));
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(updateRequest.uri));
}
deleteParameterContext(deleteParameterContext: DeleteParameterContextRequest): Observable<any> {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.module.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.module.ts
index 69787cc17e..24fdbcf7be 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.module.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-listing.module.ts
@@ -28,7 +28,7 @@ import { RouterLink } from '@angular/router';
@NgModule({
declarations: [ParameterContextListing, ParameterContextTable],
- exports: [ParameterContextListing],
+ exports: [ParameterContextListing, ParameterContextTable],
imports: [
CommonModule,
NgxSkeletonLoaderModule,
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts
index 6925f25f9b..9794280610 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-context-table/parameter-context-table.component.ts
@@ -31,12 +31,13 @@ import { CurrentUser } from '../../../../../state/current-user';
export class ParameterContextTable {
@Input() initialSortColumn: 'name' | 'provider' | 'description' = 'name';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
+ activeSort: Sort = {
+ active: this.initialSortColumn,
+ direction: this.initialSortDirection
+ };
@Input() set parameterContexts(parameterContextEntities: ParameterContextEntity[]) {
- this.dataSource.data = this.sortEntities(parameterContextEntities, {
- active: this.initialSortColumn,
- direction: this.initialSortDirection
- });
+ this.dataSource.data = this.sortEntities(parameterContextEntities, this.activeSort);
}
@Input() selectedParameterContextId!: string;
@@ -109,6 +110,7 @@ export class ParameterContextTable {
}
sortData(sort: Sort) {
+ this.activeSort = sort;
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/provenance/service/provenance.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/provenance/service/provenance.service.ts
index d3d73883e7..3e1d238699 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/provenance/service/provenance.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/provenance/service/provenance.service.ts
@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
-import { Observable, throwError } from 'rxjs';
+import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { NiFiCommon } from '../../../service/nifi-common.service';
import { ProvenanceRequest } from '../state/provenance-event-listing';
@@ -31,19 +31,6 @@ export class ProvenanceService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getSearchOptions(): Observable<any> {
return this.httpClient.get(`${ProvenanceService.API}/provenance/search-options`);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/service/queue.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/service/queue.service.ts
index afdd3e763a..695d73ae87 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/service/queue.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/queue/service/queue.service.ts
@@ -30,25 +30,12 @@ export class QueueService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getConnection(connectionId: string): Observable<any> {
return this.httpClient.get(`${QueueService.API}/connections/${connectionId}`);
}
getFlowFile(flowfileSummary: FlowFileSummary): Observable<any> {
- return this.httpClient.get(this.stripProtocol(flowfileSummary.uri));
+ return this.httpClient.get(this.nifiCommon.stripProtocol(flowfileSummary.uri));
}
submitQueueListingRequest(queueListingRequest: SubmitQueueListingRequest): Observable<any> {
@@ -59,15 +46,15 @@ export class QueueService {
}
pollQueueListingRequest(listingRequest: ListingRequest): Observable<any> {
- return this.httpClient.get(this.stripProtocol(listingRequest.uri));
+ return this.httpClient.get(this.nifiCommon.stripProtocol(listingRequest.uri));
}
deleteQueueListingRequest(listingRequest: ListingRequest): Observable<any> {
- return this.httpClient.delete(this.stripProtocol(listingRequest.uri));
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(listingRequest.uri));
}
downloadContent(flowfileSummary: FlowFileSummary): void {
- let dataUri: string = `${this.stripProtocol(flowfileSummary.uri)}/content`;
+ let dataUri: string = `${this.nifiCommon.stripProtocol(flowfileSummary.uri)}/content`;
const queryParameters: any = {};
@@ -83,7 +70,7 @@ export class QueueService {
viewContent(flowfileSummary: FlowFileSummary, contentViewerUrl: string): void {
// build the uri to the data
- let dataUri: string = `${this.stripProtocol(flowfileSummary.uri)}/content`;
+ let dataUri: string = `${this.nifiCommon.stripProtocol(flowfileSummary.uri)}/content`;
const dataUriParameters: any = {};
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings-routing.module.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings-routing.module.ts
index 441a5bd06c..b60ccc93af 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings-routing.module.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings-routing.module.ts
@@ -99,7 +99,26 @@ const routes: Routes = [
}
]
},
- { path: 'parameter-providers', component: ParameterProviders }
+ {
+ path: 'parameter-providers',
+ component: ParameterProviders,
+ children: [
+ {
+ path: ':id',
+ component: ParameterProviders,
+ children: [
+ {
+ path: 'edit',
+ component: ParameterProviders
+ },
+ {
+ path: 'fetch',
+ component: ParameterProviders
+ }
+ ]
+ }
+ ]
+ }
]
}
];
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings.module.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings.module.ts
index ba43f59442..c15b377c6e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings.module.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/feature/settings.module.ts
@@ -35,6 +35,7 @@ import { ReportingTasksEffects } from '../state/reporting-tasks/reporting-tasks.
import { RegistryClientsEffects } from '../state/registry-clients/registry-clients.effects';
import { FlowAnalysisRulesEffects } from '../state/flow-analysis-rules/flow-analysis-rules.effects';
import { Navigation } from '../../../ui/common/navigation/navigation.component';
+import { ParameterProvidersEffects } from '../state/parameter-providers/parameter-providers.effects';
@NgModule({
declarations: [Settings],
@@ -54,7 +55,8 @@ import { Navigation } from '../../../ui/common/navigation/navigation.component';
ManagementControllerServicesEffects,
ReportingTasksEffects,
FlowAnalysisRulesEffects,
- RegistryClientsEffects
+ RegistryClientsEffects,
+ ParameterProvidersEffects
),
MatTabsModule,
Navigation
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/flow-analysis-rule.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/flow-analysis-rule.service.ts
index b6f0a9ca14..c15ae5072c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/flow-analysis-rule.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/flow-analysis-rule.service.ts
@@ -27,24 +27,12 @@ import {
EnableFlowAnalysisRuleRequest,
FlowAnalysisRuleEntity
} from '../state/flow-analysis-rules';
+import { PropertyDescriptorRetriever } from '../../../state/shared';
@Injectable({ providedIn: 'root' })
-export class FlowAnalysisRuleService {
+export class FlowAnalysisRuleService implements PropertyDescriptorRetriever {
private static readonly API: string = '../nifi-api';
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
constructor(
private httpClient: HttpClient,
private client: Client,
@@ -68,7 +56,7 @@ export class FlowAnalysisRuleService {
deleteFlowAnalysisRule(deleteFlowAnalysisRule: DeleteFlowAnalysisRuleRequest): Observable<any> {
const entity: FlowAnalysisRuleEntity = deleteFlowAnalysisRule.flowAnalysisRule;
const revision: any = this.client.getRevision(entity);
- return this.httpClient.delete(this.stripProtocol(entity.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(entity.uri), { params: revision });
}
getPropertyDescriptor(id: string, propertyName: string, sensitive: boolean): Observable<any> {
@@ -83,14 +71,14 @@ export class FlowAnalysisRuleService {
updateFlowAnalysisRule(configureFlowAnalysisRule: ConfigureFlowAnalysisRuleRequest): Observable<any> {
return this.httpClient.put(
- this.stripProtocol(configureFlowAnalysisRule.uri),
+ this.nifiCommon.stripProtocol(configureFlowAnalysisRule.uri),
configureFlowAnalysisRule.payload
);
}
setEnable(flowAnalysisRule: EnableFlowAnalysisRuleRequest, enabled: boolean): Observable<any> {
const entity: FlowAnalysisRuleEntity = flowAnalysisRule.flowAnalysisRule;
- return this.httpClient.put(`${this.stripProtocol(entity.uri)}/run-status`, {
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(entity.uri)}/run-status`, {
revision: this.client.getRevision(entity),
state: enabled ? 'ENABLED' : 'DISABLED',
uiOnly: true
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/management-controller-service.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/management-controller-service.service.ts
index e241e76544..9557f3d271 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/management-controller-service.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/management-controller-service.service.ts
@@ -16,34 +16,25 @@
*/
import { Injectable } from '@angular/core';
-import { Observable, throwError } from 'rxjs';
+import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import {
ConfigureControllerServiceRequest,
- CreateControllerServiceRequest,
DeleteControllerServiceRequest
} from '../state/management-controller-services';
import { Client } from '../../../service/client.service';
import { NiFiCommon } from '../../../service/nifi-common.service';
-import { ControllerServiceEntity } from '../../../state/shared';
+import {
+ ControllerServiceCreator,
+ ControllerServiceEntity,
+ CreateControllerServiceRequest,
+ PropertyDescriptorRetriever
+} from '../../../state/shared';
@Injectable({ providedIn: 'root' })
-export class ManagementControllerServiceService {
+export class ManagementControllerServiceService implements ControllerServiceCreator, PropertyDescriptorRetriever {
private static readonly API: string = '../nifi-api';
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
constructor(
private httpClient: HttpClient,
private client: Client,
@@ -79,7 +70,7 @@ export class ManagementControllerServiceService {
updateControllerService(configureControllerService: ConfigureControllerServiceRequest): Observable<any> {
return this.httpClient.put(
- this.stripProtocol(configureControllerService.uri),
+ this.nifiCommon.stripProtocol(configureControllerService.uri),
configureControllerService.payload
);
}
@@ -87,6 +78,6 @@ export class ManagementControllerServiceService {
deleteControllerService(deleteControllerService: DeleteControllerServiceRequest): Observable<any> {
const entity: ControllerServiceEntity = deleteControllerService.controllerService;
const revision: any = this.client.getRevision(entity);
- return this.httpClient.delete(this.stripProtocol(entity.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(entity.uri), { params: revision });
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/parameter-provider.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/parameter-provider.service.ts
new file mode 100644
index 0000000000..ed22e317c0
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/parameter-provider.service.ts
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Client } from '../../../service/client.service';
+import { NiFiCommon } from '../../../service/nifi-common.service';
+import { Observable } from 'rxjs';
+import {
+ ConfigureParameterProviderRequest,
+ CreateParameterProviderRequest,
+ DeleteParameterProviderRequest,
+ ParameterProviderEntity
+} from '../state/parameter-providers';
+import { PropertyDescriptorRetriever, Revision } from '../../../state/shared';
+
+@Injectable({ providedIn: 'root' })
+export class ParameterProviderService implements PropertyDescriptorRetriever {
+ private static readonly API: string = '../nifi-api';
+
+ constructor(
+ private httpClient: HttpClient,
+ private client: Client,
+ private nifiCommon: NiFiCommon
+ ) {}
+
+ getParameterProviders(): Observable<any> {
+ return this.httpClient.get(`${ParameterProviderService.API}/flow/parameter-providers`);
+ }
+
+ createParameterProvider(request: CreateParameterProviderRequest) {
+ return this.httpClient.post(`${ParameterProviderService.API}/controller/parameter-providers`, {
+ revision: request.revision,
+ component: {
+ bundle: request.parameterProviderBundle,
+ type: request.parameterProviderType
+ }
+ });
+ }
+
+ deleteParameterProvider(request: DeleteParameterProviderRequest) {
+ const entity: ParameterProviderEntity = request.parameterProvider;
+ const revision: any = this.client.getRevision(entity);
+ const params: any = {
+ ...revision,
+ disconnectedNodeAcknowledged: false
+ };
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(entity.uri), { params: revision });
+ }
+
+ getPropertyDescriptor(id: string, propertyName: string, sensitive: boolean): Observable<any> {
+ const params: any = {
+ propertyName,
+ sensitive
+ };
+ return this.httpClient.get(`${ParameterProviderService.API}/parameter-providers/${id}/descriptors`, {
+ params
+ });
+ }
+
+ updateParameterProvider(configureRequest: ConfigureParameterProviderRequest): Observable<any> {
+ return this.httpClient.put(this.nifiCommon.stripProtocol(configureRequest.uri), configureRequest.payload);
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/registry-client.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/registry-client.service.ts
index b76e08b453..c1aeab3473 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/registry-client.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/registry-client.service.ts
@@ -26,24 +26,12 @@ import {
EditRegistryClientRequest,
RegistryClientEntity
} from '../state/registry-clients';
+import { PropertyDescriptorRetriever } from '../../../state/shared';
@Injectable({ providedIn: 'root' })
-export class RegistryClientService {
+export class RegistryClientService implements PropertyDescriptorRetriever {
private static readonly API: string = '../nifi-api';
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
constructor(
private httpClient: HttpClient,
private client: Client,
@@ -69,12 +57,12 @@ export class RegistryClientService {
}
updateRegistryClient(request: EditRegistryClientRequest): Observable<any> {
- return this.httpClient.put(this.stripProtocol(request.uri), request.payload);
+ return this.httpClient.put(this.nifiCommon.stripProtocol(request.uri), request.payload);
}
deleteRegistryClient(deleteRegistryClient: DeleteRegistryClientRequest): Observable<any> {
const entity: RegistryClientEntity = deleteRegistryClient.registryClient;
const revision: any = this.client.getRevision(entity);
- return this.httpClient.delete(this.stripProtocol(entity.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(entity.uri), { params: revision });
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/reporting-task.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/reporting-task.service.ts
index 102fab05c5..d6358e6a3e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/reporting-task.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/service/reporting-task.service.ts
@@ -28,24 +28,12 @@ import {
StartReportingTaskRequest,
StopReportingTaskRequest
} from '../state/reporting-tasks';
+import { PropertyDescriptorRetriever } from '../../../state/shared';
@Injectable({ providedIn: 'root' })
-export class ReportingTaskService {
+export class ReportingTaskService implements PropertyDescriptorRetriever {
private static readonly API: string = '../nifi-api';
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
constructor(
private httpClient: HttpClient,
private client: Client,
@@ -69,7 +57,7 @@ export class ReportingTaskService {
deleteReportingTask(deleteReportingTask: DeleteReportingTaskRequest): Observable<any> {
const entity: ReportingTaskEntity = deleteReportingTask.reportingTask;
const revision: any = this.client.getRevision(entity);
- return this.httpClient.delete(this.stripProtocol(entity.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(entity.uri), { params: revision });
}
startReportingTask(startReportingTask: StartReportingTaskRequest): Observable<any> {
@@ -79,7 +67,7 @@ export class ReportingTaskService {
revision,
state: 'RUNNING'
};
- return this.httpClient.put(`${this.stripProtocol(entity.uri)}/run-status`, payload);
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(entity.uri)}/run-status`, payload);
}
stopReportingTask(stopReportingTask: StopReportingTaskRequest): Observable<any> {
@@ -89,7 +77,7 @@ export class ReportingTaskService {
revision,
state: 'STOPPED'
};
- return this.httpClient.put(`${this.stripProtocol(entity.uri)}/run-status`, payload);
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(entity.uri)}/run-status`, payload);
}
getPropertyDescriptor(id: string, propertyName: string, sensitive: boolean): Observable<any> {
@@ -103,6 +91,9 @@ export class ReportingTaskService {
}
updateReportingTask(configureReportingTask: ConfigureReportingTaskRequest): Observable<any> {
- return this.httpClient.put(this.stripProtocol(configureReportingTask.uri), configureReportingTask.payload);
+ return this.httpClient.put(
+ this.nifiCommon.stripProtocol(configureReportingTask.uri),
+ configureReportingTask.payload
+ );
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/flow-analysis-rules.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/flow-analysis-rules.effects.ts
index dadda56080..57d734a6cb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/flow-analysis-rules.effects.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/flow-analysis-rules/flow-analysis-rules.effects.ts
@@ -18,7 +18,7 @@
import { Injectable } from '@angular/core';
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
import * as FlowAnalysisRuleActions from './flow-analysis-rules.actions';
-import { catchError, from, map, NEVER, Observable, of, switchMap, take, takeUntil, tap } from 'rxjs';
+import { catchError, from, map, of, switchMap, take, takeUntil, tap } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { NiFiState } from '../../../../state';
@@ -30,20 +30,11 @@ import { ManagementControllerServiceService } from '../../service/management-con
import { CreateFlowAnalysisRule } from '../../ui/flow-analysis-rules/create-flow-analysis-rule/create-flow-analysis-rule.component';
import { Router } from '@angular/router';
import { selectSaving } from '../management-controller-services/management-controller-services.selectors';
-import {
- InlineServiceCreationRequest,
- InlineServiceCreationResponse,
- NewPropertyDialogRequest,
- NewPropertyDialogResponse,
- Property,
- PropertyDescriptor,
- UpdateControllerServiceRequest
-} from '../../../../state/shared';
+import { UpdateControllerServiceRequest } from '../../../../state/shared';
import { EditFlowAnalysisRule } from '../../ui/flow-analysis-rules/edit-flow-analysis-rule/edit-flow-analysis-rule.component';
import { CreateFlowAnalysisRuleSuccess } from './index';
-import { NewPropertyDialog } from '../../../../ui/common/new-property-dialog/new-property-dialog.component';
-import { CreateControllerService } from '../../../../ui/common/controller-service/create-controller-service/create-controller-service.component';
import { ExtensionTypesService } from '../../../../service/extension-types.service';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
@Injectable()
export class FlowAnalysisRulesEffects {
@@ -55,7 +46,8 @@ export class FlowAnalysisRulesEffects {
private extensionTypesService: ExtensionTypesService,
private flowAnalysisRuleService: FlowAnalysisRuleService,
private dialog: MatDialog,
- private router: Router
+ private router: Router,
+ private propertyTableHelperService: PropertyTableHelperService
) {}
loadFlowAnalysisRule$ = createEffect(() =>
@@ -225,36 +217,8 @@ export class FlowAnalysisRulesEffects {
editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
- editDialogReference.componentInstance.createNewProperty = (
- existingProperties: string[],
- allowsSensitive: boolean
- ): Observable<Property> => {
- const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
- const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
- data: dialogRequest,
- panelClass: 'small-dialog'
- });
-
- return newPropertyDialogReference.componentInstance.newProperty.pipe(
- take(1),
- switchMap((dialogResponse: NewPropertyDialogResponse) => {
- return this.flowAnalysisRuleService
- .getPropertyDescriptor(request.id, dialogResponse.name, dialogResponse.sensitive)
- .pipe(
- take(1),
- map((response) => {
- newPropertyDialogReference.close();
-
- return {
- property: dialogResponse.name,
- value: null,
- descriptor: response.propertyDescriptor
- };
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(request.id, this.flowAnalysisRuleService);
const goTo = (commands: string[], destination: string): void => {
if (editDialogReference.componentInstance.editFlowAnalysisRuleForm.dirty) {
@@ -285,73 +249,12 @@ export class FlowAnalysisRulesEffects {
goTo(commands, 'Controller Service');
};
- editDialogReference.componentInstance.createNewService = (
- request: InlineServiceCreationRequest
- ): Observable<InlineServiceCreationResponse> => {
- const descriptor: PropertyDescriptor = request.descriptor;
-
- // fetch all services that implement the requested service api
- return this.extensionTypesService
- .getImplementingControllerServiceTypes(
- // @ts-ignore
- descriptor.identifiesControllerService,
- descriptor.identifiesControllerServiceBundle
- )
- .pipe(
- take(1),
- switchMap((implementingTypesResponse) => {
- // show the create controller service dialog with the types that implemented the interface
- const createServiceDialogReference = this.dialog.open(CreateControllerService, {
- data: {
- controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
- },
- panelClass: 'medium-dialog'
- });
-
- return createServiceDialogReference.componentInstance.createControllerService.pipe(
- take(1),
- switchMap((controllerServiceType) => {
- // typically this sequence would be implemented with ngrx actions, however we are
- // currently in an edit session and we need to return both the value (new service id)
- // and updated property descriptor so the table renders correctly
- return this.managementControllerServiceService
- .createControllerService({
- revision: {
- clientId: this.client.getClientId(),
- version: 0
- },
- controllerServiceType: controllerServiceType.type,
- controllerServiceBundle: controllerServiceType.bundle
- })
- .pipe(
- take(1),
- switchMap((createResponse) => {
- // fetch an updated property descriptor
- return this.flowAnalysisRuleService
- .getPropertyDescriptor(ruleId, descriptor.name, false)
- .pipe(
- take(1),
- map((descriptorResponse) => {
- createServiceDialogReference.close();
-
- return {
- value: createResponse.id,
- descriptor:
- descriptorResponse.propertyDescriptor
- };
- })
- );
- }),
- catchError((error) => {
- // TODO - show error
- return NEVER;
- })
- );
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ request.id,
+ this.managementControllerServiceService,
+ this.flowAnalysisRuleService
+ );
editDialogReference.componentInstance.editFlowAnalysisRule
.pipe(takeUntil(editDialogReference.afterClosed()))
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/index.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/index.ts
index 1182b01024..9367df4e90 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/index.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/index.ts
@@ -29,6 +29,8 @@ import { registryClientsFeatureKey, RegistryClientsState } from './registry-clie
import { registryClientsReducer } from './registry-clients/registry-clients.reducer';
import { flowAnalysisRulesFeatureKey, FlowAnalysisRulesState } from './flow-analysis-rules';
import { flowAnalysisRulesReducer } from './flow-analysis-rules/flow-analysis-rules.reducer';
+import { parameterProvidersFeatureKey, ParameterProvidersState } from './parameter-providers';
+import { parameterProvidersReducer } from './parameter-providers/parameter-providers.reducer';
export const settingsFeatureKey = 'settings';
@@ -38,6 +40,7 @@ export interface SettingsState {
[reportingTasksFeatureKey]: ReportingTasksState;
[flowAnalysisRulesFeatureKey]: FlowAnalysisRulesState;
[registryClientsFeatureKey]: RegistryClientsState;
+ [parameterProvidersFeatureKey]: ParameterProvidersState;
}
export function reducers(state: SettingsState | undefined, action: Action) {
@@ -46,7 +49,8 @@ export function reducers(state: SettingsState | undefined, action: Action) {
[managementControllerServicesFeatureKey]: managementControllerServicesReducer,
[reportingTasksFeatureKey]: reportingTasksReducer,
[flowAnalysisRulesFeatureKey]: flowAnalysisRulesReducer,
- [registryClientsFeatureKey]: registryClientsReducer
+ [registryClientsFeatureKey]: registryClientsReducer,
+ [parameterProvidersFeatureKey]: parameterProvidersReducer
})(state, action);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts
index 9db8417be2..b1725d338c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/index.ts
@@ -24,12 +24,6 @@ export interface LoadManagementControllerServicesResponse {
loadedTimestamp: string;
}
-export interface CreateControllerServiceRequest {
- controllerServiceType: string;
- controllerServiceBundle: Bundle;
- revision: Revision;
-}
-
export interface CreateControllerServiceSuccess {
controllerService: ControllerServiceEntity;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts
index 7165d17de7..0ecaca9f51 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.actions.ts
@@ -19,7 +19,6 @@ import { createAction, props } from '@ngrx/store';
import {
ConfigureControllerServiceRequest,
ConfigureControllerServiceSuccess,
- CreateControllerServiceRequest,
CreateControllerServiceSuccess,
DeleteControllerServiceRequest,
DeleteControllerServiceSuccess,
@@ -27,6 +26,7 @@ import {
SelectControllerServiceRequest
} from './index';
import {
+ CreateControllerServiceRequest,
DisableControllerServiceDialogRequest,
EditControllerServiceDialogRequest,
SetEnableControllerServiceDialogRequest
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts
index 2e9ff9772e..62abf521cb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/management-controller-services/management-controller-services.effects.ts
@@ -33,18 +33,15 @@ import {
ControllerServiceReferencingComponent,
InlineServiceCreationRequest,
InlineServiceCreationResponse,
- NewPropertyDialogRequest,
- NewPropertyDialogResponse,
- Property,
PropertyDescriptor,
UpdateControllerServiceRequest
} from '../../../../state/shared';
-import { NewPropertyDialog } from '../../../../ui/common/new-property-dialog/new-property-dialog.component';
import { Router } from '@angular/router';
import { ExtensionTypesService } from '../../../../service/extension-types.service';
import { selectSaving } from './management-controller-services.selectors';
import { EnableControllerService } from '../../../../ui/common/controller-service/enable-controller-service/enable-controller-service.component';
import { DisableControllerService } from '../../../../ui/common/controller-service/disable-controller-service/disable-controller-service.component';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
@Injectable()
export class ManagementControllerServicesEffects {
@@ -55,7 +52,8 @@ export class ManagementControllerServicesEffects {
private managementControllerServiceService: ManagementControllerServiceService,
private extensionTypesService: ExtensionTypesService,
private dialog: MatDialog,
- private router: Router
+ private router: Router,
+ private propertyTableHelperService: PropertyTableHelperService
) {}
loadManagementControllerServices$ = createEffect(() =>
@@ -193,36 +191,11 @@ export class ManagementControllerServicesEffects {
editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
- editDialogReference.componentInstance.createNewProperty = (
- existingProperties: string[],
- allowsSensitive: boolean
- ): Observable<Property> => {
- const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
- const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
- data: dialogRequest,
- panelClass: 'small-dialog'
- });
-
- return newPropertyDialogReference.componentInstance.newProperty.pipe(
- take(1),
- switchMap((dialogResponse: NewPropertyDialogResponse) => {
- return this.managementControllerServiceService
- .getPropertyDescriptor(request.id, dialogResponse.name, dialogResponse.sensitive)
- .pipe(
- take(1),
- map((response) => {
- newPropertyDialogReference.close();
-
- return {
- property: dialogResponse.name,
- value: null,
- descriptor: response.propertyDescriptor
- };
- })
- );
- })
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(
+ request.id,
+ this.managementControllerServiceService
);
- };
const goTo = (commands: string[], destination: string): void => {
if (editDialogReference.componentInstance.editControllerServiceForm.dirty) {
@@ -260,84 +233,21 @@ export class ManagementControllerServicesEffects {
goTo(route, component.referenceType);
};
- editDialogReference.componentInstance.createNewService = (
- request: InlineServiceCreationRequest
- ): Observable<InlineServiceCreationResponse> => {
- const descriptor: PropertyDescriptor = request.descriptor;
-
- // fetch all services that implement the requested service api
- return this.extensionTypesService
- .getImplementingControllerServiceTypes(
- // @ts-ignore
- descriptor.identifiesControllerService,
- descriptor.identifiesControllerServiceBundle
- )
- .pipe(
- take(1),
- switchMap((implementingTypesResponse) => {
- // show the create controller service dialog with the types that implemented the interface
- const createServiceDialogReference = this.dialog.open(CreateControllerService, {
- data: {
- controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
- },
- panelClass: 'medium-dialog'
- });
-
- return createServiceDialogReference.componentInstance.createControllerService.pipe(
- take(1),
- switchMap((controllerServiceType) => {
- // typically this sequence would be implemented with ngrx actions, however we are
- // currently in an edit session and we need to return both the value (new service id)
- // and updated property descriptor so the table renders correctly
- return this.managementControllerServiceService
- .createControllerService({
- revision: {
- clientId: this.client.getClientId(),
- version: 0
- },
- controllerServiceType: controllerServiceType.type,
- controllerServiceBundle: controllerServiceType.bundle
- })
- .pipe(
- take(1),
- switchMap((createResponse) => {
- // dispatch an inline create service success action so the new service is in the state
- this.store.dispatch(
- ManagementControllerServicesActions.inlineCreateControllerServiceSuccess(
- {
- response: {
- controllerService: createResponse
- }
- }
- )
- );
-
- // fetch an updated property descriptor
- return this.managementControllerServiceService
- .getPropertyDescriptor(serviceId, descriptor.name, false)
- .pipe(
- take(1),
- map((descriptorResponse) => {
- createServiceDialogReference.close();
-
- return {
- value: createResponse.id,
- descriptor:
- descriptorResponse.propertyDescriptor
- };
- })
- );
- }),
- catchError((error) => {
- // TODO - show error
- return NEVER;
- })
- );
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ request.id,
+ this.managementControllerServiceService,
+ this.managementControllerServiceService,
+ null,
+ (createResponse) =>
+ this.store.dispatch(
+ ManagementControllerServicesActions.inlineCreateControllerServiceSuccess({
+ response: {
+ controllerService: createResponse
+ }
+ })
+ )
+ );
editDialogReference.componentInstance.editControllerService
.pipe(takeUntil(editDialogReference.afterClosed()))
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts
new file mode 100644
index 0000000000..957951e435
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/index.ts
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+import {
+ Bundle,
+ DocumentedType,
+ ParameterContextReferenceEntity,
+ Permissions,
+ PropertyDescriptor,
+ Revision
+} from '../../../../state/shared';
+
+export const parameterProvidersFeatureKey = 'parameterProviders';
+
+export interface ParameterProvider {
+ bundle: Bundle;
+ comments: string;
+ deprecated: boolean;
+ descriptors: { [key: string]: PropertyDescriptor };
+ extensionMissing: boolean;
+ id: string;
+ multipleVersionsAvailable: boolean;
+ name: string;
+ parameterGroupConfigurations: any[];
+ persistsState: boolean;
+ properties: { [key: string]: string };
+ referencingParameterContexts: ParameterContextReferenceEntity[];
+ restricted: boolean;
+ type: string;
+ validationStatus: string;
+ validationErrors?: string[];
+}
+
+export interface ParameterProviderEntity {
+ id: string;
+ bulletins: [];
+ component: ParameterProvider;
+ permissions: Permissions;
+ revision: Revision;
+ uri: string;
+}
+
+export interface ParameterProvidersState {
+ parameterProviders: ParameterProviderEntity[];
+ saving: boolean;
+ loadedTimestamp: string;
+ error: string | null;
+ status: 'pending' | 'loading' | 'error' | 'success';
+}
+
+export interface LoadParameterProvidersResponse {
+ parameterProviders: ParameterProviderEntity[];
+ loadedTimestamp: string;
+}
+
+export interface SelectParameterProviderRequest {
+ id: string;
+}
+
+export interface CreateParameterProviderDialogRequest {
+ parameterProviderTypes: DocumentedType[];
+}
+
+export interface CreateParameterProviderRequest {
+ parameterProviderType: string;
+ parameterProviderBundle: Bundle;
+ revision: Revision;
+}
+
+export interface CreateParameterProviderSuccessResponse {
+ parameterProvider: ParameterProviderEntity;
+}
+
+export interface DeleteParameterProviderRequest {
+ parameterProvider: ParameterProviderEntity;
+}
+
+export interface DeleteParameterProviderSuccess {
+ parameterProvider: ParameterProviderEntity;
+}
+
+export interface EditParameterProviderRequest {
+ id: string;
+ parameterProvider: ParameterProviderEntity;
+}
+
+export interface ConfigureParameterProviderRequest {
+ id: string;
+ uri: string;
+ payload: any;
+ postUpdateNavigation?: string[];
+}
+
+export interface ConfigureParameterProviderSuccess {
+ id: string;
+ parameterProvider: ParameterProviderEntity;
+ postUpdateNavigation?: string[];
+}
+
+export interface UpdateParameterProviderRequest {
+ payload: any;
+ postUpdateNavigation?: string[];
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts
new file mode 100644
index 0000000000..ae7166e57e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.actions.ts
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+import { createAction, props } from '@ngrx/store';
+import {
+ ConfigureParameterProviderRequest,
+ ConfigureParameterProviderSuccess,
+ CreateParameterProviderRequest,
+ CreateParameterProviderSuccessResponse,
+ DeleteParameterProviderRequest,
+ DeleteParameterProviderSuccess,
+ EditParameterProviderRequest,
+ LoadParameterProvidersResponse,
+ SelectParameterProviderRequest
+} from './index';
+
+const PARAMETER_PROVIDERS_PREFIX: string = '[Parameter Providers]';
+
+export const resetParameterProvidersState = createAction(`${PARAMETER_PROVIDERS_PREFIX} Reset Parameter Providers`);
+
+export const loadParameterProviders = createAction(`${PARAMETER_PROVIDERS_PREFIX} Load Parameter Providers`);
+
+export const loadParameterProvidersSuccess = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Load Parameter Providers Success`,
+ props<{ response: LoadParameterProvidersResponse }>()
+);
+
+export const parameterProvidersApiError = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Load Parameter Providers Error`,
+ props<{ error: string }>()
+);
+
+export const selectParameterProvider = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Select Parameter Provider`,
+ props<{ request: SelectParameterProviderRequest }>()
+);
+
+export const openNewParameterProviderDialog = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Open New Parameter Provider Dialog`
+);
+
+export const createParameterProvider = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Create Parameter Provider`,
+ props<{ request: CreateParameterProviderRequest }>()
+);
+
+export const createParameterProviderSuccess = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Create Parameter Provider Success`,
+ props<{ response: CreateParameterProviderSuccessResponse }>()
+);
+
+export const promptParameterProviderDeletion = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Prompt Parameter Provider Deletion`,
+ props<{ request: DeleteParameterProviderRequest }>()
+);
+
+export const deleteParameterProvider = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Delete Parameter Provider`,
+ props<{ request: DeleteParameterProviderRequest }>()
+);
+
+export const deleteParameterProviderSuccess = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Delete Parameter Provider Success`,
+ props<{ response: DeleteParameterProviderSuccess }>()
+);
+
+export const navigateToEditParameterProvider = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Navigate To Edit Parameter Provider`,
+ props<{ id: string }>()
+);
+
+export const openConfigureParameterProviderDialog = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Open Configure Parameter Provider Dialog`,
+ props<{ request: EditParameterProviderRequest }>()
+);
+
+export const configureParameterProvider = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Configure Parameter Provider`,
+ props<{ request: ConfigureParameterProviderRequest }>()
+);
+
+export const configureParameterProviderSuccess = createAction(
+ `${PARAMETER_PROVIDERS_PREFIX} Configure Parameter Provider Success`,
+ props<{ response: ConfigureParameterProviderSuccess }>()
+);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts
new file mode 100644
index 0000000000..67cbdbfce1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts
@@ -0,0 +1,359 @@
+/*
+ * 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.
+ */
+
+import { Injectable } from '@angular/core';
+import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
+import { Store } from '@ngrx/store';
+import { NiFiState } from '../../../../state';
+import { Client } from '../../../../service/client.service';
+import { MatDialog } from '@angular/material/dialog';
+import { Router } from '@angular/router';
+import { ParameterProviderService } from '../../service/parameter-provider.service';
+import * as ParameterProviderActions from './parameter-providers.actions';
+import { loadParameterProviders, selectParameterProvider } from './parameter-providers.actions';
+import { catchError, from, map, of, switchMap, take, takeUntil, tap } from 'rxjs';
+import { selectSaving } from './parameter-providers.selectors';
+import { selectParameterProviderTypes } from '../../../../state/extension-types/extension-types.selectors';
+import { CreateParameterProvider } from '../../ui/parameter-providers/create-parameter-provider/create-parameter-provider.component';
+import { YesNoDialog } from '../../../../ui/common/yes-no-dialog/yes-no-dialog.component';
+import { EditParameterProvider } from '../../ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
+import { UpdateParameterProviderRequest } from './index';
+import { ManagementControllerServiceService } from '../../service/management-controller-service.service';
+
+@Injectable()
+export class ParameterProvidersEffects {
+ constructor(
+ private actions$: Actions,
+ private store: Store<NiFiState>,
+ private client: Client,
+ private dialog: MatDialog,
+ private router: Router,
+ private parameterProviderService: ParameterProviderService,
+ private propertyTableHelperService: PropertyTableHelperService,
+ private managementControllerServiceService: ManagementControllerServiceService
+ ) {}
+
+ loadParameterProviders$ = createEffect(() =>
+ this.actions$.pipe(
+ ofType(loadParameterProviders),
+ switchMap(() =>
+ from(this.parameterProviderService.getParameterProviders()).pipe(
+ map((response) =>
+ ParameterProviderActions.loadParameterProvidersSuccess({
+ response: {
+ parameterProviders: response.parameterProviders,
+ loadedTimestamp: response.currentTime
+ }
+ })
+ ),
+ catchError((error) =>
+ of(ParameterProviderActions.parameterProvidersApiError({ error: error.error }))
+ )
+ )
+ )
+ )
+ );
+
+ selectParameterProvider$ = createEffect(
+ () =>
+ this.actions$.pipe(
+ ofType(selectParameterProvider),
+ map((action) => action.request),
+ tap((request) => {
+ this.router.navigate(['/settings', 'parameter-providers', request.id]);
+ })
+ ),
+ { dispatch: false }
+ );
+
+ openNewParameterProviderDialog$ = createEffect(
+ () =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.openNewParameterProviderDialog),
+ concatLatestFrom(() => this.store.select(selectParameterProviderTypes)),
+ tap(([action, parameterProviderTypes]) => {
+ const dialogReference = this.dialog.open(CreateParameterProvider, {
+ data: {
+ parameterProviderTypes
+ },
+ panelClass: 'medium-dialog'
+ });
+
+ dialogReference.componentInstance.saving$ = this.store.select(selectSaving);
+
+ dialogReference.componentInstance.createParameterProvider
+ .pipe(take(1))
+ .subscribe((parameterProviderType) => {
+ this.store.dispatch(
+ ParameterProviderActions.createParameterProvider({
+ request: {
+ parameterProviderType: parameterProviderType.type,
+ parameterProviderBundle: parameterProviderType.bundle,
+ revision: {
+ clientId: this.client.getClientId(),
+ version: 0
+ }
+ }
+ })
+ );
+ });
+ })
+ ),
+ { dispatch: false }
+ );
+
+ createParameterProvider$ = createEffect(() =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.createParameterProvider),
+ map((action) => action.request),
+ switchMap((request) =>
+ from(this.parameterProviderService.createParameterProvider(request)).pipe(
+ map((response: any) =>
+ ParameterProviderActions.createParameterProviderSuccess({
+ response: {
+ parameterProvider: response
+ }
+ })
+ ),
+ catchError((error) =>
+ of(ParameterProviderActions.parameterProvidersApiError({ error: error.error }))
+ )
+ )
+ )
+ )
+ );
+
+ createParameterProviderSuccess$ = createEffect(() =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.createParameterProviderSuccess),
+ map((action) => action.response),
+ tap(() => {
+ this.dialog.closeAll();
+ }),
+ switchMap((response) =>
+ of(
+ ParameterProviderActions.selectParameterProvider({
+ request: {
+ id: response.parameterProvider.id
+ }
+ })
+ )
+ )
+ )
+ );
+
+ promptParameterProviderDeletion$ = createEffect(
+ () =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.promptParameterProviderDeletion),
+ map((action) => action.request),
+ tap((request) => {
+ const dialogReference = this.dialog.open(YesNoDialog, {
+ data: {
+ title: 'Delete Parameter Provider',
+ message: `Delete parameter provider ${request.parameterProvider.component.name}?`
+ },
+ panelClass: 'small-dialog'
+ });
+
+ dialogReference.componentInstance.yes.pipe(take(1)).subscribe(() =>
+ this.store.dispatch(
+ ParameterProviderActions.deleteParameterProvider({
+ request
+ })
+ )
+ );
+ })
+ ),
+ { dispatch: false }
+ );
+
+ deleteParameterProvider = createEffect(() =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.deleteParameterProvider),
+ map((action) => action.request),
+ switchMap((request) =>
+ from(this.parameterProviderService.deleteParameterProvider(request)).pipe(
+ map((response: any) =>
+ ParameterProviderActions.deleteParameterProviderSuccess({
+ response: {
+ parameterProvider: response
+ }
+ })
+ ),
+ catchError((error) =>
+ of(
+ ParameterProviderActions.parameterProvidersApiError({
+ error: error.error
+ })
+ )
+ )
+ )
+ )
+ )
+ );
+
+ navigateToEditParameterProvider$ = createEffect(
+ () =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.navigateToEditParameterProvider),
+ map((action) => action.id),
+ tap((id) => {
+ this.router.navigate(['settings', 'parameter-providers', id, 'edit']);
+ })
+ ),
+ { dispatch: false }
+ );
+
+ openConfigureParameterProviderDialog$ = createEffect(
+ () =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.openConfigureParameterProviderDialog),
+ map((action) => action.request),
+ tap((request) => {
+ const id = request.id;
+ const editDialogReference = this.dialog.open(EditParameterProvider, {
+ data: {
+ parameterProvider: request.parameterProvider
+ },
+ id,
+ panelClass: 'large-dialog'
+ });
+
+ editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
+
+ const goTo = (commands: string[], destination: string) => {
+ // confirm navigating away while changes are unsaved
+ if (editDialogReference.componentInstance.editParameterProviderForm.dirty) {
+ const promptSaveDialogRef = this.dialog.open(YesNoDialog, {
+ data: {
+ title: 'Parameter Provider Configuration',
+ message: `Save changes before going to this ${destination}`
+ },
+ panelClass: 'small-dialog'
+ });
+
+ promptSaveDialogRef.componentInstance.yes.pipe(take(1)).subscribe(() => {
+ editDialogReference.componentInstance.submitForm(commands);
+ });
+
+ promptSaveDialogRef.componentInstance.no.pipe(take(1)).subscribe(() => {
+ editDialogReference.close('ROUTED');
+ this.router.navigate(commands);
+ });
+ } else {
+ editDialogReference.close('ROUTED');
+ this.router.navigate(commands);
+ }
+ };
+
+ editDialogReference.componentInstance.goToReferencingParameterContext = (id: string) => {
+ const commands: string[] = ['parameter-contexts', id];
+ goTo(commands, 'Parameter Context');
+ };
+
+ editDialogReference.componentInstance.goToService = (serviceId: string) => {
+ const commands: string[] = ['/settings', 'management-controller-services', serviceId];
+ goTo(commands, 'Controller Service');
+ };
+
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(request.id, this.parameterProviderService);
+
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ request.id,
+ this.managementControllerServiceService,
+ this.parameterProviderService
+ );
+
+ editDialogReference.componentInstance.editParameterProvider
+ .pipe(takeUntil(editDialogReference.afterClosed()))
+ .subscribe((updateRequest: UpdateParameterProviderRequest) => {
+ this.store.dispatch(
+ ParameterProviderActions.configureParameterProvider({
+ request: {
+ id: request.parameterProvider.id,
+ uri: request.parameterProvider.uri,
+ payload: updateRequest.payload,
+ postUpdateNavigation: updateRequest.postUpdateNavigation
+ }
+ })
+ );
+ });
+
+ editDialogReference.afterClosed().subscribe((response) => {
+ if (response !== 'ROUTED') {
+ this.store.dispatch(
+ ParameterProviderActions.selectParameterProvider({
+ request: {
+ id
+ }
+ })
+ );
+ }
+ });
+ })
+ ),
+ { dispatch: false }
+ );
+
+ configureParameterProvider$ = createEffect(() =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.configureParameterProvider),
+ map((action) => action.request),
+ switchMap((request) =>
+ from(this.parameterProviderService.updateParameterProvider(request)).pipe(
+ map((response) =>
+ ParameterProviderActions.configureParameterProviderSuccess({
+ response: {
+ id: request.id,
+ parameterProvider: response,
+ postUpdateNavigation: request.postUpdateNavigation
+ }
+ })
+ ),
+ catchError((error) =>
+ of(
+ ParameterProviderActions.parameterProvidersApiError({
+ error: error.error
+ })
+ )
+ )
+ )
+ )
+ )
+ );
+
+ configureParameterProviderSuccess$ = createEffect(
+ () =>
+ this.actions$.pipe(
+ ofType(ParameterProviderActions.configureParameterProviderSuccess),
+ map((action) => action.response),
+ tap((response) => {
+ if (response.postUpdateNavigation) {
+ this.router.navigate(response.postUpdateNavigation);
+ this.dialog.getDialogById(response.id)?.close('ROUTED');
+ } else {
+ this.dialog.closeAll();
+ }
+ })
+ ),
+ { dispatch: false }
+ );
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.reducer.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.reducer.ts
new file mode 100644
index 0000000000..574fcffd39
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.reducer.ts
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+import { ParameterProvidersState } from './index';
+import { createReducer, on } from '@ngrx/store';
+import {
+ configureParameterProvider,
+ configureParameterProviderSuccess,
+ createParameterProvider,
+ createParameterProviderSuccess,
+ deleteParameterProvider,
+ deleteParameterProviderSuccess,
+ loadParameterProviders,
+ loadParameterProvidersSuccess,
+ parameterProvidersApiError,
+ resetParameterProvidersState
+} from './parameter-providers.actions';
+import { produce } from 'immer';
+
+export const initialParameterProvidersState: ParameterProvidersState = {
+ parameterProviders: [],
+ saving: false,
+ loadedTimestamp: '',
+ error: null,
+ status: 'pending'
+};
+
+export const parameterProvidersReducer = createReducer(
+ initialParameterProvidersState,
+
+ on(resetParameterProvidersState, (state: ParameterProvidersState) => ({
+ ...initialParameterProvidersState
+ })),
+
+ on(loadParameterProviders, (state: ParameterProvidersState) => ({
+ ...state,
+ status: 'loading' as const
+ })),
+
+ on(loadParameterProvidersSuccess, (state: ParameterProvidersState, { response }) => ({
+ ...state,
+ parameterProviders: response.parameterProviders,
+ loadedTimestamp: response.loadedTimestamp,
+ error: null,
+ status: 'success' as const
+ })),
+
+ on(parameterProvidersApiError, (state: ParameterProvidersState, { error }) => ({
+ ...state,
+ saving: false,
+ error,
+ status: 'error' as const
+ })),
+
+ on(createParameterProvider, configureParameterProvider, deleteParameterProvider, (state, { request }) => ({
+ ...state,
+ saving: true
+ })),
+
+ on(createParameterProviderSuccess, (state, { response }) => {
+ return produce(state, (draftState) => {
+ draftState.parameterProviders.push(response.parameterProvider);
+ draftState.saving = false;
+ });
+ }),
+
+ on(deleteParameterProviderSuccess, (state, { response }) => {
+ return produce(state, (draftState) => {
+ const idx = draftState.parameterProviders.findIndex(
+ (provider) => provider.id === response.parameterProvider.id
+ );
+ if (idx > -1) {
+ draftState.parameterProviders.splice(idx, 1);
+ }
+ draftState.saving = false;
+ });
+ }),
+
+ on(configureParameterProviderSuccess, (state, { response }) => {
+ return produce(state, (draftState) => {
+ const idx = draftState.parameterProviders.findIndex(
+ (provider) => provider.id === response.parameterProvider.id
+ );
+
+ if (idx > -1) {
+ draftState.parameterProviders[idx] = response.parameterProvider;
+ }
+
+ draftState.saving = false;
+ });
+ })
+);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.selectors.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.selectors.ts
new file mode 100644
index 0000000000..0afa75b379
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.selectors.ts
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+import { createSelector } from '@ngrx/store';
+import { selectSettingsState, SettingsState } from '../index';
+import { ParameterProviderEntity, parameterProvidersFeatureKey, ParameterProvidersState } from './index';
+import { selectCurrentRoute } from '../../../../state/router/router.selectors';
+
+export const selectParameterProvidersState = createSelector(
+ selectSettingsState,
+ (state: SettingsState) => state[parameterProvidersFeatureKey]
+);
+
+export const selectSaving = createSelector(
+ selectParameterProvidersState,
+ (state: ParameterProvidersState) => state.saving
+);
+
+export const selectParameterProviderIdFromRoute = createSelector(selectCurrentRoute, (route) => {
+ if (route) {
+ // always select the parameter provider from the route
+ return route.params.id;
+ }
+ return null;
+});
+
+export const selectSingleEditedParameterProvider = createSelector(selectCurrentRoute, (route) => {
+ if (route?.routeConfig?.path == 'edit') {
+ return route.params.id;
+ }
+ return null;
+});
+
+export const selectParameterProviders = createSelector(
+ selectParameterProvidersState,
+ (state: ParameterProvidersState) => state.parameterProviders
+);
+
+export const selectParameterProvider = (id: string) =>
+ createSelector(selectParameterProviders, (entities: ParameterProviderEntity[]) =>
+ entities.find((entity) => id == entity.id)
+ );
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts
index 37eeb8e480..bd431167f1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/registry-clients/registry-clients.effects.ts
@@ -18,7 +18,7 @@
import { Injectable } from '@angular/core';
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
import * as RegistryClientsActions from './registry-clients.actions';
-import { catchError, from, map, NEVER, Observable, of, switchMap, take, takeUntil, tap } from 'rxjs';
+import { catchError, from, map, of, switchMap, take, takeUntil, tap } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { NiFiState } from '../../../../state';
@@ -29,20 +29,11 @@ import { RegistryClientService } from '../../service/registry-client.service';
import { CreateRegistryClient } from '../../ui/registry-clients/create-registry-client/create-registry-client.component';
import { selectSaving } from './registry-clients.selectors';
import { EditRegistryClient } from '../../ui/registry-clients/edit-registry-client/edit-registry-client.component';
-import {
- InlineServiceCreationRequest,
- InlineServiceCreationResponse,
- NewPropertyDialogRequest,
- NewPropertyDialogResponse,
- Property,
- PropertyDescriptor
-} from '../../../../state/shared';
-import { NewPropertyDialog } from '../../../../ui/common/new-property-dialog/new-property-dialog.component';
import { ExtensionTypesService } from '../../../../service/extension-types.service';
-import { CreateControllerService } from '../../../../ui/common/controller-service/create-controller-service/create-controller-service.component';
import { ManagementControllerServiceService } from '../../service/management-controller-service.service';
import { Client } from '../../../../service/client.service';
import { EditRegistryClientRequest } from './index';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
@Injectable()
export class RegistryClientsEffects {
@@ -54,7 +45,8 @@ export class RegistryClientsEffects {
private extensionTypesService: ExtensionTypesService,
private managementControllerServiceService: ManagementControllerServiceService,
private dialog: MatDialog,
- private router: Router
+ private router: Router,
+ private propertyTableHelperService: PropertyTableHelperService
) {}
loadRegistryClients$ = createEffect(() =>
@@ -181,40 +173,8 @@ export class RegistryClientsEffects {
editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
- editDialogReference.componentInstance.createNewProperty = (
- existingProperties: string[],
- allowsSensitive: boolean
- ): Observable<Property> => {
- const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
- const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
- data: dialogRequest,
- panelClass: 'small-dialog'
- });
-
- return newPropertyDialogReference.componentInstance.newProperty.pipe(
- take(1),
- switchMap((dialogResponse: NewPropertyDialogResponse) => {
- return this.registryClientService
- .getPropertyDescriptor(
- registryClientId,
- dialogResponse.name,
- dialogResponse.sensitive
- )
- .pipe(
- take(1),
- map((response) => {
- newPropertyDialogReference.close();
-
- return {
- property: dialogResponse.name,
- value: null,
- descriptor: response.propertyDescriptor
- };
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(registryClientId, this.registryClientService);
editDialogReference.componentInstance.goToService = (serviceId: string) => {
const commands: string[] = ['/settings', 'management-controller-services', serviceId];
@@ -242,77 +202,12 @@ export class RegistryClientsEffects {
}
};
- editDialogReference.componentInstance.createNewService = (
- request: InlineServiceCreationRequest
- ): Observable<InlineServiceCreationResponse> => {
- const descriptor: PropertyDescriptor = request.descriptor;
-
- // fetch all services that implement the requested service api
- return this.extensionTypesService
- .getImplementingControllerServiceTypes(
- // @ts-ignore
- descriptor.identifiesControllerService,
- descriptor.identifiesControllerServiceBundle
- )
- .pipe(
- take(1),
- switchMap((implementingTypesResponse) => {
- // show the create controller service dialog with the types that implemented the interface
- const createServiceDialogReference = this.dialog.open(CreateControllerService, {
- data: {
- controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
- },
- panelClass: 'medium-dialog'
- });
-
- return createServiceDialogReference.componentInstance.createControllerService.pipe(
- take(1),
- switchMap((controllerServiceType) => {
- // typically this sequence would be implemented with ngrx actions, however we are
- // currently in an edit session and we need to return both the value (new service id)
- // and updated property descriptor so the table renders correctly
- return this.managementControllerServiceService
- .createControllerService({
- revision: {
- clientId: this.client.getClientId(),
- version: 0
- },
- controllerServiceType: controllerServiceType.type,
- controllerServiceBundle: controllerServiceType.bundle
- })
- .pipe(
- take(1),
- switchMap((createReponse) => {
- // fetch an updated property descriptor
- return this.registryClientService
- .getPropertyDescriptor(
- registryClientId,
- descriptor.name,
- false
- )
- .pipe(
- take(1),
- map((descriptorResponse) => {
- createServiceDialogReference.close();
-
- return {
- value: createReponse.id,
- descriptor:
- descriptorResponse.propertyDescriptor
- };
- })
- );
- }),
- catchError((error) => {
- // TODO - show error
- return NEVER;
- })
- );
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ registryClientId,
+ this.managementControllerServiceService,
+ this.registryClientService
+ );
editDialogReference.componentInstance.editRegistryClient
.pipe(takeUntil(editDialogReference.afterClosed()))
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts
index 05528bf004..b668f3da78 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/state/reporting-tasks/reporting-tasks.effects.ts
@@ -44,6 +44,7 @@ import { ExtensionTypesService } from '../../../../service/extension-types.servi
import { CreateControllerService } from '../../../../ui/common/controller-service/create-controller-service/create-controller-service.component';
import { ManagementControllerServiceService } from '../../service/management-controller-service.service';
import { Client } from '../../../../service/client.service';
+import { PropertyTableHelperService } from '../../../../service/property-table-helper.service';
@Injectable()
export class ReportingTasksEffects {
@@ -55,7 +56,8 @@ export class ReportingTasksEffects {
private managementControllerServiceService: ManagementControllerServiceService,
private extensionTypesService: ExtensionTypesService,
private dialog: MatDialog,
- private router: Router
+ private router: Router,
+ private propertyTableHelperService: PropertyTableHelperService
) {}
loadReportingTasks$ = createEffect(() =>
@@ -225,36 +227,8 @@ export class ReportingTasksEffects {
editDialogReference.componentInstance.saving$ = this.store.select(selectSaving);
- editDialogReference.componentInstance.createNewProperty = (
- existingProperties: string[],
- allowsSensitive: boolean
- ): Observable<Property> => {
- const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
- const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
- data: dialogRequest,
- panelClass: 'small-dialog'
- });
-
- return newPropertyDialogReference.componentInstance.newProperty.pipe(
- take(1),
- switchMap((dialogResponse: NewPropertyDialogResponse) => {
- return this.reportingTaskService
- .getPropertyDescriptor(request.id, dialogResponse.name, dialogResponse.sensitive)
- .pipe(
- take(1),
- map((response) => {
- newPropertyDialogReference.close();
-
- return {
- property: dialogResponse.name,
- value: null,
- descriptor: response.propertyDescriptor
- };
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewProperty =
+ this.propertyTableHelperService.createNewProperty(request.id, this.reportingTaskService);
const goTo = (commands: string[], destination: string): void => {
if (editDialogReference.componentInstance.editReportingTaskForm.dirty) {
@@ -285,73 +259,12 @@ export class ReportingTasksEffects {
goTo(commands, 'Controller Service');
};
- editDialogReference.componentInstance.createNewService = (
- request: InlineServiceCreationRequest
- ): Observable<InlineServiceCreationResponse> => {
- const descriptor: PropertyDescriptor = request.descriptor;
-
- // fetch all services that implement the requested service api
- return this.extensionTypesService
- .getImplementingControllerServiceTypes(
- // @ts-ignore
- descriptor.identifiesControllerService,
- descriptor.identifiesControllerServiceBundle
- )
- .pipe(
- take(1),
- switchMap((implementingTypesResponse) => {
- // show the create controller service dialog with the types that implemented the interface
- const createServiceDialogReference = this.dialog.open(CreateControllerService, {
- data: {
- controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
- },
- panelClass: 'medium-dialog'
- });
-
- return createServiceDialogReference.componentInstance.createControllerService.pipe(
- take(1),
- switchMap((controllerServiceType) => {
- // typically this sequence would be implemented with ngrx actions, however we are
- // currently in an edit session and we need to return both the value (new service id)
- // and updated property descriptor so the table renders correctly
- return this.managementControllerServiceService
- .createControllerService({
- revision: {
- clientId: this.client.getClientId(),
- version: 0
- },
- controllerServiceType: controllerServiceType.type,
- controllerServiceBundle: controllerServiceType.bundle
- })
- .pipe(
- take(1),
- switchMap((createResponse) => {
- // fetch an updated property descriptor
- return this.reportingTaskService
- .getPropertyDescriptor(taskId, descriptor.name, false)
- .pipe(
- take(1),
- map((descriptorResponse) => {
- createServiceDialogReference.close();
-
- return {
- value: createResponse.id,
- descriptor:
- descriptorResponse.propertyDescriptor
- };
- })
- );
- }),
- catchError((error) => {
- // TODO - show error
- return NEVER;
- })
- );
- })
- );
- })
- );
- };
+ editDialogReference.componentInstance.createNewService =
+ this.propertyTableHelperService.createNewService(
+ request.id,
+ this.managementControllerServiceService,
+ this.reportingTaskService
+ );
editDialogReference.componentInstance.editReportingTask
.pipe(takeUntil(editDialogReference.afterClosed()))
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.html
similarity index 73%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.html
index 1e7c10a0b4..a1a278685e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.html
@@ -6,7 +6,7 @@
~ (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
+ ~ 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,
@@ -15,4 +15,8 @@
~ limitations under the License.
-->
-<p>parameter-providers works!</p>
+<extension-creation
+ [componentType]="'Parameter Provider'"
+ [documentedTypes]="parameterProviderTypes"
+ [saving]="(saving$ | async)!"
+ (extensionTypeSelected)="parameterProviderTypeSelected($event)"></extension-creation>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.scss
similarity index 71%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.scss
index 1149a35b5f..b33f7cac34 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -14,12 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-import { Component } from '@angular/core';
-
-@Component({
- selector: 'parameter-providers',
- templateUrl: './parameter-providers.component.html',
- styleUrls: ['./parameter-providers.component.scss']
-})
-export class ParameterProviders {}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.spec.ts
new file mode 100644
index 0000000000..25517a106f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.spec.ts
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateParameterProvider } from './create-parameter-provider.component';
+import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { provideMockStore } from '@ngrx/store/testing';
+import { initialParameterProvidersState } from '../../../state/parameter-providers/parameter-providers.reducer';
+import {
+ CreateParameterProviderDialogRequest,
+ CreateParameterProviderRequest
+} from '../../../state/parameter-providers';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+
+describe('CreateParameterProvider', () => {
+ let component: CreateParameterProvider;
+ let fixture: ComponentFixture<CreateParameterProvider>;
+ const data: CreateParameterProviderDialogRequest = {
+ parameterProviderTypes: [
+ {
+ type: 'org.apache.nifi.parameter.aws.AwsSecretsManagerParameterProvider',
+ bundle: {
+ group: 'org.apache.nifi',
+ artifact: 'nifi-aws-nar',
+ version: '2.0.0-SNAPSHOT'
+ },
+ description:
+ 'Fetches parameters from AWS SecretsManager. Each secret becomes a Parameter group, which can map to a Parameter Context, with key/value pairs in the secret mapping to Parameters in the group.',
+ restricted: false,
+ tags: ['secretsmanager', 'manager', 'aws', 'secrets']
+ },
+ {
+ type: 'org.apache.nifi.parameter.azure.AzureKeyVaultSecretsParameterProvider',
+ bundle: {
+ group: 'org.apache.nifi',
+ artifact: 'nifi-azure-nar',
+ version: '2.0.0-SNAPSHOT'
+ },
+ description:
+ "Fetches parameters from Azure Key Vault Secrets. Each secret becomes a Parameter, which map to a Parameter Group byadding a secret tag named 'group-name'.",
+ restricted: false,
+ tags: ['keyvault', 'secrets', 'key', 'vault', 'azure']
+ }
+ ]
+ };
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [CreateParameterProvider, NoopAnimationsModule],
+ providers: [
+ {
+ provide: MAT_DIALOG_DATA,
+ useValue: data
+ },
+ provideMockStore({ initialState: initialParameterProvidersState })
+ ]
+ });
+ fixture = TestBed.createComponent(CreateParameterProvider);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.ts
similarity index 53%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.ts
index 9eef6781c5..a23e226a8a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/create-parameter-provider/create-parameter-provider.component.ts
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -16,30 +16,31 @@
*/
import { Component, EventEmitter, Inject, Input, Output } from '@angular/core';
-import { MAT_DIALOG_DATA } from '@angular/material/dialog';
-import { CreateControllerServiceRequest, DocumentedType } from '../../../../state/shared';
-import { ExtensionCreation } from '../../extension-creation/extension-creation.component';
+import { CommonModule } from '@angular/common';
import { Observable } from 'rxjs';
-import { AsyncPipe } from '@angular/common';
+import { DocumentedType } from '../../../../../state/shared';
+import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { CreateParameterProviderDialogRequest } from '../../../state/parameter-providers';
+import { ExtensionCreation } from '../../../../../ui/common/extension-creation/extension-creation.component';
@Component({
- selector: 'create-controller-service',
+ selector: 'create-parameter-provider',
standalone: true,
- imports: [ExtensionCreation, AsyncPipe],
- templateUrl: './create-controller-service.component.html',
- styleUrls: ['./create-controller-service.component.scss']
+ imports: [CommonModule, ExtensionCreation],
+ templateUrl: './create-parameter-provider.component.html',
+ styleUrls: ['./create-parameter-provider.component.scss']
})
-export class CreateControllerService {
+export class CreateParameterProvider {
@Input() saving$!: Observable<boolean>;
- @Output() createControllerService: EventEmitter<DocumentedType> = new EventEmitter<DocumentedType>();
+ @Output() createParameterProvider: EventEmitter<DocumentedType> = new EventEmitter<DocumentedType>();
- controllerServiceTypes: DocumentedType[];
+ parameterProviderTypes: DocumentedType[];
- constructor(@Inject(MAT_DIALOG_DATA) private dialogRequest: CreateControllerServiceRequest) {
- this.controllerServiceTypes = dialogRequest.controllerServiceTypes;
+ constructor(@Inject(MAT_DIALOG_DATA) private dialogRequest: CreateParameterProviderDialogRequest) {
+ this.parameterProviderTypes = dialogRequest.parameterProviderTypes;
}
- controllerServiceTypeSelected(controllerServiceType: DocumentedType): void {
- this.createControllerService.next(controllerServiceType);
+ parameterProviderTypeSelected(parameterProviderType: DocumentedType) {
+ this.createParameterProvider.next(parameterProviderType);
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.html
new file mode 100644
index 0000000000..a2eaf019a2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.html
@@ -0,0 +1,91 @@
+<!--
+ ~ 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.
+ -->
+
+<h2 mat-dialog-title>Edit Parameter Provider</h2>
+<form class="parameter-provider-edit-form" [formGroup]="editParameterProviderForm">
+ <mat-dialog-content>
+ <mat-tab-group>
+ <mat-tab label="Settings">
+ <div class="tab-content py-4 flex gap-x-4">
+ <div class="w-full">
+ <div>
+ <mat-form-field>
+ <mat-label>Name</mat-label>
+ <input matInput formControlName="name" type="text" />
+ </mat-form-field>
+ </div>
+ <div class="flex flex-col mb-5">
+ <div>Id</div>
+ <div class="value">{{ request.parameterProvider.id }}</div>
+ </div>
+ <div class="flex flex-col mb-5">
+ <div>Type</div>
+ <div class="value">{{ formatType(request.parameterProvider) }}</div>
+ </div>
+ <div class="flex flex-col mb-5">
+ <div>Bundle</div>
+ <div class="value">{{ formatBundle(request.parameterProvider) }}</div>
+ </div>
+ </div>
+ <div class="flex flex-col w-full">
+ <div>Referencing Components</div>
+ <div>
+ <parameter-provider-references
+ [parameterProviderReferences]="
+ request.parameterProvider.component.referencingParameterContexts
+ "
+ (goToParameterContext)="
+ navigateToParameterContext($event)
+ "></parameter-provider-references>
+ </div>
+ </div>
+ </div>
+ </mat-tab>
+
+ <mat-tab label="Properties">
+ <div class="tab-content py-4">
+ <property-table
+ formControlName="properties"
+ [createNewProperty]="createNewProperty"
+ [createNewService]="createNewService"
+ [goToService]="goToService"></property-table>
+ </div>
+ </mat-tab>
+
+ <mat-tab label="Comments">
+ <div class="tab-content py-4">
+ <mat-form-field>
+ <mat-label>Comments</mat-label>
+ <textarea matInput formControlName="comments" type="text" rows="5"></textarea>
+ </mat-form-field>
+ </div>
+ </mat-tab>
+ </mat-tab-group>
+ </mat-dialog-content>
+
+ <mat-dialog-actions align="end" *ngIf="{ value: (saving$ | async)! } as saving">
+ <button color="accent" mat-raised-button mat-dialog-close>Cancel</button>
+ <button
+ [disabled]="!editParameterProviderForm.dirty || editParameterProviderForm.invalid || saving.value"
+ type="button"
+ color="primary"
+ (click)="submitForm()"
+ mat-raised-button>
+ <span *nifiSpinner="saving.value">Apply</span>
+ </button>
+ </mat-dialog-actions>
+</form>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.scss
similarity index 66%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.scss
index 1149a35b5f..717bc5565d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -15,11 +15,22 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
+@use '@angular/material' as mat;
-@Component({
- selector: 'parameter-providers',
- templateUrl: './parameter-providers.component.html',
- styleUrls: ['./parameter-providers.component.scss']
-})
-export class ParameterProviders {}
+.parameter-provider-edit-form {
+ @include mat.button-density(-1);
+
+ .mdc-dialog__content {
+ padding: 0 16px;
+ font-size: 14px;
+
+ .tab-content {
+ height: 475px;
+ overflow-y: auto;
+ }
+ }
+
+ .mat-mdc-form-field {
+ width: 100%;
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.spec.ts
new file mode 100644
index 0000000000..dccbe3d0b2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.spec.ts
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { EditParameterProvider } from './edit-parameter-provider.component';
+import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { EditParameterProviderRequest } from '../../../state/parameter-providers';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+
+describe('EditParameterProvider', () => {
+ let component: EditParameterProvider;
+ let fixture: ComponentFixture<EditParameterProvider>;
+ const data: EditParameterProviderRequest = {
+ id: 'id',
+ parameterProvider: {
+ revision: {
+ clientId: '36ba1cc1-018d-1000-bc2c-787bc552d63d',
+ version: 6
+ },
+ id: '369487d7-018d-1000-817a-1d8d9a8f4a91',
+ uri: 'https://localhost:8443/nifi-api/parameter-providers/369487d7-018d-1000-817a-1d8d9a8f4a91',
+ permissions: {
+ canRead: true,
+ canWrite: true
+ },
+ bulletins: [],
+ component: {
+ id: '369487d7-018d-1000-817a-1d8d9a8f4a91',
+ name: 'Group 1 - FileParameterProvider',
+ type: 'org.apache.nifi.parameter.FileParameterProvider',
+ bundle: {
+ group: 'org.apache.nifi',
+ artifact: 'nifi-standard-nar',
+ version: '2.0.0-SNAPSHOT'
+ },
+ comments: '',
+ persistsState: false,
+ restricted: true,
+ deprecated: false,
+ multipleVersionsAvailable: false,
+ properties: {
+ 'parameter-group-directories': '/Users/rfellows/tmp/parameterProviders/group1',
+ 'parameter-value-byte-limit': '256 B',
+ 'parameter-value-encoding': 'plaintext'
+ },
+ descriptors: {
+ 'parameter-group-directories': {
+ name: 'parameter-group-directories',
+ displayName: 'Parameter Group Directories',
+ description:
+ 'A comma-separated list of directory absolute paths that will map to named parameter groups. Each directory that contains files will map to a parameter group, named after the innermost directory in the path. Files inside the directory will map to parameter names, whose values are the content of each respective file.',
+ required: true,
+ sensitive: false,
+ dynamic: false,
+ supportsEl: false,
+ expressionLanguageScope: 'Not Supported',
+ dependencies: []
+ },
+ 'parameter-value-byte-limit': {
+ name: 'parameter-value-byte-limit',
+ displayName: 'Parameter Value Byte Limit',
+ description:
+ 'The maximum byte size of a parameter value. Since parameter values are pulled from the contents of files, this is a safeguard that can prevent memory issues if large files are included.',
+ defaultValue: '256 B',
+ required: true,
+ sensitive: false,
+ dynamic: false,
+ supportsEl: false,
+ expressionLanguageScope: 'Not Supported',
+ dependencies: []
+ },
+ 'parameter-value-encoding': {
+ name: 'parameter-value-encoding',
+ displayName: 'Parameter Value Encoding',
+ description: 'Indicates how parameter values are encoded inside Parameter files.',
+ defaultValue: 'base64',
+ allowableValues: [
+ {
+ allowableValue: {
+ displayName: 'Base64',
+ value: 'base64',
+ description:
+ 'File content is Base64-encoded, and will be decoded before providing the value as a Parameter.'
+ },
+ canRead: true
+ },
+ {
+ allowableValue: {
+ displayName: 'Plain text',
+ value: 'plaintext',
+ description:
+ 'File content is not encoded, and will be provided directly as a Parameter value.'
+ },
+ canRead: true
+ }
+ ],
+ required: true,
+ sensitive: false,
+ dynamic: false,
+ supportsEl: false,
+ expressionLanguageScope: 'Not Supported',
+ dependencies: []
+ }
+ },
+ parameterGroupConfigurations: [
+ {
+ groupName: 'group1',
+ parameterContextName: 'group1',
+ parameterSensitivities: {
+ bytes: 'NON_SENSITIVE',
+ password: 'SENSITIVE',
+ username: 'NON_SENSITIVE'
+ },
+ synchronized: true
+ }
+ ],
+ referencingParameterContexts: [
+ {
+ id: '3716e18d-018d-1000-f203-4f6d571d572e',
+ permissions: {
+ canRead: true,
+ canWrite: true
+ },
+ bulletins: [],
+ component: {
+ id: '3716e18d-018d-1000-f203-4f6d571d572e',
+ name: 'group1'
+ }
+ }
+ ],
+ validationStatus: 'VALID',
+ extensionMissing: false
+ }
+ }
+ };
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [EditParameterProvider, NoopAnimationsModule],
+ providers: [
+ {
+ provide: MAT_DIALOG_DATA,
+ useValue: data
+ }
+ ]
+ });
+ fixture = TestBed.createComponent(EditParameterProvider);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts
new file mode 100644
index 0000000000..2032ab2868
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/edit-parameter-provider/edit-parameter-provider.component.ts
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+import { Component, EventEmitter, Inject, Input, Output } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
+import { MatTabsModule } from '@angular/material/tabs';
+import { MatButtonModule } from '@angular/material/button';
+import { NifiSpinnerDirective } from '../../../../../ui/common/spinner/nifi-spinner.directive';
+import { Observable } from 'rxjs';
+import {
+ ControllerServiceReferencingComponent,
+ InlineServiceCreationRequest,
+ InlineServiceCreationResponse,
+ ParameterContextReferenceEntity,
+ Property
+} from '../../../../../state/shared';
+import {
+ EditParameterProviderRequest,
+ ParameterProviderEntity,
+ UpdateParameterProviderRequest
+} from '../../../state/parameter-providers';
+import { AbstractControl, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Client } from '../../../../../service/client.service';
+import { NiFiCommon } from '../../../../../service/nifi-common.service';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { ControllerServiceReferences } from '../../../../../ui/common/controller-service/controller-service-references/controller-service-references.component';
+import { ParameterProviderReferences } from '../parameter-context-references/parameter-provider-references.component';
+import { PropertyTable } from '../../../../../ui/common/property-table/property-table.component';
+
+@Component({
+ selector: 'edit-parameter-provider',
+ standalone: true,
+ imports: [
+ CommonModule,
+ MatDialogModule,
+ MatTabsModule,
+ MatButtonModule,
+ NifiSpinnerDirective,
+ ReactiveFormsModule,
+ MatFormFieldModule,
+ MatInputModule,
+ ControllerServiceReferences,
+ ParameterProviderReferences,
+ PropertyTable
+ ],
+ templateUrl: './edit-parameter-provider.component.html',
+ styleUrls: ['./edit-parameter-provider.component.scss']
+})
+export class EditParameterProvider {
+ @Input() createNewProperty!: (existingProperties: string[], allowsSensitive: boolean) => Observable<Property>;
+ @Input() createNewService!: (request: InlineServiceCreationRequest) => Observable<InlineServiceCreationResponse>;
+ @Input() goToService!: (serviceId: string) => void;
+ @Input() goToReferencingParameterContext!: (parameterContextId: string) => void;
+ @Input() saving$!: Observable<boolean>;
+
+ @Output() editParameterProvider: EventEmitter<UpdateParameterProviderRequest> =
+ new EventEmitter<UpdateParameterProviderRequest>();
+
+ editParameterProviderForm: FormGroup;
+
+ constructor(
+ @Inject(MAT_DIALOG_DATA) public request: EditParameterProviderRequest,
+ private formBuilder: FormBuilder,
+ private client: Client,
+ private nifiCommon: NiFiCommon
+ ) {
+ const providerProperties = request.parameterProvider.component.properties;
+ const properties: Property[] = Object.entries(providerProperties).map((entry: any) => {
+ const [property, value] = entry;
+ return {
+ property,
+ value,
+ descriptor: request.parameterProvider.component.descriptors[property]
+ };
+ });
+
+ // build the form
+ this.editParameterProviderForm = this.formBuilder.group({
+ name: new FormControl(request.parameterProvider.component.name, Validators.required),
+ properties: new FormControl(properties),
+ comments: new FormControl(request.parameterProvider.component.comments)
+ });
+ }
+
+ formatType(entity: ParameterProviderEntity): string {
+ return this.nifiCommon.formatType(entity.component);
+ }
+
+ formatBundle(entity: ParameterProviderEntity): string {
+ return this.nifiCommon.formatBundle(entity.component.bundle);
+ }
+
+ submitForm(postUpdateNavigation?: string[]) {
+ const payload: any = {
+ revision: this.client.getRevision(this.request.parameterProvider),
+ component: {
+ id: this.request.parameterProvider.id,
+ name: this.editParameterProviderForm.get('name')?.value,
+ comments: this.editParameterProviderForm.get('comments')?.value
+ }
+ };
+
+ const propertyControl: AbstractControl | null = this.editParameterProviderForm.get('properties');
+ if (propertyControl && propertyControl.dirty) {
+ const properties: Property[] = propertyControl.value;
+ const values: { [key: string]: string | null } = {};
+ properties.forEach((property) => (values[property.property] = property.value));
+ payload.component.properties = values;
+ payload.component.sensitiveDynamicPropertyNames = properties
+ .filter((property) => property.descriptor.dynamic && property.descriptor.sensitive)
+ .map((property) => property.descriptor.name);
+ }
+
+ this.editParameterProvider.next({
+ payload,
+ postUpdateNavigation
+ });
+ }
+
+ navigateToParameterContext(parameterContextReference: ParameterContextReferenceEntity) {
+ if (parameterContextReference.component?.id) {
+ this.goToReferencingParameterContext(parameterContextReference.component?.id);
+ }
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-provider-references.component.spec.ts
similarity index 71%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-provider-references.component.spec.ts
index 842641ea8b..f7a7d2ec23 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-provider-references.component.spec.ts
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -17,17 +17,17 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ParameterProviders } from './parameter-providers.component';
+import { ParameterProviderReferences } from './parameter-provider-references.component';
-describe('ParameterProviders', () => {
- let component: ParameterProviders;
- let fixture: ComponentFixture<ParameterProviders>;
+describe('ParameterProviderReferences', () => {
+ let component: ParameterProviderReferences;
+ let fixture: ComponentFixture<ParameterProviderReferences>;
beforeEach(() => {
TestBed.configureTestingModule({
- declarations: [ParameterProviders]
+ imports: [ParameterProviderReferences]
});
- fixture = TestBed.createComponent(ParameterProviders);
+ fixture = TestBed.createComponent(ParameterProviderReferences);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-provider-references.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-provider-references.component.ts
new file mode 100644
index 0000000000..652aaac777
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-provider-references.component.ts
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ParameterContextReferenceEntity } from '../../../../../state/shared';
+import { NiFiCommon } from '../../../../../service/nifi-common.service';
+import { RouterLink } from '@angular/router';
+
+@Component({
+ selector: 'parameter-provider-references',
+ standalone: true,
+ imports: [CommonModule, RouterLink],
+ templateUrl: './parameter-providers-references.component.html',
+ styleUrls: ['./parameter-providers-references.component.scss']
+})
+export class ParameterProviderReferences {
+ @Input() parameterProviderReferences!: ParameterContextReferenceEntity[];
+ @Output() goToParameterContext: EventEmitter<ParameterContextReferenceEntity> =
+ new EventEmitter<ParameterContextReferenceEntity>();
+
+ constructor(private nifiCommon: NiFiCommon) {}
+
+ getUnauthorized(references: ParameterContextReferenceEntity[]) {
+ return references.filter((p) => !p.permissions.canRead);
+ }
+
+ getAuthorized(references: ParameterContextReferenceEntity[]) {
+ return references.filter((p) => p.permissions.canRead);
+ }
+
+ goToParameterContextClicked(event: MouseEvent, parameterContextReference: ParameterContextReferenceEntity) {
+ event.stopPropagation();
+ this.goToParameterContext.next(parameterContextReference);
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-providers-references.component.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-providers-references.component.html
new file mode 100644
index 0000000000..84ec9b4444
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-providers-references.component.html
@@ -0,0 +1,76 @@
+<!--
+ ~ 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="parameter-provider-references">
+ <div
+ *ngIf="!parameterProviderReferences || parameterProviderReferences?.length === 0; else hasReferences"
+ class="value">
+ No referencing components
+ </div>
+
+ <ng-template #hasReferences>
+ <ul>
+ <ng-container
+ *ngTemplateOutlet="
+ parameterContexts;
+ context: {
+ $implicit: getAuthorized(parameterProviderReferences),
+ label: 'Parameter Contexts'
+ }
+ "></ng-container>
+
+ <ng-container
+ *ngTemplateOutlet="
+ unauthorized;
+ context: {
+ $implicit: getUnauthorized(parameterProviderReferences),
+ label: 'Unauthorized'
+ }
+ "></ng-container>
+ </ul>
+ </ng-template>
+
+ <ng-template #parameterContexts let-references let-label="label">
+ <ng-container *ngIf="references.length > 0">
+ <li>
+ <h4>
+ <span class="value">{{ label }}</span> ({{ references.length }})
+ </h4>
+ <div class="references">
+ <div *ngFor="let reference of references" class="flex items-center gap-x-2">
+ <a (click)="goToParameterContextClicked($event, reference)">{{ reference.component?.name }}</a>
+ </div>
+ </div>
+ </li>
+ </ng-container>
+ </ng-template>
+
+ <ng-template #unauthorized let-references let-label="label">
+ <ng-container *ngIf="references.length > 0">
+ <li>
+ <h4>
+ <span class="value">{{ label }}</span> ({{ references.length }})
+ </h4>
+ <div class="references">
+ <div *ngFor="let reference of references" class="flex items-center gap-x-2">
+ <div class="unset">{{ reference.id }}</div>
+ </div>
+ </div>
+ </li>
+ </ng-container>
+ </ng-template>
+</div>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-providers-references.component.scss
similarity index 71%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-providers-references.component.scss
index 1149a35b5f..c6abda8ba2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-context-references/parameter-providers-references.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -15,11 +15,12 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
+.parameter-provider-references {
+ ul.nested {
+ padding-inline-start: 20px;
+ }
-@Component({
- selector: 'parameter-providers',
- templateUrl: './parameter-providers.component.html',
- styleUrls: ['./parameter-providers.component.scss']
-})
-export class ParameterProviders {}
+ .references {
+ margin-left: 20px;
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html
new file mode 100644
index 0000000000..7c3eb1e925
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.html
@@ -0,0 +1,121 @@
+<!--
+ ~ 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.
+ -->
+
+<ng-container>
+ <div class="parameter-providers-table h-full flex flex-col">
+ <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">
+ <div class="flex items-center gap-x-3">
+ <!-- TODO: open details -->
+ <div class="pointer fa fa-info-circle" title="View details"></div>
+
+ <!-- TODO: open documentation -->
+ <div class="pointer fa fa-book" title="View Documentation"></div>
+
+ <!-- Validation Errors -->
+ <div *ngIf="hasErrors(item)">
+ <div
+ class="pointer fa fa-warning has-errors"
+ nifiTooltip
+ [delayClose]="false"
+ [tooltipComponentType]="ValidationErrorsTip"
+ [tooltipInputData]="getValidationErrorsTipData(item)"></div>
+ </div>
+ </div>
+ </td>
+ </ng-container>
+
+ <!-- Name Column -->
+ <ng-container matColumnDef="name">
+ <th mat-header-cell *matHeaderCellDef mat-sort-header>
+ <div class="flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap">Name</div>
+ </th>
+ <td mat-cell *matCellDef="let item" [title]="formatName(item)">
+ <div [ngClass]="{ unset: !canRead(item) }">{{ formatName(item) }}</div>
+ </td>
+ </ng-container>
+
+ <!-- Type column -->
+ <ng-container matColumnDef="type">
+ <th mat-header-cell *matHeaderCellDef mat-sort-header>
+ <div class="flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap">Type</div>
+ </th>
+ <td mat-cell *matCellDef="let item" [title]="formatType(item)">
+ {{ formatType(item) }}
+ </td>
+ </ng-container>
+
+ <!-- Bundle column -->
+ <ng-container matColumnDef="bundle">
+ <th mat-header-cell *matHeaderCellDef mat-sort-header>
+ <div class="flex-1 overflow-ellipsis overflow-hidden whitespace-nowrap">Bundle</div>
+ </th>
+ <td mat-cell *matCellDef="let item" [title]="formatBundle(item)">
+ {{ formatBundle(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-pencil"
+ (click)="configureClicked(item, $event)"
+ title="Edit"></div>
+ <div
+ class="pointer fa fa-arrow-circle-down"
+ (click)="fetchClicked(item, $event)"
+ title="Fetch Parameters"></div>
+ <div
+ class="pointer fa fa-trash"
+ (click)="deleteClicked(item, $event)"
+ title="Remove"></div>
+ <div
+ *ngIf="canManageAccessPolicies()"
+ class="pointer fa fa-key"
+ (click)="$event.stopPropagation()"
+ [routerLink]="getPolicyLink(item)"
+ title="Access Policies"></div>
+ </div>
+ </td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
+ <tr
+ mat-row
+ *matRowDef="let row; let even = even; columns: displayedColumns"
+ [class.even]="even"
+ (click)="selectParameterProvider.next(row)"
+ [class.selected]="isSelected(row)"></tr>
+ </table>
+ </div>
+ </div>
+ </div>
+</ng-container>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.scss
similarity index 71%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.scss
index 1149a35b5f..e44f2b386a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -15,11 +15,8 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
-
-@Component({
- selector: 'parameter-providers',
- templateUrl: './parameter-providers.component.html',
- styleUrls: ['./parameter-providers.component.scss']
-})
-export class ParameterProviders {}
+.parameter-providers-table {
+ .listing-table {
+ // overrides to the listing-table styles go here
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.spec.ts
similarity index 68%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.spec.ts
index 842641ea8b..5f6a0e3767 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.spec.ts
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -17,17 +17,18 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ParameterProviders } from './parameter-providers.component';
+import { ParameterProvidersTable } from './parameter-providers-table.component';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-describe('ParameterProviders', () => {
- let component: ParameterProviders;
- let fixture: ComponentFixture<ParameterProviders>;
+describe('ParameterProvidersTable', () => {
+ let component: ParameterProvidersTable;
+ let fixture: ComponentFixture<ParameterProvidersTable>;
beforeEach(() => {
TestBed.configureTestingModule({
- declarations: [ParameterProviders]
+ imports: [ParameterProvidersTable, NoopAnimationsModule]
});
- fixture = TestBed.createComponent(ParameterProviders);
+ fixture = TestBed.createComponent(ParameterProvidersTable);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts
new file mode 100644
index 0000000000..2916239c6e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers-table/parameter-providers-table.component.ts
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { MatSortModule, Sort, SortDirection } from '@angular/material/sort';
+import { MatTableDataSource, MatTableModule } from '@angular/material/table';
+import { ParameterProviderEntity } from '../../../state/parameter-providers';
+import { NiFiCommon } from '../../../../../service/nifi-common.service';
+import { CurrentUser } from '../../../../../state/current-user';
+import { FlowConfiguration } from '../../../../../state/flow-configuration';
+import { MatPaginatorModule } from '@angular/material/paginator';
+import { SummaryTableFilterModule } from '../../../../summary/ui/common/summary-table-filter/summary-table-filter.module';
+import { PortStatusSnapshotEntity } from '../../../../summary/state/summary-listing';
+import { ValidationErrorsTip } from '../../../../../ui/common/tooltips/validation-errors-tip/validation-errors-tip.component';
+import { NifiTooltipDirective } from '../../../../../ui/common/tooltips/nifi-tooltip.directive';
+import { ControllerServiceEntity, ValidationErrorsTipInput } from '../../../../../state/shared';
+import { RouterLink } from '@angular/router';
+
+export type SupportedColumns = 'name' | 'type' | 'bundle';
+
+@Component({
+ selector: 'parameter-providers-table',
+ standalone: true,
+ imports: [
+ CommonModule,
+ MatPaginatorModule,
+ MatSortModule,
+ MatTableModule,
+ SummaryTableFilterModule,
+ NifiTooltipDirective,
+ RouterLink
+ ],
+ templateUrl: './parameter-providers-table.component.html',
+ styleUrls: ['./parameter-providers-table.component.scss', '../../../../../../assets/styles/listing-table.scss']
+})
+export class ParameterProvidersTable {
+ @Input() initialSortColumn: SupportedColumns = 'name';
+ @Input() initialSortDirection: SortDirection = 'asc';
+
+ displayedColumns: string[] = ['moreDetails', 'name', 'type', 'bundle', 'actions'];
+ dataSource: MatTableDataSource<ParameterProviderEntity> = new MatTableDataSource<ParameterProviderEntity>();
+ activeSort: Sort = {
+ active: this.initialSortColumn,
+ direction: this.initialSortDirection
+ };
+
+ constructor(private nifiCommon: NiFiCommon) {}
+
+ @Input() selectedParameterProviderId!: string;
+ @Input() currentUser!: CurrentUser;
+ @Input() flowConfiguration!: FlowConfiguration;
+
+ @Input() set parameterProviders(parameterProviders: ParameterProviderEntity[]) {
+ if (parameterProviders) {
+ this.dataSource.data = this.sortEntities(parameterProviders, this.activeSort);
+ }
+ }
+
+ @Output() selectParameterProvider: EventEmitter<ParameterProviderEntity> =
+ new EventEmitter<ParameterProviderEntity>();
+ @Output() configureParameterProvider: EventEmitter<ParameterProviderEntity> =
+ new EventEmitter<ParameterProviderEntity>();
+ @Output() deleteParameterProvider: EventEmitter<ParameterProviderEntity> =
+ new EventEmitter<ParameterProviderEntity>();
+ @Output() fetchParameterProvider: EventEmitter<ParameterProviderEntity> =
+ new EventEmitter<ParameterProviderEntity>();
+ @Output() manageAccessPolicies: EventEmitter<ParameterProviderEntity> = new EventEmitter<ParameterProviderEntity>();
+
+ protected readonly ValidationErrorsTip = ValidationErrorsTip;
+
+ canRead(entity: ParameterProviderEntity): boolean {
+ return entity.permissions.canRead;
+ }
+
+ canWrite(entity: ParameterProviderEntity): boolean {
+ return entity.permissions.canWrite;
+ }
+
+ canManageAccessPolicies(): boolean {
+ return this.flowConfiguration.supportsManagedAuthorizer && this.currentUser.tenantsPermissions.canRead;
+ }
+
+ isSelected(parameterProvider: ParameterProviderEntity): boolean {
+ if (this.selectedParameterProviderId) {
+ return parameterProvider.id === this.selectedParameterProviderId;
+ }
+ return false;
+ }
+
+ formatName(entity: ParameterProviderEntity): string {
+ return this.canRead(entity) ? entity.component.name : entity.id;
+ }
+
+ formatType(entity: ParameterProviderEntity): string {
+ return this.canRead(entity) ? this.nifiCommon.formatType(entity.component) : '';
+ }
+
+ formatBundle(entity: ParameterProviderEntity): string {
+ return this.canRead(entity) ? this.nifiCommon.formatBundle(entity.component.bundle) : '';
+ }
+
+ hasErrors(entity: ParameterProviderEntity): boolean {
+ return this.canRead(entity) && !this.nifiCommon.isEmpty(entity.component.validationErrors);
+ }
+
+ getValidationErrorsTipData(entity: ParameterProviderEntity): ValidationErrorsTipInput | null {
+ return {
+ isValidating: entity.component.validationStatus === 'VALIDATING',
+ validationErrors: entity.component?.validationErrors || []
+ };
+ }
+
+ sortData(sort: Sort) {
+ this.activeSort = sort;
+ this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
+ }
+
+ private sortEntities(data: ParameterProviderEntity[], sort: Sort): ParameterProviderEntity[] {
+ if (!data) {
+ return [];
+ }
+ return data.slice().sort((a, b) => {
+ const isAsc: boolean = 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;
+ default:
+ return 0;
+ }
+
+ return retVal * (isAsc ? 1 : -1);
+ });
+ }
+
+ configureClicked(entity: ParameterProviderEntity, event: MouseEvent) {
+ event.stopPropagation();
+ this.configureParameterProvider.next(entity);
+ }
+
+ fetchClicked(entity: ParameterProviderEntity, event: MouseEvent) {
+ event.stopPropagation();
+ this.fetchParameterProvider.next(entity);
+ }
+
+ deleteClicked(entity: ParameterProviderEntity, event: MouseEvent) {
+ event.stopPropagation();
+ this.deleteParameterProvider.next(entity);
+ }
+
+ getPolicyLink(entity: ParameterProviderEntity): string[] {
+ return ['/access-policies', 'read', 'component', 'parameter-providers', entity.id];
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html
index 1e7c10a0b4..d0b715d847 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.html
@@ -15,4 +15,39 @@
~ limitations under the License.
-->
-<p>parameter-providers works!</p>
+<ng-container *ngIf="parameterProvidersState$ | async; let parameterProvidersState">
+ <div *ngIf="isInitialLoading(parameterProvidersState); else loaded">
+ <ngx-skeleton-loader count="3"></ngx-skeleton-loader>
+ </div>
+ <ng-template #loaded>
+ <div class="flex flex-col h-full gap-y-2" *ngIf="currentUser$ | async; let currentUser">
+ <div class="flex justify-end" *ngIf="currentUser.controllerPermissions.canWrite">
+ <button
+ class="nifi-button"
+ (click)="openNewParameterProviderDialog()"
+ title="Add a new parameter provider">
+ <i class="fa fa-plus"></i>
+ </button>
+ </div>
+ <div class="flex-1">
+ <parameter-providers-table
+ [currentUser]="currentUser"
+ [flowConfiguration]="(flowConfiguration$ | async)!"
+ [parameterProviders]="parameterProvidersState.parameterProviders"
+ [selectedParameterProviderId]="selectedParameterProviderId$ | async"
+ (deleteParameterProvider)="deleteParameterProvider($event)"
+ (configureParameterProvider)="openConfigureParameterProviderDialog($event)"
+ (selectParameterProvider)="selectParameterProvider($event)"></parameter-providers-table>
+ </div>
+ <div class="flex justify-between">
+ <div class="refresh-container flex items-center gap-x-2">
+ <button class="nifi-button" (click)="refreshParameterProvidersListing()">
+ <i class="fa fa-refresh" [class.fa-spin]="parameterProvidersState.status === 'loading'"></i>
+ </button>
+ <div>Last updated:</div>
+ <div class="refresh-timestamp">{{ parameterProvidersState.loadedTimestamp }}</div>
+ </div>
+ </div>
+ </div>
+ </ng-template>
+</ng-container>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
index 842641ea8b..66357cb49c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.spec.ts
@@ -18,6 +18,8 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ParameterProviders } from './parameter-providers.component';
+import { provideMockStore } from '@ngrx/store/testing';
+import { initialParameterProvidersState } from '../../state/parameter-providers/parameter-providers.reducer';
describe('ParameterProviders', () => {
let component: ParameterProviders;
@@ -25,7 +27,12 @@ describe('ParameterProviders', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- declarations: [ParameterProviders]
+ declarations: [ParameterProviders],
+ providers: [
+ provideMockStore({
+ initialState: initialParameterProvidersState
+ })
+ ]
});
fixture = TestBed.createComponent(ParameterProviders);
component = fixture.componentInstance;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
index 1149a35b5f..aab8243728 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.component.ts
@@ -15,11 +15,105 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Store } from '@ngrx/store';
+import { NiFiState } from '../../../../state';
+import { ParameterProviderEntity, ParameterProvidersState } from '../../state/parameter-providers';
+import { selectCurrentUser } from '../../../../state/current-user/current-user.selectors';
+import {
+ selectParameterProvider,
+ selectParameterProviderIdFromRoute,
+ selectParameterProvidersState,
+ selectSingleEditedParameterProvider
+} from '../../state/parameter-providers/parameter-providers.selectors';
+import { selectFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.selectors';
+import { loadFlowConfiguration } from '../../../../state/flow-configuration/flow-configuration.actions';
+import * as ParameterProviderActions from '../../state/parameter-providers/parameter-providers.actions';
+import { initialParameterProvidersState } from '../../state/parameter-providers/parameter-providers.reducer';
+import { filter, switchMap, take } from 'rxjs';
+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { isDefinedAndNotNull } from '../../../../state/shared';
@Component({
selector: 'parameter-providers',
templateUrl: './parameter-providers.component.html',
styleUrls: ['./parameter-providers.component.scss']
})
-export class ParameterProviders {}
+export class ParameterProviders implements OnInit, OnDestroy {
+ currentUser$ = this.store.select(selectCurrentUser);
+ parameterProvidersState$ = this.store.select(selectParameterProvidersState);
+ selectedParameterProviderId$ = this.store.select(selectParameterProviderIdFromRoute);
+ flowConfiguration$ = this.store.select(selectFlowConfiguration);
+
+ constructor(private store: Store<NiFiState>) {
+ this.store
+ .select(selectSingleEditedParameterProvider)
+ .pipe(
+ isDefinedAndNotNull(),
+ switchMap((id: string) =>
+ this.store.select(selectParameterProvider(id)).pipe(isDefinedAndNotNull(), take(1))
+ ),
+ takeUntilDestroyed()
+ )
+ .subscribe((entity) => {
+ this.store.dispatch(
+ ParameterProviderActions.openConfigureParameterProviderDialog({
+ request: {
+ id: entity.id,
+ parameterProvider: entity
+ }
+ })
+ );
+ });
+ }
+
+ ngOnInit(): void {
+ this.store.dispatch(loadFlowConfiguration());
+ this.store.dispatch(ParameterProviderActions.loadParameterProviders());
+ }
+
+ ngOnDestroy(): void {
+ this.store.dispatch(ParameterProviderActions.resetParameterProvidersState());
+ }
+
+ isInitialLoading(state: ParameterProvidersState): boolean {
+ // using the current timestamp to detect the initial load event
+ return state.loadedTimestamp == initialParameterProvidersState.loadedTimestamp;
+ }
+
+ refreshParameterProvidersListing(): void {
+ this.store.dispatch(ParameterProviderActions.loadParameterProviders());
+ }
+
+ openNewParameterProviderDialog() {
+ this.store.dispatch(ParameterProviderActions.openNewParameterProviderDialog());
+ }
+
+ openConfigureParameterProviderDialog(parameterProvider: ParameterProviderEntity) {
+ this.store.dispatch(
+ ParameterProviderActions.navigateToEditParameterProvider({
+ id: parameterProvider.component.id
+ })
+ );
+ }
+
+ selectParameterProvider(parameterProvider: ParameterProviderEntity) {
+ this.store.dispatch(
+ ParameterProviderActions.selectParameterProvider({
+ request: {
+ id: parameterProvider.id
+ }
+ })
+ );
+ }
+
+ deleteParameterProvider(parameterProvider: ParameterProviderEntity) {
+ this.store.dispatch(
+ ParameterProviderActions.promptParameterProviderDeletion({
+ request: {
+ parameterProvider
+ }
+ })
+ );
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.module.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.module.ts
index 9eff52810f..6ea65f94f6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.module.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/parameter-providers/parameter-providers.module.ts
@@ -18,10 +18,13 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ParameterProviders } from './parameter-providers.component';
+import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
+import { ParameterContextListingModule } from '../../../parameter-contexts/ui/parameter-context-listing/parameter-context-listing.module';
+import { ParameterProvidersTable } from './parameter-providers-table/parameter-providers-table.component';
@NgModule({
declarations: [ParameterProviders],
exports: [ParameterProviders],
- imports: [CommonModule]
+ imports: [CommonModule, NgxSkeletonLoaderModule, ParameterProvidersTable]
})
export class ParameterProvidersModule {}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts
index a09304f2ee..b63c92162d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/settings/ui/reporting-tasks/reporting-task-table/reporting-task-table.component.ts
@@ -35,12 +35,13 @@ import { CurrentUser } from '../../../../../state/current-user';
export class ReportingTaskTable {
@Input() initialSortColumn: 'name' | 'type' | 'bundle' | 'state' = 'name';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
+ activeSort: Sort = {
+ active: this.initialSortColumn,
+ direction: this.initialSortDirection
+ };
@Input() set reportingTasks(reportingTaskEntities: ReportingTaskEntity[]) {
- this.dataSource.data = this.sortEntities(reportingTaskEntities, {
- active: this.initialSortColumn,
- direction: this.initialSortDirection
- });
+ this.dataSource.data = this.sortEntities(reportingTaskEntities, this.activeSort);
}
@Input() selectedReportingTaskId!: string;
@@ -258,6 +259,7 @@ export class ReportingTaskTable {
}
sortData(sort: Sort) {
+ this.activeSort = sort;
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/users/service/users.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/users/service/users.service.ts
index 2b1f18e95f..75d8dfa953 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/users/service/users.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/pages/users/service/users.service.ts
@@ -32,19 +32,6 @@ import {
export class UsersService {
private static readonly API: string = '../nifi-api';
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
constructor(
private httpClient: HttpClient,
private client: Client,
@@ -83,7 +70,7 @@ export class UsersService {
...request.userPayload
}
};
- return this.httpClient.put(this.stripProtocol(request.uri), payload);
+ return this.httpClient.put(this.nifiCommon.stripProtocol(request.uri), payload);
}
updateUserGroup(request: UpdateUserGroupRequest): Observable<any> {
@@ -94,16 +81,16 @@ export class UsersService {
...request.userGroupPayload
}
};
- return this.httpClient.put(this.stripProtocol(request.uri), payload);
+ return this.httpClient.put(this.nifiCommon.stripProtocol(request.uri), payload);
}
deleteUser(user: UserEntity): Observable<any> {
const revision: any = this.client.getRevision(user);
- return this.httpClient.delete(this.stripProtocol(user.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(user.uri), { params: revision });
}
deleteUserGroup(userGroup: UserGroupEntity): Observable<any> {
const revision: any = this.client.getRevision(userGroup);
- return this.httpClient.delete(this.stripProtocol(userGroup.uri), { params: revision });
+ return this.httpClient.delete(this.nifiCommon.stripProtocol(userGroup.uri), { params: revision });
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/component-state.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/component-state.service.ts
index f87d93b7b4..1fef85eb30 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/component-state.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/component-state.service.ts
@@ -28,24 +28,11 @@ export class ComponentStateService {
private nifiCommon: NiFiCommon
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getComponentState(request: LoadComponentStateRequest): Observable<any> {
- return this.httpClient.get(`${this.stripProtocol(request.componentUri)}/state`);
+ return this.httpClient.get(`${this.nifiCommon.stripProtocol(request.componentUri)}/state`);
}
clearComponentState(request: ClearComponentStateRequest): Observable<any> {
- return this.httpClient.post(`${this.stripProtocol(request.componentUri)}/state/clear-requests`, {});
+ return this.httpClient.post(`${this.nifiCommon.stripProtocol(request.componentUri)}/state/clear-requests`, {});
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/controller-service-state.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/controller-service-state.service.ts
index 679ad50685..7d446c5aa7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/controller-service-state.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/controller-service-state.service.ts
@@ -36,25 +36,12 @@ export class ControllerServiceStateService {
private client: Client
) {}
- /**
- * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
- * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
- *
- * https://stackoverflow.com/a/59586462
- *
- * @param url
- * @private
- */
- private stripProtocol(url: string): string {
- return this.nifiCommon.substringAfterFirst(url, ':');
- }
-
getControllerService(id: string): Observable<any> {
return this.httpClient.get(`${ControllerServiceStateService.API}/controller-services/${id}`);
}
setEnable(controllerService: ControllerServiceEntity, enabled: boolean): Observable<any> {
- return this.httpClient.put(`${this.stripProtocol(controllerService.uri)}/run-status`, {
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(controllerService.uri)}/run-status`, {
revision: this.client.getRevision(controllerService),
state: enabled ? 'ENABLED' : 'DISABLED',
uiOnly: true
@@ -69,7 +56,7 @@ export class ControllerServiceStateService {
true
);
- return this.httpClient.put(`${this.stripProtocol(controllerService.uri)}/references`, {
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(controllerService.uri)}/references`, {
id: controllerService.id,
state: enabled ? 'ENABLED' : 'DISABLED',
referencingComponentRevisions: referencingComponentRevisions,
@@ -89,7 +76,7 @@ export class ControllerServiceStateService {
false
);
- return this.httpClient.put(`${this.stripProtocol(controllerService.uri)}/references`, {
+ return this.httpClient.put(`${this.nifiCommon.stripProtocol(controllerService.uri)}/references`, {
id: controllerService.id,
state: running ? 'RUNNING' : 'STOPPED',
referencingComponentRevisions: referencingComponentRevisions,
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/nifi-common.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/nifi-common.service.ts
index 556cc95ba7..85ec206b4f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/nifi-common.service.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/nifi-common.service.ts
@@ -511,4 +511,17 @@ export class NiFiCommon {
public getAllPolicyTypeListing(): SelectOption[] {
return this.policyTypeListing;
}
+
+ /**
+ * The NiFi model contain the url for each component. That URL is an absolute URL. Angular CSRF handling
+ * does not work on absolute URLs, so we need to strip off the proto for the request header to be added.
+ *
+ * https://stackoverflow.com/a/59586462
+ *
+ * @param url
+ * @private
+ */
+ public stripProtocol(url: string): string {
+ return this.substringAfterFirst(url, ':');
+ }
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/property-table-helper.service.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/property-table-helper.service.ts
new file mode 100644
index 0000000000..c359980e6f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/service/property-table-helper.service.ts
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+import { Injectable } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { catchError, map, NEVER, Observable, switchMap, take } from 'rxjs';
+import {
+ ControllerServiceCreator,
+ ControllerServiceEntity,
+ CreateControllerServiceRequest,
+ InlineServiceCreationRequest,
+ InlineServiceCreationResponse,
+ NewPropertyDialogRequest,
+ NewPropertyDialogResponse,
+ Property,
+ PropertyDescriptor,
+ PropertyDescriptorRetriever
+} from '../state/shared';
+import { NewPropertyDialog } from '../ui/common/new-property-dialog/new-property-dialog.component';
+import { CreateControllerService } from '../ui/common/controller-service/create-controller-service/create-controller-service.component';
+import { ManagementControllerServiceService } from '../pages/settings/service/management-controller-service.service';
+import { ExtensionTypesService } from './extension-types.service';
+import { Client } from './client.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PropertyTableHelperService {
+ constructor(
+ private dialog: MatDialog,
+ private extensionTypesService: ExtensionTypesService,
+ private client: Client
+ ) {}
+
+ /**
+ * Returns a function that can be used to pass into a PropertyTable to support creating a new property
+ * @param id id of the component to create the property for
+ * @param propertyDescriptorService the service to call to get property descriptors
+ */
+ createNewProperty(
+ id: string,
+ propertyDescriptorService: PropertyDescriptorRetriever
+ ): (existingProperties: string[], allowsSensitive: boolean) => Observable<Property> {
+ return (existingProperties: string[], allowsSensitive: boolean) => {
+ const dialogRequest: NewPropertyDialogRequest = { existingProperties, allowsSensitive };
+ const newPropertyDialogReference = this.dialog.open(NewPropertyDialog, {
+ data: dialogRequest,
+ panelClass: 'small-dialog'
+ });
+
+ return newPropertyDialogReference.componentInstance.newProperty.pipe(
+ take(1),
+ switchMap((dialogResponse: NewPropertyDialogResponse) => {
+ return propertyDescriptorService
+ .getPropertyDescriptor(id, dialogResponse.name, dialogResponse.sensitive)
+ .pipe(
+ take(1),
+ map((response) => {
+ newPropertyDialogReference.close();
+
+ return {
+ property: dialogResponse.name,
+ value: null,
+ descriptor: response.propertyDescriptor
+ };
+ })
+ );
+ })
+ );
+ };
+ }
+
+ /**
+ * Returns a function that can be used to pass into a PropertyTable to create a controller service, inline.
+ *
+ * @param id id of the component where the inline-create controller service was initiated
+ * @param controllerServiceCreator service to use to create the controller service and lookup property descriptors
+ * @param propertyDescriptorService the service to call to get property descriptors
+ * @param afterServiceCreated OPTIONAL - callback function to possibly dispatch an action after the controller service has been created
+ * @param processGroupId OPTIONAL - process group id to create the
+ */
+ createNewService(
+ id: string,
+ controllerServiceCreator: ControllerServiceCreator,
+ propertyDescriptorService: PropertyDescriptorRetriever,
+ processGroupId?: string | null,
+ afterServiceCreated?: (createdResponse: ControllerServiceEntity) => void
+ ): (request: InlineServiceCreationRequest) => Observable<InlineServiceCreationResponse> {
+ return (request: InlineServiceCreationRequest) => {
+ const descriptor: PropertyDescriptor = request.descriptor;
+
+ // fetch all services that implement the requested service api
+ return this.extensionTypesService
+ .getImplementingControllerServiceTypes(
+ // @ts-ignore
+ descriptor.identifiesControllerService,
+ descriptor.identifiesControllerServiceBundle
+ )
+ .pipe(
+ take(1),
+ switchMap((implementingTypesResponse) => {
+ // show the create controller service dialog with the types that implemented the interface
+ const createServiceDialogReference = this.dialog.open(CreateControllerService, {
+ data: {
+ controllerServiceTypes: implementingTypesResponse.controllerServiceTypes
+ },
+ panelClass: 'medium-dialog'
+ });
+
+ return createServiceDialogReference.componentInstance.createControllerService.pipe(
+ take(1),
+ switchMap((controllerServiceType) => {
+ // typically this sequence would be implemented with ngrx actions, however we are
+ // currently in an edit session, and we need to return both the value (new service id)
+ // and updated property descriptor so the table renders correctly
+ const payload: CreateControllerServiceRequest = {
+ revision: {
+ clientId: this.client.getClientId(),
+ version: 0
+ },
+ controllerServiceType: controllerServiceType.type,
+ controllerServiceBundle: controllerServiceType.bundle
+ };
+
+ if (processGroupId) {
+ payload.processGroupId = processGroupId;
+ }
+
+ return controllerServiceCreator.createControllerService(payload).pipe(
+ take(1),
+ switchMap((createResponse) => {
+ // if provided, call the callback function
+ if (afterServiceCreated) {
+ afterServiceCreated(createResponse);
+ }
+
+ // fetch an updated property descriptor
+ return propertyDescriptorService
+ .getPropertyDescriptor(id, descriptor.name, false)
+ .pipe(
+ take(1),
+ map((descriptorResponse) => {
+ createServiceDialogReference.close();
+
+ return {
+ value: createResponse.id,
+ descriptor: descriptorResponse.propertyDescriptor
+ };
+ })
+ );
+ }),
+ catchError((error) => {
+ // TODO - show error
+ return NEVER;
+ })
+ );
+ })
+ );
+ })
+ );
+ };
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.selectors.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.selectors.ts
index db29215cb9..24203c3827 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.selectors.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/extension-types/extension-types.selectors.ts
@@ -51,6 +51,11 @@ export const selectFlowAnalysisRuleTypes = createSelector(
(state: ExtensionTypesState) => state.flowAnalysisRuleTypes
);
+export const selectParameterProviderTypes = createSelector(
+ selectExtensionTypesState,
+ (state: ExtensionTypesState) => state.parameterProviderTypes
+);
+
export const selectTypesToIdentifyComponentRestrictions = createSelector(
selectExtensionTypesState,
(state: ExtensionTypesState) => {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts
index dcd872cace..aec81d5933 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/state/shared/index.ts
@@ -112,7 +112,7 @@ export interface EditTenantResponse {
userGroup?: any;
}
-export interface CreateControllerServiceRequest {
+export interface CreateControllerServiceDialogRequest {
controllerServiceTypes: DocumentedType[];
}
@@ -306,6 +306,7 @@ export interface ParameterContextReferenceEntity {
permissions: Permissions;
id: string;
component?: ParameterContextReference;
+ bulletins?: BulletinEntity[];
}
export interface ParameterContextReference {
@@ -508,6 +509,10 @@ export interface PropertyDescriptor {
identifiesControllerServiceBundle?: Bundle;
}
+export interface PropertyDescriptorEntity {
+ propertyDescriptor: PropertyDescriptor;
+}
+
export interface Property {
property: string;
value: string | null;
@@ -522,3 +527,18 @@ export interface InlineServiceCreationResponse {
value: string;
descriptor: PropertyDescriptor;
}
+
+export interface PropertyDescriptorRetriever {
+ getPropertyDescriptor(id: string, propertyName: string, sensitive: boolean): Observable<PropertyDescriptorEntity>;
+}
+
+export interface CreateControllerServiceRequest {
+ processGroupId?: string;
+ controllerServiceType: string;
+ controllerServiceBundle: Bundle;
+ revision: Revision;
+}
+
+export interface ControllerServiceCreator {
+ createControllerService(createControllerService: CreateControllerServiceRequest): Observable<any>;
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts
index fe33870ba1..afa33ccef7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/controller-service-table/controller-service-table.component.ts
@@ -55,12 +55,13 @@ import { CurrentUser } from '../../../../state/current-user';
export class ControllerServiceTable {
@Input() initialSortColumn: 'name' | 'type' | 'bundle' | 'state' | 'scope' = 'name';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
+ activeSort: Sort = {
+ active: this.initialSortColumn,
+ direction: this.initialSortDirection
+ };
@Input() set controllerServices(controllerServiceEntities: ControllerServiceEntity[]) {
- this.dataSource.data = this.sortEntities(controllerServiceEntities, {
- active: this.initialSortColumn,
- direction: this.initialSortDirection
- });
+ this.dataSource.data = this.sortEntities(controllerServiceEntities, this.activeSort);
}
@Input() selectedServiceId!: string;
@@ -277,6 +278,7 @@ export class ControllerServiceTable {
}
sortData(sort: Sort) {
+ this.activeSort = sort;
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.spec.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.spec.ts
index 951a5d206d..b7ebcc1c17 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.spec.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.spec.ts
@@ -18,7 +18,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateControllerService } from './create-controller-service.component';
-import { CreateControllerServiceRequest, DocumentedType } from '../../../../state/shared';
+import { CreateControllerServiceDialogRequest, DocumentedType } from '../../../../state/shared';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { provideMockStore } from '@ngrx/store/testing';
import { initialState } from '../../../../state/extension-types/extension-types.reducer';
@@ -28,7 +28,7 @@ describe('CreateControllerService', () => {
let component: CreateControllerService;
let fixture: ComponentFixture<CreateControllerService>;
- const data: CreateControllerServiceRequest = {
+ const data: CreateControllerServiceDialogRequest = {
controllerServiceTypes: [
{
type: 'org.apache.nifi.services.azure.storage.ADLSCredentialsControllerService',
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts
index 9eef6781c5..56d27ed3db 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/controller-service/create-controller-service/create-controller-service.component.ts
@@ -17,7 +17,7 @@
import { Component, EventEmitter, Inject, Input, Output } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
-import { CreateControllerServiceRequest, DocumentedType } from '../../../../state/shared';
+import { CreateControllerServiceDialogRequest, DocumentedType } from '../../../../state/shared';
import { ExtensionCreation } from '../../extension-creation/extension-creation.component';
import { Observable } from 'rxjs';
import { AsyncPipe } from '@angular/common';
@@ -35,7 +35,7 @@ export class CreateControllerService {
controllerServiceTypes: DocumentedType[];
- constructor(@Inject(MAT_DIALOG_DATA) private dialogRequest: CreateControllerServiceRequest) {
+ constructor(@Inject(MAT_DIALOG_DATA) private dialogRequest: CreateControllerServiceDialogRequest) {
this.controllerServiceTypes = dialogRequest.controllerServiceTypes;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts
index 82d5872b04..ab439d166a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-frontend/src/main/nifi/src/app/ui/common/extension-creation/extension-creation.component.ts
@@ -49,16 +49,17 @@ export class ExtensionCreation {
this.selectedType = documentedTypes[0];
}
- this.dataSource.data = this.sortEntities(documentedTypes, {
- active: this.initialSortColumn,
- direction: this.initialSortDirection
- });
+ this.dataSource.data = this.sortEntities(documentedTypes, this.activeSort);
}
@Input() componentType!: string;
@Input() saving!: boolean;
@Input() initialSortColumn: 'type' | 'version' | 'tags' = 'type';
@Input() initialSortDirection: 'asc' | 'desc' = 'asc';
+ activeSort: Sort = {
+ active: this.initialSortColumn,
+ direction: this.initialSortDirection
+ };
@Output() extensionTypeSelected: EventEmitter<DocumentedType> = new EventEmitter<DocumentedType>();
@@ -151,6 +152,7 @@ export class ExtensionCreation {
}
sortData(sort: Sort) {
+ this.activeSort = sort;
this.dataSource.data = this.sortEntities(this.dataSource.data, sort);
}