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 2019/08/29 18:49:22 UTC
[nifi] branch master updated: [NIFI-6282] manage parameters and
parameter contexts [NIFI-6282] when creating a parameter context inline
during PG configuration set the newly created parameter context as the
selected option [NIFI-6282] If a request to update a parameter context
fails,
then update the button model to give the user the ability to Apply or Cancel
again. [NIFI-6282] address pr review comments [NIFI-6282] remove es6 let
[NIFI-6282] update marshall parameters logic and add comments [NIFI-6282]
deterministic p [...]
This is an automated email from the ASF dual-hosted git repository.
mcgilman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/master by this push:
new f678c75 [NIFI-6282] manage parameters and parameter contexts [NIFI-6282] when creating a parameter context inline during PG configuration set the newly created parameter context as the selected option [NIFI-6282] If a request to update a parameter context fails, then update the button model to give the user the ability to Apply or Cancel again. [NIFI-6282] address pr review comments [NIFI-6282] remove es6 let [NIFI-6282] update marshall parameters logic and add comments [NIFI-62 [...]
f678c75 is described below
commit f678c75d7004656918d42496666db49350515cc2
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Thu Jul 25 23:03:27 2019 -0400
[NIFI-6282] manage parameters and parameter contexts
[NIFI-6282] when creating a parameter context inline during PG configuration set the newly created parameter context as the selected option
[NIFI-6282] If a request to update a parameter context fails, then update the button model to give the user the ability to Apply or Cancel again.
[NIFI-6282] address pr review comments
[NIFI-6282] remove es6 let
[NIFI-6282] update marshall parameters logic and add comments
[NIFI-6282] deterministic parameter usage listing, update CS status on PG PC change, expand all twisties by default, remove es6 const
[NIFI-6282] update regex and
[NIFI-6282] update parameter loading/serialization/marshalling
[NIFI-6282] use referencingComponents instead of affectedComponents
[NIFI-6282] activate Apply button for sensitive parameter set empty string change
[NIFI-6282] fix bug with PG parameters context menu enable
[NIFI-6282] only allow delete and recreate of a parameter with equivalent sensitivity
[NIFI-6282] display referencing components during parameter management as well as during the parameter context update
[NIFI-6282] display no value set in parameter table when parameter value is null
[NIFI-6282]
- Add ellipsis to referencing component names.
- Addressing issues canceling update requests.
- Addressing issues with incorrect service scope.
- Addressing issue showing the affected parameters.
---
.../api/dto/ParameterContextUpdateRequestDTO.java | 12 +-
.../nifi/web/api/dto/ProcessGroupNameDTO.java | 45 +
.../web/api/entity/AffectedComponentEntity.java | 14 +-
.../nifi/web/api/entity/CurrentUserEntity.java | 13 +
.../ParameterContextUpdateEndpointMerger.java | 4 +-
.../manager/AffectedComponentEntityMerger.java | 4 +
.../apache/nifi/web/StandardNiFiServiceFacade.java | 5 +-
.../nifi/web/api/ParameterContextResource.java | 6 +-
.../web/api/concurrent/AsyncRequestManager.java | 5 +-
.../org/apache/nifi/web/api/dto/DtoFactory.java | 75 +-
.../org/apache/nifi/web/api/dto/EntityFactory.java | 5 +-
.../web/dao/impl/StandardParameterContextDAO.java | 4 +-
.../util/ClusterReplicationComponentLifecycle.java | 6 +-
.../nifi-framework/nifi-web/nifi-web-ui/pom.xml | 39 +-
.../src/main/resources/filters/canvas.properties | 3 +-
.../src/main/webapp/WEB-INF/pages/canvas.jsp | 4 +-
.../WEB-INF/partials/canvas/canvas-header.jsp | 8 +-
.../canvas/new-parameter-context-dialog.jsp | 146 ++
.../partials/canvas/parameter-contexts-content.jsp | 32 +
.../WEB-INF/partials/canvas/policy-management.jsp | 12 +-
.../canvas/process-group-configuration.jsp | 15 +-
.../partials/canvas/variable-configuration.jsp | 4 +-
.../nifi-web-ui/src/main/webapp/css/canvas.css | 4 +-
.../nifi-web-ui/src/main/webapp/css/dialog.css | 7 +
.../webapp/css/new-parameter-context-dialog.css | 103 +
...up-configuration.css => parameter-contexts.css} | 84 +-
.../webapp/css/process-group-configuration.css | 6 +-
.../nf-ng-canvas-global-menu-controller.js | 30 +-
.../src/main/webapp/js/nf/canvas/nf-actions.js | 35 +-
.../webapp/js/nf/canvas/nf-canvas-bootstrap.js | 14 +-
.../main/webapp/js/nf/canvas/nf-canvas-utils.js | 18 +-
.../src/main/webapp/js/nf/canvas/nf-canvas.js | 26 +-
.../main/webapp/js/nf/canvas/nf-context-menu.js | 18 +-
.../webapp/js/nf/canvas/nf-parameter-contexts.js | 2305 ++++++++++++++++++++
.../webapp/js/nf/canvas/nf-policy-management.js | 107 +-
.../js/nf/canvas/nf-process-group-configuration.js | 171 +-
.../src/main/webapp/js/nf/canvas/nf-settings.js | 12 +-
.../webapp/js/nf/canvas/nf-variable-registry.js | 8 +-
.../nifi-web-ui/src/main/webapp/js/nf/nf-common.js | 19 +-
39 files changed, 3280 insertions(+), 148 deletions(-)
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ParameterContextUpdateRequestDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ParameterContextUpdateRequestDTO.java
index 76acc8d..94ab468 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ParameterContextUpdateRequestDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ParameterContextUpdateRequestDTO.java
@@ -25,7 +25,7 @@ import java.util.Set;
@XmlType(name = "parameterContextUpdateRequest")
public class ParameterContextUpdateRequestDTO extends AsynchronousRequestDTO<ParameterContextUpdateStepDTO> {
private ParameterContextDTO parameterContext;
- private Set<AffectedComponentEntity> affectedComponents;
+ private Set<AffectedComponentEntity> referencingComponents;
@ApiModelProperty(value = "The Parameter Context that is being operated on. This may not be populated until the request has successfully completed.", readOnly = true)
public ParameterContextDTO getParameterContext() {
@@ -36,12 +36,12 @@ public class ParameterContextUpdateRequestDTO extends AsynchronousRequestDTO<Par
this.parameterContext = parameterContext;
}
- @ApiModelProperty(value = "The components that are affected by the update.", readOnly = true)
- public Set<AffectedComponentEntity> getAffectedComponents() {
- return affectedComponents;
+ @ApiModelProperty(value = "The components that are referenced by the update.", readOnly = true)
+ public Set<AffectedComponentEntity> getReferencingComponents() {
+ return referencingComponents;
}
- public void setAffectedComponents(final Set<AffectedComponentEntity> affectedComponents) {
- this.affectedComponents = affectedComponents;
+ public void setReferencingComponents(final Set<AffectedComponentEntity> referencingComponents) {
+ this.referencingComponents = referencingComponents;
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupNameDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupNameDTO.java
new file mode 100644
index 0000000..dc5190d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupNameDTO.java
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name="processGroupName")
+public class ProcessGroupNameDTO {
+ private String id;
+ private String name;
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @ApiModelProperty("The ID of the Process Group")
+ public String getId() {
+ return id;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @ApiModelProperty("The name of the Process Group, or the ID of the Process Group if the user does not have the READ policy for the Process Group")
+ public String getName() {
+ return name;
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AffectedComponentEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AffectedComponentEntity.java
index efb7505..737d9c0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AffectedComponentEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AffectedComponentEntity.java
@@ -16,7 +16,9 @@
*/
package org.apache.nifi.web.api.entity;
+import io.swagger.annotations.ApiModelProperty;
import org.apache.nifi.web.api.dto.AffectedComponentDTO;
+import org.apache.nifi.web.api.dto.ProcessGroupNameDTO;
import javax.xml.bind.annotation.XmlRootElement;
@@ -24,10 +26,11 @@ import javax.xml.bind.annotation.XmlRootElement;
* A serialized representation of this class can be placed in the entity body of a response to the API.
* This particular entity holds a reference to component that references a variable.
*/
-@XmlRootElement(name = "affectComponentEntity")
+@XmlRootElement(name = "affectedComponentEntity")
public class AffectedComponentEntity extends ComponentEntity implements Permissible<AffectedComponentDTO> {
private AffectedComponentDTO component;
+ private ProcessGroupNameDTO processGroup;
/**
* @return variable referencing components that is being serialized
@@ -42,6 +45,15 @@ public class AffectedComponentEntity extends ComponentEntity implements Permissi
this.component = component;
}
+ @ApiModelProperty("The Process Group that the component belongs to")
+ public ProcessGroupNameDTO getProcessGroup() {
+ return processGroup;
+ }
+
+ public void setProcessGroup(ProcessGroupNameDTO processGroup) {
+ this.processGroup = processGroup;
+ }
+
@Override
public String toString() {
return component == null ? "AffectedComponent[No Component]" : component.toString();
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
index c157c8b..a020a48 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
@@ -38,6 +38,7 @@ public class CurrentUserEntity extends Entity {
private PermissionsDTO controllerPermissions;
private PermissionsDTO policiesPermissions;
private PermissionsDTO systemPermissions;
+ private PermissionsDTO parameterContextPermissions;
private PermissionsDTO restrictedComponentsPermissions;
private Set<ComponentRestrictionPermissionDTO> componentRestrictionPermissions;
@@ -140,6 +141,18 @@ public class CurrentUserEntity extends Entity {
}
/**
+ * @return permissions for accessing parameter contexts
+ */
+ @ApiModelProperty("Permissions for accessing parameter contexts.")
+ public PermissionsDTO getParameterContextPermissions() {
+ return parameterContextPermissions;
+ }
+
+ public void setParameterContextPermissions(PermissionsDTO parameterContextPermissions) {
+ this.parameterContextPermissions = parameterContextPermissions;
+ }
+
+ /**
* @return permissions for accessing the restricted components
*/
@ApiModelProperty("Permissions for accessing restricted components. Note: the read permission are not used and will always be false.")
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextUpdateEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextUpdateEndpointMerger.java
index 3ea4aac..2d7de0d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextUpdateEndpointMerger.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextUpdateEndpointMerger.java
@@ -66,7 +66,7 @@ public class ParameterContextUpdateEndpointMerger extends AbstractSingleEntityEn
clientUpdateRequestDto.setPercentCompleted(Math.min(clientUpdateRequestDto.getPercentCompleted(), updateRequestDto.getPercentCompleted()));
// Merge the Affected Components.
- for (final AffectedComponentEntity entity : requestEntity.getRequest().getAffectedComponents()) {
+ for (final AffectedComponentEntity entity : requestEntity.getRequest().getReferencingComponents()) {
final AffectedComponentEntity mergedAffectedComponentEntity = affectedComponentEntities.get(entity.getId());
if (mergedAffectedComponentEntity == null) {
affectedComponentEntities.put(entity.getId(), entity);
@@ -81,7 +81,7 @@ public class ParameterContextUpdateEndpointMerger extends AbstractSingleEntityEn
entityMap.forEach( (nodeId, entity) -> contextDtoMap.put(nodeId, entity.getRequest().getParameterContext()));
ParameterContextMerger.merge(clientUpdateRequestDto.getParameterContext(), contextDtoMap);
- clientUpdateRequestDto.setAffectedComponents(new HashSet<>(affectedComponentEntities.values()));
+ clientUpdateRequestDto.setReferencingComponents(new HashSet<>(affectedComponentEntities.values()));
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AffectedComponentEntityMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AffectedComponentEntityMerger.java
index 60a605d..1e66cbb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AffectedComponentEntityMerger.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AffectedComponentEntityMerger.java
@@ -95,6 +95,10 @@ public class AffectedComponentEntityMerger {
} else {
affectedComponent.setPermissions(permissions);
affectedComponent.setComponent(null);
+
+ if (affectedComponent.getProcessGroup() != null) {
+ affectedComponent.getProcessGroup().setName(affectedComponent.getProcessGroup().getId());
+ }
}
}
}
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 da5ada2..03cdc31 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
@@ -1277,7 +1277,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
final Parameter parameter = parameterOption.get();
- final boolean updated = !Objects.equals(updatedValue, parameter.getValue());
+ final boolean valueUpdated = !Objects.equals(updatedValue, parameter.getValue());
+ final boolean descriptionUpdated = parameterDto.getDescription() != null && !parameterDto.getDescription().equals(parameter.getDescriptor().getDescription());
+ final boolean updated = valueUpdated || descriptionUpdated;
if (updated) {
updatedParameters.add(parameterName);
}
@@ -4004,6 +4006,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
entity.setControllerPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getController()));
entity.setPoliciesPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getPolicies()));
entity.setSystemPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getSystem()));
+ entity.setParameterContextPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getParameterContexts()));
entity.setCanVersionFlows(CollectionUtils.isNotEmpty(flowRegistryClient.getRegistryIdentifiers()));
entity.setRestrictedComponentsPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getRestrictedComponents()));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java
index 9a0805d..63fcad6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java
@@ -802,7 +802,7 @@ public class ParameterContextResource extends ApplicationResource {
final Consumer<AsynchronousWebRequest<ParameterContextEntity, ParameterContextEntity>> updateTask = asyncRequest -> {
try {
final ParameterContextEntity updatedParameterContextEntity = updateParameterContext(asyncRequest, requestWrapper.getComponentLifecycle(), requestWrapper.getExampleUri(),
- requestWrapper.getAffectedComponents(), requestWrapper.isReplicateRequest(), requestRevision, requestWrapper.getParameterContextEntity());
+ requestWrapper.getReferencingComponents(), requestWrapper.isReplicateRequest(), requestRevision, requestWrapper.getParameterContextEntity());
asyncRequest.markStepComplete(updatedParameterContextEntity);
} catch (final ResumeFlowException rfe) {
@@ -1162,7 +1162,7 @@ public class ParameterContextResource extends ApplicationResource {
}
}
- updateRequestDto.setAffectedComponents(new HashSet<>(affectedComponents.values()));
+ updateRequestDto.setReferencingComponents(new HashSet<>(affectedComponents.values()));
// Populate the Affected Components
final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(asyncRequest.getComponentId(), NiFiUserUtils.getNiFiUser());
@@ -1211,7 +1211,7 @@ public class ParameterContextResource extends ApplicationResource {
return exampleUri;
}
- public Set<AffectedComponentEntity> getAffectedComponents() {
+ public Set<AffectedComponentEntity> getReferencingComponents() {
return affectedComponents;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/concurrent/AsyncRequestManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/concurrent/AsyncRequestManager.java
index 4ac11bf..5a6eec5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/concurrent/AsyncRequestManager.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/concurrent/AsyncRequestManager.java
@@ -144,10 +144,11 @@ public class AsyncRequestManager<R, T> implements RequestManager<R, T> {
}
if (!request.isComplete()) {
- throw new IllegalStateException("Cannot remove the request because it is not yet complete");
+ request.cancel();
}
- return requests.remove(key);
+ requests.remove(key);
+ return request;
}
@Override
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 3adc531..8e94a5b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -1943,12 +1943,17 @@ public final class DtoFactory {
final ProcessorDTO processorDto = processorEntity.getComponent();
final AffectedComponentDTO componentDto = new AffectedComponentDTO();
- componentDto.setId(processorDto.getId());
- componentDto.setName(processorDto.getName());
- componentDto.setProcessGroupId(processorDto.getParentGroupId());
- componentDto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_PROCESSOR);
- componentDto.setState(processorDto.getState());
- componentDto.setValidationErrors(processorDto.getValidationErrors());
+ if (componentDto == null) {
+ componentDto.setId(processorEntity.getId());
+ componentDto.setName(processorEntity.getId());
+ } else {
+ componentDto.setId(processorDto.getId());
+ componentDto.setName(processorDto.getName());
+ componentDto.setProcessGroupId(processorDto.getParentGroupId());
+ componentDto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_PROCESSOR);
+ componentDto.setState(processorDto.getState());
+ componentDto.setValidationErrors(processorDto.getValidationErrors());
+ }
component.setComponent(componentDto);
return component;
@@ -1969,12 +1974,18 @@ public final class DtoFactory {
final PortDTO portDto = portEntity.getComponent();
final AffectedComponentDTO componentDto = new AffectedComponentDTO();
- componentDto.setId(portDto.getId());
- componentDto.setName(portDto.getName());
- componentDto.setProcessGroupId(portDto.getParentGroupId());
- componentDto.setReferenceType(referenceType);
- componentDto.setState(portDto.getState());
- componentDto.setValidationErrors(portDto.getValidationErrors());
+ if (componentDto == null) {
+ componentDto.setId(portEntity.getId());
+ componentDto.setName(portEntity.getId());
+ } else {
+ componentDto.setId(portDto.getId());
+ componentDto.setName(portDto.getName());
+ componentDto.setProcessGroupId(portDto.getParentGroupId());
+ componentDto.setReferenceType(referenceType);
+ componentDto.setState(portDto.getState());
+ componentDto.setValidationErrors(portDto.getValidationErrors());
+ }
+
component.setComponent(componentDto);
return component;
@@ -1995,12 +2006,19 @@ public final class DtoFactory {
final ControllerServiceDTO serviceDto = serviceEntity.getComponent();
final AffectedComponentDTO componentDto = new AffectedComponentDTO();
- componentDto.setId(serviceDto.getId());
- componentDto.setName(serviceDto.getName());
- componentDto.setProcessGroupId(serviceDto.getParentGroupId());
- componentDto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_CONTROLLER_SERVICE);
- componentDto.setState(serviceDto.getState());
- componentDto.setValidationErrors(serviceDto.getValidationErrors());
+ if (serviceDto == null) {
+ componentDto.setId(serviceEntity.getId());
+ componentDto.setName(serviceEntity.getId());
+ componentDto.setProcessGroupId(serviceEntity.getParentGroupId());
+ } else {
+ componentDto.setId(serviceDto.getId());
+ componentDto.setName(serviceDto.getName());
+ componentDto.setProcessGroupId(serviceDto.getParentGroupId());
+ componentDto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_CONTROLLER_SERVICE);
+ componentDto.setState(serviceDto.getState());
+ componentDto.setValidationErrors(serviceDto.getValidationErrors());
+ }
+
component.setComponent(componentDto);
return component;
@@ -2707,7 +2725,26 @@ public final class DtoFactory {
final AffectedComponentDTO affectedComponent = createAffectedComponentDto(componentNode);
final PermissionsDTO permissions = createPermissionsDto(componentNode);
final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(componentNode.getIdentifier()));
- return entityFactory.createAffectedComponentEntity(affectedComponent, revision, permissions);
+
+ final ProcessGroupNameDTO groupNameDto = new ProcessGroupNameDTO();
+ groupNameDto.setId(componentNode.getProcessGroupIdentifier());
+ groupNameDto.setName(componentNode.getProcessGroupIdentifier());
+
+ ProcessGroup processGroup = null;
+ if (componentNode instanceof ProcessorNode) {
+ processGroup = ((ProcessorNode) componentNode).getProcessGroup();
+ } else if (componentNode instanceof ControllerServiceNode) {
+ processGroup = ((ControllerServiceNode) componentNode).getProcessGroup();
+ }
+
+ if (processGroup != null) {
+ final boolean authorized = processGroup.isAuthorized(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
+ if (authorized) {
+ groupNameDto.setName(processGroup.getName());
+ }
+ }
+
+ return entityFactory.createAffectedComponentEntity(affectedComponent, revision, permissions, groupNameDto);
}
public VariableRegistryDTO createVariableRegistryDto(final ProcessGroup processGroup, final RevisionManager revisionManager) {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
index 915ad2c..b55bfdb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
@@ -358,7 +358,8 @@ public final class EntityFactory {
return entity;
}
- public AffectedComponentEntity createAffectedComponentEntity(final AffectedComponentDTO dto, final RevisionDTO revision, final PermissionsDTO permissions) {
+ public AffectedComponentEntity createAffectedComponentEntity(final AffectedComponentDTO dto, final RevisionDTO revision, final PermissionsDTO permissions,
+ final ProcessGroupNameDTO processGroupNameDto) {
final AffectedComponentEntity entity = new AffectedComponentEntity();
entity.setRevision(revision);
if (dto != null) {
@@ -369,6 +370,8 @@ public final class EntityFactory {
entity.setComponent(dto);
}
}
+
+ entity.setProcessGroup(processGroupNameDto);
return entity;
}
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/StandardParameterContextDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
index 9ad06a3..bb5ec9a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
@@ -81,10 +81,10 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
final boolean deletion = parameterDto.getDescription() == null && parameterDto.getSensitive() == null && parameterDto.getValue() == null;
if (deletion) {
- parameterMap.put(parameterDto.getName(), null);
+ parameterMap.put(parameterDto.getName().trim(), null);
} else {
final Parameter parameter = createParameter(parameterDto);
- parameterMap.put(parameterDto.getName(), parameter);
+ parameterMap.put(parameterDto.getName().trim(), parameter);
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ClusterReplicationComponentLifecycle.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ClusterReplicationComponentLifecycle.java
index 23825e7..934e927 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ClusterReplicationComponentLifecycle.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ClusterReplicationComponentLifecycle.java
@@ -406,7 +406,11 @@ public class ClusterReplicationComponentLifecycle implements ComponentLifecycle
boolean allReachedDesiredState = true;
for (final ControllerServiceEntity serviceEntity : serviceEntities) {
final ControllerServiceDTO serviceDto = serviceEntity.getComponent();
- if (!affectedServices.containsKey(serviceDto.getId())) {
+ if (serviceDto == null) {
+ continue;
+ }
+
+ if (!serviceIds.contains(serviceDto.getId())) {
continue;
}
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 ef283de..3e27542 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
@@ -394,6 +394,40 @@
</build>
<profiles>
<profile>
+ <id>development-mode</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <!--
+ Speed up build time by excluding node, npm, and any node_modules from `mvn clean` since the front-end-maven plugin uses these
+ directories as cache.
+ -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>3.0.0</version>
+ <configuration>
+ <excludeDefaultDirectories>true</excludeDefaultDirectories>
+ <filesets>
+ <fileset>
+ <directory>${project.build.directory}</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>frontend-working-directory/node/**/*</exclude>
+ <exclude>frontend-working-directory/node_modules/**/*</exclude>
+ </excludes>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
<id>minify-and-compress</id>
<activation>
<activeByDefault>true</activeByDefault>
@@ -486,6 +520,7 @@
<include>${staging.dir}/js/nf/nf-status-history.js</include>
<include>${staging.dir}/js/nf/canvas/nf-queue-listing.js</include>
<include>${staging.dir}/js/nf/canvas/nf-policy-management.js</include>
+ <include>${staging.dir}/js/nf/canvas/nf-parameter-contexts.js</include>
<include>${staging.dir}/js/nf/canvas/nf-actions.js</include>
<include>${staging.dir}/js/nf/canvas/nf-canvas.js</include>
<include>${staging.dir}/js/nf/canvas/nf-canvas-error-handler.js</include>
@@ -688,12 +723,14 @@
<include>${staging.dir}/css/new-port-dialog.css</include>
<include>${staging.dir}/css/new-controller-service-dialog.css</include>
<include>${staging.dir}/css/new-reporting-task-dialog.css</include>
+ <include>${staging.dir}/css/new-parameter-context-dialog.css</include>
<include>${staging.dir}/css/graph.css</include>
<include>${staging.dir}/css/header.css</include>
<include>${staging.dir}/css/main.css</include>
<include>${staging.dir}/css/banner.css</include>
<include>${staging.dir}/css/navigation.css</include>
<include>${staging.dir}/css/flow-status.css</include>
+ <include>${staging.dir}/css/parameter-contexts.css</include>
<include>${staging.dir}/css/settings.css</include>
<include>${staging.dir}/css/about.css</include>
<include>${staging.dir}/css/status-history.css</include>
@@ -922,7 +959,7 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<scope>provided</scope>
- </dependency>
+ </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
index 40a3b1f..5cc9f3f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
@@ -62,6 +62,7 @@ nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-ng-bridge.js?
<script type="text/javascript" src="js/nf/nf-status-history.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-queue-listing.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-policy-management.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/canvas/nf-parameter-contexts.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-actions.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-canvas.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-canvas-error-handler.js?${project.version}"></script>\n\
@@ -91,4 +92,4 @@ nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-ng-bridge.js?
<script type="text/javascript" src="js/nf/nf-ng-app-config.js?${project.version}"></script>\n\
<script type="text/javascript" src="js/nf/canvas/nf-canvas-bootstrap.js?${project.version}"></script>
nf.canvas.style.tags=<link rel="stylesheet" href="css/canvas.css?${project.version}" type="text/css" />\n\
-<link rel="stylesheet" href="css/common-ui.css?${project.version}" type="text/css" />
\ No newline at end of file
+<link rel="stylesheet" href="css/common-ui.css?${project.version}" type="text/css" />
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index cee2c5e..90e5888 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -110,6 +110,7 @@
<jsp:include page="/WEB-INF/partials/canvas/enable-controller-service-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/new-controller-service-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/new-reporting-task-dialog.jsp"/>
+ <jsp:include page="/WEB-INF/partials/canvas/new-parameter-context-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/new-processor-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/new-port-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/new-process-group-dialog.jsp"/>
@@ -133,6 +134,7 @@
</div>
<jsp:include page="/WEB-INF/partials/canvas/navigation.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/settings-content.jsp"/>
+ <jsp:include page="/WEB-INF/partials/canvas/parameter-contexts-content.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/shell.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/controller-service-configuration.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/reporting-task-configuration.jsp"/>
@@ -160,4 +162,4 @@
<div id="context-menu" class="context-menu unselectable"></div>
<span id="nifi-content-viewer-url" class="hidden"></span>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
index a242c53..928e8f5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
@@ -132,6 +132,12 @@
<i class="fa fa-wrench"></i>Controller Settings
</a>
</md-menu-item>
+ <md-menu-item layout-align="space-around center">
+ <a id="parameter-contexts-link"
+ ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.parameterContexts.shell.launch();">
+ <i class="fa"></i>Parameter Contexts
+ </a>
+ </md-menu-item>
<md-menu-item ng-if="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.cluster.visible();"
layout-align="space-around center">
<a id="cluster-link"
@@ -185,4 +191,4 @@
</md-menu>
</div>
</div>
-</md-toolbar>
\ No newline at end of file
+</md-toolbar>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-parameter-context-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-parameter-context-dialog.jsp
new file mode 100644
index 0000000..bc264bd
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-parameter-context-dialog.jsp
@@ -0,0 +1,146 @@
+<%--
+ 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.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="parameter-context-dialog" layout="column" class="hidden">
+ <div id="parameter-context-status-bar"></div>
+ <div class="parameter-context-tab-container dialog-content">
+ <div id="parameter-context-tabs" class="tab-container"></div>
+ <div id="parameter-context-tabs-content">
+ <div id="parameter-context-standard-settings-tab-content" class="configuration-tab">
+ <div class="settings-left">
+ <div class="setting">
+ <div class="setting-name">Name</div>
+ <div id="parameter-context-name-container" class="setting-field">
+ <input type="text" id="parameter-context-name" name="parameter-context-name"/>
+ </div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">Description</div>
+ <div class="setting-field parameter-context-description-container">
+ <textarea id="parameter-context-description-field" rows="6"></textarea>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+ <div class="spacer"> </div>
+ <div class="settings-right">
+ </div>
+ </div>
+ <div id="parameter-context-parameters-tab-content" class="configuration-tab">
+ <div class="settings-left">
+ <div>
+ <div id="add-parameter"><button class="button fa fa-plus"></button></div>
+ <div class="clear"></div>
+ </div>
+ <div id="parameter-table"></div>
+ <div id="parameter-context-update-status" class="hidden">
+ <div class="setting">
+ <div class="setting-name">
+ Steps to update parameters
+ </div>
+ <div class="setting-field">
+ <ol id="parameter-context-update-steps"></ol>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="spacer"> </div>
+ <div id="parameter-context-usage" class="settings-right">
+ <div class="setting">
+ <div class="setting-name">
+ Parameter
+ </div>
+ <div class="setting-field">
+ <div id="parameter-referencing-components-context"></div>
+ </div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">
+ Referencing Components
+ <div class="fa fa-question-circle" alt="Info" title="Components referencing this parameter grouped by process group."></div>
+ </div>
+ <div id="parameter-referencing-components-container" class="setting-field">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div id="parameter-dialog" class="dialog cancellable hidden">
+ <div class="dialog-content">
+ <div class="setting">
+ <div class="setting-name">Name</div>
+ <div class="setting-field new-parameter-name-container">
+ <input id="parameter-name" type="text"/>
+ </div>
+ <div class="clear"></div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">Value</div>
+ <div class="setting-field new-parameter-value-container">
+ <textarea id="parameter-value-field"></textarea>
+ <div class="string-check-container">
+ <div id="parameter-set-empty-string-field" class="nf-checkbox string-check checkbox-unchecked"></div>
+ <span class="string-check-label nf-checkbox-label">Set empty string</span>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+ <div class="setting">
+ <div class="setting-field new-parameter-sensitive-value-container">
+ <div class="setting-name">Sensitive value</div>
+ <input id="parameter-sensitive-radio-button" type="radio" name="sensitive" value="sensitive"/> Yes
+ <input id="parameter-not-sensitive-radio-button" type="radio" name="sensitive" value="plain" checked="checked" style="margin-left: 20px;"/> No
+ </div>
+ <div class="clear"></div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">Description</div>
+ <div class="setting-field new-parameter-description-container">
+ <textarea id="parameter-description-field" rows="6"></textarea>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+</div>
+<div id="referencing-components-template" class="referencing-components-template hidden clear">
+ <div class="setting">
+ <div class="setting-name">
+ Referencing Processors
+ </div>
+ <div class="setting-field">
+ <ul class="parameter-context-referencing-processors"></ul>
+ </div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">
+ Referencing Controller Services
+ </div>
+ <div class="setting-field">
+ <ul class="parameter-context-referencing-controller-services"></ul>
+ </div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">
+ Unauthorized referencing components
+ </div>
+ <div class="setting-field">
+ <ul class="parameter-context-referencing-unauthorized-components"></ul>
+ </div>
+ </div>
+</div>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/parameter-contexts-content.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/parameter-contexts-content.jsp
new file mode 100644
index 0000000..f177871
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/parameter-contexts-content.jsp
@@ -0,0 +1,32 @@
+<%--
+ 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.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="parameter-contexts" class="hidden">
+ <button id="new-parameter-context" class="add-button fa fa-plus" title="Create a new parameter context" style="display: block;"></button>
+ <div id="parameter-contexts-header-text" class="parameter-contexts-header-text">NiFi Parameter Contexts</div>
+ <div class="parameter-contexts-container">
+ <div id="parameter-contexts-table" class="parameter-contexts-table"></div>
+ </div>
+ <div id="parameter-contexts-refresh-container">
+ <button id="parameter-contexts-refresh-button" class="refresh-button pointer fa fa-refresh" title="Refresh"></button>
+ <div id="parameter-contexts-last-refreshed-container" class="last-refreshed-container">
+ Last updated: <span id="parameter-contexts-last-refreshed" class="value-color"></span>
+ </div>
+ <div id="parameter-contexts-loading-container" class="loading-container"></div>
+ <div class="clear"></div>
+ </div>
+</div>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
index 946c53d..024c7ba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
@@ -74,6 +74,16 @@
</div>
<div class="clear"></div>
</div>
+ <div id="policy-selected-parameter-context-container" class="hidden policy-selected-component-container">
+ <div class="policy-selected-component-type-icon">
+ <i class="icon icon-drop"></i>
+ </div>
+ <div class="policy-selected-component-details-container">
+ <div class="policy-selected-component-name"></div>
+ <div class="policy-selected-component-type">Parameter Context</div>
+ </div>
+ <div class="clear"></div>
+ </div>
<div id="selected-policy-component-id" class="hidden"></div>
<div id="selected-policy-component-type" class="hidden"></div>
<div id="component-policy-target"></div>
@@ -94,4 +104,4 @@
<div id="restriction-message" class="hidden">Only listing restriction specific users. Users with permission "regardless of restrictions" not shown but are also allowed.</div>
<div class="clear"></div>
</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 6fd904d..b21ba0c 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
@@ -33,7 +33,16 @@
<input type="text" id="process-group-name" class="setting-input"/>
</div>
<div class="read-only setting-field">
- <span id="read-only-process-group-name"></span>
+ <span id="read-only-process-group-name" class="unset"></span>
+ </div>
+ </div>
+ <div class="setting">
+ <div class="setting-name">Process group parameter context</div>
+ <div class="editable setting-field">
+ <div id="process-group-parameter-context-combo"></div>
+ </div>
+ <div class="read-only setting-field">
+ <span id="read-only-process-group-parameter-context" class="unset">Unauthorized</span>
</div>
</div>
<div class="setting">
@@ -42,7 +51,7 @@
<textarea id="process-group-comments" class="setting-input"></textarea>
</div>
<div class="read-only setting-field">
- <span id="read-only-process-group-comments"></span>
+ <span id="read-only-process-group-comments" class="unset"></span>
</div>
</div>
<div class="editable settings-buttons">
@@ -65,4 +74,4 @@
<div id="flow-cs-availability" class="hidden">Listed services are available to all descendant Processors and services of this Process Group.</div>
<div class="clear"></div>
</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/variable-configuration.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
index 4bbd9c8..054de83 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
@@ -48,7 +48,7 @@
Variables
</div>
<div class="setting-field">
- <div id="affected-components-context"></div>
+ <div id="variable-affected-components-context"></div>
</div>
</div>
<div class="setting">
@@ -91,4 +91,4 @@
</div>
</div>
</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/css/canvas.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
index 7a9c1f6..8159795 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
@@ -34,16 +34,18 @@
@import url(new-port-dialog.css);
@import url(new-controller-service-dialog.css);
@import url(new-reporting-task-dialog.css);
+@import url(new-parameter-context-dialog.css);
@import url(graph.css);
@import url(header.css);
@import url(main.css);
@import url(banner.css);
@import url(navigation.css);
@import url(flow-status.css);
+@import url(parameter-contexts.css);
@import url(settings.css);
@import url(about.css);
@import url(message-pane.css);
@import url(common-ui.css);
@import url(status-history.css);
@import url(../fonts/flowfont/flowfont.css);
-@import url(../assets/font-awesome/css/font-awesome.css);
\ No newline at end of file
+@import url(../assets/font-awesome/css/font-awesome.css);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
index 82ffc38..eb71a9e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
@@ -377,3 +377,10 @@ div.variable-step {
width: 300px;
margin-bottom: 2px;
}
+
+div.parameter-context-step {
+ width: 16px;
+ height: 16px;
+ background-color: transparent;
+ float: right;
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-parameter-context-dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-parameter-context-dialog.css
new file mode 100644
index 0000000..2ccb910
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-parameter-context-dialog.css
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+/*
+ Parameter context dialog
+ */
+
+#parameter-context-dialog {
+ width: 850px;
+ height: 575px;
+}
+
+#parameter-context-dialog div.settings-left {
+ float: left;
+ width: 65%;
+}
+
+#parameter-context-dialog div.settings-right {
+ float: left;
+ width: 33%;
+ height: 100%;
+ position: absolute;
+ left: calc(65% - -15px);
+}
+
+#parameter-context-standard-settings-tab-content,
+#parameter-context-parameters-tab-content {
+ bottom: 10px;
+}
+
+#parameter-table {
+ height: 370px;
+}
+
+#add-parameter {
+ float: right;
+ margin-bottom: 4px;
+ font-size: 16px;
+ text-transform: uppercase;
+}
+
+#parameter-context-update-steps li {
+ width: 300px;
+ margin-bottom: 2px;
+}
+
+#parameter-value-field {
+ height: 54px;
+}
+
+#parameter-description-field {
+ height: 85px;
+}
+
+#parameter-context-description-field {
+ height: 85px;
+}
+
+#parameter-referencing-components-container {
+ position: absolute;
+ bottom: 10px;
+ top: 75px;
+ width: calc(100% - 5px);
+ overflow: auto;
+ border: 0 solid #CCCCCC;
+ overflow: auto;
+ padding: 2px;
+}
+
+.referencing-components-template {
+ position: relative;
+ left: 15px;
+ width: calc(100% - 15px);
+}
+
+/*
+ Parameter creation/configuration dialog
+ */
+
+#parameter-dialog {
+ width: 470px;
+ height: 470px;
+}
+
+span.parameter-context-referencing-component-name {
+ margin-left: 5px;
+ margin-right: 5px;
+ max-width: calc(100% - 10px);
+}
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/parameter-contexts.css
similarity index 57%
copy from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css
copy to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/parameter-contexts.css
index dcafd5d..ef512e4 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/parameter-contexts.css
@@ -15,8 +15,7 @@
* limitations under the License.
*/
-#process-group-configuration {
- display: none;
+#parameter-contexts {
position: absolute;
top: 0px;
bottom: 0px;
@@ -25,34 +24,61 @@
overflow: auto;
}
-#add-process-group-configuration-controller-service {
- float: right;
+#new-parameter-context {
+ position: absolute;
+ right: 0;
+ top: 26px;
}
-/* settings tabs */
-
-#process-group-configuration-tabs {
- float: left;
+div.parameter-contexts-header-text {
+ height: 28px;
+ font-size: 18px;
+ font-weight: bold;
+ color: #728E9B;
+ margin-bottom: 30px;
}
-#process-group-configuration-tabs-content {
- top: 53px;
+div.parameter-contexts-container {
+ padding: 0;
+ position: absolute;
+ top: 58px;
bottom: 52px;
+ left: 0px;
+ right: 0px;
}
-#process-group-refresh-container {
+#parameter-contexts-refresh-container {
position: absolute;
bottom: 20px;
- left: 0px;
right: 0px;
+ left: 0px;
height: 32px;
}
-#process-group-configuration-refresh-button {
+div.parameter-contexts-table {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ bottom: 20px;
+ right: 0px;
+ min-height: 150px;
+}
+
+#parameter-contexts-table div.slick-viewport {
+ overflow-x: hidden !important;
+}
+
+span.sorted {
+ text-decoration: underline;
+}
+
+div.parameter-contexts-refresh-button {
+ height: 24px;
+ width: 26px;
float: left;
}
-#process-group-configuration-loading-container {
+#parameter-contexts-loading-container {
float: left;
width: 16px;
height: 16px;
@@ -61,34 +87,6 @@
margin-left: 3px;
}
-#process-group-configuration-last-refreshed {
- color: #775351;
+#parameter-contexts-last-refreshed {
font-weight: 500;
}
-
-#flow-cs-availability {
- float: right;
- margin-top: 8px;
- color: #775351;
- font-family: Roboto;
- font-size: 13px;
-}
-
-/* general */
-
-#general-process-group-configuration input, #general-process-group-configuration textarea {
- width: 350px;
- vertical-align: middle;
-}
-
-#process-group-comments {
- height: 100px;
-}
-
-#read-only-process-group-comments {
- white-space: pre-wrap;
-}
-
-#process-group-controller-services-tab-content {
- top: 32px;
-}
\ 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/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 dcafd5d..ac968b4 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
@@ -81,6 +81,10 @@
vertical-align: middle;
}
+#process-group-parameter-context-combo {
+ width: 328px;
+}
+
#process-group-comments {
height: 100px;
}
@@ -91,4 +95,4 @@
#process-group-controller-services-tab-content {
top: 32px;
-}
\ 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/controllers/nf-ng-canvas-global-menu-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
index 28d818e..88dc30d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
@@ -23,12 +23,13 @@
'nf.Common',
'nf.QueueListing',
'nf.Shell',
+ 'nf.ParameterContexts',
'nf.PolicyManagement',
'nf.ClusterSummary',
'nf.ErrorHandler',
'nf.Settings',
'nf.CanvasUtils'],
- function ($, nfCommon, nfQueueListing, nfShell, nfPolicyManagement, nfClusterSummary, nfErrorHandler, nfSettings, nfCanvasUtils) {
+ function ($, nfCommon, nfQueueListing, nfShell, nfParameterContexts, nfPolicyManagement, nfClusterSummary, nfErrorHandler, nfSettings, nfCanvasUtils) {
return (nf.ng.Canvas.GlobalMenuCtrl = factory($, nfCommon, nfQueueListing, nfShell, nfPolicyManagement, nfClusterSummary, nfErrorHandler, nfSettings, nfCanvasUtils));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
@@ -37,6 +38,7 @@
require('nf.Common'),
require('nf.QueueListing'),
require('nf.Shell'),
+ require('nf.ParameterContexts'),
require('nf.PolicyManagement'),
require('nf.ClusterSummary'),
require('nf.ErrorHandler'),
@@ -47,13 +49,14 @@
root.nf.Common,
root.nf.QueueListing,
root.nf.Shell,
+ root.nf.ParameterContexts,
root.nf.PolicyManagement,
root.nf.ClusterSummary,
root.nf.ErrorHandler,
root.nf.Settings,
root.nf.CanvasUtils);
}
-}(this, function ($, nfCommon, nfQueueListing, nfShell, nfPolicyManagement, nfClusterSummary, nfErrorHandler, nfSettings, nfCanvasUtils) {
+}(this, function ($, nfCommon, nfQueueListing, nfShell, nfParameterContexts, nfPolicyManagement, nfClusterSummary, nfErrorHandler, nfSettings, nfCanvasUtils) {
'use strict';
return function (serviceProvider) {
@@ -168,6 +171,25 @@
};
/**
+ * The parameter contexts menu item controller.
+ */
+ this.parameterContexts = {
+
+ /**
+ * The parameter contexts menu item's shell controller.
+ */
+ shell: {
+
+ /**
+ * Launch the parameter contexts shell.
+ */
+ launch: function () {
+ nfParameterContexts.showParameterContexts();
+ }
+ }
+ };
+
+ /**
* The cluster menu item controller.
*/
this.cluster = {
@@ -432,9 +454,9 @@
init: function () {
this.about.init();
}
- }
+ };
var globalMenuCtrl = new GlobalMenuCtrl();
return globalMenuCtrl;
};
-}));
\ 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-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
index 0aeaf43..3d0c9d0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
@@ -28,6 +28,7 @@
'nf.Client',
'nf.ErrorHandler',
'nf.Clipboard',
+ 'nf.ParameterContexts',
'nf.Snippet',
'nf.GoTo',
'nf.ng.Bridge',
@@ -57,8 +58,8 @@
'nf.ComponentVersion',
'nf.QueueListing',
'nf.StatusHistory'],
- function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfStorage, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionD [...]
- return (nf.Actions = factory($, d3, nfCanvasUtils, nfCommon, nfDialog, nfStorage, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfi [...]
+ function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfStorage, nfClient, nfErrorHandler, nfClipboard, nfParameterContexts, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfigu [...]
+ return (nf.Actions = factory($, d3, nfCanvasUtils, nfCommon, nfDialog, nfStorage, nfClient, nfErrorHandler, nfClipboard, nfParameterContexts, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetai [...]
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.Actions =
@@ -71,6 +72,7 @@
require('nf.Client'),
require('nf.ErrorHandler'),
require('nf.Clipboard'),
+ require('nf.ParameterContexts'),
require('nf.Snippet'),
require('nf.GoTo'),
require('nf.ng.Bridge'),
@@ -110,6 +112,7 @@
root.nf.Client,
root.nf.ErrorHandler,
root.nf.Clipboard,
+ root.nf.ParameterContexts,
root.nf.Snippet,
root.nf.GoTo,
root.nf.ng.Bridge,
@@ -140,13 +143,14 @@
root.nf.QueueListing,
root.nf.StatusHistory);
}
-}(this, function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfStorage, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetai [...]
+}(this, function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfStorage, nfClient, nfErrorHandler, nfClipboard, nfParameterContexts, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfigurati [...]
'use strict';
var config = {
urls: {
api: '../nifi-api',
- controller: '../nifi-api/controller'
+ controller: '../nifi-api/controller',
+ parameterContexts: '../nifi-api/parameter-contexts'
}
};
@@ -1402,6 +1406,27 @@
},
/**
+ * Opens the parameter context for the specified selection of the current group if the selection is empty.
+ *
+ * @param {selection} selection
+ */
+ openParameterContext: function (selection) {
+ var pcid;
+ if (selection.empty()) {
+ pcid = nfCanvasUtils.getParameterContextId();
+ } else if (selection.size() === 1) {
+ if (nfCanvasUtils.isProcessGroup(selection)) {
+ var pg = selection.datum();
+ pcid = pg.component.parameterContext.id;
+ }
+ }
+
+ if (nfCommon.isDefinedAndNotNull(pcid)) {
+ nfParameterContexts.showParameterContext(pcid);
+ }
+ },
+
+ /**
* Views the state for the specified processor.
*
* @param {selection} selection
@@ -1944,4 +1969,4 @@
};
return nfActions;
-}));
\ 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-canvas-bootstrap.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js
index ac0bb47..485d290 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js
@@ -32,6 +32,7 @@
'nf.ContextMenu',
'nf.QuickSelect',
'nf.Shell',
+ 'nf.ParameterContexts',
'nf.Settings',
'nf.Snippet',
'nf.Actions',
@@ -82,8 +83,8 @@
'nf.ng.Canvas.OperateCtrl',
'nf.ng.BreadcrumbsDirective',
'nf.ng.DraggableDirective'],
- function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfContro [...]
- return factory($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, [...]
+ function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupCo [...]
+ return factory($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProce [...]
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = factory(require('jquery'),
@@ -99,6 +100,7 @@
require('nf.ContextMenu'),
require('nf.QuickSelect'),
require('nf.Shell'),
+ require('nf.ParameterContexts'),
require('nf.Settings'),
require('nf.Actions'),
require('nf.Snippet'),
@@ -163,6 +165,7 @@
root.nf.ContextMenu,
root.nf.QuickSelect,
root.nf.Shell,
+ root.nf.ParameterContexts,
root.nf.Settings,
root.nf.Actions,
root.nf.Snippet,
@@ -214,7 +217,7 @@
root.nf.ng.BreadcrumbsDirective,
root.nf.ng.DraggableDirective);
}
-}(this, function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfController [...]
+}(this, function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfig [...]
var config = {
urls: {
@@ -343,6 +346,7 @@
nfShell.init(nfContextMenu);
nfNgBridge.injector.get('headerCtrl').init();
nfSettings.init();
+ nfParameterContexts.init();
nfActions.init();
nfQueueListing.init();
nfVariableRegistry.init();
@@ -369,8 +373,8 @@
supportsStatusBar : true,
nfActions : nfActions
});
- // initialize the PG config and invert control of the controllerServices
- nfProcessGroupConfiguration.init(nfControllerServices);
+ // initialize the PG config and invert control of the controllerServices and parameter contexts
+ nfProcessGroupConfiguration.init(nfControllerServices, nfParameterContexts);
nfRemoteProcessGroupConfiguration.init();
nfRemoteProcessGroupPorts.init();
nfPortConfiguration.init();
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
index 34ac67f..5241263 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
@@ -2089,6 +2089,22 @@
},
/**
+ * Set the parameter context id.
+ *
+ * @argument {string} pcid The parameter context id
+ */
+ setParameterContextId: function (pcid) {
+ return nfCanvas.setParameterContextId(pcid);
+ },
+
+ /**
+ * Get the parameter context id.
+ */
+ getParameterContextId: function () {
+ return nfCanvas.getParameterContextId();
+ },
+
+ /**
* Get the group name.
*/
getGroupName: function () {
@@ -2199,4 +2215,4 @@
}
};
return nfCanvasUtils;
-}));
\ 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-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
index c06da21..67b7a54 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
@@ -86,6 +86,7 @@
var polling = false;
var allowPageRefresh = false;
var groupId = 'root';
+ var parameterContextId;
var groupName = null;
var permissions = null;
var parentGroupId = null;
@@ -147,8 +148,9 @@
// get the controller and its contents
var processGroupFlow = flowResponse.processGroupFlow;
- // set the group details
+ // set the group and parameter context details
nfCanvas.setGroupId(processGroupFlow.id);
+ nfCanvas.setParameterContextId(processGroupFlow.parameterContextId);
// get the current group name from the breadcrumb
var breadcrumb = processGroupFlow.breadcrumb;
@@ -218,15 +220,17 @@
var changeProcessGroup = function (processGroupId, options) {
// capture the current group id to reset to in case of failure
var currentProcessGroup = nfCanvas.getGroupId();
+ var currentParameterContext = nfCanvas.getParameterContextId();
// update process group id and attempt to reload
nfCanvas.setGroupId(processGroupId);
var processGroupXhr = reloadProcessGroup(options);
- // if the request fails, ensure the process group id is reset
+ // if the request fails, ensure the process group id and parameter context id is reset
processGroupXhr
.fail(function (xhr, status, error) {
nfCanvas.setGroupId(currentProcessGroup);
+ nfCanvas.setParameterContextId(currentParameterContext);
});
return processGroupXhr;
@@ -904,6 +908,22 @@
},
/**
+ * Set the parameter context id.
+ *
+ * @argument {string} pcid The parameter context id
+ */
+ setParameterContextId: function (pcid) {
+ parameterContextId = pcid;
+ },
+
+ /**
+ * Get the parameter context id.
+ */
+ getParameterContextId: function () {
+ return parameterContextId;
+ },
+
+ /**
* Set the group id.
*
* @argument {string} gi The group id
@@ -1369,4 +1389,4 @@
};
return nfCanvas;
-}));
\ 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-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
index 7420758..9cbd904 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
@@ -82,6 +82,21 @@
};
/**
+ * Determines whether the component in the specified selection has a parameter context.
+ *
+ * @param {selection} selection The selection of currently selected components
+ */
+ var hasParameterContext = function (selection) {
+ if (selection.empty()) {
+ return !nfCommon.isUndefinedOrNull(nfCanvasUtils.getParameterContextId());
+ } else if (nfCanvasUtils.isProcessGroup(selection)) {
+ var pg = selection.datum();
+ return !nfCommon.isUndefinedOrNull(pg.component.parameterContext.id);
+ }
+ return false;
+ };
+
+ /**
* Determines whether the component in the specified selection has configuration details.
*
* @param {selection} selection The selection of currently selected components
@@ -832,6 +847,7 @@
{separator: true},
{id: 'show-configuration-menu-item', condition: isConfigurable, menuItem: {clazz: 'fa fa-gear', text: 'Configure', action: 'showConfiguration'}},
{id: 'show-details-menu-item', condition: hasDetails, menuItem: {clazz: 'fa fa-gear', text: 'View configuration', action: 'showDetails'}},
+ {id: 'parameters-menu-item', condition: hasParameterContext, menuItem: {clazz: 'fa', text: 'Parameters', action: 'openParameterContext'}},
{id: 'variable-registry-menu-item', condition: hasVariables, menuItem: {clazz: 'fa', text: 'Variables', action: 'openVariableRegistry'}},
{separator: true},
{id: 'version-menu-item', groupMenuItem: {clazz: 'fa', text: 'Version'}, menuItems: [
@@ -1116,4 +1132,4 @@
};
return nfContextMenu;
-}));
\ 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-parameter-contexts.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
new file mode 100644
index 0000000..336d7de
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
@@ -0,0 +1,2305 @@
+/*
+ * 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.
+ */
+
+/* global define, module, require, exports */
+
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(['jquery',
+ 'Slick',
+ 'd3',
+ 'nf.Client',
+ 'nf.Dialog',
+ 'nf.Storage',
+ 'nf.Common',
+ 'nf.CanvasUtils',
+ 'nf.ng.Bridge',
+ 'nf.ErrorHandler',
+ 'nf.FilteredDialogCommon',
+ 'nf.Shell',
+ 'nf.ComponentState',
+ 'nf.ComponentVersion',
+ 'nf.PolicyManagement',
+ 'nf.Processor',
+ 'nf.ProcessGroup',
+ 'nf.ProcessGroupConfiguration'],
+ function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfNgBridge, nfErrorHandler, nfFilteredDialogCommon, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfProcessor, nfProcessGroup, nfProcessGroupConfiguration) {
+ return (nf.ParameterContexts = factory($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfNgBridge, nfErrorHandler, nfFilteredDialogCommon, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfProcessor, nfProcessGroup, nfProcessGroupConfiguration));
+ });
+ } else if (typeof exports === 'object' && typeof module === 'object') {
+ module.exports = (nf.ParameterContexts =
+ factory(require('jquery'),
+ require('Slick'),
+ require('d3'),
+ require('nf.Client'),
+ require('nf.Dialog'),
+ require('nf.Storage'),
+ require('nf.Common'),
+ require('nf.CanvasUtils'),
+ require('nf.ng.Bridge'),
+ require('nf.ErrorHandler'),
+ require('nf.FilteredDialogCommon'),
+ require('nf.Shell'),
+ require('nf.ComponentState'),
+ require('nf.ComponentVersion'),
+ require('nf.PolicyManagement'),
+ require('nf.Processor'),
+ require('nf.ProcessGroup'),
+ require('nf.ProcessGroupConfiguration')));
+ } else {
+ nf.ParameterContexts = factory(root.$,
+ root.Slick,
+ root.d3,
+ root.nf.Client,
+ root.nf.Dialog,
+ root.nf.Storage,
+ root.nf.Common,
+ root.nf.CanvasUtils,
+ root.nf.ng.Bridge,
+ root.nf.ErrorHandler,
+ root.nf.FilteredDialogCommon,
+ root.nf.Shell,
+ root.nf.ComponentState,
+ root.nf.ComponentVersion,
+ root.nf.PolicyManagement,
+ root.nf.Processor,
+ root.nf.ProcessGroup,
+ root.nf.ProcessGroupConfiguration);
+ }
+}(this, function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfNgBridge, nfErrorHandler, nfFilteredDialogCommon, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfProcessor, nfProcessGroup, nfProcessGroupConfiguration) {
+ 'use strict';
+
+ var config = {
+ urls: {
+ parameterContexts: '../nifi-api/parameter-contexts'
+ }
+ };
+
+ var parameterContextsGridOptions = {
+ forceFitColumns: true,
+ enableTextSelectionOnCells: true,
+ enableCellNavigation: true,
+ enableColumnReorder: false,
+ autoEdit: false,
+ multiSelect: false,
+ rowHeight: 24
+ };
+
+ var parametersGridOptions = {
+ forceFitColumns: true,
+ enableTextSelectionOnCells: true,
+ enableCellNavigation: true,
+ enableColumnReorder: false,
+ editable: false,
+ enableAddRow: false,
+ autoEdit: false,
+ multiSelect: false,
+ rowHeight: 24
+ };
+
+ /**
+ * Formatter for the name column.
+ *
+ * @param {type} row
+ * @param {type} cell
+ * @param {type} value
+ * @param {type} columnDef
+ * @param {type} dataContext
+ * @returns {String}
+ */
+ var nameFormatter = function (row, cell, value, columnDef, dataContext) {
+ if (!dataContext.permissions.canRead) {
+ return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
+ }
+
+ return nfCommon.escapeHtml(dataContext.component.name);
+ };
+
+ /**
+ * Sorts the specified data using the specified sort details.
+ *
+ * @param {object} sortDetails
+ * @param {object} data
+ */
+ var sort = function (sortDetails, data) {
+ // defines a function for sorting
+ var comparer = function (a, b) {
+ if (a.permissions.canRead && b.permissions.canRead) {
+ var aString = nfCommon.isDefinedAndNotNull(a.component[sortDetails.columnId]) ? a.component[sortDetails.columnId] : '';
+ var bString = nfCommon.isDefinedAndNotNull(b.component[sortDetails.columnId]) ? b.component[sortDetails.columnId] : '';
+ return aString === bString ? 0 : aString > bString ? 1 : -1;
+ } else {
+ if (!a.permissions.canRead && !b.permissions.canRead) {
+ return 0;
+ }
+ if (a.permissions.canRead) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ };
+
+ // perform the sort
+ data.sort(comparer, sortDetails.sortAsc);
+ };
+
+ var lastSelectedId = null;
+
+ /**
+ * Sorts the specified data using the specified sort details.
+ *
+ * @param {object} sortDetails
+ * @param {object} data
+ */
+ var sortParameters = function (sortDetails, data) {
+ // defines a function for sorting
+ var comparer = function (a, b) {
+ if (sortDetails.columnId === 'name') {
+ var aString = nfCommon.isDefinedAndNotNull(a[sortDetails.columnId]) ? a[sortDetails.columnId] : '';
+ var bString = nfCommon.isDefinedAndNotNull(b[sortDetails.columnId]) ? b[sortDetails.columnId] : '';
+ return aString === bString ? 0 : aString > bString ? 1 : -1;
+ }
+ };
+
+ // perform the sort
+ data.sort(comparer, sortDetails.sortAsc);
+ };
+
+ /**
+ * Reset the dialog.
+ */
+ var resetDialog = function () {
+ $('#parameter-context-name').val('');
+ $('#parameter-context-description-field').val('');
+ $('#parameter-table, #add-parameter').show();
+ $('#parameter-context-tabs').show();
+ $('#parameter-context-tabs').find('.tab')[0].click();
+ $('#parameter-context-update-status').hide();
+
+ $('#process-group-parameter').text('');
+ $('#parameter-process-group-id').text('').removeData('revision');
+ $('#parameter-referencing-components-context').removeClass('unset').text('');
+
+ var parameterGrid = $('#parameter-table').data('gridInstance');
+ var parameterData = parameterGrid.getData();
+ parameterData.setItems([]);
+
+ resetUsage();
+
+ // reset the last selected parameter
+ lastSelectedId = null;
+
+ // reset the current parameter context
+ currentParameterContextEntity = null;
+
+ // clean up any tooltips that may have been generated
+ nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle');
+ };
+
+ /**
+ * Marshals the parameters in the table.
+ */
+ var marshalParameters = function () {
+ var parameters = [];
+ var table = $('#parameter-table');
+ var parameterGrid = table.data('gridInstance');
+ var parameterData = parameterGrid.getData();
+ $.each(parameterData.getItems(), function () {
+ var parameter = {
+ 'name': this.name
+ };
+
+ // if the parameter has been deleted
+ if (this.hidden === true && this.isNew !== true) {
+ // hidden parameters were removed by the user, clear the value
+ parameters.push({
+ 'parameter': parameter
+ });
+ } else if (this.isNew === true) {
+ parameter['value'] = this.value;
+ parameter['sensitive'] = this.sensitive;
+ parameter['description'] = this.description;
+
+ parameters.push({
+ 'parameter': parameter
+ });
+ } else if (this.isModified === true) {
+ parameter['sensitive'] = this.sensitive;
+
+ // if modified grab what's changed
+ if (this.hasValueChanged) {
+ parameter['value'] = this.value;
+ }
+
+ parameter['description'] = this.description;
+
+ parameters.push({
+ 'parameter': parameter
+ });
+ }
+ });
+
+ return parameters;
+ };
+
+ /**
+ * Handles outstanding changes.
+ *
+ * @returns {deferred}
+ */
+ var handleOutstandingChanges = function () {
+ if (!$('#parameter-dialog').hasClass('hidden')) {
+ // commit the current edit
+ addNewParameter();
+ }
+
+ return $.Deferred(function (deferred) {
+ if ($('#parameter-context-update-status').is(':visible')) {
+ close();
+ deferred.resolve();
+ } else {
+ var parameters = marshalParameters();
+
+ // if there are no parameters there is nothing to save
+ if ($.isEmptyObject(parameters)) {
+ close();
+ deferred.resolve();
+ } else {
+ // see if those changes should be saved
+ nfDialog.showYesNoDialog({
+ headerText: 'Parameters',
+ dialogContent: 'Save changes before leaving parameter context configuration?',
+ noHandler: function () {
+ close();
+ deferred.resolve();
+ },
+ yesHandler: function () {
+ updateParameterContext(currentParameterContextEntity).done(function () {
+ deferred.resolve();
+ }).fail(function () {
+ deferred.reject();
+ });
+ }
+ });
+ }
+ }
+
+ }).promise();
+ };
+
+ /**
+ * Adds a border to the controller service referencing components if necessary.
+ *
+ * @argument {jQuery} referenceContainer
+ */
+ var updateReferencingComponentsBorder = function (referenceContainer) {
+ // determine if it is too big
+ var tooBig = referenceContainer.get(0).scrollHeight > Math.round(referenceContainer.innerHeight()) ||
+ referenceContainer.get(0).scrollWidth > Math.round(referenceContainer.innerWidth());
+
+ // draw the border if necessary
+ if (referenceContainer.is(':visible') && tooBig) {
+ referenceContainer.css('border-width', '1px');
+ } else {
+ referenceContainer.css('border-width', '0px');
+ }
+ };
+
+ /**
+ * Cancels adding a new parameter context.
+ */
+ var close = function () {
+ $('#parameter-context-dialog').modal('hide');
+ };
+
+ /**
+ * Renders the specified referencing component.
+ *
+ * @param {object} referencingProcessorEntity
+ * @param {jQuery} container
+ */
+ var renderReferencingProcessor = function (referencingProcessorEntity, container) {
+ var referencingProcessorContainer = $('<li class="referencing-component-container"></li>').appendTo(container);
+ var referencingProcessor = referencingProcessorEntity.component;
+
+ // processor state
+ $('<div class="referencing-component-state"></div>').addClass(function () {
+ if (nfCommon.isDefinedAndNotNull(referencingProcessor.state)) {
+ var icon = $(this);
+
+ var state = referencingProcessor.state.toLowerCase();
+ if (state === 'stopped' && !nfCommon.isEmpty(referencingProcessor.validationErrors)) {
+ state = 'invalid';
+
+ // build the validation error listing
+ var list = nfCommon.formatUnorderedList(referencingProcessor.validationErrors);
+
+ // add tooltip for the warnings
+ icon.qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+
+ return state;
+ } else {
+ return '';
+ }
+ }).appendTo(referencingProcessorContainer);
+
+
+ // processor name
+ $('<span class="parameter-context-referencing-component-name link ellipsis"></span>').prop('title', referencingProcessor.name).text(referencingProcessor.name).on('click', function () {
+ // check if there are outstanding changes
+ handleOutstandingChanges().done(function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the component in question
+ nfCanvasUtils.showComponent(referencingProcessorEntity.processGroup.id, referencingProcessor.id);
+ });
+ }).appendTo(referencingProcessorContainer);
+
+ // bulletin
+ $('<div class="referencing-component-bulletins"></div>').addClass(referencingProcessor.id + '-referencing-bulletins').appendTo(referencingProcessorContainer);
+
+ // processor active threads
+ $('<span class="referencing-component-active-thread-count"></span>').text(function () {
+ if (nfCommon.isDefinedAndNotNull(referencingProcessor.activeThreadCount) && referencingProcessor.activeThreadCount > 0) {
+ return '(' + referencingProcessor.activeThreadCount + ')';
+ } else {
+ return '';
+ }
+ }).appendTo(referencingProcessorContainer);
+ };
+
+ /**
+ * Renders the specified affect controller service.
+ *
+ * @param {object} referencingControllerServiceEntity
+ * @param {jQuery} container
+ */
+ var renderReferencingControllerService = function (referencingControllerServiceEntity, container) {
+ var referencingControllerServiceContainer = $('<li class="referencing-component-container"></li>').appendTo(container);
+ var referencingControllerService = referencingControllerServiceEntity.component;
+
+ // controller service state
+ $('<div class="referencing-component-state"></div>').addClass(function () {
+ if (nfCommon.isDefinedAndNotNull(referencingControllerService.state)) {
+ var icon = $(this);
+
+ var state = referencingControllerService.state === 'ENABLED' ? 'enabled' : 'disabled';
+ if (state === 'disabled' && !nfCommon.isEmpty(referencingControllerService.validationErrors)) {
+ state = 'invalid';
+
+ // build the error listing
+ var list = nfCommon.formatUnorderedList(referencingControllerService.validationErrors);
+
+ // add tooltip for the warnings
+ icon.qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+ return state;
+ } else {
+ return '';
+ }
+ }).appendTo(referencingControllerServiceContainer);
+
+ // bulletin
+ $('<div class="referencing-component-bulletins"></div>').addClass(referencingControllerService.id + '-referencing-bulletins').appendTo(referencingControllerServiceContainer);
+
+ // controller service name
+ $('<span class="parameter-context-referencing-component-name link ellipsis"></span>').prop('title', referencingControllerService.name).text(referencingControllerService.name).on('click', function () {
+ // check if there are outstanding changes
+ handleOutstandingChanges().done(function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the component in question
+ nfProcessGroupConfiguration.showConfiguration(referencingControllerService.processGroupId).done(function () {
+ nfProcessGroupConfiguration.selectControllerService(referencingControllerService.id);
+ });
+ });
+ }).appendTo(referencingControllerServiceContainer);
+ };
+
+ /**
+ * Populates the referencing components for the specified parameter context.
+ *
+ * @param {object} referencingComponents
+ */
+ var populateReferencingComponents = function (referencingComponents) {
+ // toggles the visibility of a container
+ var toggle = function (twist, container) {
+ if (twist.hasClass('expanded')) {
+ twist.removeClass('expanded').addClass('collapsed');
+ container.hide();
+ } else {
+ twist.removeClass('collapsed').addClass('expanded');
+ container.show();
+ }
+ };
+
+ var referencingProcessors = [];
+ var referencingControllerServices = [];
+ var unauthorizedReferencingComponents = [];
+
+ // clear the referencing components from the previous selection
+ resetUsage();
+
+ var parameterReferencingComponentsContainer = $('#parameter-referencing-components-container');
+
+ // referencing component will be undefined when a new parameter is added
+ if (nfCommon.isUndefined(referencingComponents)) {
+ // set to pending
+ $('<div class="referencing-component-container"><span class="unset">Pending Apply</span></div>').appendTo(parameterReferencingComponentsContainer);
+ } else {
+ var referencingComponentsForBulletinRetrieval = [];
+
+ // bin the referencing components according to their type
+ $.each(referencingComponents, function (_, referencingComponentEntity) {
+ if (referencingComponentEntity.permissions.canRead === true && referencingComponentEntity.permissions.canWrite === true) {
+ referencingComponentsForBulletinRetrieval.push(referencingComponentEntity.id);
+
+ if (referencingComponentEntity.component.referenceType === 'PROCESSOR') {
+ referencingProcessors.push(referencingComponentEntity);
+ } else {
+ referencingControllerServices.push(referencingComponentEntity);
+ }
+ } else {
+ // if we're unauthorized only because the user is lacking write permissions, we can still query for bulletins
+ if (referencingComponentEntity.permissions.canRead === true) {
+ referencingComponentsForBulletinRetrieval.push(referencingComponentEntity.id);
+ }
+
+ unauthorizedReferencingComponents.push(referencingComponentEntity);
+ }
+ });
+
+ var referencingProcessGroups = {};
+
+ // bin the referencing processors according to their PG
+ $.each(referencingProcessors, function (_, referencingProcessorEntity) {
+ if (referencingProcessGroups[referencingProcessorEntity.processGroup.id]) {
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].referencingProcessors.push(referencingProcessorEntity);
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].id = referencingProcessorEntity.processGroup.id;
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].name = referencingProcessorEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: referencingProcessorEntity.processGroup.name,
+ id: referencingProcessorEntity.processGroup.id
+ };
+
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].referencingProcessors.push(referencingProcessorEntity);
+ }
+ });
+
+ // bin the referencing CS according to their PG
+ $.each(referencingControllerServices, function (_, referencingControllerServiceEntity) {
+ if (referencingProcessGroups[referencingControllerServiceEntity.processGroup.id]) {
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].referencingControllerServices.push(referencingControllerServiceEntity);
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].id = referencingControllerServiceEntity.processGroup.id;
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].name = referencingControllerServiceEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: referencingControllerServiceEntity.processGroup.name,
+ id: referencingControllerServiceEntity.processGroup.id
+ };
+
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].referencingControllerServices.push(referencingControllerServiceEntity);
+ }
+ });
+
+ // bin the referencing unauthorized components according to their PG
+ $.each(unauthorizedReferencingComponents, function (_, unauthorizedReferencingComponentEntity) {
+ if (referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id]) {
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].unauthorizedReferencingComponents.push(unauthorizedReferencingComponentEntity);
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].id = unauthorizedReferencingComponentEntity.processGroup.id;
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].name = unauthorizedReferencingComponentEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: unauthorizedReferencingComponentEntity.processGroup.name,
+ id: unauthorizedReferencingComponentEntity.processGroup.id
+ };
+
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].unauthorizedReferencingComponents.push(unauthorizedReferencingComponentEntity);
+ }
+ });
+
+ var parameterReferencingComponentsContainer = $('#parameter-referencing-components-container');
+ var groups = $('<ul class="referencing-component-listing clear"></ul>');
+
+ var referencingProcessGroupsArray = [];
+ for (var key in referencingProcessGroups) {
+ if (referencingProcessGroups.hasOwnProperty(key)) {
+ referencingProcessGroupsArray.push(referencingProcessGroups[key]);
+ }
+ }
+
+ //sort alphabetically
+ var sortedReferencingProcessGroups = referencingProcessGroupsArray.sort(function (a, b) {
+ if (a.name < b.name) {
+ return -1;
+ }
+ if (a.name > b.name) {
+ return 1;
+ }
+ return 0;
+ });
+
+ sortedReferencingProcessGroups.forEach(function (referencingProcessGroup) {
+ // container for this pg's references
+ var referencingPgReferencesContainer = $('<div class="referencing-component-references"></div>');
+ parameterReferencingComponentsContainer.append(referencingPgReferencesContainer);
+
+ // create the collapsable listing for each PG
+ var createReferenceBlock = function (referencingProcessGroup, list) {
+ var twist = $('<div class="expansion-button collapsed"></div>');
+ var title = $('<span class="referencing-component-title"></span>').text(referencingProcessGroup.name);
+ var count = $('<span class="referencing-component-count"></span>').text('(' + (referencingProcessGroup.referencingProcessors.length + referencingProcessGroup.referencingControllerServices.length + referencingProcessGroup.unauthorizedReferencingComponents.length) + ')');
+ var referencingComponents = $('#referencing-components-template').clone();
+ referencingComponents.removeAttr('id');
+ referencingComponents.removeClass('hidden');
+
+ // create the reference block
+ var groupTwist = $('<div class="referencing-component-block pointer unselectable"></div>').data('processGroupId', referencingProcessGroup.id).on('click', function () {
+ if (twist.hasClass('collapsed')) {
+ groupTwist.append(referencingComponents);
+
+ var processorContainer = groupTwist.find('.parameter-context-referencing-processors');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-bulletins');
+ processorContainer.empty();
+
+ var controllerServiceContainer = groupTwist.find('.parameter-context-referencing-controller-services');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-bulletins');
+ controllerServiceContainer.empty();
+
+ var unauthorizedComponentsContainer = groupTwist.find('.parameter-context-referencing-unauthorized-components').empty();
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors.length === 0) {
+ $('<li class="referencing-component-container"><span class="unset">None</span></li>').appendTo(processorContainer);
+ } else {
+ // sort the referencing processors
+ referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors.sort(nameComparator);
+
+ // render each and register a click handler
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors, function (_, referencingProcessorEntity) {
+ renderReferencingProcessor(referencingProcessorEntity, processorContainer);
+ });
+ }
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices.length === 0) {
+ $('<li class="referencing-component-container"><span class="unset">None</span></li>').appendTo(controllerServiceContainer);
+ } else {
+ // sort the referencing controller services
+ referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices.sort(nameComparator);
+
+ // render each and register a click handler
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices, function (_, referencingControllerServiceEntity) {
+ renderReferencingControllerService(referencingControllerServiceEntity, controllerServiceContainer);
+ });
+ }
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents.length === 0) {
+ $('<li class="referencing-component-container"><span class="unset">None</span></li>').appendTo(unauthorizedComponentsContainer);
+ } else {
+ // sort the unauthorized referencing components
+ referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents.sort(function (a, b) {
+ if (a.permissions.canRead === true && b.permissions.canRead === true) {
+ // processors before controller services
+ var sortVal = a.component.referenceType === b.component.referenceType ? 0 : a.component.referenceType > b.component.referenceType ? -1 : 1;
+
+ // if a and b are the same type, then sort by name
+ if (sortVal === 0) {
+ sortVal = a.component.name === b.component.name ? 0 : a.component.name > b.component.name ? 1 : -1;
+ }
+
+ return sortVal;
+ } else {
+
+ // if lacking read and write perms on both, sort by id
+ if (a.permissions.canRead === false && b.permissions.canRead === false) {
+ return a.id > b.id ? 1 : -1;
+ } else {
+ // if only one has read perms, then let it come first
+ if (a.permissions.canRead === true) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+ });
+
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents, function (_, unauthorizedReferencingComponentEntity) {
+ if (unauthorizedReferencingComponentEntity.permissions.canRead === true) {
+ if (unauthorizedReferencingComponentEntity.component.referenceType === 'PROCESSOR') {
+ renderReferencingProcessor(unauthorizedReferencingComponentEntity, unauthorizedComponentsContainer);
+ } else {
+ renderReferencingControllerService(unauthorizedReferencingComponentEntity, unauthorizedComponentsContainer);
+ }
+ } else {
+ var referencingUnauthorizedComponentContainer = $('<li class="referencing-component-container"></li>').appendTo(unauthorizedComponentsContainer);
+ $('<span class="parameter-context-referencing-component-name link ellipsis"></span>').prop('title', unauthorizedReferencingComponentEntity.id).text(unauthorizedReferencingComponentEntity.id).on('click', function () {
+ // check if there are outstanding changes
+ handleOutstandingChanges().done(function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the component in question
+ nfCanvasUtils.showComponent(unauthorizedReferencingComponentEntity.processGroup.id, unauthorizedReferencingComponentEntity.id);
+ });
+ }).appendTo(referencingUnauthorizedComponentContainer);
+ }
+ });
+ }
+
+ // query for the bulletins
+ if (referencingComponentsForBulletinRetrieval.length > 0) {
+ nfCanvasUtils.queryBulletins(referencingComponentsForBulletinRetrieval).done(function (response) {
+ var bulletins = response.bulletinBoard.bulletins;
+
+ var bulletinsBySource = d3.nest()
+ .key(function (d) {
+ return d.sourceId;
+ })
+ .map(bulletins, d3.map);
+
+ bulletinsBySource.each(function (sourceBulletins, sourceId) {
+ $('div.' + sourceId + '-referencing-bulletins').each(function () {
+ var bulletinIcon = $(this);
+
+ // if there are bulletins update them
+ if (sourceBulletins.length > 0) {
+ // format the new bulletins
+ var formattedBulletins = nfCommon.getFormattedBulletins(sourceBulletins);
+
+ var list = nfCommon.formatUnorderedList(formattedBulletins);
+
+ // update existing tooltip or initialize a new one if appropriate
+ bulletinIcon.addClass('has-bulletins').show().qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+ });
+ });
+ });
+ }
+ } else {
+ groupTwist.find('.referencing-components-template').remove();
+ }
+
+ // toggle this block
+ toggle(twist, list);
+
+ // update the border if necessary
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }).append(twist).append(title).append(count).appendTo(referencingPgReferencesContainer);
+
+ // add the listing
+ list.appendTo(referencingPgReferencesContainer);
+
+ // expand the group twist
+ groupTwist.click();
+ };
+
+ // create block for this process group
+ createReferenceBlock(referencingProcessGroup, groups);
+ });
+ }
+ };
+
+ /**
+ * Sorts the specified entities based on the name.
+ *
+ * @param {object} a
+ * @param {object} b
+ * @returns {number}
+ */
+ var nameComparator = function (a, b) {
+ return a.component.name.localeCompare(b.component.name);
+ };
+
+ var parameterKeyRegex = /^[a-zA-Z0-9-_. ]+$/;
+
+ /**
+ * Adds a new parameter.
+ */
+ var addNewParameter = function () {
+ var parameterName = $.trim($('#parameter-name').val());
+
+ // ensure the parameter name is specified
+ if (parameterName !== '' && parameterKeyRegex.test(parameterName)) {
+ var parameterGrid = $('#parameter-table').data('gridInstance');
+ var parameterData = parameterGrid.getData();
+
+ // ensure the parameter name is unique
+ var matchingParameter = null;
+ $.each(parameterData.getItems(), function (_, item) {
+ if (parameterName === item.name) {
+ matchingParameter = item;
+ return false;
+ }
+ });
+
+ var isSensitive = $('#parameter-dialog').find('input[name="sensitive"]:checked').val() === "sensitive" ? true : false;
+ var isChecked = $('#parameter-set-empty-string-field').hasClass('checkbox-checked');
+
+ if (matchingParameter === null) {
+ var parameter = {
+ id: parameterCount,
+ hidden: false,
+ type: 'Parameter',
+ sensitive: isSensitive,
+ name: parameterName,
+ description: $('#parameter-description-field').val(),
+ previousValue: null,
+ previousDescription: null,
+ isEditable: true,
+ isEmptyStringSet: isChecked,
+ isModified: true,
+ hasValueChanged: false,
+ isNew: true
+ };
+
+ var value = $('#parameter-value-field').val();
+ if (!nfCommon.isBlank(value)) {
+ parameter.value = value;
+ } else {
+ if (isChecked) {
+ parameter.value = '';
+ } else {
+ parameter.value = null;
+ }
+ }
+
+ // add a row for the new parameter
+ parameterData.addItem(parameter);
+
+ // sort the data
+ parameterData.reSort();
+
+ // select the new parameter row
+ var row = parameterData.getRowById(parameterCount);
+ parameterGrid.setActiveCell(row, parameterGrid.getColumnIndex('value'));
+ parameterCount++;
+ } else {
+ // if this row is currently hidden, make sure the sensitivity is equivalent before we allow recreate
+ if (matchingParameter.hidden === true && matchingParameter.sensitive !== isSensitive) {
+ nfDialog.showOkDialog({
+ headerText: 'Parameter Exists',
+ dialogContent: 'A parameter with this name has been marked for deletion. Please apply this change to delete this parameter from the parameter context before recreating it with a different sensitivity.'
+ });
+ } else if (matchingParameter.hidden === true && matchingParameter.sensitive === isSensitive) {
+ var parameter = $.extend(matchingParameter, {
+ hidden: false,
+ sensitive: isSensitive,
+ previousValue: null,
+ description: $('#parameter-description-field').val(),
+ previousDescription: null,
+ isEditable: true,
+ isEmptyStringSet: isChecked,
+ isModified: true,
+ hasValueChanged: false,
+ isNew: true
+ });
+
+ var value = $('#parameter-value-field').val();
+ if (!nfCommon.isBlank(value)) {
+ parameter.value = value;
+ } else {
+ if (isChecked) {
+ parameter.value = '';
+ } else {
+ parameter.value = null;
+ }
+ }
+
+ parameterData.updateItem(matchingParameter.id, parameter);
+
+ // sort the data
+ parameterData.reSort();
+
+ // select the new parameter row
+ var row = parameterData.getRowById(matchingParameter.id);
+ parameterGrid.setActiveCell(row, parameterGrid.getColumnIndex('value'));
+ parameterCount++;
+ } else {
+ nfDialog.showOkDialog({
+ headerText: 'Parameter Exists',
+ dialogContent: 'A parameter with this name already exists.'
+ });
+
+ // select the existing properties row
+ var matchingRow = parameterData.getRowById(matchingParameter.id);
+ parameterGrid.setSelectedRows([matchingRow]);
+ parameterGrid.scrollRowIntoView(matchingRow);
+ }
+ }
+
+ // close the new parameter dialog
+ $('#parameter-dialog').modal('hide');
+
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-context-dialog').modal('refreshButtons');
+
+ } else if (!parameterKeyRegex.test(parameterName)) {
+ nfDialog.showOkDialog({
+ headerText: 'Configuration Error',
+ dialogContent: 'This parameter appears to have an invalid character or characters. Only alpha-numeric characters (a-z, A-Z, 0-9), hyphens (-), underscores (_), periods (.), and spaces ( ) are accepted.'
+ });
+ } else {
+ nfDialog.showOkDialog({
+ headerText: 'Configuration Error',
+ dialogContent: 'The name of the parameter must be specified.'
+ });
+ }
+ };
+
+ var serializeValue = function (input, parameter, isChecked) {
+ var serializedValue;
+ var hasChanged = true;
+
+ var value = input.val();
+ if (!nfCommon.isBlank(value)) {
+ // if the value is sensitive and the user has not made a change
+ if (parameter.sensitive === true && input.hasClass('sensitive') && parameter.isNew === false) {
+ serializedValue = parameter.previousValue;
+ hasChanged = false;
+ } else {
+ // value is not sensitive or it is sensitive and the user has changed it then always take the current value
+ serializedValue = value;
+ }
+ } else {
+ if (isChecked) {
+ serializedValue = '';
+ } else {
+ serializedValue = null;
+ }
+ }
+
+ return {
+ value: serializedValue,
+ hasChanged: hasChanged
+ };
+ };
+
+ /**
+ * Update a parameter.
+ */
+ var updateParameter = function () {
+ var parameterName = $('#parameter-name').val();
+
+ // ensure the parameter name is specified
+ if (parameterName !== '') {
+ var parameterGrid = $('#parameter-table').data('gridInstance');
+ var parameterData = parameterGrid.getData();
+
+ // ensure the parameter name is unique
+ var matchingParameter = null;
+ $.each(parameterData.getItems(), function (_, item) {
+ if (parameterName === item.name) {
+ matchingParameter = item;
+ return false;
+ }
+ });
+
+ if (matchingParameter !== null) {
+ var isChecked = $('#parameter-set-empty-string-field').hasClass('checkbox-checked');
+
+ var parameter = {
+ id: matchingParameter.id,
+ hidden: false,
+ type: 'Parameter',
+ sensitive: matchingParameter.sensitive,
+ name: parameterName,
+ description: $('#parameter-description-field').val(),
+ referencingComponents: matchingParameter.referencingComponents,
+ previousValue: matchingParameter.value,
+ previousDescription: matchingParameter.description,
+ isEditable: matchingParameter.isEditable,
+ isEmptyStringSet: isChecked,
+ isNew: matchingParameter.isNew
+ };
+
+ var input = $('#parameter-value-field');
+ var serializedValue = serializeValue(input, parameter, isChecked);
+ parameter.value = serializedValue.value;
+ parameter.isModified = serializedValue.hasChanged || parameter.description !== parameter.previousDescription;
+ parameter.hasValueChanged = serializedValue.hasChanged;
+
+ // update row for the parameter
+ parameterData.updateItem(matchingParameter.id, parameter);
+
+ // sort the data
+ parameterData.reSort();
+
+ // select the parameter row
+ var row = parameterData.getRowById(matchingParameter.id);
+ parameterGrid.setActiveCell(row, parameterGrid.getColumnIndex('value'));
+ } else {
+ nfDialog.showOkDialog({
+ headerText: 'Parameter Does Not Exists',
+ dialogContent: 'A parameter with this name does not exist.'
+ });
+ }
+
+ // close the new parameter dialog
+ $('#parameter-dialog').modal('hide');
+
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-context-dialog').modal('refreshButtons');
+ } else {
+ nfDialog.showOkDialog({
+ headerText: 'Create Parameter Error',
+ dialogContent: 'The name of the parameter must be specified.'
+ });
+ }
+ };
+
+ /**
+ * Updates parameter contexts by issuing an update request and polling until it's completion.
+ *
+ * @param parameterContextEntity
+ * @returns {*}
+ */
+ var updateParameterContext = function (parameterContextEntity) {
+ var parameters = marshalParameters();
+
+ if (parameters.length === 0) {
+ // nothing to update
+ parameterContextEntity.component.parameters = [];
+ if ($('#parameter-context-name').val() === parameterContextEntity.component.name &&
+ $('#parameter-context-description-field').val() === parameterContextEntity.component.description) {
+ close();
+
+ return;
+ }
+ } else {
+ parameterContextEntity.component.parameters = parameters;
+ }
+
+ parameterContextEntity.component.name = $('#parameter-context-name').val();
+ parameterContextEntity.component.description = $('#parameter-context-description-field').val();
+
+ return $.Deferred(function (deferred) {
+ // updates the button model to show the close button
+ var updateToCloseButtonModel = function () {
+ $('#parameter-context-dialog').modal('setButtonModel', [{
+ buttonText: 'Close',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ handler: {
+ click: function () {
+ deferred.resolve();
+ close();
+ }
+ }
+ }]);
+ };
+
+ var updateToApplyOrCancelButtonModel = function () {
+ $('#parameter-context-dialog').modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ if ($('#parameter-context-name').val() !== '') {
+ return false;
+ }
+ return true;
+ },
+ handler: {
+ click: function () {
+ if ($('#parameter-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }
+
+ updateParameterContext(parameterContextEntity);
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ deferred.resolve();
+
+ if ($('#parameter-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }
+
+ close();
+ }
+ }
+ }]);
+ };
+
+ var cancelled = false;
+
+ // update the button model to show the cancel button
+ $('#parameter-context-dialog').modal('setButtonModel', [{
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ cancelled = true;
+
+ if ($('#parameter-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }
+
+ updateToCloseButtonModel();
+ }
+ }
+ }]);
+
+ var requestId;
+ var handleAjaxFailure = function (xhr, status, error) {
+ // delete the request if possible
+ if (nfCommon.isDefinedAndNotNull(requestId)) {
+ deleteUpdateRequest(parameterContextEntity.id, requestId);
+ }
+
+ // update the step status
+ $('#parameter-context-update-steps').find('div.parameter-context-step.ajax-loading').removeClass('ajax-loading').addClass('ajax-error');
+
+ if ($('#parameter-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }
+
+ // update the button model
+ updateToApplyOrCancelButtonModel();
+ };
+
+ submitUpdateRequest(parameterContextEntity).done(function (response) {
+ var pollUpdateRequest = function (updateRequestEntity) {
+ var updateRequest = updateRequestEntity.request;
+ var errored = nfCommon.isDefinedAndNotNull(updateRequest.failureReason);
+
+ // get the request id
+ requestId = updateRequest.requestId;
+
+ // update the referencing components
+ populateReferencingComponents(updateRequest.referencingComponents);
+
+ // get the updated parameter names
+ var parameterNames = [];
+ $.each(parameters, function (_, parameterEntity) {
+ parameterNames.push(parameterEntity.parameter.name);
+ });
+ $('#parameter-referencing-components-context').removeClass('unset').text(parameterNames.join(', '));
+
+ // update the progress/steps
+ populateParameterContextUpdateStep(updateRequest.updateSteps, cancelled, errored);
+
+ // if this request was cancelled, remove the update request
+ if (cancelled) {
+ deleteUpdateRequest(parameterContextEntity.id, requestId);
+ } else {
+ if (updateRequest.complete === true) {
+ if (errored) {
+ nfDialog.showOkDialog({
+ headerText: 'Parameter Context Update Error',
+ dialogContent: 'Unable to complete parameter context update request: ' + nfCommon.escapeHtml(updateRequest.failureReason)
+ });
+ }
+
+ // reload referencing processors
+ $.each(updateRequest.referencingComponents, function (_, referencingComponentEntity) {
+ if (referencingComponentEntity.permissions.canRead === true) {
+ var referencingComponent = referencingComponentEntity.component;
+
+ // reload the processor if it's in the current group
+ if (referencingComponent.referenceType === 'PROCESSOR' && nfCanvasUtils.getGroupId() === referencingComponent.processGroupId) {
+ nfProcessor.reload(referencingComponent.id);
+ }
+ }
+ });
+
+ // update the parameter context table if displayed
+ var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
+ if (nfCommon.isDefinedAndNotNull(parameterContextGrid)) {
+ var parameterContextData = parameterContextGrid.getData();
+
+ $.extend(parameterContextEntity, {
+ revision: updateRequestEntity.parameterContextRevision,
+ component: updateRequestEntity.request.parameterContext
+ });
+
+ var item = parameterContextData.getItem(parameterContextEntity.id);
+ if (nfCommon.isDefinedAndNotNull(item)) {
+ parameterContextData.updateItem(parameterContextEntity.id, parameterContextEntity);
+ }
+ }
+
+ // delete the update request
+ deleteUpdateRequest(parameterContextEntity.id, requestId);
+
+ // update the button model
+ updateToCloseButtonModel();
+
+ // check if border is necessary
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ } else {
+ // wait to get an updated status
+ setTimeout(function () {
+ getUpdateRequest(parameterContextEntity.id, requestId).done(function (getResponse) {
+ pollUpdateRequest(getResponse);
+ }).fail(handleAjaxFailure);
+ }, 2000);
+ }
+ }
+ };
+
+ // update the visibility
+ $('#parameter-table, #add-parameter').hide();
+ $('#parameter-context-tabs').find('.tab')[1].click();
+ $('#parameter-context-tabs').hide();
+ $('#parameter-context-update-status').show();
+
+ pollUpdateRequest(response);
+ }).fail(handleAjaxFailure);
+ }).promise();
+ };
+
+ /**
+ * Obtains the current state of the updateRequest using the specified update request id.
+ *
+ * @param {string} updateRequestId
+ * @returns {deferred} update request xhr
+ */
+ var getUpdateRequest = function (parameterContextId, updateRequestId) {
+ return $.ajax({
+ type: 'GET',
+ url: config.urls.parameterContexts + '/' + encodeURIComponent(parameterContextId) + '/update-requests/' + encodeURIComponent(updateRequestId),
+ dataType: 'json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Deletes an updateRequest using the specified update request id.
+ *
+ * @param {string} updateRequestId
+ * @returns {deferred} update request xhr
+ */
+ var deleteUpdateRequest = function (parameterContextId, updateRequestId) {
+ return $.ajax({
+ type: 'DELETE',
+ url: config.urls.parameterContexts + '/' + encodeURIComponent(parameterContextId) + '/update-requests/' + encodeURIComponent(updateRequestId) + '?' + $.param({
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged()
+ }),
+ dataType: 'json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Submits an parameter context update request.
+ *
+ * @param {object} parameterContextEntity
+ * @returns {deferred} update request xhr
+ */
+ var submitUpdateRequest = function (parameterContextEntity) {
+ return $.ajax({
+ type: 'POST',
+ data: JSON.stringify(parameterContextEntity),
+ url: config.urls.parameterContexts + '/' + encodeURIComponent(parameterContextEntity.id) + '/update-requests',
+ dataType: 'json',
+ contentType: 'application/json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Populates the parameter update steps.
+ *
+ * @param {array} updateSteps
+ * @param {boolean} whether this request has been cancelled
+ * @param {boolean} whether this request has errored
+ */
+ var populateParameterContextUpdateStep = function (updateSteps, cancelled, errored) {
+ var updateStatusContainer = $('#parameter-context-update-steps').empty();
+
+ // go through each step
+ $.each(updateSteps, function (_, updateStep) {
+ var stepItem = $('<li></li>').text(updateStep.description).appendTo(updateStatusContainer);
+
+ $('<div class="parameter-context-step"></div>').addClass(function () {
+ if (nfCommon.isDefinedAndNotNull(updateStep.failureReason)) {
+ return 'ajax-error';
+ } else {
+ if (updateStep.complete === true) {
+ return 'ajax-complete';
+ } else {
+ return cancelled === true || errored === true ? 'ajax-error' : 'ajax-loading';
+ }
+ }
+ }).appendTo(stepItem);
+
+ $('<div class="clear"></div>').appendTo(stepItem);
+ });
+ };
+
+ var parameterCount = 0;
+ var parameterIndex = 0;
+
+ /**
+ * Loads the specified parameter registry.
+ *
+ * @param {object} parameterContext
+ * @param {string} parameterToSelect to select
+ */
+ var loadParameters = function (parameterContext, parameterToSelect) {
+ if (nfCommon.isDefinedAndNotNull(parameterContext)) {
+
+ var parameterGrid = $('#parameter-table').data('gridInstance');
+ var parameterData = parameterGrid.getData();
+
+ // begin the update
+ parameterData.beginUpdate();
+
+ var parameters = [];
+ $.each(parameterContext.component.parameters, function (i, parameterEntity) {
+ var parameter = {
+ id: parameterCount++,
+ hidden: false,
+ type: 'Parameter',
+ isNew: false,
+ isModified: false,
+ hasValueChanged: false,
+ name: parameterEntity.parameter.name,
+ value: parameterEntity.parameter.value,
+ sensitive: parameterEntity.parameter.sensitive,
+ description: parameterEntity.parameter.description,
+ previousValue: parameterEntity.parameter.value,
+ previousDescription: parameterEntity.parameter.description,
+ isEditable: parameterEntity.canWrite,
+ referencingComponents: parameterEntity.parameter.referencingComponents
+ };
+
+ parameters.push({
+ parameter: parameter
+ });
+
+ parameterData.addItem(parameter);
+ });
+
+ // complete the update
+ parameterData.endUpdate();
+ parameterData.reSort();
+
+ // if we are pre-selecting a specific parameter, get it's parameterIndex
+ if (nfCommon.isDefinedAndNotNull(parameterToSelect)) {
+ $.each(parameters, function (i, parameterEntity) {
+ if (parameterEntity.parameter.name === parameterToSelect) {
+ parameterIndex = parameterData.getRowById(parameterEntity.parameter.id);
+ return false;
+ }
+ });
+ }
+
+ if (parameters.length === 0) {
+ resetUsage();
+ } else {
+ // select the desired row
+ parameterGrid.setSelectedRows([parameterIndex]);
+ }
+ }
+ };
+
+ var resetUsage = function () {
+ // empty the containers
+ var processorContainer = $('.parameter-context-referencing-processors');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-bulletins');
+ processorContainer.empty();
+
+ var controllerServiceContainer = $('.parameter-context-referencing-controller-services');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-bulletins');
+ controllerServiceContainer.empty();
+
+ var unauthorizedComponentsContainer = $('.parameter-context-referencing-unauthorized-components').empty();
+
+ $('#parameter-referencing-components-container').empty();
+
+ // reset the last selected parameter
+ lastSelectedId = null;
+
+ // indicate no referencing components
+ $('<li class="referencing-component-container"><span class="unset">None</span></li>').appendTo(processorContainer);
+ $('<li class="referencing-component-container"><span class="unset">None</span></li>').appendTo(controllerServiceContainer);
+ $('<li class="referencing-component-container"><span class="unset">None</span></li>').appendTo(unauthorizedComponentsContainer);
+
+ // update the selection context
+ $('#parameter-referencing-components-context').addClass('unset').text('None');
+
+ // check if border is necessary
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ };
+
+ /**
+ * Performs the filtering.
+ *
+ * @param {object} item The item subject to filtering
+ * @param {object} args Filter arguments
+ * @returns {Boolean} Whether or not to include the item
+ */
+ var filter = function (item, args) {
+ return item.hidden === false;
+ };
+
+ /**
+ * Initializes the parameter table
+ */
+ var initParameterTable = function () {
+ var parameterTable = $('#parameter-table');
+
+ var nameFormatter = function (row, cell, value, columnDef, dataContext) {
+ var nameWidthOffset = 30;
+ var cellContent = $('<div></div>');
+
+ // format the contents
+ var formattedValue = $('<span/>').addClass('table-cell').text(value).appendTo(cellContent);
+ if (dataContext.type === 'required') {
+ formattedValue.addClass('required');
+ }
+
+ // show the parameter description if applicable
+ if (!nfCommon.isBlank(dataContext.description)) {
+ $('<div class="fa fa-question-circle" alt="Info" style="float: right;"></div>').appendTo(cellContent);
+ $('<span class="hidden parameter-row"></span>').text(row).appendTo(cellContent);
+ nameWidthOffset = 46; // 10 + icon width (10) + icon margin (6) + padding (20)
+ }
+
+ // adjust the width accordingly
+ formattedValue.width(columnDef.width - nameWidthOffset).ellipsis();
+
+ // return the cell content
+ return cellContent.html();
+ };
+
+ var valueFormatter = function (row, cell, value, columnDef, dataContext) {
+ if (dataContext.sensitive === true) {
+ return '<span class="table-cell sensitive">Sensitive value set</span>';
+ } else if (value === '') {
+ return '<span class="table-cell blank">Empty string set</span>';
+ } else if (nfCommon.isNull(value)) {
+ return '<span class="unset">No value set</span>';
+ } else {
+ return nfCommon.escapeHtml(value);
+ }
+ };
+
+ var parameterActionFormatter = function (row, cell, value, columnDef, dataContext) {
+ var markup = '';
+
+ if (dataContext.isEditable === true) {
+ markup += '<div title="Edit" class="edit-parameter pointer fa fa-pencil"></div>';
+ markup += '<div title="Delete" class="delete-parameter pointer fa fa-trash"></div>';
+ }
+
+ return markup;
+ };
+
+ // define the column model for the controller services table
+ var parameterColumns = [
+ {
+ id: 'name',
+ name: 'Name',
+ field: 'name',
+ formatter: nameFormatter,
+ sortable: true,
+ resizable: true,
+ rerenderOnResize: true
+ },
+ {
+ id: 'value',
+ name: 'Value',
+ field: 'value',
+ formatter: valueFormatter,
+ sortable: false,
+ resizable: true
+ },
+ {
+ id: 'actions',
+ name: ' ',
+ resizable: false,
+ rerenderOnResize: true,
+ formatter: parameterActionFormatter,
+ sortable: false,
+ width: 90,
+ maxWidth: 90
+ }
+ ];
+
+ // initialize the dataview
+ var parameterData = new Slick.Data.DataView({
+ inlineFilters: false
+ });
+ parameterData.setFilterArgs({
+ searchString: '',
+ property: 'hidden'
+ });
+ parameterData.setFilter(filter);
+
+ // initialize the sort
+ sortParameters({
+ columnId: 'name',
+ sortAsc: true
+ }, parameterData);
+
+ // initialize the grid
+ var parametersGrid = new Slick.Grid(parameterTable, parameterData, parameterColumns, parametersGridOptions);
+ parametersGrid.setSelectionModel(new Slick.RowSelectionModel());
+ parametersGrid.registerPlugin(new Slick.AutoTooltips());
+ parametersGrid.setSortColumn('name', true);
+ parametersGrid.onSort.subscribe(function (e, args) {
+ sortParameters({
+ columnId: args.sortCol.id,
+ sortAsc: args.sortAsc
+ }, parameterData);
+ });
+ parametersGrid.onClick.subscribe(function (e, args) {
+ // get the parameter at this row
+ var parameter = parameterData.getItem(args.row);
+
+ if (parametersGrid.getColumns()[args.cell].id === 'actions') {
+ var target = $(e.target);
+
+ // determine the desired action
+ if (target.hasClass('delete-parameter')) {
+ // mark the property in question for removal and refresh the table
+ parameterData.updateItem(parameter.id, $.extend(parameter, {
+ hidden: true
+ }));
+
+ // reset the selection if necessary
+ var selectedRows = parametersGrid.getSelectedRows();
+ if (selectedRows.length === 0) {
+ parametersGrid.setSelectedRows([0]);
+ }
+
+ var rows = parameterData.getItems();
+
+ if (rows.length === 0) {
+ // clear usages
+ resetUsage();
+ } else {
+ var reset = true;
+ $.each(rows, function (_, parameter) {
+ if (!parameter.hidden) {
+ reset = false;
+ }
+ });
+
+ if (reset) {
+ // clear usages
+ resetUsage();
+ }
+ }
+
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-context-dialog').modal('refreshButtons');
+
+ // prevents standard edit logic
+ e.stopImmediatePropagation();
+ } else if (target.hasClass('edit-parameter')) {
+ var closeHandler = function () {
+ $('#parameter-name').val('');
+ $('#parameter-value-field').val('');
+ $('#parameter-description-field').val('');
+ $('#parameter-sensitive-radio-button').prop('checked', false);
+ $('#parameter-not-sensitive-radio-button').prop('checked', false);
+ $('#parameter-name').prop('disabled', false);
+ $('#parameter-sensitive-radio-button').prop('disabled', false);
+ $('#parameter-not-sensitive-radio-button').prop('disabled', false);
+ $('#parameter-set-empty-string-field').removeClass('checkbox-checked').addClass('checkbox-unchecked');
+ };
+
+ var openHandler = function () {
+ $('#parameter-sensitive-radio-button').prop('checked', false);
+ $('#parameter-not-sensitive-radio-button').prop('checked', true);
+ $('#parameter-name').focus();
+
+ $('#parameter-name').val(parameter.name);
+ $('#parameter-name').prop('disabled', true);
+ $('#parameter-sensitive-radio-button').prop('disabled', true);
+ $('#parameter-not-sensitive-radio-button').prop('disabled', true);
+ if (parameter.value === '') {
+ $('#parameter-set-empty-string-field').removeClass('checkbox-unchecked').addClass('checkbox-checked');
+ } else {
+ $('#parameter-set-empty-string-field').removeClass('checkbox-checked').addClass('checkbox-unchecked');
+ }
+
+ if (parameter.sensitive) {
+ $('#parameter-sensitive-radio-button').prop('checked', true);
+ $('#parameter-not-sensitive-radio-button').prop('checked', false);
+ $('#parameter-value-field').addClass('sensitive').val(nfCommon.config.sensitiveText).select();
+ } else {
+ $('#parameter-sensitive-radio-button').prop('checked', false);
+ $('#parameter-not-sensitive-radio-button').prop('checked', true);
+ $('#parameter-value-field').val(parameter.value);
+ }
+ $('#parameter-description-field').val(parameter.description);
+
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-dialog').modal('refreshButtons');
+ };
+
+ $('#parameter-dialog')
+ .modal('setHeaderText', 'Edit Parameter')
+ .modal('setOpenHandler', openHandler)
+ .modal('setCloseHandler', closeHandler)
+ .modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ var input = $('#parameter-value-field');
+ var isChecked = $('#parameter-set-empty-string-field').hasClass('checkbox-checked');
+ var serializedValue = serializeValue(input, parameter, isChecked);
+
+ var description = $('#parameter-description-field').val();
+
+ var hasChanged = serializedValue.hasChanged || description !== parameter.previousDescription;
+
+ return !hasChanged;
+ },
+ handler: {
+ click: function () {
+ updateParameter();
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $(this).modal('hide');
+ }
+ }
+ }]).modal('show');
+
+ // prevents standard edit logic
+ e.stopImmediatePropagation();
+ }
+ }
+ });
+ parametersGrid.onSelectedRowsChanged.subscribe(function (e, args) {
+ if ($.isArray(args.rows) && args.rows.length === 1) {
+ // show the referencing components for the selected parameter
+ if (parametersGrid.getDataLength() > 0) {
+ var parameterIndex = args.rows[0];
+ var parameter = parametersGrid.getDataItem(parameterIndex);
+
+ // only populate referencing components if this parameter is different than the last selected
+ if (lastSelectedId === null || lastSelectedId !== parameter.id) {
+ populateReferencingComponents(parameter.referencingComponents);
+
+ // update the details for this parameter
+ $('#parameter-referencing-components-context').removeClass('unset').text(parameter.name);
+
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+
+ // update the last selected id
+ lastSelectedId = parameter.id;
+ }
+ }
+ }
+ });
+ parametersGrid.onBeforeCellEditorDestroy.subscribe(function (e, args) {
+ setTimeout(function () {
+ parametersGrid.resizeCanvas();
+ }, 50);
+ });
+
+ // wire up the dataview to the grid
+ parameterData.onRowCountChanged.subscribe(function (e, args) {
+ parametersGrid.updateRowCount();
+ parametersGrid.render();
+ });
+ parameterData.onRowsChanged.subscribe(function (e, args) {
+ parametersGrid.invalidateRows(args.rows);
+ parametersGrid.render();
+ });
+ parameterData.syncGridSelection(parametersGrid, true);
+
+ // hold onto an instance of the grid and create parameter description tooltip
+ parameterTable.data('gridInstance', parametersGrid).on('mouseenter', 'div.slick-cell', function (e) {
+ var infoIcon = $(this).find('div.fa-question-circle');
+ if (infoIcon.length) {
+ if (infoIcon.data('qtip')) {
+ infoIcon.qtip('destroy', true);
+ }
+
+ var row = $(this).find('span.parameter-row').text();
+
+ // get the parameter
+ var parameter = parameterData.getItem(row);
+
+ if (nfCommon.isDefinedAndNotNull(parameter.description)) {
+ infoIcon.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: parameter.description
+ }));
+ }
+ }
+ });
+ };
+
+ /**
+ * Initializes the new parameter context dialog.
+ */
+ var initNewParameterContextDialog = function () {
+ // initialize the parameter context tabs
+ $('#parameter-context-tabs').tabbs({
+ tabStyle: 'tab',
+ selectedTabStyle: 'selected-tab',
+ scrollableTabContentStyle: 'scrollable',
+ tabs: [{
+ name: 'Settings',
+ tabContentId: 'parameter-context-standard-settings-tab-content'
+ }, {
+ name: 'Parameters',
+ tabContentId: 'parameter-context-parameters-tab-content'
+ }],
+ select: function () {
+ // update the parameters table size in case this is the first time its rendered
+ if ($(this).text() === 'Parameters') {
+ var parameterGrid = $('#parameter-table').data('gridInstance');
+ if (nfCommon.isDefinedAndNotNull(parameterGrid)) {
+ parameterGrid.resizeCanvas();
+ }
+ }
+ }
+ });
+
+ // initialize the parameter context dialog
+ $('#parameter-context-dialog').modal({
+ scrollableContentStyle: 'scrollable',
+ handler: {
+ close: function () {
+ resetDialog();
+ }
+ }
+ });
+
+ $('#parameter-dialog').modal();
+
+ $('#parameter-value-field').on('keydown', function () {
+ var sensitiveInput = $(this);
+ if (sensitiveInput.hasClass('sensitive')) {
+ sensitiveInput.removeClass('sensitive');
+ if (sensitiveInput.val() === nfCommon.config.sensitiveText) {
+ sensitiveInput.val('');
+ }
+ }
+ });
+
+ $('#parameter-set-empty-string-field').on('click', function () {
+ var sensitiveInput = $('#parameter-value-field');
+ if (sensitiveInput.hasClass('sensitive')) {
+ sensitiveInput.removeClass('sensitive');
+ if (sensitiveInput.val() === nfCommon.config.sensitiveText) {
+ sensitiveInput.val('');
+ }
+ }
+ });
+
+ $('#parameter-name').on('keydown', function (e) {
+ var code = e.keyCode ? e.keyCode : e.which;
+ if (code === $.ui.keyCode.ENTER) {
+ addNewParameter();
+
+ // prevents the enter from propagating into the field for editing the new parameter value
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
+ });
+
+ $('#add-parameter').on('click', function () {
+ var closeHandler = function () {
+ $('#parameter-name').val('');
+ $('#parameter-value-field').val('');
+ $('#parameter-description-field').val('');
+ $('#parameter-sensitive-radio-button').prop('checked', false);
+ $('#parameter-not-sensitive-radio-button').prop('checked', false);
+ $('#parameter-name').prop('disabled', false);
+ $('#parameter-sensitive-radio-button').prop('disabled', false);
+ $('#parameter-not-sensitive-radio-button').prop('disabled', false);
+ $('#parameter-set-empty-string-field').removeClass('checkbox-checked').addClass('checkbox-unchecked');
+ };
+
+ var openHandler = function () {
+ $('#parameter-sensitive-radio-button').prop('checked', false);
+ $('#parameter-not-sensitive-radio-button').prop('checked', true);
+ $('#parameter-name').focus();
+ };
+
+ $('#parameter-dialog')
+ .modal('setHeaderText', 'Add Parameter')
+ .modal('setOpenHandler', openHandler)
+ .modal('setCloseHandler', closeHandler)
+ .modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ if ($('#parameter-name').val() !== '') {
+ return false;
+ }
+ return true;
+ },
+ handler: {
+ click: function () {
+ addNewParameter();
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $(this).modal('hide');
+ }
+ }
+ }]).modal('show');
+ $('#parameter-dialog').modal('show');
+ });
+
+ $('#parameter-context-name').on('keyup', function (evt) {
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-context-dialog').modal('refreshButtons');
+ });
+
+ $('#parameter-name').on('keyup', function (evt) {
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-dialog').modal('refreshButtons');
+ });
+
+ $('#parameter-value-field').on('keyup', function (evt) {
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-dialog').modal('refreshButtons');
+ });
+
+ $('#parameter-description-field').on('keyup', function (evt) {
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-dialog').modal('refreshButtons');
+ });
+
+ $('#parameter-set-empty-string-field').on('change', function (evt) {
+ // update the buttons to possibly trigger the disabled state
+ $('#parameter-dialog').modal('refreshButtons');
+ });
+
+ initParameterTable();
+ };
+
+ /**
+ * Loads the parameter contexts.
+ */
+ var loadParameterContexts = function () {
+ var parameterContexts = $.Deferred(function (deferred) {
+ $.ajax({
+ type: 'GET',
+ url: '../nifi-api/flow/parameter-contexts',
+ dataType: 'json'
+ }).done(function (response) {
+ deferred.resolve(response);
+ }).fail(function (xhr, status, error) {
+ deferred.reject(xhr, status, error);
+ });
+ }).promise();
+
+ // return a deferred for all parts of the parameter contexts
+ return $.when(parameterContexts).done(function (response) {
+ $('#parameter-contexts-last-refreshed').text(response.currentTime);
+
+ var contexts = [];
+ $.each(response.parameterContexts, function (_, parameterContext) {
+ contexts.push($.extend({
+ type: 'ParameterContext'
+ }, parameterContext));
+ });
+
+ // update the parameter contexts
+ var parameterContextsGrid = $('#parameter-contexts-table').data('gridInstance');
+ var parameterContextsData = parameterContextsGrid.getData();
+ parameterContextsData.setItems(contexts);
+ parameterContextsData.reSort();
+ parameterContextsGrid.invalidate();
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Shows the parameter contexts.
+ */
+ var showParameterContexts = function (response) {
+ // show the parameter contexts dialog
+ nfShell.showContent('#parameter-contexts');
+
+ // adjust the table size
+ nfParameterContexts.resetTableSize();
+ };
+
+ /**
+ * Initializes the parameter contexts.
+ */
+ var initParameterContexts = function () {
+ var parameterContextActionFormatter = function (row, cell, value, columnDef, dataContext) {
+ var markup = '';
+
+ var canWrite = dataContext.permissions.canWrite;
+ var canRead = dataContext.permissions.canRead;
+
+ if (canRead && canWrite) {
+ markup += '<div title="Edit" class="pointer edit-parameter-context fa fa-pencil"></div>';
+ }
+
+ if (canRead && canWrite && nfCommon.canModifyParameterContexts()) {
+ markup += '<div title="Remove" class="pointer delete-parameter-context fa fa-trash"></div>';
+ }
+
+ // allow policy configuration conditionally
+ if (nfCanvasUtils.isManagedAuthorizer() && nfCommon.canAccessTenants()) {
+ markup += '<div title="Access Policies" class="pointer edit-access-policies fa fa-key"></div>';
+ }
+
+ return markup;
+ };
+
+ var descriptionFormatter = function (row, cell, value, columnDef, dataContext) {
+ if (!dataContext.permissions.canRead) {
+ return '';
+ }
+
+ return nfCommon.escapeHtml(dataContext.component.description);
+ };
+
+ // define the column model for the parameter contexts table
+ var parameterContextsColumnModel = [
+ {
+ id: 'name',
+ name: 'Name',
+ sortable: true,
+ resizable: true,
+ formatter: nameFormatter
+ },
+ {
+ id: 'description',
+ name: 'Description',
+ sortable: true,
+ resizable: true,
+ formatter: descriptionFormatter
+ }
+ ];
+
+ // action column should always be last
+ parameterContextsColumnModel.push({
+ id: 'actions',
+ name: ' ',
+ resizable: false,
+ formatter: parameterContextActionFormatter,
+ sortable: false,
+ width: 90,
+ maxWidth: 90
+ });
+
+ // initialize the dataview
+ var parameterContextsData = new Slick.Data.DataView({
+ inlineFilters: false
+ });
+
+ parameterContextsData.setItems([]);
+
+ // initialize the sort
+ sort({
+ columnId: 'name',
+ sortAsc: true
+ }, parameterContextsData);
+
+ // initialize the grid
+ var parameterContextsGrid = new Slick.Grid('#parameter-contexts-table', parameterContextsData, parameterContextsColumnModel, parameterContextsGridOptions);
+ parameterContextsGrid.setSelectionModel(new Slick.RowSelectionModel());
+ parameterContextsGrid.registerPlugin(new Slick.AutoTooltips());
+ parameterContextsGrid.setSortColumn('name', true);
+ parameterContextsGrid.onSort.subscribe(function (e, args) {
+ sort({
+ columnId: args.sortCol.id,
+ sortAsc: args.sortAsc
+ }, parameterContextsData);
+ });
+
+ // configure a click listener
+ parameterContextsGrid.onClick.subscribe(function (e, args) {
+ var target = $(e.target);
+
+ // get the context at this row
+ var parameterContextEntity = parameterContextsData.getItem(args.row);
+
+ // determine the desired action
+ if (parameterContextsGrid.getColumns()[args.cell].id === 'actions') {
+ if (target.hasClass('edit-parameter-context')) {
+ nfParameterContexts.showParameterContext(parameterContextEntity.id);
+ } else if (target.hasClass('delete-parameter-context')) {
+ nfParameterContexts.promptToDeleteParameterContext(parameterContextEntity);
+ } else if (target.hasClass('edit-access-policies')) {
+ nfPolicyManagement.showParameterContextPolicy(parameterContextEntity);
+
+ // close the settings dialog
+ $('#shell-close-button').click();
+ }
+ }
+ });
+
+ // wire up the dataview to the grid
+ parameterContextsData.onRowCountChanged.subscribe(function (e, args) {
+ parameterContextsGrid.updateRowCount();
+ parameterContextsGrid.render();
+ });
+ parameterContextsData.onRowsChanged.subscribe(function (e, args) {
+ parameterContextsGrid.invalidateRows(args.rows);
+ parameterContextsGrid.render();
+ });
+ parameterContextsData.syncGridSelection(parameterContextsGrid, true);
+
+ // hold onto an instance of the grid
+ $('#parameter-contexts-table').data('gridInstance', parameterContextsGrid).on('mouseenter', 'div.slick-cell', function (e) {
+ var errorIcon = $(this).find('div.has-errors');
+ if (errorIcon.length && !errorIcon.data('qtip')) {
+ var contextId = $(this).find('span.row-id').text();
+
+ // get the task item
+ var parameterContextEntity = parameterContextsData.getItemById(contextId);
+
+ // format the errors
+ var tooltip = nfCommon.formatUnorderedList(parameterContextEntity.component.validationErrors);
+
+ // show the tooltip
+ if (nfCommon.isDefinedAndNotNull(tooltip)) {
+ errorIcon.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: tooltip,
+ position: {
+ target: 'mouse',
+ viewport: $('#shell-container'),
+ adjust: {
+ x: 8,
+ y: 8,
+ method: 'flipinvert flipinvert'
+ }
+ }
+ }));
+ }
+ }
+ });
+ };
+
+ var currentParameterContextEntity = null;
+
+ var nfParameterContexts = {
+ /**
+ * Initializes the parameter contexts page.
+ */
+ init: function () {
+ // parameter context refresh button
+ $('#parameter-contexts-refresh-button').on('click', function () {
+ loadParameterContexts();
+ });
+
+ // create a new parameter context
+ $('#new-parameter-context').on('click', function () {
+ resetUsage();
+
+ $('#parameter-context-dialog').modal('setHeaderText', 'Add Parameter Context').modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ if ($('#parameter-context-name').val() !== '') {
+ return false;
+ }
+ return true;
+ },
+ handler: {
+ click: function () {
+ nfParameterContexts.addParameterContext();
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $(this).modal('hide');
+ }
+ }
+ }]).modal('show');
+
+ // set the initial focus
+ $('#parameter-context-name').focus();
+ });
+
+ // initialize the new parameter context dialog
+ initNewParameterContextDialog();
+
+ initParameterContexts();
+
+ $(window).on('resize', function (e) {
+ if ($('#parameter-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }
+ })
+ },
+
+ /**
+ * Adds a new parameter context.
+ *
+ * @param {object} parameterContextCreatedDeferred The parameter context created callback.
+ */
+ addParameterContext: function (parameterContextCreatedDeferred) {
+ // build the parameter context entity
+ var parameterContextEntity = {
+ "component": {
+ "name": $('#parameter-context-name').val(),
+ "description": $('#parameter-context-description-field').val(),
+ "parameters": marshalParameters()
+ },
+ 'revision': nfClient.getRevision({
+ 'revision': {
+ 'version': 0
+ }
+ })
+ };
+
+ var addContext = $.ajax({
+ type: 'POST',
+ url: config.urls.parameterContexts,
+ data: JSON.stringify(parameterContextEntity),
+ dataType: 'json',
+ contentType: 'application/json'
+ }).done(function (parameterContextEntity) {
+ // add the item
+ var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
+
+ if (nfCommon.isDefinedAndNotNull(parameterContextGrid)) {
+ var parameterContextData = parameterContextGrid.getData();
+ parameterContextData.addItem(parameterContextEntity);
+
+ // resort
+ parameterContextData.reSort();
+ parameterContextGrid.invalidate();
+
+ // select the new parameter context
+ var row = parameterContextData.getRowById(parameterContextEntity.id);
+ nfFilteredDialogCommon.choseRow(parameterContextGrid, row);
+ parameterContextGrid.scrollRowIntoView(row);
+ }
+
+ // invoke callback if necessary
+ if (typeof parameterContextCreatedDeferred === 'function') {
+ parameterContextCreatedDeferred(parameterContextEntity);
+ }
+ }).fail(nfErrorHandler.handleAjaxError);
+
+ // hide the dialog
+ $('#parameter-context-dialog').modal('hide');
+
+ return addContext;
+ },
+
+ /**
+ * Update the size of the grid based on its container's current size.
+ */
+ resetTableSize: function () {
+ var parameterContextsGrid = $('#parameter-contexts-table').data('gridInstance');
+ if (nfCommon.isDefinedAndNotNull(parameterContextsGrid)) {
+ parameterContextsGrid.resizeCanvas();
+ }
+ },
+
+ /**
+ * Shows the parameter context dialog.
+ */
+ showParameterContexts: function () {
+ // conditionally allow creation of new parameter contexts
+ $('#new-parameter-context').prop('disabled', !nfCommon.canModifyParameterContexts());
+
+ // load the parameter contexts
+ return loadParameterContexts().done(showParameterContexts);
+ },
+
+ /**
+ * Shows the dialog for the specified parameter context.
+ *
+ * @argument id The parameter context id
+ */
+ showParameterContext: function (id) {
+ parameterCount = 0;
+
+ // reload the parameter context in case the parameters have changed
+ var reloadContext = $.ajax({
+ type: 'GET',
+ url: config.urls.parameterContexts + '/' + encodeURIComponent(id),
+ dataType: 'json'
+ });
+
+ // once everything is loaded, show the dialog
+ reloadContext.done(function (parameterContextEntity) {
+ currentParameterContextEntity = parameterContextEntity;
+ $('#parameter-context-name').val(parameterContextEntity.component.name);
+ $('#parameter-context-description-field').val(parameterContextEntity.component.description);
+
+ loadParameters(parameterContextEntity);
+
+ // show the context
+ $('#parameter-context-dialog').modal('setHeaderText', 'Update Parameter Context').modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ if ($('#parameter-context-name').val() !== '') {
+ return false;
+ }
+ return true;
+ },
+ handler: {
+ click: function () {
+ updateParameterContext(currentParameterContextEntity);
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $(this).modal('hide');
+ }
+ }
+ }]).modal('show');
+
+ // select the parameters tab
+ $('#parameter-context-tabs').find('li:last').click();
+
+ // check if border is necessary
+ updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
+ }).fail(nfErrorHandler.handleAjaxError);
+ },
+
+ /**
+ * Prompts the user before attempting to delete the specified parameter context.
+ *
+ * @param {object} parameterContextEntity
+ */
+ promptToDeleteParameterContext: function (parameterContextEntity) {
+ // prompt for deletion
+ nfDialog.showYesNoDialog({
+ headerText: 'Delete Parameter Context',
+ dialogContent: 'Delete parameter context \'' + nfCommon.escapeHtml(parameterContextEntity.component.name) + '\'?',
+ yesHandler: function () {
+ nfParameterContexts.remove(parameterContextEntity);
+ }
+ });
+ },
+
+ /**
+ * Deletes the specified parameter context.
+ *
+ * @param {object} parameterContextEntity
+ */
+ remove: function (parameterContextEntity) {
+ $.ajax({
+ type: 'DELETE',
+ url: config.urls.parameterContexts + '/' + encodeURIComponent(parameterContextEntity.id) + '?' + $.param({
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
+ 'clientId': parameterContextEntity.revision.clientId,
+ 'version': parameterContextEntity.revision.version
+ }),
+ dataType: 'json'
+ }).done(function (response) {
+ // remove the parameter context
+ var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
+ var parameterContextData = parameterContextGrid.getData();
+ parameterContextData.deleteItem(parameterContextEntity.id);
+ }).fail(nfErrorHandler.handleAjaxError);
+ }
+ };
+
+ return nfParameterContexts;
+}));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
index 548ee20..5bcc4b6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
@@ -58,7 +58,7 @@
}
}(this, function ($, Slick, nfErrorHandler, nfCommon, nfClient, nfStorage, nfCanvasUtils, nfNgBridge, nfDialog, nfShell) {
'use strict';
-
+
var config = {
urls: {
api: '../nifi-api',
@@ -68,6 +68,7 @@
var initialized = false;
var initializedComponentRestrictions = false;
+ var initializingComponentPolicy = false;
var initAddTenantToPolicyDialog = function () {
$('#new-policy-user-button').on('click', function () {
@@ -337,7 +338,7 @@
* @returns {boolean} whether the policy supports read/write options
*/
var globalPolicySupportsReadWrite = function (policyType) {
- return policyType === 'controller' || policyType === 'counters' || policyType === 'policies' || policyType === 'tenants';
+ return policyType === 'controller' || policyType === 'parameter-contexts' || policyType === 'counters' || policyType === 'policies' || policyType === 'tenants';
};
/**
@@ -407,6 +408,7 @@
options: [
nfCommon.getPolicyTypeListing('flow'),
nfCommon.getPolicyTypeListing('controller'),
+ nfCommon.getPolicyTypeListing('parameter-contexts'),
nfCommon.getPolicyTypeListing('provenance'),
nfCommon.getPolicyTypeListing('restricted-components'),
nfCommon.getPolicyTypeListing('policies'),
@@ -518,7 +520,7 @@
}
}
});
-
+
// component policy target
$('#component-policy-target').combo({
options: [{
@@ -601,8 +603,10 @@
// set the resource
$('#selected-policy-type').text(resource);
- // reload the policy
- loadPolicy();
+ // reload the policy if we are finished loading
+ if (!initializingComponentPolicy) {
+ loadPolicy();
+ }
}
}
});
@@ -810,7 +814,7 @@
var deletePolicy = function () {
var currentEntity = $('#policy-table').data('policy');
var revision = nfClient.getRevision(currentEntity);
-
+
if (nfCommon.isDefinedAndNotNull(currentEntity)) {
$.ajax({
type: 'DELETE',
@@ -908,6 +912,8 @@
return $('<span>Showing effective policy inherited from all policies.</span>');
} else if (resource === '/controller') {
return $('<span>Showing effective policy inherited from the controller.</span>');
+ } else if (resource === '/parameter-contexts') {
+ return $('<span>Showing effective policy inherited from global parameter context policy.</span>');
} else {
// extract the group id
var processGroupId = nfCommon.substringAfterLast(resource, '/');
@@ -1319,7 +1325,7 @@
'userGroups': userGroups
}
};
-
+
$.ajax({
type: 'PUT',
url: currentEntity.uri,
@@ -1406,7 +1412,7 @@
$('#selected-policy-action').text('');
$('#selected-policy-component-id').text('');
$('#selected-policy-component-type').text('');
-
+
// clear the selected component details
$('div.policy-selected-component-container').hide();
};
@@ -1454,6 +1460,8 @@
* @param d
*/
showControllerServicePolicy: function (d) {
+ initializingComponentPolicy = true;
+
// reset the policy message
resetPolicyMessage();
@@ -1492,6 +1500,8 @@
value: 'read-component'
});
+ initializingComponentPolicy = false;
+
return loadPolicy().always(showPolicy);
},
@@ -1501,6 +1511,8 @@
* @param d
*/
showReportingTaskPolicy: function (d) {
+ initializingComponentPolicy = true;
+
// reset the policy message
resetPolicyMessage();
@@ -1515,7 +1527,7 @@
$('#policy-selected-reporting-task-container div.policy-selected-component-name').text(d.id);
}
$('#policy-selected-reporting-task-container').show();
-
+
// populate the initial resource
$('#selected-policy-component-id').text(d.id);
$('#selected-policy-component-type').text('reporting-tasks');
@@ -1539,6 +1551,8 @@
value: 'read-component'
});
+ initializingComponentPolicy = false;
+
return loadPolicy().always(showPolicy);
},
@@ -1548,6 +1562,8 @@
* @param d
*/
showTemplatePolicy: function (d) {
+ initializingComponentPolicy = true;
+
// reset the policy message
resetPolicyMessage();
@@ -1568,6 +1584,63 @@
$('#selected-policy-component-type').text('templates');
$('#component-policy-target')
.combo('setOptionEnabled', {
+ value: 'operate-component'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'write-receive-data'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'write-send-data'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'read-data'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'read-provenance'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'write-data'
+ }, false)
+ .combo('setSelectedOption', {
+ value: 'read-component'
+ });
+
+ initializingComponentPolicy = false;
+
+ return loadPolicy().always(showPolicy);
+ },
+
+ /**
+ * Shows the parameter context policy.
+ *
+ * @param d
+ */
+ showParameterContextPolicy: function (d) {
+ initializingComponentPolicy = true;
+
+ // reset the policy message
+ resetPolicyMessage();
+
+ // update the policy controls visibility
+ $('#component-policy-controls').show();
+ $('#global-policy-controls').hide();
+
+ // update the visibility
+ if (d.permissions.canRead === true) {
+ $('#policy-selected-parameter-context-container div.policy-selected-component-name').text(d.component.name);
+ } else {
+ $('#policy-selected-parameter-context-container div.policy-selected-component-name').text(d.id);
+ }
+ $('#policy-selected-parameter-context-container').show();
+
+ // populate the initial resource
+ $('#selected-policy-component-id').text(d.id);
+ $('#selected-policy-component-type').text('parameter-contexts');
+ $('#component-policy-target')
+ .combo('setOptionEnabled', {
+ value: 'operate-component'
+ }, false)
+ .combo('setOptionEnabled', {
value: 'write-receive-data'
}, false)
.combo('setOptionEnabled', {
@@ -1586,6 +1659,8 @@
value: 'read-component'
});
+ initializingComponentPolicy = false;
+
return loadPolicy().always(showPolicy);
},
@@ -1593,6 +1668,8 @@
* Shows the component policy dialog.
*/
showComponentPolicy: function (selection) {
+ initializingComponentPolicy = true;
+
// reset the policy message
resetPolicyMessage();
@@ -1602,7 +1679,7 @@
// update the visibility
$('#policy-selected-component-container').show();
-
+
var resource;
if (selection.empty()) {
$('#selected-policy-component-id').text(nfCanvasUtils.getGroupId());
@@ -1611,6 +1688,9 @@
// disable site to site option
$('#component-policy-target')
.combo('setOptionEnabled', {
+ value: 'operate-component'
+ }, true)
+ .combo('setOptionEnabled', {
value: 'write-receive-data'
}, false)
.combo('setOptionEnabled', {
@@ -1648,6 +1728,9 @@
// enable site to site option
$('#component-policy-target')
.combo('setOptionEnabled', {
+ value: 'operate-component'
+ }, !nfCanvasUtils.isLabel(selection))
+ .combo('setOptionEnabled', {
value: 'write-receive-data'
}, nfCanvasUtils.isInputPort(selection) && d.allowRemoteAccess === true)
.combo('setOptionEnabled', {
@@ -1667,6 +1750,8 @@
value: 'read-component'
});
+ initializingComponentPolicy = false;
+
return loadPolicy().always(showPolicy);
},
@@ -1698,4 +1783,4 @@
};
return nfPolicyManagement;
-}));
\ 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-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 d354096..9650d32 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
@@ -60,10 +60,12 @@
'use strict';
var nfControllerServices;
+ var nfParameterContexts;
var config = {
urls: {
- api: '../nifi-api'
+ api: '../nifi-api',
+ parameterContexts: '../nifi-api/flow/parameter-contexts'
}
};
@@ -100,7 +102,10 @@
'component': {
'id': groupId,
'name': $('#process-group-name').val(),
- 'comments': $('#process-group-comments').val()
+ 'comments': $('#process-group-comments').val(),
+ 'parameterContext': {
+ 'id': $('#process-group-parameter-context-combo').combo('getSelectedOption').value
+ }
}
};
@@ -128,6 +133,25 @@
saveConfiguration(response.revision.version, groupId);
});
+ var controllerServicesUri = config.urls.api + '/flow/process-groups/' + encodeURIComponent(groupId) + '/controller-services';
+
+ $.ajax({
+ type: 'GET',
+ url: controllerServicesUri,
+ dataType: 'json'
+ }).done(function (response) {
+ var serviceTable = getControllerServicesTable();
+
+ nfCommon.cleanUpTooltips(serviceTable, 'div.has-errors');
+
+ var controllerServicesGrid = serviceTable.data('gridInstance');
+ var controllerServicesData = controllerServicesGrid.getData();
+
+ $.each(response.controllerServices, function (_, controllerServiceEntity) {
+ controllerServicesData.updateItem(controllerServiceEntity.id, controllerServiceEntity);
+ });
+ });
+
nfCanvasUtils.reload();
}).fail(nfErrorHandler.handleConfigurationUpdateAjaxError);
};
@@ -139,8 +163,8 @@
*/
var loadConfiguration = function (groupId) {
var setUnauthorizedText = function () {
- $('#read-only-process-group-name').addClass('unset').text('Unauthorized');
- $('#read-only-process-group-comments').addClass('unset').text('Unauthorized');
+ $('#read-only-process-group-name').text('Unauthorized');
+ $('#read-only-process-group-comments').text('Unauthorized');
};
var setEditable = function (editable) {
@@ -201,8 +225,8 @@
} else {
if (response.permissions.canRead) {
// populate the process group settings
- $('#read-only-process-group-name').removeClass('unset').text(processGroup.name);
- $('#read-only-process-group-comments').removeClass('unset').text(processGroup.comments);
+ $('#read-only-process-group-name').text(processGroup.name);
+ $('#read-only-process-group-comments').text(processGroup.comments);
// populate the header
$('#process-group-configuration-header-text').text(processGroup.name + ' Configuration');
@@ -212,23 +236,25 @@
setEditable(false);
}
- deferred.resolve();
+ deferred.resolve(response);
}).fail(function (xhr, status, error) {
if (xhr.status === 403) {
+ var unauthorizedGroup;
if (groupId === nfCanvasUtils.getGroupId()) {
- $('#process-group-configuration').data('process-group', {
+ unauthorizedGroup = {
'permissions': {
canRead: false,
canWrite: nfCanvasUtils.canWriteCurrentGroup()
}
- });
+ };
} else {
- $('#process-group-configuration').data('process-group', nfProcessGroup.get(groupId));
+ unauthorizedGroup = nfProcessGroup.get(groupId);
}
+ $('#process-group-configuration').data('process-group', unauthorizedGroup);
setUnauthorizedText();
setEditable(false);
- deferred.resolve();
+ deferred.resolve(unauthorizedGroup);
} else {
deferred.reject(xhr, status, error);
}
@@ -239,12 +265,127 @@
var controllerServicesUri = config.urls.api + '/flow/process-groups/' + encodeURIComponent(groupId) + '/controller-services';
var controllerServices = nfControllerServices.loadControllerServices(controllerServicesUri, getControllerServicesTable());
+ var parameterContexts = $.ajax({
+ type: 'GET',
+ url: config.urls.parameterContexts,
+ dataType: 'json'
+ });
+
// wait for everything to complete
- return $.when(processGroup, controllerServices).done(function (processGroupResult, controllerServicesResult) {
+ return $.when(processGroup, controllerServices, parameterContexts).done(function (processGroupResult, controllerServicesResult, parameterContextsResult) {
var controllerServicesResponse = controllerServicesResult[0];
+ var parameterContextsResponse = parameterContextsResult[0];
// update the current time
$('#process-group-configuration-last-refreshed').text(controllerServicesResponse.currentTime);
+
+ var parameterContexts = parameterContextsResponse.parameterContexts;
+ var options = [{
+ text: 'No parameter context',
+ value: null
+ }];
+ parameterContexts.forEach(function (parameterContext) {
+ var option;
+ if (parameterContext.permissions.canRead) {
+ option = {
+ 'text': parameterContext.component.name,
+ 'value': parameterContext.id,
+ 'description': parameterContext.component.description
+ };
+ } else {
+ option = {
+ 'text': parameterContext.id,
+ 'value': parameterContext.id
+ }
+ }
+
+ options.push(option);
+ });
+
+ var createNewParameterContextOption = {
+ text: 'Create new parameter context...',
+ value: undefined,
+ optionClass: 'unset'
+ };
+
+ if (nfCommon.canModifyParameterContexts()) {
+ options.push(createNewParameterContextOption);
+ }
+
+ var comboOptions = {
+ options: options,
+ select: function (option) {
+ if (typeof option.value === 'undefined') {
+ $('#parameter-context-dialog').modal('setHeaderText', 'Add Parameter Context').modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ if ($('#parameter-context-name').val() !== '') {
+ return false;
+ }
+ return true;
+ },
+ handler: {
+ click: function () {
+ nfParameterContexts.addParameterContext(function (parameterContextEntity) {
+ options.pop();
+ var option = {
+ 'text': parameterContextEntity.component.name,
+ 'value': parameterContextEntity.component.id,
+ 'description': parameterContextEntity.component.description
+ };
+ options.push(option);
+
+ if (nfCommon.canModifyParameterContexts()) {
+ options.push(createNewParameterContextOption);
+ }
+
+ comboOptions.selectedOption = {
+ value: parameterContextEntity.component.id
+ };
+
+ combo.combo('destroy').combo(comboOptions);
+ });
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $(this).modal('hide');
+ }
+ }
+ }]).modal('show');
+
+ // set the initial focus
+ $('#parameter-context-name').focus();
+ }
+ }
+ };
+
+ // initialize the parameter context combo
+ var combo = $('#process-group-parameter-context-combo').combo('destroy').combo(comboOptions);
+
+ // populate the parameter context
+ if (processGroupResult.permissions.canRead) {
+ var parameterContextId = null;
+ if ($.isEmptyObject(processGroupResult.component.parameterContext) === false) {
+ parameterContextId = processGroupResult.component.parameterContext.id;
+ }
+
+ $('#process-group-parameter-context-combo').combo('setSelectedOption', {
+ value: parameterContextId
+ });
+ }
}).fail(nfErrorHandler.handleAjaxError);
};
@@ -288,9 +429,11 @@
* Initialize the process group configuration.
*
* @param nfControllerServicesRef The nfControllerServices module.
+ * @param nfParameterContextsRef The nfParameterContexts module.
*/
- init: function (nfControllerServicesRef) {
+ init: function (nfControllerServicesRef, nfParameterContextsRef) {
nfControllerServices = nfControllerServicesRef;
+ nfParameterContexts = nfParameterContextsRef;
// initialize the process group configuration tabs
$('#process-group-configuration-tabs').tabbs({
@@ -384,4 +527,4 @@
};
return nfProcessGroupConfiguration;
-}));
\ 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-settings.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index d6a5796..c2533f0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -1229,11 +1229,11 @@
// open the documentation for this reporting task
nfShell.showPage('../nifi-docs/documentation?' + $.param({
- select: reportingTaskEntity.component.type,
- group: reportingTaskEntity.component.bundle.group,
- artifact: reportingTaskEntity.component.bundle.artifact,
- version: reportingTaskEntity.component.bundle.version
- })).done(function () {
+ select: reportingTaskEntity.component.type,
+ group: reportingTaskEntity.component.bundle.group,
+ artifact: reportingTaskEntity.component.bundle.artifact,
+ version: reportingTaskEntity.component.bundle.version
+ })).done(function () {
nfSettings.showSettings();
});
}
@@ -1944,4 +1944,4 @@
};
return nfSettings;
-}));
\ 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-variable-registry.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js
index 120506e..cfd18f5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js
@@ -576,7 +576,7 @@
// only populate affected components if this variable is different than the last selected
if (lastSelectedId === null || lastSelectedId !== variable.id) {
// update the details for this variable
- $('#affected-components-context').removeClass('unset').text(variable.name);
+ $('#variable-affected-components-context').removeClass('unset').text(variable.name);
populateAffectedComponents(variable.affectedComponents);
// update the last selected id
@@ -1150,7 +1150,7 @@
$('<li class="affected-component-container"><span class="unset">None</span></li>').appendTo(unauthorizedComponentsContainer);
// update the selection context
- $('#affected-components-context').addClass('unset').text('None');
+ $('#variable-affected-components-context').addClass('unset').text('None');
} else {
// select the desired row
variableGrid.setSelectedRows([index]);
@@ -1202,7 +1202,7 @@
var variableNames = variables.map(function (v) {
return v.variable.name;
});
- $('#affected-components-context').removeClass('unset').text(variableNames.join(', '));
+ $('#variable-affected-components-context').removeClass('unset').text(variableNames.join(', '));
// get the current group id
var processGroupId = $('#variable-registry-process-group-id').text();
@@ -1533,7 +1533,7 @@
$('#process-group-variable-registry').text('');
$('#variable-registry-process-group-id').text('').removeData('revision');
- $('#affected-components-context').removeClass('unset').text('');
+ $('#variable-affected-components-context').removeClass('unset').text('');
var variableGrid = $('#variable-registry-table').data('gridInstance');
var variableData = variableGrid.getData();
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 7e5a1c0..1b918ff 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
@@ -115,7 +115,11 @@
}, {
text: 'access the controller',
value: 'controller',
- description: 'Allows users to view/modify the controller including Reporting Tasks, Controller Services, and Nodes in the Cluster'
+ description: 'Allows users to view/modify the controller including Reporting Tasks, Controller Services, Parameter Contexts, and Nodes in the Cluster'
+ }, {
+ text: 'access parameter contexts',
+ value: 'parameter-contexts',
+ description: 'Allows users to view/modify Parameter Contexts'
}, {
text: 'query provenance',
value: 'provenance',
@@ -709,6 +713,19 @@
},
/**
+ * Determines whether the current user can modify parameter contexts.
+ *
+ * @returns {boolean}
+ */
+ canModifyParameterContexts: function () {
+ if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
+ return nfCommon.currentUser.parameterContextPermissions.canRead === true && nfCommon.currentUser.parameterContextPermissions.canWrite === true;
+ } else {
+ return false;
+ }
+ },
+
+ /**
* Determines whether the current user can access counters.
*
* @returns {boolean}