You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by pv...@apache.org on 2024/05/23 18:12:44 UTC
(nifi) branch support/nifi-1.x updated: NIFI-11658 Streamline using single Parameter Context for nested PGs
This is an automated email from the ASF dual-hosted git repository.
pvillard pushed a commit to branch support/nifi-1.x
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/support/nifi-1.x by this push:
new 4aae517cca NIFI-11658 Streamline using single Parameter Context for nested PGs
4aae517cca is described below
commit 4aae517cca997b12e254a7778199a6fe048d2439
Author: Timea Barna <ti...@apache.org>
AuthorDate: Fri Jun 2 10:58:44 2023 +0200
NIFI-11658 Streamline using single Parameter Context for nested PGs
Including applicable modifications from NIFI-12101 by Mark Payne
This closes #7353
Co-authored-by: Matt Gilman <mc...@apache.org>
Signed-off-by: David Handermann <ex...@apache.org>
(cherry picked from commit 42910e80d1d0a71c8f3de51bdd5c6dd0183da26d)
Signed-off-by: Pierre Villard <pi...@gmail.com>
This closes #8868.
---
.../nifi/web/api/entity/ProcessGroupEntity.java | 14 ++
.../web/api/entity/ProcessGroupRecursivity.java | 22 +++
.../org/apache/nifi/web/NiFiServiceFacade.java | 10 +-
.../apache/nifi/web/StandardNiFiServiceFacade.java | 5 +-
.../apache/nifi/web/api/ProcessGroupResource.java | 149 +++++++++-----
.../org/apache/nifi/web/dao/ProcessGroupDAO.java | 4 +-
.../nifi/web/dao/impl/StandardProcessGroupDAO.java | 9 +-
.../nifi/web/api/TestProcessGroupResource.java | 43 +++-
.../nifi-framework/nifi-web/nifi-web-ui/pom.xml | 1 +
.../partials/canvas/new-process-group-dialog.jsp | 15 +-
.../canvas/process-group-configuration.jsp | 8 +-
.../nifi-web-ui/src/main/webapp/css/canvas.css | 1 +
.../nifi-web-ui/src/main/webapp/css/common-ui.css | 2 +-
.../nifi-web-ui/src/main/webapp/css/main.css | 28 +--
.../main/webapp/css/new-process-group-dialog.css | 37 ++++
.../webapp/css/process-group-configuration.css | 17 +-
.../main/webapp/js/jquery/combo/jquery.combo.css | 4 +-
.../header/components/nf-ng-group-component.js | 217 ++++++++++++++-------
.../main/webapp/js/nf/canvas/nf-flow-version.js | 12 +-
.../js/nf/canvas/nf-process-group-configuration.js | 44 ++---
.../nifi-web-ui/src/main/webapp/js/nf/nf-common.js | 40 ++++
21 files changed, 474 insertions(+), 208 deletions(-)
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java
index 1e726dc21d..7d46e8a13a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java
@@ -56,6 +56,8 @@ public class ProcessGroupEntity extends ComponentEntity implements Permissible<P
private ParameterContextReferenceEntity parameterContext;
+ private String processGroupUpdateStrategy;
+
/**
* The ProcessGroupDTO that is being serialized.
*
@@ -328,4 +330,16 @@ public class ProcessGroupEntity extends ComponentEntity implements Permissible<P
public void setParameterContext(ParameterContextReferenceEntity parameterContext) {
this.parameterContext = parameterContext;
}
+
+ @ApiModelProperty(
+ value = "Determines the process group update strategy",
+ allowableValues = "DIRECT_CHILDREN, ALL_DESCENDANTS"
+ )
+ public String getProcessGroupUpdateStrategy() {
+ return processGroupUpdateStrategy;
+ }
+
+ public void setProcessGroupUpdateStrategy(String processGroupUpdateStrategy) {
+ this.processGroupUpdateStrategy = processGroupUpdateStrategy;
+ }
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupRecursivity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupRecursivity.java
new file mode 100644
index 0000000000..c6710b96f4
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupRecursivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.web.api.entity;
+
+public enum ProcessGroupRecursivity {
+ DIRECT_CHILDREN,
+ ALL_DESCENDANTS
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
index ee6f8571ab..e819f4d342 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
@@ -91,7 +91,6 @@ import org.apache.nifi.web.api.entity.AccessPolicyEntity;
import org.apache.nifi.web.api.entity.ActionEntity;
import org.apache.nifi.web.api.entity.ActivateControllerServicesEntity;
import org.apache.nifi.web.api.entity.AffectedComponentEntity;
-import org.apache.nifi.web.api.entity.FlowRegistryBucketEntity;
import org.apache.nifi.web.api.entity.BulletinEntity;
import org.apache.nifi.web.api.entity.ComponentValidationResultEntity;
import org.apache.nifi.web.api.entity.ConfigurationAnalysisEntity;
@@ -106,6 +105,8 @@ import org.apache.nifi.web.api.entity.CurrentUserEntity;
import org.apache.nifi.web.api.entity.FlowComparisonEntity;
import org.apache.nifi.web.api.entity.FlowConfigurationEntity;
import org.apache.nifi.web.api.entity.FlowEntity;
+import org.apache.nifi.web.api.entity.FlowRegistryBucketEntity;
+import org.apache.nifi.web.api.entity.FlowRegistryClientEntity;
import org.apache.nifi.web.api.entity.FunnelEntity;
import org.apache.nifi.web.api.entity.LabelEntity;
import org.apache.nifi.web.api.entity.ParameterContextEntity;
@@ -115,12 +116,12 @@ import org.apache.nifi.web.api.entity.PortEntity;
import org.apache.nifi.web.api.entity.PortStatusEntity;
import org.apache.nifi.web.api.entity.ProcessGroupEntity;
import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ProcessorDiagnosticsEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
import org.apache.nifi.web.api.entity.ProcessorsRunStatusDetailsEntity;
-import org.apache.nifi.web.api.entity.FlowRegistryClientEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
@@ -1225,9 +1226,10 @@ public interface NiFiServiceFacade {
* Gets all process groups in the specified parent group.
*
* @param parentGroupId The id of the parent group
- * @return process group
+ * @param processGroupUpdateStrategy if process groups with its child groups should be included
+ * @return List of process groups
*/
- Set<ProcessGroupEntity> getProcessGroups(String parentGroupId);
+ Set<ProcessGroupEntity> getProcessGroups(String parentGroupId, ProcessGroupRecursivity processGroupUpdateStrategy);
/**
* Verifies the contents of the specified process group can be scheduled or unscheduled.
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index c2d5a7fd16..af00ecbc5e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -302,6 +302,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupEntity;
import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import org.apache.nifi.web.api.entity.ProcessorDiagnosticsEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ProcessorRunStatusDetailsEntity;
@@ -4577,8 +4578,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
- public Set<ProcessGroupEntity> getProcessGroups(final String parentGroupId) {
- final Set<ProcessGroup> groups = processGroupDAO.getProcessGroups(parentGroupId);
+ public Set<ProcessGroupEntity> getProcessGroups(final String parentGroupId, final ProcessGroupRecursivity processGroupUpdateStrategy) {
+ final Set<ProcessGroup> groups = processGroupDAO.getProcessGroups(parentGroupId, processGroupUpdateStrategy);
return groups.stream()
.map(group -> createProcessGroupEntity(group))
.collect(Collectors.toSet());
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
index 04a626b7fd..939b97868e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
@@ -111,6 +111,7 @@ import org.apache.nifi.web.api.entity.PortEntity;
import org.apache.nifi.web.api.entity.ProcessGroupEntity;
import org.apache.nifi.web.api.entity.ProcessGroupImportEntity;
import org.apache.nifi.web.api.entity.ProcessGroupReplaceRequestEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import org.apache.nifi.web.api.entity.ProcessGroupUploadEntity;
import org.apache.nifi.web.api.entity.ProcessGroupsEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity;
@@ -169,6 +170,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -480,7 +482,7 @@ public class ProcessGroupResource extends FlowUpdateResource<ProcessGroupImportE
* @param httpServletRequest request
* @param id The id of the process group.
* @param requestProcessGroupEntity A processGroupEntity.
- * @return A processGroupEntity.
+ * @return A processGroupEntity or the parent processGroupEntity for recursive requests.
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@@ -536,6 +538,15 @@ public class ProcessGroupResource extends FlowUpdateResource<ProcessGroupImportE
}
}
+ final String processGroupUpdateStrategy = requestProcessGroupEntity.getProcessGroupUpdateStrategy();
+ final ProcessGroupRecursivity updateStrategy;
+ if (processGroupUpdateStrategy == null) {
+ updateStrategy = ProcessGroupRecursivity.DIRECT_CHILDREN;
+ } else {
+ updateStrategy = ProcessGroupRecursivity.valueOf(processGroupUpdateStrategy);
+ }
+
+
if (isReplicateRequest()) {
return replicate(HttpMethod.PUT, requestProcessGroupEntity);
} else if (isDisconnectedFromCluster()) {
@@ -543,68 +554,100 @@ public class ProcessGroupResource extends FlowUpdateResource<ProcessGroupImportE
}
// handle expects request (usually from the cluster manager)
- final Revision requestRevision = getRevision(requestProcessGroupEntity, id);
+ final ParameterContextReferenceEntity requestParamContext = requestProcessGroupDTO.getParameterContext();
+ final String requestGroupId = requestProcessGroupDTO.getId();
+ final Map<ProcessGroupEntity, Revision> updatableProcessGroups = new HashMap<>();
+
+ updatableProcessGroups.put(requestProcessGroupEntity, getRevision(requestProcessGroupEntity, requestGroupId));
+
+ if (updateStrategy == ProcessGroupRecursivity.ALL_DESCENDANTS) {
+ for (ProcessGroupEntity processGroupEntity : serviceFacade.getProcessGroups(requestGroupId, updateStrategy)) {
+ final ProcessGroupDTO processGroupDTO = processGroupEntity.getComponent();
+ final String processGroupId = processGroupDTO == null ? processGroupEntity.getId() : processGroupDTO.getId();
+ if (processGroupDTO != null) {
+ processGroupDTO.setParameterContext(requestParamContext);
+ }
+ updatableProcessGroups.put(processGroupEntity, getRevision(processGroupEntity, processGroupId));
+ }
+ }
+
return withWriteLock(
serviceFacade,
requestProcessGroupEntity,
- requestRevision,
+ new HashSet<>(updatableProcessGroups.values()),
lookup -> {
final NiFiUser user = NiFiUserUtils.getNiFiUser();
- Authorizable authorizable = lookup.getProcessGroup(id).getAuthorizable();
- authorizable.authorize(authorizer, RequestAction.WRITE, user);
-
- // Ensure that user has READ permission on current Parameter Context (if any) because user is un-binding.
- final ParameterContextReferenceEntity referencedParamContext = requestProcessGroupDTO.getParameterContext();
- if (referencedParamContext != null) {
- // Lookup the current Parameter Context and determine whether or not the Parameter Context is changing
- final String groupId = requestProcessGroupDTO.getId();
- final ProcessGroupEntity currentGroupEntity = serviceFacade.getProcessGroup(groupId);
- final ProcessGroupDTO groupDto = currentGroupEntity.getComponent();
- final ParameterContextReferenceEntity currentParamContext = groupDto.getParameterContext();
- final String currentParamContextId = currentParamContext == null ? null : currentParamContext.getId();
- final boolean parameterContextChanging = !Objects.equals(referencedParamContext.getId(), currentParamContextId);
-
- // If Parameter Context is changing...
- if (parameterContextChanging) {
- // In order to bind to a Parameter Context, the user must have the READ policy to that Parameter Context.
- if (referencedParamContext.getId() != null) {
- lookup.getParameterContext(referencedParamContext.getId()).authorize(authorizer, RequestAction.READ, user);
- }
-
- // If currently referencing a Parameter Context, we must authorize that the user has READ permissions on the Parameter Context in order to un-bind to it.
- if (currentParamContextId != null) {
- lookup.getParameterContext(currentParamContextId).authorize(authorizer, RequestAction.READ, user);
- }
-
- // Because the user will be changing the behavior of any component in this group that is currently referencing any Parameter, we must ensure that the user has
- // both READ and WRITE policies for each of those components.
- for (final AffectedComponentEntity affectedComponentEntity : serviceFacade.getProcessorsReferencingParameter(groupId)) {
- final Authorizable processorAuthorizable = lookup.getProcessor(affectedComponentEntity.getId()).getAuthorizable();
- processorAuthorizable.authorize(authorizer, RequestAction.READ, user);
- processorAuthorizable.authorize(authorizer, RequestAction.WRITE, user);
- }
-
- for (final AffectedComponentEntity affectedComponentEntity : serviceFacade.getControllerServicesReferencingParameter(groupId)) {
- final Authorizable serviceAuthorizable = lookup.getControllerService(affectedComponentEntity.getId()).getAuthorizable();
- serviceAuthorizable.authorize(authorizer, RequestAction.READ, user);
- serviceAuthorizable.authorize(authorizer, RequestAction.WRITE, user);
+ for (final ProcessGroupEntity updatableGroupEntity : updatableProcessGroups.keySet()) {
+ final ProcessGroupDTO updatableGroupDto = updatableGroupEntity.getComponent();
+ final String groupId = updatableGroupDto == null ? updatableGroupEntity.getId() : updatableGroupDto.getId();
+
+ Authorizable authorizable = lookup.getProcessGroup(groupId).getAuthorizable();
+ authorizable.authorize(authorizer, RequestAction.WRITE, user);
+
+ // Ensure that user has READ permission on current Parameter Context (if any) because user is un-binding.
+ final ParameterContextReferenceEntity referencedParamContext = updatableGroupDto.getParameterContext();
+ if (referencedParamContext != null) {
+ // Lookup the current Parameter Context and determine whether or not the Parameter Context is changing
+ final ProcessGroupEntity currentGroupEntity = serviceFacade.getProcessGroup(groupId);
+ final ProcessGroupDTO groupDto = currentGroupEntity.getComponent();
+ final ParameterContextReferenceEntity currentParamContext = groupDto.getParameterContext();
+ final String currentParamContextId = currentParamContext == null ? null : currentParamContext.getId();
+ final boolean parameterContextChanging = !Objects.equals(referencedParamContext.getId(), currentParamContextId);
+
+ // If Parameter Context is changing...
+ if (parameterContextChanging) {
+ // In order to bind to a Parameter Context, the user must have the READ policy to that Parameter Context.
+ if (referencedParamContext.getId() != null) {
+ lookup.getParameterContext(referencedParamContext.getId()).authorize(authorizer, RequestAction.READ, user);
+ }
+
+ // If currently referencing a Parameter Context, we must authorize that the user has READ permissions on the Parameter Context in order to un-bind to it.
+ if (currentParamContextId != null) {
+ lookup.getParameterContext(currentParamContextId).authorize(authorizer, RequestAction.READ, user);
+ }
+
+ // Because the user will be changing the behavior of any component in this group that is currently referencing any Parameter, we must ensure that the user has
+ // both READ and WRITE policies for each of those components.
+ for (final AffectedComponentEntity affectedComponentEntity : serviceFacade.getProcessorsReferencingParameter(groupId)) {
+ final Authorizable processorAuthorizable = lookup.getProcessor(affectedComponentEntity.getId()).getAuthorizable();
+ processorAuthorizable.authorize(authorizer, RequestAction.READ, user);
+ processorAuthorizable.authorize(authorizer, RequestAction.WRITE, user);
+ }
+
+ for (final AffectedComponentEntity affectedComponentEntity : serviceFacade.getControllerServicesReferencingParameter(groupId)) {
+ final Authorizable serviceAuthorizable = lookup.getControllerService(affectedComponentEntity.getId()).getAuthorizable();
+ serviceAuthorizable.authorize(authorizer, RequestAction.READ, user);
+ serviceAuthorizable.authorize(authorizer, RequestAction.WRITE, user);
+ }
}
}
}
},
- () -> serviceFacade.verifyUpdateProcessGroup(requestProcessGroupDTO),
- (revision, processGroupEntity) -> {
- // update the process group
- final ProcessGroupEntity entity = serviceFacade.updateProcessGroup(revision, processGroupEntity.getComponent());
- populateRemainingProcessGroupEntityContent(entity);
-
- // prune response as necessary
- if (entity.getComponent() != null) {
- entity.getComponent().setContents(null);
+ () -> {
+ for (final ProcessGroupEntity entity : updatableProcessGroups.keySet()) {
+ serviceFacade.verifyUpdateProcessGroup(entity.getComponent());
}
-
- return generateOkResponse(entity).build();
+ },
+ (revisions, entities) -> {
+ ProcessGroupEntity responseEntity = null;
+ for (Map.Entry<ProcessGroupEntity, Revision> entry : updatableProcessGroups.entrySet()) {
+ // update the process group
+ final Revision revision = entry.getValue();
+ final ProcessGroupDTO groupDTO = entry.getKey().getComponent();
+ final ProcessGroupEntity entity = serviceFacade.updateProcessGroup(revision, groupDTO);
+
+ if (requestGroupId.equals(entity.getId())) {
+ responseEntity = entity;
+ populateRemainingProcessGroupEntityContent(responseEntity);
+
+ // prune response as necessary
+ if (responseEntity.getComponent() != null) {
+ responseEntity.getComponent().setContents(null);
+ }
+ }
+ }
+ return generateOkResponse(responseEntity).build();
}
);
}
@@ -2175,7 +2218,7 @@ public class ProcessGroupResource extends FlowUpdateResource<ProcessGroupImportE
});
// get the process groups
- final Set<ProcessGroupEntity> entities = serviceFacade.getProcessGroups(groupId);
+ final Set<ProcessGroupEntity> entities = serviceFacade.getProcessGroups(groupId, ProcessGroupRecursivity.DIRECT_CHILDREN);
// always prune the contents
for (final ProcessGroupEntity entity : entities) {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
index 47abf91b66..f21abf3219 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
@@ -24,6 +24,7 @@ import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.web.api.dto.ProcessGroupDTO;
import org.apache.nifi.web.api.dto.VariableRegistryDTO;
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
+import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import java.util.Collection;
import java.util.Map;
@@ -59,9 +60,10 @@ public interface ProcessGroupDAO {
* Gets all of the process groups.
*
* @param parentGroupId The parent group id
+ * @param processGroupUpdateStrategy if process groups with its child groups should be included
* @return The process groups
*/
- Set<ProcessGroup> getProcessGroups(String parentGroupId);
+ Set<ProcessGroup> getProcessGroups(String parentGroupId, ProcessGroupRecursivity processGroupUpdateStrategy);
/**
* Verifies the specified process group can be modified.
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
index ecfe35e2a2..2de0d52288 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
@@ -45,6 +45,7 @@ import org.apache.nifi.web.api.dto.ProcessGroupDTO;
import org.apache.nifi.web.api.dto.VariableRegistryDTO;
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
import org.apache.nifi.web.api.entity.ParameterContextReferenceEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import org.apache.nifi.web.api.entity.VariableEntity;
import org.apache.nifi.web.dao.ProcessGroupDAO;
@@ -136,9 +137,13 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
}
@Override
- public Set<ProcessGroup> getProcessGroups(String parentGroupId) {
+ public Set<ProcessGroup> getProcessGroups(final String parentGroupId, final ProcessGroupRecursivity processGroupUpdateStrategy) {
ProcessGroup group = locateProcessGroup(flowController, parentGroupId);
- return group.getProcessGroups();
+ if (processGroupUpdateStrategy == ProcessGroupRecursivity.ALL_DESCENDANTS) {
+ return new HashSet<>(group.findAllProcessGroups());
+ } else {
+ return group.getProcessGroups();
+ }
}
@Override
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestProcessGroupResource.java
index f9dd7c5460..9c6033264f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestProcessGroupResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestProcessGroupResource.java
@@ -16,10 +16,16 @@
*/
package org.apache.nifi.web.api;
+import org.apache.nifi.authorization.AccessDeniedException;
+import org.apache.nifi.authorization.AuthorizeAccess;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.registry.flow.RegisteredFlowSnapshot;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.NiFiServiceFacade;
+import org.apache.nifi.web.api.dto.ProcessGroupDTO;
+import org.apache.nifi.web.api.dto.RevisionDTO;
+import org.apache.nifi.web.api.entity.ProcessGroupEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import org.apache.nifi.web.api.dto.FlowSnippetDTO;
import org.apache.nifi.web.api.dto.TemplateDTO;
import org.apache.nifi.web.api.entity.TemplateEntity;
@@ -41,10 +47,14 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.junit.jupiter.api.Assertions.assertFalse;
@ExtendWith(MockitoExtension.class)
public class TestProcessGroupResource {
@@ -110,4 +120,33 @@ public class TestProcessGroupResource {
assertFalse(Pattern.compile("<script.*>").matcher(response.getEntity().toString()).find());
});
}
+ @Test
+ public void testUpdateProcessGroupNotExecuted_WhenUserNotAuthorized(@Mock HttpServletRequest httpServletRequest, @Mock NiFiProperties properties) {
+ when(httpServletRequest.getHeader(any())).thenReturn(null);
+ when(properties.isNode()).thenReturn(Boolean.FALSE);
+
+ processGroupResource.properties = properties;
+ processGroupResource.serviceFacade = serviceFacade;
+ processGroupResource.httpServletRequest = httpServletRequest;
+
+ final ProcessGroupEntity processGroupEntity = new ProcessGroupEntity();
+ final ProcessGroupDTO groupDTO = new ProcessGroupDTO();
+ groupDTO.setId("id");
+ groupDTO.setName("name");
+ final RevisionDTO revisionDTO = new RevisionDTO();
+ revisionDTO.setClientId("clientId");
+ revisionDTO.setVersion(1L);
+
+ processGroupEntity.setRevision(revisionDTO);
+ processGroupEntity.setProcessGroupUpdateStrategy(ProcessGroupRecursivity.DIRECT_CHILDREN.name());
+ processGroupEntity.setComponent(groupDTO);
+
+ doThrow(AccessDeniedException.class).when(serviceFacade).authorizeAccess(any(AuthorizeAccess.class));
+
+ assertThrows(AccessDeniedException.class, () ->
+ processGroupResource.updateProcessGroup(httpServletRequest, "id", processGroupEntity));
+
+ verify(serviceFacade, never()).verifyUpdateProcessGroup(any());
+ verify(serviceFacade, never()).updateProcessGroup(any(), any());
+ }
}
\ No newline at end of file
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
index 89cd405306..d4f210141a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
@@ -739,6 +739,7 @@
<include>${staging.dir}/css/processor-configuration.css</include>
<include>${staging.dir}/css/processor-details.css</include>
<include>${staging.dir}/css/process-group-configuration.css</include>
+ <include>${staging.dir}/css/new-process-group-dialog.css</include>
<include>${staging.dir}/css/policy-management.css</include>
<include>${staging.dir}/css/remote-process-group-configuration.css</include>
<include>${staging.dir}/css/port-configuration.css</include>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-process-group-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-process-group-dialog.jsp
index 4ae9bcc862..b0d2555823 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-process-group-dialog.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-process-group-dialog.jsp
@@ -28,6 +28,13 @@
</div>
<input id="new-process-group-name" type="text" placeholder="Enter a name or select a file to upload"/>
</div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">Parameter Context</div>
+ <div class="setting-field">
+ <div id="new-pg-parameter-context-combo"></div>
+ <div id="parameters-from-uploaded-flow">Parameters will be imported from the uploaded Flow Definition.</div>
+ </div>
</div>
<div id="file-cancel-button-container">
<button class="icon" id="file-cancel-button" aria-hidden="true" title="Cancel the selected file">
@@ -45,10 +52,4 @@
</div>
</div>
</div>
- <div class="setting">
- <span id="import-process-group-link" class="link" title="Import a flow from a registry">
- <i class="fa fa-cloud-download" aria-hidden="true" style="margin-left: 5px; margin-right: 5px;"></i>
- Import from Registry...
- </span>
- </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp
index f54f5a1314..a17192f1e9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp
@@ -42,7 +42,13 @@
<div class="setting-name">Process group parameter context</div>
<div class="editable setting-field">
<div id="process-group-parameter-context-combo"></div>
- </div>
+ <div id="parameter-contexts-recursive-container">
+ <div id="parameter-contexts-recursive" class="nf-checkbox checkbox-unchecked"></div>
+ <div class="nf-checkbox-label">Apply recursively</div>
+ <div class="fa fa-question-circle" alt="Info" title="When checked Parameter Context will be applied to the Process Group and all the embedded Process Groups recursively, if the user has the proper permissions on all the respective components. If the user does not have the proper permissions on any embedded Process Group, then the Parameter Context will not be applied for any components."></div>
+ </div>
+ <div class="clear"></div>
+ </div>
<div class="read-only setting-field">
<span id="read-only-process-group-parameter-context" class="unset">Unauthorized</span>
</div>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
index a9de76f303..ec148daec0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
@@ -37,6 +37,7 @@
@import url(new-reporting-task-dialog.css);
@import url(new-parameter-provider-dialog.css);
@import url(new-parameter-context-dialog.css);
+@import url(new-process-group-dialog.css);
@import url(graph.css);
@import url(header.css);
@import url(main.css);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
index ef56a9b454..f07bfd38d6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
@@ -484,7 +484,7 @@ div.button-icon span {
div.button-icon {
float: left !important;
- margin-left: 20px;
+ margin-left: 0;
font-size: 18px !important;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
index 8f0500fd85..8290d0a4f3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
@@ -385,32 +385,6 @@ span.details-title {
width: 300px;
}
-span#import-process-group-link.link:focus {
- outline: none;
-}
-
-span#import-process-group-link.link {
- position: relative;
- top: 164px;
- left: 20px;
- color: #004849; /*link-color*/
- font-weight: normal;
- display: inline-block;
- border-bottom: 1px solid #CCDADB;
- font-size: 13px;
- font-family: Roboto;
- z-index: 1;
-}
-
-span#import-process-group-link.link-over {
- border-bottom: 1px solid #004849;
-}
-
-span#import-process-group-link.link-bold {
- font-weight: bold;
- border-bottom: none;
-}
-
#file-cancel-button {
position: absolute;
width: 0px;
@@ -421,4 +395,4 @@ span#import-process-group-link.link-bold {
background-color: transparent;
padding: 0px;
margin-top: 16px;
-}
\ No newline at end of file
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-process-group-dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-process-group-dialog.css
new file mode 100644
index 0000000000..a245922015
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-process-group-dialog.css
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/*
+ New process group dialog.
+*/
+
+#new-process-group-dialog {
+ min-height:320px;
+ height: 320px;
+ width: 540px;
+ min-width: 500px;
+}
+
+div.fa-cloud-download.button-icon {
+ width: 160px;
+}
+
+#parameters-from-uploaded-flow {
+ color: #888;
+ font-weight: 400;
+ display: none;
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css
index b340e9610f..56b06c2838 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css
@@ -93,6 +93,19 @@
width: 328px;
}
+#parameter-contexts-recursive-container {
+ margin-left: 10px;
+}
+
+#parameter-contexts-recursive-container > div {
+ float: left;
+ line-height: 30px;
+}
+
+#parameter-contexts-recursive {
+ margin-top: 8px;
+}
+
#process-group-flowfile-concurrency-combo {
width: 328px;
}
@@ -128,8 +141,4 @@
#upload-process-group-link {
float: right;
-}
-
-#process-group-log-to-own-file-combo {
- width: 328px;
}
\ No newline at end of file
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/combo/jquery.combo.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/combo/jquery.combo.css
index 1846ca9c05..a1902e2168 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/combo/jquery.combo.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/combo/jquery.combo.css
@@ -55,7 +55,7 @@
.combo-arrow {
float: right;
width: 10px;
- margin-top: 8px;
+ margin-top: 4px;
}
.combo-text {
@@ -115,4 +115,4 @@ div.combo-nifi-tooltip {
div.combo-button-normal {
background-color: #eaeef0;
-}
\ No newline at end of file
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-group-component.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-group-component.js
index bdf4952e93..42d90c6c48 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-group-component.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-group-component.js
@@ -26,10 +26,11 @@
'nf.Graph',
'nf.CanvasUtils',
'nf.ErrorHandler',
+ 'nf.FlowVersion',
'nf.Common',
'nf.Dialog'],
- function ($, nfClient, nfBirdseye, nfStorage, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon, nfDialog) {
- return (nf.ng.GroupComponent = factory($, nfClient, nfBirdseye, nfStorage, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon, nfDialog));
+ function ($, nfClient, nfBirdseye, nfStorage, nfGraph, nfCanvasUtils, nfErrorHandler, nfFlowVersion, nfCommon, nfDialog) {
+ return (nf.ng.GroupComponent = factory($, nfClient, nfBirdseye, nfStorage, nfGraph, nfCanvasUtils, nfErrorHandler, nfFlowVersion, nfCommon, nfDialog));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.ng.GroupComponent =
@@ -40,6 +41,7 @@
require('nf.Graph'),
require('nf.CanvasUtils'),
require('nf.ErrorHandler'),
+ require('nf.FlowVersion'),
require('nf.Common'),
require('nf.Dialog')));
} else {
@@ -50,10 +52,11 @@
root.nf.Graph,
root.nf.CanvasUtils,
root.nf.ErrorHandler,
+ root.nf.FlowVersion,
root.nf.Common,
root.nf.Dialog);
}
-}(this, function ($, nfClient, nfBirdseye, nfStorage, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon, nfDialog) {
+}(this, function ($, nfClient, nfBirdseye, nfStorage, nfGraph, nfCanvasUtils, nfErrorHandler, nfFlowVersion, nfCommon, nfDialog) {
'use strict';
return function (serviceProvider) {
@@ -63,13 +66,19 @@
var cancelFileBtn = $('#file-cancel-button');
var submitFileContainer = $('#submit-file-container');
+ var noParameterContext = {
+ text: 'No parameter context',
+ value: null
+ };
+
/**
* Create the group and add to the graph.
*
* @argument {string} groupName The name of the group.
* @argument {object} pt The point that the group was dropped.
+ * @argument {string} parameterContextId Option parameter context reference
*/
- var createGroup = function (groupName, pt) {
+ var createGroup = function (groupName, pt, parameterContextId) {
var processGroupEntity = {
'revision': nfClient.getRevision({
'revision': {
@@ -86,6 +95,13 @@
}
};
+ // include the parameter context if specified
+ if (nf.Common.isDefinedAndNotNull(parameterContextId)) {
+ processGroupEntity.component.parameterContext = {
+ 'id': parameterContextId
+ };
+ }
+
// create a new processor of the defined type
return $.ajax({
type: 'POST',
@@ -127,6 +143,50 @@
return filepath.replace(/^.*[\\\/]/, '').replace(/\..*/, '');
};
+ var setParameterContextOptions = function () {
+ return new $.Deferred(function (deferred) {
+ $.ajax({
+ type: 'GET',
+ url: '../nifi-api/flow/parameter-contexts',
+ dataType: 'json'
+ }).done(function (response) {
+ var selectedOption = noParameterContext;
+ var parameterContextOptions = [noParameterContext];
+ var parentParameterContext = nf.CanvasUtils.getParameterContext();
+
+ // prepare the options
+ var sortedParameterContexts = nfCommon.sortParameterContextsAlphabeticallyBasedOnAuthorization(response.parameterContexts);
+ sortedParameterContexts.forEach(function (parameterContext) {
+ if (parameterContext.permissions.canRead) {
+ var option = {
+ text: parameterContext.component.name,
+ value: parameterContext.id,
+ description: parameterContext.component.description
+ };
+
+ if (nfCommon.isDefinedAndNotNull(parentParameterContext) && parentParameterContext.id === parameterContext.id) {
+ selectedOption = option;
+ }
+
+ parameterContextOptions.push(option);
+ }
+ });
+
+ // set the combo options
+ $('#new-pg-parameter-context-combo').combo({
+ selectedOption: {
+ value: selectedOption.value
+ },
+ options: parameterContextOptions
+ });
+
+ deferred.resolve();
+ }).fail(function (xhr, status, error) {
+ deferred.reject(xhr, status, error);
+ }).fail(nfErrorHandler.handleAjaxError);
+ }).promise();
+ };
+
function GroupComponent() {
this.icon = 'icon icon-group';
@@ -170,8 +230,13 @@
selectedFilename.text('');
uploadFileField.val('');
self.fileToBeUploaded = null;
+
+ // reset the parameter context fields
+ $('#parameters-from-uploaded-flow').hide();
+ $('#new-pg-parameter-context-combo').show();
}
+
self.fileForm = $('#file-upload-form').ajaxForm({
url: '../nifi-api/process-groups/',
dataType: 'json',
@@ -235,6 +300,10 @@
processGroupDialog.modal('refreshButtons');
}
+ // update the parameter context
+ $('#parameters-from-uploaded-flow').show();
+ $('#new-pg-parameter-context-combo').hide();
+
cancelFileBtn.show();
});
@@ -354,6 +423,8 @@
// get the name of the group and clear the textfield
var groupName = $('#new-process-group-name').val();
+ var parameterContextId = $('#new-pg-parameter-context-combo').combo('getSelectedOption').value
+
// ensure the group name is specified
if (nfCommon.isBlank(groupName)) {
nfDialog.showOkDialog({
@@ -437,7 +508,7 @@
self.modal.fileForm.submit();
} else {
// create the group and resolve the deferred accordingly
- createGroup(groupName, pt).done(function (response) {
+ createGroup(groupName, pt, parameterContextId).done(function (response) {
deferred.resolve(response.component);
}).fail(function () {
deferred.reject();
@@ -449,74 +520,88 @@
}
};
- groupComponent.modal.update('setButtonModel', [{
- buttonText: 'Add',
- color: {
- base: '#728E9B',
- hover: '#004849',
- text: '#ffffff'
- },
- disabled: function () {
- if (nfCommon.isBlank($('#new-process-group-name').val())) {
- return true;
- } else {
- return false;
- }
- },
- handler: {
- click: addGroup
- }
- },
- {
- buttonText: 'Cancel',
- color: {
- base: '#E3E8EB',
- hover: '#C7D2D7',
- text: '#004849'
+ // set the parameter context options and then proceed with showing the new pg dialog
+ setParameterContextOptions().done(function () {
+ var buttonModel = [{
+ buttonText: 'Add',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ if (nfCommon.isBlank($('#new-process-group-name').val())) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ handler: {
+ click: addGroup
+ }
},
- handler: {
- click: function () {
- // reject the deferred
- deferred.reject();
-
- // close the dialog
- groupComponent.modal.hide();
+ {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ // reject the deferred
+ deferred.reject();
+
+ // close the dialog
+ groupComponent.modal.hide();
+ }
}
- }
- }]);
-
- // hide the selected file to upload title
- submitFileContainer.hide();
+ }];
+
+ if (showImportLink === true && nfCommon.canVersionFlows()) {
+ buttonModel.push({
+ buttonText: 'Import from Registry',
+ clazz: 'fa fa-cloud-download button-icon',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ nfFlowVersion.showImportFlowDialog();
+ }
+ }
+ });
+ }
- // hide file cancel button
- cancelFileBtn.hide();
+ // set the button model
+ groupComponent.modal.update('setButtonModel', buttonModel);
- // determine if import from registry link should show
- var importProcessGroupLink = $('#import-process-group-link');
+ // hide the selected file to upload title
+ submitFileContainer.hide();
- if (showImportLink === true && nfCommon.canVersionFlows()) {
- importProcessGroupLink.show();
- } else {
- importProcessGroupLink.hide();
- }
+ // hide file cancel button
+ cancelFileBtn.hide();
- // determine if Upload File button should show
- if (showUploadFileButton === true) {
- uploadFileBtn.show();
- } else {
- uploadFileBtn.hide();
- }
+ // determine if Upload File button should show
+ if (showUploadFileButton === true) {
+ uploadFileBtn.show();
+ } else {
+ uploadFileBtn.hide();
+ }
- // show the dialog
- groupComponent.modal.storePt(pt);
- groupComponent.modal.show();
+ // show the dialog
+ groupComponent.modal.storePt(pt);
+ groupComponent.modal.show();
- // set up the focus and key handlers
- $('#new-process-group-name').focus().off('keyup').on('keyup', function (e) {
- var code = e.keyCode ? e.keyCode : e.which;
- if (code === $.ui.keyCode.ENTER) {
- addGroup();
- }
+ // set up the focus and key handlers
+ $('#new-process-group-name').focus().off('keyup').on('keyup', function (e) {
+ var code = e.keyCode ? e.keyCode : e.which;
+ if (code === $.ui.keyCode.ENTER) {
+ addGroup();
+ }
+ });
});
}).promise();
}
@@ -525,4 +610,4 @@
var groupComponent = new GroupComponent();
return groupComponent;
};
-}));
\ No newline at end of file
+}));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
index 07c8b0207c..ea2991c3cf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
@@ -1791,17 +1791,19 @@
}
});
- // handle the click for the process group import
- $('#import-process-group-link').on('click', function() {
- showImportFlowVersionDialog();
- });
-
// initialize the import flow version table
initImportFlowVersionTable();
initLocalChangesTable($('#revert-local-changes-table'), $('#revert-local-changes-filter'), $('#displayed-revert-local-changes-entries'), $('#total-revert-local-changes-entries'));
initLocalChangesTable($('#show-local-changes-table'), $('#show-local-changes-filter'), $('#displayed-show-local-changes-entries'), $('#total-show-local-changes-entries'));
},
+ /**
+ * Shows the import flow dialog.
+ */
+ showImportFlowDialog: function () {
+ showImportFlowVersionDialog();
+ },
+
/**
* Shows the flow version dialog.
*
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js
index d2c9fb289c..5b17ad689b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js
@@ -93,6 +93,13 @@
*/
var saveConfiguration = function (version, groupId) {
// build the entity
+ var updateStrategy;
+ if ($('#parameter-contexts-recursive').hasClass('checkbox-unchecked')) {
+ updateStrategy = 'DIRECT_CHILDREN';
+ } else {
+ updateStrategy = 'ALL_DESCENDANTS';
+ };
+
var entity = {
'revision': nfClient.getRevision({
'revision': {
@@ -100,6 +107,7 @@
}
}),
'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
+ 'processGroupUpdateStrategy': updateStrategy,
'component': {
'id': groupId,
'name': $('#process-group-name').val(),
@@ -375,37 +383,7 @@
value: null
}];
- var authorizedParameterContexts = parameterContexts.filter(function (parameterContext) {
- return parameterContext.permissions.canRead;
- });
-
- var unauthorizedParameterContexts = parameterContexts.filter(function (parameterContext) {
- return !parameterContext.permissions.canRead;
- });
-
- //sort alphabetically
- var sortedAuthorizedParameterContexts = authorizedParameterContexts.sort(function (a, b) {
- if (a.component.name < b.component.name) {
- return -1;
- }
- if (a.component.name > b.component.name) {
- return 1;
- }
- return 0;
- });
-
- //sort alphabetically
- var sortedUnauthorizedParameterContexts = unauthorizedParameterContexts.sort(function (a, b) {
- if (a.id < b.id) {
- return -1;
- }
- if (a.id > b.id) {
- return 1;
- }
- return 0;
- });
-
- var sortedParameterContexts = sortedAuthorizedParameterContexts.concat(sortedUnauthorizedParameterContexts);
+ var sortedParameterContexts = nfCommon.sortParameterContextsAlphabeticallyBasedOnAuthorization(parameterContexts);
sortedParameterContexts.forEach(function (parameterContext) {
var option;
@@ -517,6 +495,10 @@
// initialize the parameter context combo
$('#process-group-parameter-context-combo').combo('destroy').combo(comboOptions);
+
+ // initialize parameter context recursive checkbox
+ $('#parameter-contexts-recursive').removeClass().addClass('nf-checkbox checkbox-unchecked');
+
}).fail(nfErrorHandler.handleAjaxError);
};
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index 758a19f8e7..3c6d0b1115 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -1855,6 +1855,46 @@
return true;
}
return false;
+ },
+
+ /**
+ * Sorts Parameter Contexts alphabetically for authorized items first, following unauthorized items.
+ *
+ * @param Array
+ * @returns {Array}
+ */
+ sortParameterContextsAlphabeticallyBasedOnAuthorization: function (parameterContexts) {
+ var authorizedParameterContexts = parameterContexts.filter(function (parameterContext) {
+ return parameterContext.permissions.canRead;
+ });
+
+ var unauthorizedParameterContexts = parameterContexts.filter(function (parameterContext) {
+ return !parameterContext.permissions.canRead;
+ });
+
+ // sort alphabetically
+ var sortedAuthorizedParameterContexts = authorizedParameterContexts.sort(function (a, b) {
+ if (a.component.name < b.component.name) {
+ return -1;
+ }
+ if (a.component.name > b.component.name) {
+ return 1;
+ }
+ return 0;
+ });
+
+ // sort alphabetically
+ var sortedUnauthorizedParameterContexts = unauthorizedParameterContexts.sort(function (a, b) {
+ if (a.id < b.id) {
+ return -1;
+ }
+ if (a.id > b.id) {
+ return 1;
+ }
+ return 0;
+ });
+
+ return sortedAuthorizedParameterContexts.concat(sortedUnauthorizedParameterContexts);
}
};