NIFI-8491: Adding support for configuring parameter context inheritance (#5371)

* NIFI-8491:
- Adding support for configuring parameter context inheritance.

* NIFI-8491:
- Allowing changes to the parameter context inheritance to drive Apply disabled state.

* NIFI-8491: Updating StandardParameterContext#isAuthorized check

* NIFI-8491:
- Showing selected inherited parameter contexts in ready only form when appropriate.
- Allowing available parameter contexts to be inherited by double clicking.
- Removing support for rendering unauthorized inherited parameter contexts as they can no longer be opened.

* NIFI-8491: Adding inherited param context verification earlier

* NIFI-8491:
- Addressing CI failures by rolling back to some order JS language spec to allow yui-compress to minify and compress.

* NIFI-8491:
- Ensuring selected context sort order is honored.
- Ensuring the Apply button is correctly enabled.
- Showing Pending Apply message when selected Parameter Context changes.
- Ensuring the Parameter's tab is selected now that there is a third tab.

* Updates to inherited param context verification

* Improving validation between parameters/inherited parameters

* NIFI-8491:
- Ensuring the available parameter contexts are loaded whether the edit dialog is opened from the listing or outside of the listing.

* NIFI-8491:
- Fixing conditions we check if the parameter context listing is currently open.

* NIFI-8491:
- Waiting for the parameter contexts to load prior to rendering the parameter context inheritance tab and showing the dialog.

* NIFI-8491:
- Fixing pending apply message clipping.
- Hiding pending apply message after clicking Apply.

Co-authored-by: Joe Gresock <jgresock@gmail.com>

This closes #5371
This commit is contained in:
Matt Gilman 2021-09-29 17:04:35 -04:00 committed by GitHub
parent 46a5e3f096
commit be57a210ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 700 additions and 195 deletions

View File

@ -32,6 +32,7 @@ public class ParameterDTO {
private Boolean valueRemoved;
private Set<AffectedComponentEntity> referencingComponents;
private ParameterContextReferenceEntity parameterContext;
private Boolean inherited;
@ApiModelProperty("The name of the Parameter")
public String getName() {
@ -42,6 +43,15 @@ public class ParameterDTO {
this.name = name;
}
@ApiModelProperty(value = "Whether or not the Parameter is inherited from another context", accessMode = ApiModelProperty.AccessMode.READ_ONLY)
public Boolean getInherited() {
return inherited;
}
public void setInherited(final Boolean inherited) {
this.inherited = inherited;
}
@ApiModelProperty("The description of the Parameter")
public String getDescription() {
return description;

View File

@ -35,6 +35,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -123,7 +124,7 @@ public class StandardParameterContext implements ParameterContext {
final Map<String, Parameter> effectiveParameterUpdates = getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
verifyCanSetParameters(effectiveParameterUpdates);
verifyCanSetParameters(effectiveParameterUpdates, true);
// Update the actual parameters
updateParameters(parameters, updatedParameters, true);
@ -339,6 +340,17 @@ public class StandardParameterContext implements ParameterContext {
}
}
@Override
public Map<String, Parameter> getEffectiveParameterUpdates(final Map<String, Parameter> parameterUpdates, final List<ParameterContext> inheritedParameterContexts) {
Objects.requireNonNull(parameterUpdates, "Parameter Updates must be specified");
Objects.requireNonNull(inheritedParameterContexts, "Inherited parameter contexts must be specified");
final Map<ParameterDescriptor, Parameter> currentEffectiveParameters = getEffectiveParameters();
final Map<ParameterDescriptor, Parameter> effectiveProposedParameters = getEffectiveParameters(inheritedParameterContexts, getProposedParameters(parameterUpdates), new HashMap<>());
return getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
}
/**
* Constructs an effective view of the parameters, including nested parameters, assuming the given map of parameters.
* This allows an inspection of what parameters would be available if the given parameters were set in this ParameterContext.
@ -373,15 +385,23 @@ public class StandardParameterContext implements ParameterContext {
// Loop backwards so that the first ParameterContext in the list will override any parameters later in the list
for(int i = parameterContexts.size() - 1; i >= 0; i--) {
ParameterContext parameterContext = parameterContexts.get(i);
allOverrides.putAll(overrideParameters(effectiveParameters, parameterContext.getEffectiveParameters(), parameterContext));
combineOverrides(allOverrides, overrideParameters(effectiveParameters, parameterContext.getEffectiveParameters(), parameterContext));
}
// Finally, override all child parameters with our own
allOverrides.putAll(overrideParameters(effectiveParameters, proposedParameters, this));
combineOverrides(allOverrides, overrideParameters(effectiveParameters, proposedParameters, this));
return effectiveParameters;
}
private void combineOverrides(final Map<ParameterDescriptor, List<Parameter>> existingOverrides, final Map<ParameterDescriptor, List<Parameter>> newOverrides) {
for (final Map.Entry<ParameterDescriptor, List<Parameter>> entry : newOverrides.entrySet()) {
final ParameterDescriptor key = entry.getKey();
final List<Parameter> existingOverrideList = existingOverrides.computeIfAbsent(key, k -> new ArrayList<>());
existingOverrideList.addAll(entry.getValue());
}
}
private Map<ParameterDescriptor, List<Parameter>> overrideParameters(final Map<ParameterDescriptor, Parameter> existingParameters,
final Map<ParameterDescriptor, Parameter> overridingParameters,
final ParameterContext overridingContext) {
@ -456,32 +476,49 @@ public class StandardParameterContext implements ParameterContext {
}
}
@Override
public void verifyCanUpdateParameterContext(final Map<String, Parameter> parameterUpdates, final List<ParameterContext> inheritedParameterContexts) {
verifyCanUpdateParameterContext(parameterUpdates, inheritedParameterContexts, false);
}
private void verifyCanUpdateParameterContext(final Map<String, Parameter> parameterUpdates, final List<ParameterContext> inheritedParameterContexts, final boolean duringUpdate) {
if (inheritedParameterContexts == null) {
return;
}
verifyNoCycles(inheritedParameterContexts);
final Map<ParameterDescriptor, Parameter> currentEffectiveParameters = getEffectiveParameters();
final Map<ParameterDescriptor, Parameter> effectiveProposedParameters = getEffectiveParameters(inheritedParameterContexts, getProposedParameters(parameterUpdates), new HashMap<>());
final Map<String, Parameter> effectiveParameterUpdates = getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
try {
verifyCanSetParameters(currentEffectiveParameters, effectiveParameterUpdates, duringUpdate);
} catch (final IllegalStateException e) {
// Wrap with a more accurate message
throw new IllegalStateException(String.format("Could not update inherited Parameter Contexts for Parameter Context [%s] because: %s",
name, e.getMessage()), e);
}
}
@Override
public void setInheritedParameterContexts(final List<ParameterContext> inheritedParameterContexts) {
if (inheritedParameterContexts.equals(this.inheritedParameterContexts)) {
if (inheritedParameterContexts == null || inheritedParameterContexts.equals(this.inheritedParameterContexts)) {
// No changes
return;
}
verifyCanUpdateParameterContext(Collections.emptyMap(), inheritedParameterContexts, true);
final Map<String, ParameterUpdate> parameterUpdates = new HashMap<>();
writeLock.lock();
try {
this.version++;
verifyNoCycles(inheritedParameterContexts);
final Map<ParameterDescriptor, Parameter> currentEffectiveParameters = getEffectiveParameters();
final Map<ParameterDescriptor, Parameter> effectiveProposedParameters = getEffectiveParameters(inheritedParameterContexts);
final Map<String, Parameter> effectiveParameterUpdates = getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
try {
verifyCanSetParameters(currentEffectiveParameters, effectiveParameterUpdates);
} catch (final IllegalStateException e) {
// Wrap with a more accurate message
throw new IllegalStateException(String.format("Could not update inherited Parameter Contexts for Parameter Context [%s] because: %s",
name, e.getMessage()), e);
}
this.inheritedParameterContexts.clear();
this.inheritedParameterContexts.addAll(inheritedParameterContexts);
@ -570,17 +607,30 @@ public class StandardParameterContext implements ParameterContext {
@Override
public void verifyCanSetParameters(final Map<String, Parameter> updatedParameters) {
verifyCanSetParameters(parameters, updatedParameters);
verifyCanSetParameters(updatedParameters, false);
}
public void verifyCanSetParameters(final Map<ParameterDescriptor, Parameter> currentParameters, final Map<String, Parameter> updatedParameters) {
/**
* Ensures that it is legal to update the Parameters for this Parameter Context to match the given set of Parameters
* @param updatedParameters the updated set of parameters, keyed by Parameter name
* @param duringUpdate If true, this check will be treated as if a ParameterContext update is imminent, meaning
* referencing components may not be active even for updated values. If false, a parameter
* value update will be valid even if referencing components are active because it will be
* assumed that these will be stopped prior to the actual update.
* @throws IllegalStateException if setting the given set of Parameters is not legal
*/
public void verifyCanSetParameters(final Map<String, Parameter> updatedParameters, final boolean duringUpdate) {
verifyCanSetParameters(parameters, updatedParameters, duringUpdate);
}
public void verifyCanSetParameters(final Map<ParameterDescriptor, Parameter> currentParameters, final Map<String, Parameter> updatedParameters, final boolean duringUpdate) {
// Ensure that the updated parameters will not result in changing the sensitivity flag of any parameter.
for (final Map.Entry<String, Parameter> entry : updatedParameters.entrySet()) {
final String parameterName = entry.getKey();
final Parameter parameter = entry.getValue();
if (parameter == null) {
// parameter is being deleted.
validateReferencingComponents(parameterName, null,"remove");
validateReferencingComponents(parameterName, null, duringUpdate);
continue;
}
@ -589,7 +639,7 @@ public class StandardParameterContext implements ParameterContext {
}
validateSensitiveFlag(currentParameters, parameter);
validateReferencingComponents(parameterName, parameter, "update");
validateReferencingComponents(parameterName, parameter, duringUpdate);
}
}
@ -611,11 +661,12 @@ public class StandardParameterContext implements ParameterContext {
}
}
private void validateReferencingComponents(final String parameterName, final Parameter parameter, final String parameterAction) {
private void validateReferencingComponents(final String parameterName, final Parameter parameter, final boolean duringUpdate) {
final boolean isDeletion = (parameter == null);
final String action = isDeletion ? "remove" : "update";
for (final ProcessorNode procNode : parameterReferenceManager.getProcessorsReferencing(this, parameterName)) {
if (procNode.isRunning()) {
throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + parameterName + "' because it is referenced by " + procNode + ", which is currently running");
if (procNode.isRunning() && (isDeletion || duringUpdate)) {
throw new IllegalStateException("Cannot " + action + " parameter '" + parameterName + "' because it is referenced by " + procNode + ", which is currently running");
}
if (parameter != null) {
@ -625,9 +676,9 @@ public class StandardParameterContext implements ParameterContext {
for (final ControllerServiceNode serviceNode : parameterReferenceManager.getControllerServicesReferencing(this, parameterName)) {
final ControllerServiceState serviceState = serviceNode.getState();
if (serviceState != ControllerServiceState.DISABLED) {
throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + parameterName + "' because it is referenced by "
+ serviceNode + ", which currently has a state of " + serviceState);
if (serviceState != ControllerServiceState.DISABLED && (isDeletion || duringUpdate)) {
throw new IllegalStateException("Cannot " + action + " parameter '" + parameterName + "' because it is referenced by "
+ serviceNode + ", which currently has a state of " + serviceState);
}
if (parameter != null) {
@ -678,6 +729,22 @@ public class StandardParameterContext implements ParameterContext {
}
}
@Override
public boolean isAuthorized(final Authorizer authorizer, final RequestAction action, final NiFiUser user) {
boolean isAuthorized = ParameterContext.super.isAuthorized(authorizer, action, user);
if (RequestAction.READ == action) {
for (final ParameterContext parameterContext : inheritedParameterContexts) {
isAuthorized &= parameterContext.isAuthorized(authorizer, action, user);
if (!isAuthorized) {
break;
}
}
}
return isAuthorized;
}
@Override
public Authorizable getParentAuthorizable() {
return new Authorizable() {

View File

@ -109,12 +109,29 @@ public interface ParameterContext extends ParameterLookup, ComponentAuthorizable
*/
Map<ParameterDescriptor, Parameter> getEffectiveParameters();
/**
* Returns the resulting map of effective parameter updates if the given parameter updates and inherited parameter contexts were to be applied.
* This allows potential changes to be detected before actually applying the parameter updates.
* @param parameterUpdates A map from parameter name to updated parameter (null if removal is desired)
* @param inheritedParameterContexts An ordered list of parameter contexts to inherit from
* @return The effective map of parameter updates that would result if these changes were applied. This includes only parameters that would
* be effectively updated or removed, and is mapped by parameter name
*/
Map<String, Parameter> getEffectiveParameterUpdates(Map<String, Parameter> parameterUpdates, List<ParameterContext> inheritedParameterContexts);
/**
* Returns the ParameterReferenceManager that is associated with this ParameterContext
* @return the ParameterReferenceManager that is associated with this ParameterContext
*/
ParameterReferenceManager getParameterReferenceManager();
/**
* Verifies whether the parameter context can be updated with the provided parameters and inherited parameter contexts.
* @param parameterUpdates A map from parameter name to updated parameter (null if removal is desired)
* @param inheritedParameterContexts the list of ParameterContexts from which to inherit parameters
*/
void verifyCanUpdateParameterContext(Map<String, Parameter> parameterUpdates, List<ParameterContext> inheritedParameterContexts);
/**
* Updates the ParameterContexts within this context to match the given list of ParameterContexts. All parameter in these
* ParameterContexts are inherited by this ParameterContext, and can be referenced as if they were actually in this ParameterContext.
@ -125,7 +142,7 @@ public interface ParameterContext extends ParameterLookup, ComponentAuthorizable
*
* @param inheritedParameterContexts the list of ParameterContexts from which to inherit parameters, in priority order first to last
* @throws IllegalStateException if the list of ParameterContexts is invalid (in case of a circular reference or
* in case {@link #verifyCanSetParameters(Map)} verifyCanSetParameters} would throw an exception)
* in case {@link #verifyCanSetParameters(Map) verifyCanSetParameters} would throw an exception)
*/
void setInheritedParameterContexts(List<ParameterContext> inheritedParameterContexts);

View File

@ -91,6 +91,14 @@ import org.apache.nifi.controller.status.ProcessGroupStatus;
import org.apache.nifi.controller.status.ProcessorStatus;
import org.apache.nifi.diagnostics.SystemDiagnostics;
import org.apache.nifi.events.BulletinFactory;
import org.apache.nifi.flow.VersionedComponent;
import org.apache.nifi.flow.VersionedConfigurableComponent;
import org.apache.nifi.flow.VersionedConnection;
import org.apache.nifi.flow.VersionedControllerService;
import org.apache.nifi.flow.VersionedFlowCoordinates;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flow.VersionedProcessor;
import org.apache.nifi.flow.VersionedPropertyDescriptor;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.ProcessGroupCounts;
import org.apache.nifi.groups.RemoteProcessGroup;
@ -119,19 +127,11 @@ import org.apache.nifi.registry.flow.FlowRegistry;
import org.apache.nifi.registry.flow.FlowRegistryClient;
import org.apache.nifi.registry.flow.RestBasedFlowRegistry;
import org.apache.nifi.registry.flow.VersionControlInformation;
import org.apache.nifi.flow.VersionedComponent;
import org.apache.nifi.flow.VersionedConfigurableComponent;
import org.apache.nifi.flow.VersionedConnection;
import org.apache.nifi.flow.VersionedControllerService;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.flow.VersionedFlowCoordinates;
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import org.apache.nifi.registry.flow.VersionedFlowState;
import org.apache.nifi.registry.flow.VersionedParameterContext;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flow.VersionedProcessor;
import org.apache.nifi.flow.VersionedPropertyDescriptor;
import org.apache.nifi.registry.flow.diff.ComparableDataFlow;
import org.apache.nifi.registry.flow.diff.ConciseEvolvingDifferenceDescriptor;
import org.apache.nifi.registry.flow.diff.DifferenceType;
@ -1315,6 +1315,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
group -> group.getParameterContext() != null && (group.getParameterContext().getIdentifier().equals(parameterContextDto.getId())
|| group.getParameterContext().inheritsFrom(parameterContext.getIdentifier())));
setEffectiveParameterUpdates(parameterContextDto);
final Set<String> updatedParameterNames = getUpdatedParameterNames(parameterContextDto);
// Clear set of Affected Components for each Parameter. This parameter is read-only and it will be populated below.
@ -1371,6 +1373,39 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
return dtoFactory.createAffectedComponentEntities(affectedComponents, revisionManager);
}
private void setEffectiveParameterUpdates(final ParameterContextDTO parameterContextDto) {
final ParameterContext parameterContext = parameterContextDAO.getParameterContext(parameterContextDto.getId());
final Map<String, Parameter> parameterUpdates = parameterContextDAO.getParameters(parameterContextDto, parameterContext);
final List<ParameterContext> inheritedParameterContexts = parameterContextDAO.getInheritedParameterContexts(parameterContextDto);
final Map<String, Parameter> proposedParameterUpdates = parameterContext.getEffectiveParameterUpdates(parameterUpdates, inheritedParameterContexts);
final Map<String, ParameterEntity> parameterEntities = parameterContextDto.getParameters().stream()
.collect(Collectors.toMap(entity -> entity.getParameter().getName(), Function.identity()));
parameterContextDto.getParameters().clear();
for (final Map.Entry<String, Parameter> entry : proposedParameterUpdates.entrySet()) {
final String parameterName = entry.getKey();
final Parameter parameter = entry.getValue();
final ParameterEntity parameterEntity;
if (parameterEntities.containsKey(parameterName)) {
parameterEntity = parameterEntities.get(parameterName);
} else if (parameter == null) {
parameterEntity = new ParameterEntity();
final ParameterDTO parameterDTO = new ParameterDTO();
parameterDTO.setName(parameterName);
parameterEntity.setParameter(parameterDTO);
} else {
parameterEntity = dtoFactory.createParameterEntity(parameterContext, parameter, revisionManager, parameterContextDAO);
}
// Parameter is inherited if either this is the removal of a parameter not directly in this context, or it's parameter not specified directly in the DTO
final boolean isInherited = (parameter == null && !parameterContext.getParameters().containsKey(new ParameterDescriptor.Builder().name(parameterName).build()))
|| (parameter != null && !parameterEntities.containsKey(parameterName));
parameterEntity.getParameter().setInherited(isInherited);
parameterContextDto.getParameters().add(parameterEntity);
}
}
private void addReferencingComponents(final ControllerServiceNode service, final Set<ComponentNode> affectedComponents, final List<ParameterDTO> affectedParameterDtos,
final boolean includeInactive) {

View File

@ -575,7 +575,7 @@ public final class EntityFactory {
final ParameterContextEntity entity = new ParameterContextEntity();
entity.setRevision(revision);
if (dto != null) {
entity.setPermissions(permissions);;
entity.setPermissions(permissions);
entity.setId(dto.getId());
if (permissions != null && permissions.getCanRead()) {

View File

@ -16,10 +16,13 @@
*/
package org.apache.nifi.web.dao;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterContextLookup;
import org.apache.nifi.web.api.dto.ParameterContextDTO;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface ParameterContextDAO extends ParameterContextLookup {
@ -39,6 +42,14 @@ public interface ParameterContextDAO extends ParameterContextLookup {
*/
ParameterContext createParameterContext(ParameterContextDTO parameterContextDto);
/**
* Returns a map from parameter name to intended parameter, given the DTO.
* @param parameterContextDto A parameter context DTO containing parameter updates
* @param context The existing parameter context
* @return The resulting parameter map containing updated parameters (or removals)
*/
Map<String, Parameter> getParameters(ParameterContextDTO parameterContextDto, ParameterContext context);
/**
* Gets all of the parameter contexts.
*
@ -54,6 +65,13 @@ public interface ParameterContextDAO extends ParameterContextLookup {
*/
ParameterContext updateParameterContext(ParameterContextDTO parameterContextDto);
/**
* Returns a list of the inherited parameter contexts proposed by the DTO.
* @param parameterContextDto The parameter context DTO
* @return a list of the inherited parameter contexts proposed by the DTO
*/
List<ParameterContext> getInheritedParameterContexts(ParameterContextDTO parameterContextDto);
/**
* Determines whether this parameter context can be updated.
*

View File

@ -20,11 +20,8 @@ import org.apache.nifi.authorization.Authorizer;
import org.apache.nifi.authorization.RequestAction;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.controller.ComponentNode;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.PropertyConfiguration;
import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.controller.service.ControllerServiceState;
@ -32,8 +29,6 @@ import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterDescriptor;
import org.apache.nifi.parameter.ParameterReference;
import org.apache.nifi.parameter.ParameterReferenceManager;
import org.apache.nifi.web.ResourceNotFoundException;
import org.apache.nifi.web.api.dto.ParameterContextDTO;
import org.apache.nifi.web.api.dto.ParameterContextReferenceDTO;
@ -73,7 +68,7 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
if (inheritedParameterContexts != null) {
resolveInheritedParameterContexts(parameterContextDto);
// This will throw an exception if one is not found
inheritedParameterContexts.stream().forEach(entity -> flowManager.getParameterContextManager()
inheritedParameterContexts.forEach(entity -> flowManager.getParameterContextManager()
.getParameterContext(entity.getComponent().getId()));
}
authorizeReferences(parameterContextDto);
@ -136,7 +131,8 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
}
}
private Map<String, Parameter> getParameters(final ParameterContextDTO parameterContextDto, final ParameterContext context) {
@Override
public Map<String, Parameter> getParameters(final ParameterContextDTO parameterContextDto, final ParameterContext context) {
final Set<ParameterEntity> parameterEntities = parameterContextDto.getParameters();
if (parameterEntities == null) {
return Collections.emptyMap();
@ -146,6 +142,11 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
for (final ParameterEntity parameterEntity : parameterEntities) {
final ParameterDTO parameterDto = parameterEntity.getParameter();
// Inherited parameters are only included for referencing components, but we should not save them as direct parameters
if (parameterDto.getInherited() != null && parameterDto.getInherited()) {
continue;
}
if (parameterDto.getName() == null) {
throw new IllegalArgumentException("Cannot specify a Parameter without a name");
}
@ -226,7 +227,8 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
return context;
}
private List<ParameterContext> getInheritedParameterContexts(final ParameterContextDTO parameterContextDto) {
@Override
public List<ParameterContext> getInheritedParameterContexts(final ParameterContextDTO parameterContextDto) {
resolveInheritedParameterContexts(parameterContextDto);
final List<ParameterContext> inheritedParameterContexts = new ArrayList<>();
@ -243,76 +245,10 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
verifyInheritedParameterContextRefs(parameterContextDto);
final ParameterContext currentContext = getParameterContext(parameterContextDto.getId());
for (final ParameterEntity parameterEntity : parameterContextDto.getParameters()) {
final ParameterDTO parameterDto = parameterEntity.getParameter();
final String parameterName = parameterDto.getName();
final ParameterReferenceManager referenceManager = currentContext.getParameterReferenceManager();
for (final ProcessorNode processor : referenceManager.getProcessorsReferencing(currentContext, parameterName)) {
verifyParameterUpdate(parameterDto, processor, currentContext.getName(), verifyComponentStates, processor.isRunning(), "Processor that is running");
}
final Set<ControllerServiceNode> referencingServices = referenceManager.getControllerServicesReferencing(currentContext, parameterName);
for (final ControllerServiceNode serviceNode : referencingServices) {
final ControllerServiceState serviceState = serviceNode.getState();
final boolean serviceActive = serviceState != ControllerServiceState.DISABLED;
verifyParameterUpdate(parameterDto, serviceNode, currentContext.getName(), verifyComponentStates, serviceActive,
"Controller Service [id=" + serviceNode.getIdentifier() + "] with a state of " + serviceState + " (state expected to be DISABLED)");
}
}
}
private void verifyParameterUpdate(final ParameterDTO parameterDto, final ComponentNode component, final String contextName,
final boolean verifyComponentStates, final boolean active, final String activeExplanation) {
final String parameterName = parameterDto.getName();
final Boolean parameterSensitive = parameterDto.getSensitive();
final boolean parameterDeletion = parameterDto.getDescription() == null && parameterDto.getSensitive() == null && parameterDto.getValue() == null;
// For any parameter that is added or modified, we need to ensure that the new configuration will not result in a Sensitive Parameter being referenced by a non-Sensitive Property
// or a Non-Sensitive Parameter being referenced by a Sensitive Property.
// Additionally, if 'verifyComponentStates' or parameter is being deleted, we must ensure that any component that references a value that is to be updated
// is stopped (if a processor) or disabled (if a controller service).
for (final Map.Entry<PropertyDescriptor, PropertyConfiguration> entry : component.getProperties().entrySet()) {
final PropertyConfiguration configuration = entry.getValue();
if (configuration == null) {
continue;
}
for (final ParameterReference reference : configuration.getParameterReferences()) {
final String referencedParameterName = reference.getParameterName();
if (referencedParameterName.equals(parameterName)) {
if (entry.getKey().isSensitive() && !parameterDeletion && !Boolean.TRUE.equals(parameterSensitive)) {
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because the update would add a Non-Sensitive Parameter " +
"named '" + parameterName + "' but this Parameter already is referenced by a Sensitive Property.");
}
if (!entry.getKey().isSensitive() && !parameterDeletion && Boolean.TRUE.equals(parameterSensitive)) {
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because the update would add a Sensitive Parameter named " +
"'" + parameterName + "' but this Parameter already is referenced by a Non-Sensitive Property.");
}
if (active && (verifyComponentStates || parameterDeletion)) {
if (parameterDeletion) {
// First check if the actual parameter context is now missing the parameter: it may not be,
// if the parameter is inherited from another context
final ProcessGroup processGroup = flowManager.getGroup(component.getProcessGroupIdentifier());
final ParameterContext parameterContext = processGroup.getParameterContext();
final ParameterDescriptor parameterDescriptor = new ParameterDescriptor.Builder()
.name(parameterName).build();
if (!parameterContext.hasEffectiveValueIfRemoved(parameterDescriptor)) {
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because the " + parameterName + " Parameter is being referenced by a " +
activeExplanation + ".");
}
} else {
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because it has Parameters that are being referenced by a " +
activeExplanation + ".");
}
}
}
}
}
final List<ParameterContext> inheritedParameterContexts = getInheritedParameterContexts(parameterContextDto);
final Map<String, Parameter> parameters = parameterContextDto.getParameters() == null ? Collections.emptyMap() : getParameters(parameterContextDto, currentContext);
currentContext.verifyCanUpdateParameterContext(parameters, inheritedParameterContexts);
}
/**

View File

@ -20,7 +20,7 @@
<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 id="parameter-context-standard-settings-tab-content" class="split-65-35 configuration-tab">
<div class="settings-left">
<div id="parameter-context-id-setting" class="setting hidden">
<div class="setting-name">Id</div>
@ -57,7 +57,7 @@
</div>
</div>
</div>
<div id="parameter-context-parameters-tab-content" class="configuration-tab">
<div id="parameter-context-parameters-tab-content" class="split-65-35 configuration-tab">
<div class="settings-left">
<div class="edit-mode">
<div id="add-parameter"><button class="button fa fa-plus"></button></div>
@ -96,8 +96,51 @@
</div>
</div>
</div>
<div id="parameter-context-inheritance-tab-content" class="configuration-tab">
<div id="parameter-context-inheritance-container">
<div class="settings-left">
<div class="setting">
<div class="setting-name">
Available Parameter Contexts
<div class="fa fa-question-circle" alt="Info" title="Available Parameter Contexts that could be inherited from."></div>
</div>
<div class="setting-field">
<ol id="parameter-context-available"></ol>
</div>
</div>
</div>
<div class="spacer">&nbsp;</div>
<div class="settings-right">
<div class="setting">
<div class="setting-name">
Selected Parameter Context
<div class="fa fa-question-circle" alt="Info" title="Parameter Contexts selected for inheritance."></div>
</div>
<div class="setting-field">
<ol id="parameter-context-selected"></ol>
</div>
</div>
</div>
</div>
<div id="parameter-context-inheritance-container-read-only" style="display: none;">
<div class="settings-left">
<div class="setting">
<div class="setting-name">
Selected Parameter Context
<div class="fa fa-question-circle" alt="Info" title="Parameter Contexts selected for inheritance."></div>
</div>
<div class="setting-field">
<ol id="parameter-context-selected-read-only"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="inherited-parameter-contexts-message" class="ellipsis hidden">
Inherited Parameter Contexts have been modified. Updated listing of Parameters is pending apply.
</div>
</div>
<div id="parameter-dialog" class="dialog cancellable hidden">
<div class="dialog-content">

View File

@ -333,6 +333,7 @@ div.slick-cell div.overridden {
top: 550px;
left: 20px;
font-size: 13px;
color: #775351;
max-width: calc(100% - 230px);
z-index: 999;
}

View File

@ -32,12 +32,12 @@
display: none;
}
#parameter-context-dialog div.settings-left {
.parameter-context-tabs-content.split-65-35 div.settings-left {
float: left;
width: 65%;
}
#parameter-context-dialog div.settings-right {
.parameter-context-tabs-content.split-65-35 div.settings-right {
float: left;
width: 33%;
height: 100%;
@ -134,3 +134,79 @@ span.parameter-context-referencing-component-name {
white-space: nowrap;
margin-left: 6px;
}
/* inheritance */
#parameter-context-available, #parameter-context-selected {
list-style-type: none;
margin: 0px;
background: #eaeef0;
min-height: 32px;
margin-bottom: 5px;
padding: 2px;
}
#parameter-context-available li, #parameter-context-selected li {
margin: 2px;
padding: 5px;
cursor: pointer;
font-size: 1em;
height: 12px;
overflow: hidden;
}
#parameter-context-available li.unauthorized, #parameter-context-selected li.unauthorized {
color: #a8a8a8;
cursor: not-allowed;
}
#parameter-context-available li {
background: #fff;
border-top: 1px solid #CCDADB;
border-right: 1px solid #CCDADB;
border-bottom: 1px solid #CCDADB;
border-left: 1px solid #CCDADB;
color: #004849;
font-weight: 500;
cursor: grab;
line-height: 32px;
height: 32px;
padding: 0px 10px;
box-shadow:0 1px 1px rgba(0,0,0,0.4);
}
#parameter-context-selected li {
background: #355B6A;
border-top: 1px solid #AAC1CE;
border-right: 1px solid #85A6B8;
border-bottom: 1px solid #618BA3;
border-left: 1px solid #85A6B8;
color: #fff;
font-weight: bold;
line-height: 32px;
height: 32px;
padding: 0px 10px;
}
#parameter-context-selected .draggable-control {
float: right;
}
#parameter-context-selected .fa-remove, #parameter-context-selected .fa-question-circle {
color: #fff;
}
#parameter-context-selected-read-only {
list-style: inside none decimal;
}
#inherited-parameter-contexts-message {
position: absolute;
top: 550px;
left: 20px;
font-size: 13px;
line-height: normal;
color: #775351;
max-width: calc(100% - 230px);
z-index: 999;
}

View File

@ -219,6 +219,7 @@
parameterData.setItems([]);
resetUsage();
resetInheritance();
// reset the last selected parameter
lastSelectedId = null;
@ -300,6 +301,24 @@
return parameters;
};
/**
* Marshals the inherited parameter contexts.
*/
var marshalInheritedParameterContexts = function () {
var inheritedParameterContextIds = $('#parameter-context-selected').sortable('toArray');
return inheritedParameterContextIds.map(function (id) {
var name = $('#parameter-context-selected').find('li#' + id + ' span').text();
return {
id: id,
component: {
id: id,
name: name
}
}
});
};
/**
* Handles outstanding changes.
*
@ -1062,10 +1081,19 @@
var parameters = marshalParameters();
var proposedParamContextName = $('#parameter-context-name').val();
var proposedParamContextDesc = $('#parameter-context-description-field').val();
var inheritedParameterContexts = marshalInheritedParameterContexts();
var inheritedParameterContextEquals = isInheritedParameterContextEquals(parameterContextEntity, inheritedParameterContexts);
if (inheritedParameterContextEquals) {
$('#inherited-parameter-contexts-message').addClass('hidden');
} else {
$('#inherited-parameter-contexts-message').removeClass('hidden');
}
if (_.isEmpty(parameters) &&
proposedParamContextName === _.get(parameterContextEntity, 'component.name') &&
proposedParamContextDesc === _.get(parameterContextEntity, 'component.description')) {
proposedParamContextDesc === _.get(parameterContextEntity, 'component.description') &&
inheritedParameterContextEquals) {
return false;
} else {
@ -1073,6 +1101,24 @@
}
};
/**
* Determines if the proposed inherited parameter contexts are equal to the current configuration.
*
* @param parameterContextEntity
* @param proposedInheritedParameterContexts
* @returns {*}
*/
var isInheritedParameterContextEquals = function (parameterContextEntity, proposedInheritedParameterContexts) {
var configuredInheritedParameterContexts = parameterContextEntity.component.inheritedParameterContexts.map(function (inheritedParameterContext) {
return inheritedParameterContext.id;
});
var mappedProposedInheritedParameterContexts = proposedInheritedParameterContexts.map(function (proposedInheritedParameterContext) {
return proposedInheritedParameterContext.id;
});
return _.isEqual(configuredInheritedParameterContexts, mappedProposedInheritedParameterContexts);
}
/**
* Updates parameter contexts by issuing an update request and polling until it's completion.
*
@ -1081,12 +1127,15 @@
*/
var updateParameterContext = function (parameterContextEntity) {
var parameters = marshalParameters();
var inheritedParameterContexts = marshalInheritedParameterContexts();
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) {
if ($('#parameter-context-name').val() === _.get(parameterContextEntity, 'component.name') &&
$('#parameter-context-description-field').val() === _.get(parameterContextEntity, 'component.description') &&
isInheritedParameterContextEquals(parameterContextEntity, inheritedParameterContexts)) {
close();
return;
@ -1095,6 +1144,9 @@
parameterContextEntity.component.parameters = parameters;
}
// include the inherited parameter contexts
parameterContextEntity.component.inheritedParameterContexts = inheritedParameterContexts;
parameterContextEntity.component.name = $('#parameter-context-name').val();
parameterContextEntity.component.description = $('#parameter-context-description-field').val();
@ -1249,8 +1301,8 @@
});
// update the parameter context table if displayed
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
if (nfCommon.isDefinedAndNotNull(parameterContextGrid)) {
if ($('#parameter-contexts-table').is(':visible')) {
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
var parameterContextData = parameterContextGrid.getData();
$.extend(parameterContextEntity, {
@ -1289,6 +1341,9 @@
$('#parameter-context-tabs').hide();
$('#parameter-context-update-status').show();
// hide the pending apply message for parameter context
$('#inherited-parameter-contexts-message').addClass('hidden')
pollUpdateRequest(response);
}).fail(handleAjaxFailure);
}).promise();
@ -1530,6 +1585,57 @@
}
};
/**
* Load the parameter context inheritance tab for the current parameterContextEntity. The current parameterContextEntity could be
* null if this is a new parameter context.
*
* @param parameterContextEntity the parameter context being edited or null if new
* @param readOnly whether the controls should be read only
* @param parameterContexts all parameter contexts
*/
var loadParameterContextInheritance = function (parameterContextEntity, readOnly, parameterContexts) {
// consider each parameter context and add to the listing of available or selected contexts based on the supplied parameterContextEntity
$.each(parameterContexts, function (i, availableParameterContext) {
// don't support inheriting from the current context
var isCurrent = nfCommon.isNull(parameterContextEntity) ? false : availableParameterContext.id === parameterContextEntity.id;
// determine if this available parameter context is already selected
var isSelected = nfCommon.isNull(parameterContextEntity) ? false : parameterContextEntity.component.inheritedParameterContexts.some(function (selectedParameterContext) {
return availableParameterContext.id === selectedParameterContext.id;
});
if (readOnly) {
if (isSelected) {
$('#parameter-context-selected-read-only').append($('<li></li>').text(availableParameterContext.component.name));
}
} else {
if (isSelected) {
addParameterContextInheritanceControl(availableParameterContext, true);
} else if (!isCurrent) {
addParameterContextInheritanceControl(availableParameterContext, false);
}
}
});
if (!nfCommon.isNull(parameterContextEntity)) {
sortSelectedParameterContexts(parameterContextEntity);
}
sortAvailableParameterContexts();
if (readOnly) {
if ($('#parameter-context-selected-read-only').is(':empty')) {
$('#parameter-context-selected-read-only').append($('<span class="unset">No value set</span>'));
}
$('#parameter-context-inheritance-container-read-only').show();
$('#parameter-context-inheritance-container').hide();
} else {
$('#parameter-context-inheritance-container-read-only').hide();
$('#parameter-context-inheritance-container').show();
}
};
var resetUsage = function () {
// empty the containers
var processorContainer = $('.parameter-context-referencing-processors');
@ -1561,6 +1667,125 @@
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
};
/**
* Reset the inheritance tab.
*/
var resetInheritance = function () {
$('#parameter-context-available').empty();
$('#parameter-context-selected').empty();
$('#parameter-context-selected-read-only').empty();
$('#inherited-parameter-contexts-message').addClass('hidden');
};
/**
* Sorts the available parameter contexts.
*/
var sortAvailableParameterContexts = function () {
var availableParameterContextList = $('#parameter-context-available');
availableParameterContextList.children('li')
.detach()
.sort(function (aElement, bElement) {
var a = $(aElement);
var b = $(bElement);
// put unauthorized last
if (a.hasClass('unauthorized') && b.hasClass('unauthorized')) {
return 0;
} else if (a.hasClass('unauthorized')) {
return 1;
} else if (b.hasClass('unauthorized')) {
return -1;
}
var nameA = a.text();
var nameB = b.text();
return nameA.localeCompare(nameB);
})
.appendTo(availableParameterContextList);
};
/**
* Sorts the selected parameter context array based on the current parameter context entity.
*
* @param {object} selectedParameterContexts
*/
var sortSelectedParameterContexts = function (parameterContextEntity) {
var selectedInheritedParameterContexts = parameterContextEntity.component.inheritedParameterContexts;
var selectedParameterContextList = $('#parameter-context-selected');
selectedParameterContextList.children('li')
.detach()
.sort(function (aElement, bElement) {
var a = $(aElement);
var b = $(bElement);
var findA = function (selectedInheritedParameterContext) {
return a.attr('id') === selectedInheritedParameterContext.id;
};
var findB = function (selectedInheritedParameterContext) {
return b.attr('id') === selectedInheritedParameterContext.id;
};
return selectedInheritedParameterContexts.findIndex(findA) - selectedInheritedParameterContexts.findIndex(findB);
})
.appendTo(selectedParameterContextList);
}
/**
* Adds the specified parameter context to the list of available parameter contexts.
*
* @argument {jQuery} container The container for the parameter context
* @argument {object} parameterContext An available parameter context
* @argument {boolean} isSelected Whether the parameter context is selected (which is used to decide whether to provide a remove control)
*/
var addParameterContextInheritanceControl = function (parameterContext, isSelected) {
var label = parameterContext.id;
if (parameterContext.permissions.canRead) {
label = parameterContext.component.name;
}
// add the parameter context to the specified list
var parameterContextElement = $('<li></li>').append($('<span style="float: left;"></span>').text(label)).attr('id', parameterContext.id).addClass('ui-state-default');
if (!parameterContext.permissions.canRead) {
parameterContextElement.addClass('unauthorized');
} else {
// add the description if applicable
if (!nfCommon.isBlank(parameterContext.component.description)) {
$('<div class="fa fa-question-circle"></div>').appendTo(parameterContextElement).qtip($.extend({
content: nfCommon.escapeHtml(parameterContext.component.description)
}, nfCommon.config.tooltipConfig));
}
if (isSelected) {
addControlsForSelectedParameterContext(parameterContextElement);
}
}
parameterContextElement.appendTo(isSelected ? '#parameter-context-selected' : '#parameter-context-available');
};
/**
* Adds the controls to the specified selected draggable element.
*
* @argument {jQuery} draggableElement
*/
var addControlsForSelectedParameterContext = function (draggableElement) {
var removeIcon = $('<div class="draggable-control"><div class="fa fa-remove"></div></div>')
.on('click', function () {
// remove the remove ice
removeIcon.remove();
// restore to the available parameter contexts
$('#parameter-context-available').append(draggableElement);
// resort the available parameter contexts
sortAvailableParameterContexts();
// update the buttons to possibly trigger the disabled state
$('#parameter-context-dialog').modal('refreshButtons');
})
.appendTo(draggableElement);
}
/**
* Performs the filtering.
*
@ -1914,6 +2139,9 @@
}, {
name: 'Parameters',
tabContentId: 'parameter-context-parameters-tab-content'
}, {
name: 'Inheritance',
tabContentId: 'parameter-context-inheritance-tab-content'
}],
select: function () {
// update the parameters table size in case this is the first time its rendered
@ -2124,23 +2352,24 @@
});
};
/**
* Fetches the available Parameter Contexts.
*/
var fetchParameterContexts = function () {
return $.ajax({
type: 'GET',
url: '../nifi-api/flow/parameter-contexts',
dataType: 'json'
});
};
/**
* Loads the parameter contexts.
*
* @param parameterContextToSelect id of the parameter context to select in the grid
*/
var loadParameterContexts = function (parameterContextToSelect) {
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();
var parameterContexts = fetchParameterContexts();
// return a deferred for all parts of the parameter contexts
return $.when(parameterContexts).done(function (response) {
@ -2382,6 +2611,7 @@
// create a new parameter context
$('#new-parameter-context').on('click', function () {
resetUsage();
resetInheritance();
// new parameter contexts do not have an ID to show
if (!$('#parameter-context-id-setting').hasClass('hidden')) {
@ -2424,10 +2654,64 @@
}
}]).modal('show');
var parameterContextsGrid = $('#parameter-contexts-table').data('gridInstance');
var parameterContextsData = parameterContextsGrid.getData();
var parameterContexts = parameterContextsData.getItems();
loadParameterContextInheritance(null, false, parameterContexts);
// set the initial focus
$('#parameter-context-name').focus();
});
// work around for https://bugs.jqueryui.com/ticket/6054
var shouldAllowDrop = true;
// make the parameter context containers sortable
$('#parameter-context-available').sortable({
containment: $('#parameter-context-inheritance-tab-content'),
cancel: '.unauthorized',
connectWith: '#parameter-context-selected',
placeholder: 'available',
scroll: true,
opacity: 0.6,
beforeStop: function (event, ui) {
if ($('#parameter-context-available').find('.ui-sortable-placeholder').length) {
shouldAllowDrop = false;
}
},
stop: function (event, ui) {
const allowDrop = shouldAllowDrop;
shouldAllowDrop = true;
return allowDrop;
}
});
$('#parameter-context-selected').sortable({
containment: $('#parameter-context-inheritance-tab-content'),
cancel: '.unauthorized',
placeholder: 'selected',
scroll: true,
opacity: 0.6,
receive: function (event, ui) {
addControlsForSelectedParameterContext(ui.item);
},
update: function (event, ui) {
// update the buttons to possibly trigger the disabled state
$('#parameter-context-dialog').modal('refreshButtons');
}
});
$('#parameter-context-available, #parameter-context-selected').disableSelection();
// add a listener that will handle dblclick for all available authorized parameter context children
$(document).on('dblclick', '#parameter-context-available li:not(".unauthorized")', function() {
var availableParameterContextElement = $(this).detach().appendTo($('#parameter-context-selected'));
addControlsForSelectedParameterContext(availableParameterContextElement);
// update the buttons to possibly trigger the disabled state
$('#parameter-context-dialog').modal('refreshButtons');
});
// initialize the new parameter context dialog
initNewParameterContextDialog();
@ -2437,7 +2721,7 @@
if ($('#parameter-referencing-components-container').is(':visible')) {
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
}
})
});
},
/**
@ -2460,6 +2744,9 @@
})
};
// include the inherited parameter contexts
parameterContextEntity.component.inheritedParameterContexts = marshalInheritedParameterContexts();
var addContext = $.ajax({
type: 'POST',
url: config.urls.parameterContexts,
@ -2467,10 +2754,9 @@
dataType: 'json',
contentType: 'application/json'
}).done(function (parameterContextEntity) {
// add the item
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
if (nfCommon.isDefinedAndNotNull(parameterContextGrid)) {
// update the table if displayed
if ($('#parameter-contexts-table').is(':visible')) {
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
var parameterContextData = parameterContextGrid.getData();
parameterContextData.addItem(parameterContextEntity);
@ -2539,6 +2825,19 @@
dataType: 'json'
});
var parameterContextsDeferred;
if ($('#parameter-contexts-table').is(':visible')) {
parameterContextsDeferred = $.Deferred(function (deferred) {
var parameterContextsGrid = $('#parameter-contexts-table').data('gridInstance');
var parameterContextsData = parameterContextsGrid.getData();
deferred.resolve({
parameterContexts: parameterContextsData.getItems()
});
}).promise();
} else {
parameterContextsDeferred = fetchParameterContexts();
}
// once everything is loaded, show the dialog
reloadContext.done(function (parameterContextEntity) {
var canWrite = _.get(parameterContextEntity, 'permissions.canWrite', false);
@ -2579,71 +2878,74 @@
loadParameters(parameterContextEntity, parameterToSelect, readOnly || !canWrite);
var editModeButtonModel = [{
buttonText: 'Apply',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
disabled: function () {
if ($('#parameter-context-name').val() !== '' && hasParameterContextChanged(currentParameterContextEntity)) {
// load the parameter contexts in order to render all available parameter contexts
parameterContextsDeferred.done(function (response) {
loadParameterContextInheritance(parameterContextEntity, readOnly || !canWrite, response.parameterContexts);
var editModeButtonModel = [{
buttonText: 'Apply',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
disabled: function () {
if ($('#parameter-context-name').val() !== '' && hasParameterContextChanged(currentParameterContextEntity)) {
return false;
}
return true;
},
handler: {
click: function () {
updateParameterContext(currentParameterContextEntity);
}
}
}, {
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}];
var readOnlyButtonModel = [{
buttonText: 'Ok',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
disabled: function () {
return false;
},
handler: {
click: function () {
$(this).modal('hide');
}
}
return true;
},
handler: {
click: function () {
updateParameterContext(currentParameterContextEntity);
}
}
}, {
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}];
}];
var readOnlyButtonModel = [{
buttonText: 'Ok',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
disabled: function () {
return false;
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}];
// show the context
$('#parameter-context-dialog')
.modal('setHeaderText', canWrite ? 'Update Parameter Context' : 'View Parameter Context')
.modal('setButtonModel', canWrite ? editModeButtonModel : readOnlyButtonModel)
.modal('show');
// select the parameters tab
$('#parameter-context-tabs').find('li:eq(1)').click();
// show the context
$('#parameter-context-dialog')
.modal('setHeaderText', canWrite ? 'Update Parameter Context' : 'View Parameter Context')
.modal('setButtonModel', canWrite ? editModeButtonModel : readOnlyButtonModel)
.modal('show');
// select the parameters tab
$('#parameter-context-tabs').find('li:last').click();
// check if border is necessary
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
// show the border if necessary
updateReferencingComponentsBorder(referencingComponentsContainer);
// check if border is necessary
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
// show the border if necessary
updateReferencingComponentsBorder(referencingComponentsContainer);
}).fail(nfErrorHandler.handleAjaxError);
}).fail(nfErrorHandler.handleAjaxError);
},