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 2022/03/03 23:50:22 UTC

[nifi] branch main updated: NIFI-9543: Add bring-to-front functionality to labels (#5765)

This is an automated email from the ASF dual-hosted git repository.

mcgilman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 6cd30e3  NIFI-9543: Add bring-to-front functionality to labels (#5765)
6cd30e3 is described below

commit 6cd30e3d0aa6e7f8763afc7c4cb007b322555573
Author: Shane Ardell <sa...@users.noreply.github.com>
AuthorDate: Thu Mar 3 18:50:15 2022 -0500

    NIFI-9543: Add bring-to-front functionality to labels (#5765)
    
    * NIFI-9543: add bring-to-front functionality to labels
    
    * NIFI-9543: update zIndex changes to persist after shutdown
    
    * NIFI-9543: remove commented code
    
    * NIFI-9543: update flow comparator and snippet to account for zIndex
    
    * NIFI-9543: changed add function to sort labels when a new label is added
    
    * NIFI-9543: remove unnecessary call to position
    
    * NIFI-9543: only register difference if zIndex is not default value
    
    * NIFI-9543: add null checks to prevent primitive Long
    
    This closes #5765
---
 .../java/org/apache/nifi/flow/VersionedLabel.java  | 12 ++++
 .../java/org/apache/nifi/web/api/dto/LabelDTO.java | 15 ++++
 .../apache/nifi/web/api/entity/LabelEntity.java    | 16 +++++
 .../nifi/connectable/StandardConnection.java       |  3 +-
 .../nifi/controller/label/StandardLabel.java       | 13 ++++
 .../groups/StandardProcessGroupSynchronizer.java   |  4 ++
 .../flow/mapping/NiFiRegistryFlowMapper.java       |  1 +
 .../apache/nifi/util/FlowDifferenceFilters.java    | 56 ++++++++++++++-
 .../org/apache/nifi/controller/label/Label.java    |  4 ++
 .../nifi/controller/StandardFlowSnippet.java       |  8 +++
 .../nifi/controller/XmlFlowSynchronizer.java       |  7 ++
 .../serialization/FlowFromDOMFactory.java          |  1 +
 .../serialization/StandardFlowSerializer.java      |  1 +
 .../org/apache/nifi/web/api/dto/DtoFactory.java    |  2 +
 .../org/apache/nifi/web/api/dto/EntityFactory.java |  1 +
 .../apache/nifi/web/dao/impl/StandardLabelDAO.java |  6 ++
 .../src/main/webapp/js/nf/canvas/nf-actions.js     | 81 ++++++++++++----------
 .../main/webapp/js/nf/canvas/nf-context-menu.js    |  2 +-
 .../src/main/webapp/js/nf/canvas/nf-label.js       | 18 ++++-
 .../nifi/registry/flow/diff/DifferenceType.java    |  5 ++
 .../registry/flow/diff/StandardFlowComparator.java |  2 +
 21 files changed, 214 insertions(+), 44 deletions(-)

diff --git a/nifi-api/src/main/java/org/apache/nifi/flow/VersionedLabel.java b/nifi-api/src/main/java/org/apache/nifi/flow/VersionedLabel.java
index 61e7ebb..0020309 100644
--- a/nifi-api/src/main/java/org/apache/nifi/flow/VersionedLabel.java
+++ b/nifi-api/src/main/java/org/apache/nifi/flow/VersionedLabel.java
@@ -23,6 +23,7 @@ import io.swagger.annotations.ApiModelProperty;
 
 public class VersionedLabel extends VersionedComponent {
     private String label;
+    private Long zIndex;
 
     private Double width;
     private Double height;
@@ -66,6 +67,17 @@ public class VersionedLabel extends VersionedComponent {
         this.width = width;
     }
 
+    @ApiModelProperty(
+            value = "The z index of the connection.",
+            name = "zIndex")  // Jackson maps this method name to JSON key "zIndex", but Swagger does not by default
+    public Long getzIndex() {
+        return zIndex;
+    }
+
+    public void setzIndex(Long zIndex) {
+        this.zIndex = zIndex;
+    }
+
     @Override
     public ComponentType getComponentType() {
         return ComponentType.LABEL;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java
index 81c6e39..27421ce 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java
@@ -31,6 +31,7 @@ public class LabelDTO extends ComponentDTO {
 
     private Double width;
     private Double height;
+    private Long zIndex;
 
     // font-size = 12px
     // background-color = #eee
@@ -40,6 +41,20 @@ public class LabelDTO extends ComponentDTO {
     }
 
     /**
+     * @return z index for this label
+     */
+    @ApiModelProperty(
+            value = "The z index of the label."
+    )
+    public Long getzIndex() {
+        return zIndex;
+    }
+
+    public void setzIndex(Long zIndex) {
+        this.zIndex = zIndex;
+    }
+
+    /**
      * The text that appears in the label.
      *
      * @return The label text
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java
index 4cc9d3e..61f3afd 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.web.api.entity;
 
+import io.swagger.annotations.ApiModelProperty;
 import org.apache.nifi.web.api.dto.DimensionsDTO;
 import org.apache.nifi.web.api.dto.LabelDTO;
 
@@ -28,6 +29,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 public class LabelEntity extends ComponentEntity implements Permissible<LabelDTO> {
 
     private DimensionsDTO dimensions;
+    private Long zIndex;
     private LabelDTO component;
 
     /**
@@ -55,4 +57,18 @@ public class LabelEntity extends ComponentEntity implements Permissible<LabelDTO
     public void setDimensions(DimensionsDTO dimensions) {
         this.dimensions = dimensions;
     }
+
+    /**
+     * @return z index for this label
+     */
+    @ApiModelProperty(
+            value = "The z index of the label."
+    )
+    public Long getzIndex() {
+        return zIndex;
+    }
+
+    public void setzIndex(Long zIndex) {
+        this.zIndex = zIndex;
+    }
 }
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/connectable/StandardConnection.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/connectable/StandardConnection.java
index 2d55f8d..471cea1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/connectable/StandardConnection.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/connectable/StandardConnection.java
@@ -59,6 +59,7 @@ import java.util.stream.Collectors;
  * component.
  */
 public final class StandardConnection implements Connection, ConnectionEventListener {
+    public static final long DEFAULT_Z_INDEX = 0;
 
     private final String id;
     private final AtomicReference<ProcessGroup> processGroup;
@@ -68,7 +69,7 @@ public final class StandardConnection implements Connection, ConnectionEventList
     private final AtomicReference<Connectable> destination;
     private final AtomicReference<Collection<Relationship>> relationships;
     private final AtomicInteger labelIndex = new AtomicInteger(1);
-    private final AtomicLong zIndex = new AtomicLong(0L);
+    private final AtomicLong zIndex = new AtomicLong(DEFAULT_Z_INDEX);
     private final AtomicReference<String> versionedComponentId = new AtomicReference<>();
     private final ProcessScheduler scheduler;
     private final int hashCode;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/label/StandardLabel.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/label/StandardLabel.java
index 2e98e84..fca77c5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/label/StandardLabel.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/label/StandardLabel.java
@@ -30,8 +30,10 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicLong;
 
 public class StandardLabel implements Label {
+    public static final long DEFAULT_Z_INDEX = 0;
 
     private final String identifier;
     private final AtomicReference<Position> position;
@@ -40,6 +42,7 @@ public class StandardLabel implements Label {
     private final AtomicReference<String> value;
     private final AtomicReference<ProcessGroup> processGroup;
     private final AtomicReference<String> versionedComponentId = new AtomicReference<>();
+    private final AtomicLong zIndex = new AtomicLong(DEFAULT_Z_INDEX);
 
     public StandardLabel(final String identifier, final String value) {
         this(identifier, new Position(0D, 0D), new HashMap<String, String>(), value, null);
@@ -159,4 +162,14 @@ public class StandardLabel implements Label {
             }
         }
     }
+
+    @Override
+    public long getZIndex() {
+        return zIndex.get();
+    }
+
+    @Override
+    public void setZIndex(final long zIndex) {
+        this.zIndex.set(zIndex);
+    }
 }
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroupSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroupSynchronizer.java
index 7ec6231..baad3c4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroupSynchronizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroupSynchronizer.java
@@ -1546,6 +1546,10 @@ public class StandardProcessGroupSynchronizer implements ProcessGroupSynchronize
         label.setSize(new Size(proposed.getWidth(), proposed.getHeight()));
         label.setStyle(proposed.getStyle());
         label.setValue(proposed.getLabel());
+
+        if (proposed.getzIndex() != null) {
+            label.setZIndex(proposed.getzIndex());
+        }
     }
 
     private ProcessorNode addProcessor(final ProcessGroup destination, final VersionedProcessor proposed, final ComponentIdGenerator componentIdGenerator) throws ProcessorInstantiationException {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java
index cc3bf39..2f0d8db 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java
@@ -637,6 +637,7 @@ public class NiFiRegistryFlowMapper {
         versionedLabel.setLabel(label.getValue());
         versionedLabel.setPosition(mapPosition(label.getPosition()));
         versionedLabel.setStyle(label.getStyle());
+        versionedLabel.setzIndex(label.getZIndex());
 
         return versionedLabel;
     }
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
index 73b6a77..05ec043 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java
@@ -20,12 +20,14 @@ import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ComponentNode;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.flow.FlowManager;
+import org.apache.nifi.controller.label.StandardLabel;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.flow.ComponentType;
 import org.apache.nifi.flow.ScheduledState;
 import org.apache.nifi.flow.VersionedComponent;
 import org.apache.nifi.flow.VersionedConnection;
 import org.apache.nifi.flow.VersionedFlowCoordinates;
+import org.apache.nifi.flow.VersionedLabel;
 import org.apache.nifi.flow.VersionedPort;
 import org.apache.nifi.flow.VersionedProcessGroup;
 import org.apache.nifi.flow.VersionedProcessor;
@@ -65,7 +67,9 @@ public class FlowDifferenceFilters {
             || isScheduledStateNew(difference)
             || isLocalScheduleStateChange(difference)
             || isPropertyMissingFromGhostComponent(difference, flowManager)
-            || isNewRetryConfigWithDefaultValue(difference, flowManager);
+            || isNewRetryConfigWithDefaultValue(difference, flowManager)
+            || isNewZIndexLabelConfigWithDefaultValue(difference, flowManager)
+            || isNewZIndexConnectionConfigWithDefaultValue(difference, flowManager);
     }
 
     /**
@@ -144,6 +148,56 @@ public class FlowDifferenceFilters {
         return false;
     }
 
+    private static boolean isNewZIndexLabelConfigWithDefaultValue(final FlowDifference fd, final FlowManager flowManager) {
+        final Object valueA = fd.getValueA();
+        if (valueA != null) {
+            return false;
+        }
+
+        final VersionedComponent componentB = fd.getComponentB();
+        if (!(componentB instanceof VersionedLabel)) {
+            return false;
+        }
+
+        final VersionedLabel versionedLabel = (VersionedLabel) componentB;
+        if (fd.getDifferenceType() == DifferenceType.ZINDEX_CHANGED) {
+            final Long zIndex = versionedLabel.getzIndex();
+
+            // should not be possible as the default value will serialize as non-null but protecting the comparison below
+            if (zIndex == null) {
+                return false;
+            }
+
+            return zIndex.longValue() == StandardLabel.DEFAULT_Z_INDEX;
+        }
+        return false;
+    }
+
+    private static boolean isNewZIndexConnectionConfigWithDefaultValue(final FlowDifference fd, final FlowManager flowManager) {
+        final Object valueA = fd.getValueA();
+        if (valueA != null) {
+            return false;
+        }
+
+        final VersionedComponent componentB = fd.getComponentB();
+        if (!(componentB instanceof VersionedConnection)) {
+            return false;
+        }
+
+        final VersionedConnection versionedConnection = (VersionedConnection) componentB;
+        if (fd.getDifferenceType() == DifferenceType.ZINDEX_CHANGED) {
+            final Long zIndex = versionedConnection.getzIndex();
+
+            // should not be possible as the default value will serialize as non-null but protecting the comparison below
+            if (zIndex == null) {
+                return false;
+            }
+
+            return zIndex.longValue() == StandardLabel.DEFAULT_Z_INDEX;
+        }
+        return false;
+    }
+
     private static boolean isNewRetryConfigWithDefaultValue(final FlowDifference fd, final FlowManager flowManager) {
         final Object valueA = fd.getValueA();
         if (valueA != null) {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java
index d463725..e2e5f34 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java
@@ -44,4 +44,8 @@ public interface Label extends ComponentAuthorizable, Positionable, VersionedCom
     String getValue();
 
     void setValue(String value);
+
+    long getZIndex();
+
+    void setZIndex(long zIndex);
 }
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java
index 566b8c6..c1fb648 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java
@@ -268,6 +268,10 @@ public class StandardFlowSnippet implements FlowSnippet {
             }
 
             label.setStyle(labelDTO.getStyle());
+            if (labelDTO.getzIndex() != null) {
+                label.setZIndex(label.getZIndex());
+            }
+
             if (!topLevel) {
                 label.setVersionedComponentId(labelDTO.getVersionedComponentId());
             }
@@ -596,6 +600,10 @@ public class StandardFlowSnippet implements FlowSnippet {
                 connection.setVersionedComponentId(connectionDTO.getVersionedComponentId());
             }
 
+            if (connectionDTO.getzIndex() != null) {
+                connection.setZIndex(connection.getZIndex());
+            }
+
             if (connectionDTO.getBends() != null) {
                 final List<Position> bendPoints = new ArrayList<>();
                 for (final PositionDTO bend : connectionDTO.getBends()) {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
index 1d2c0e3..ac61da9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
@@ -1060,6 +1060,9 @@ public class XmlFlowSynchronizer implements FlowSynchronizer {
             if (labelDTO.getWidth() != null && labelDTO.getHeight() != null) {
                 label.setSize(new Size(labelDTO.getWidth(), labelDTO.getHeight()));
             }
+            if (labelDTO.getzIndex() != null) {
+                label.setZIndex(labelDTO.getzIndex());
+            }
 
             processGroup.addLabel(label);
         }
@@ -1542,6 +1545,10 @@ public class XmlFlowSynchronizer implements FlowSynchronizer {
 
             label.setPosition(toPosition(labelDTO.getPosition()));
             label.setSize(new Size(labelDTO.getWidth(), labelDTO.getHeight()));
+            final Long zIndex = labelDTO.getzIndex();
+            if (zIndex != null) {
+                label.setZIndex(zIndex);
+            }
             processGroup.addLabel(label);
         }
     }
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java
index 1fb4ded..01727c7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java
@@ -399,6 +399,7 @@ public class FlowFromDOMFactory {
         final Size size = getSize(DomUtils.getChild(element, "size"));
         dto.setWidth(size.getWidth());
         dto.setHeight(size.getHeight());
+        dto.setzIndex(getLong(element, "zIndex"));
         dto.setStyle(getStyle(DomUtils.getChild(element, "styles")));
 
         return dto;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java
index 0e4961b..202c48f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java
@@ -363,6 +363,7 @@ public class StandardFlowSerializer implements FlowSerializer<Document> {
         parentElement.appendChild(element);
         addTextElement(element, "id", label.getIdentifier());
         addTextElement(element, "versionedComponentId", label.getVersionedComponentId());
+        addTextElement(element, "zIndex", label.getZIndex());
 
         addPosition(element, label.getPosition());
         addSize(element, label.getSize());
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 bc576ec..56b276e 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
@@ -811,6 +811,7 @@ public final class DtoFactory {
         dto.setLabel(label.getValue());
         dto.setParentGroupId(label.getProcessGroup().getIdentifier());
         dto.setVersionedComponentId(label.getVersionedComponentId().orElse(null));
+        dto.setzIndex(label.getZIndex());
 
         return dto;
     }
@@ -4103,6 +4104,7 @@ public final class DtoFactory {
         copy.setWidth(original.getWidth());
         copy.setHeight(original.getHeight());
         copy.setVersionedComponentId(original.getVersionedComponentId());
+        copy.setzIndex(original.getzIndex());
 
         return copy;
     }
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 9d5ad9e..52a8010 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
@@ -319,6 +319,7 @@ public final class EntityFactory {
             dimensions.setHeight(dto.getHeight());
             dimensions.setWidth(dto.getWidth());
             entity.setDimensions(dimensions);
+            entity.setzIndex(dto.getzIndex());
 
             if (permissions != null && permissions.getCanRead()) {
                 entity.setComponent(dto);
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/StandardLabelDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardLabelDAO.java
index 04430e8..3a51bc5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardLabelDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardLabelDAO.java
@@ -66,6 +66,9 @@ public class StandardLabelDAO extends ComponentDAO implements LabelDAO {
             label.setSize(new Size(labelDTO.getWidth(), labelDTO.getHeight()));
         }
         label.setStyle(labelDTO.getStyle());
+        if (labelDTO.getzIndex() != null) {
+            label.setZIndex(labelDTO.getzIndex());
+        }
 
         // add the label
         group.addLabel(label);
@@ -101,6 +104,9 @@ public class StandardLabelDAO extends ComponentDAO implements LabelDAO {
         if (labelDTO.getWidth() != null && labelDTO.getHeight() != null) {
             label.setSize(new Size(labelDTO.getWidth(), labelDTO.getHeight()));
         }
+        if (labelDTO.getzIndex() != null) {
+            label.setZIndex(labelDTO.getzIndex());
+        }
 
         label.getProcessGroup().onComponentModified();
         return label;
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 3ac049a..24acd18 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
@@ -212,6 +212,43 @@
             }).size() > 0;
     };
 
+    var moveComponentToFront = function (selection, componentManager) {
+        var datum = selection.datum();
+
+        // determine the current max zIndex
+        var maxZIndex = -1;
+        $.each(componentManager['get'](), function (_, otherComponent) {
+            if (datum.id !== otherComponent.id && otherComponent.zIndex > maxZIndex) {
+                maxZIndex = otherComponent.zIndex;
+            }
+        });
+
+        // ensure the edge wasn't already in front
+        if (maxZIndex >= 0) {
+            var zIndex = maxZIndex + 1;
+
+            // build the connection entity
+            var componentEntity = {
+                'revision': nfClient.getRevision(datum),
+                'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
+                'component': {
+                    'id': datum.id,
+                    'zIndex': zIndex
+                }
+            };
+
+            return $.ajax({
+                type: 'PUT',
+                url: datum.uri,
+                data: JSON.stringify(componentEntity),
+                dataType: 'json',
+                contentType: 'application/json'
+            }).done(function (response) {
+                componentManager['set'](response);
+            }).fail(nfErrorHandler.handleAjaxError);
+        }
+    }
+
     var nfActions = {
         /**
          * Initializes the actions.
@@ -2202,47 +2239,15 @@
          *
          * @param {selection} selection
          */
-        toFront: function (selection) {
-            if (selection.size() !== 1 || !nfCanvasUtils.isConnection(selection)) {
+         toFront: function (selection) {
+            if (selection.size() !== 1) {
                 return;
             }
 
-            // get the connection data
-            var connection = selection.datum();
-
-            // determine the current max zIndex
-            var maxZIndex = -1;
-            $.each(nfConnection.get(), function (_, otherConnection) {
-                if (connection.id !== otherConnection.id && otherConnection.zIndex > maxZIndex) {
-                    maxZIndex = otherConnection.zIndex;
-                }
-            });
-
-            // ensure the edge wasn't already in front
-            if (maxZIndex >= 0) {
-                // use one higher
-                var zIndex = maxZIndex + 1;
-
-                // build the connection entity
-                var connectionEntity = {
-                    'revision': nfClient.getRevision(connection),
-                    'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
-                    'component': {
-                        'id': connection.id,
-                        'zIndex': zIndex
-                    }
-                };
-
-                // update the edge in question
-                $.ajax({
-                    type: 'PUT',
-                    url: connection.uri,
-                    data: JSON.stringify(connectionEntity),
-                    dataType: 'json',
-                    contentType: 'application/json'
-                }).done(function (response) {
-                    nfConnection.set(response);
-                }).fail(nfErrorHandler.handleAjaxError);
+            if (nfCanvasUtils.isConnection(selection)) {
+                moveComponentToFront(selection, nfConnection);
+            } else if (nfCanvasUtils.isLabel(selection)) {
+                moveComponentToFront(selection, nfLabel);
             }
         }
     };
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 986672d..061a6bf 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
@@ -304,7 +304,7 @@
             return false;
         }
 
-        return nfCanvasUtils.isConnection(selection);
+        return nfCanvasUtils.isConnection(selection) || nfCanvasUtils.isLabel(selection);
     };
 
     /**
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js
index 3621780..e4c07b1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js
@@ -106,6 +106,17 @@
     };
 
     /**
+     * Sorts the specified labels according to the z index.
+     *
+     * @param {type} labels
+     */
+     var sort = function (labels) {
+        labels.sort(function (a, b) {
+            return a.zIndex === b.zIndex ? 0 : a.zIndex > b.zIndex ? 1 : -1;
+        });
+    };
+
+    /**
      * Renders the labels in the specified selection.
      *
      * @param {selection} entered           The selection of labels to be rendered
@@ -135,7 +146,7 @@
                 'stroke': 'transparent'
             });
 
-        // label 
+        // label
         label.append('rect')
             .attrs({
                 'class': 'body',
@@ -470,7 +481,8 @@
             var entered = renderLabels(selection.enter(), selectAll);
 
             // update
-            updateLabels(selection.merge(entered));
+            var updated = selection.merge(entered);
+            updated.call(updateLabels).call(sort);
         },
 
         /**
@@ -527,7 +539,7 @@
 
             // update
             var updated = selection.merge(entered);
-            updated.call(updateLabels).call(nfCanvasUtils.position, transition);
+            updated.call(updateLabels).call(nfCanvasUtils.position, transition).call(sort);
 
             // exit
             selection.exit().call(removeLabels);
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java
index 712c1a5..fa89507 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java
@@ -256,6 +256,11 @@ public enum DifferenceType {
     LABEL_VALUE_CHANGED("Label Text Changed"),
 
     /**
+     * The zindex value is different in each of the components
+     */
+    ZINDEX_CHANGED("z-index Changed"),
+
+    /**
      * The variable does not exist in Flow A but exists in Flow B
      */
     VARIABLE_ADDED("Variable Added to Process Group"),
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java
index e92a317..2664425 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java
@@ -375,6 +375,7 @@ public class StandardFlowComparator implements FlowComparator {
         addIfDifferent(differences, DifferenceType.POSITION_CHANGED, labelA, labelB, VersionedLabel::getHeight);
         addIfDifferent(differences, DifferenceType.POSITION_CHANGED, labelA, labelB, VersionedLabel::getWidth);
         addIfDifferent(differences, DifferenceType.STYLE_CHANGED, labelA, labelB, VersionedLabel::getStyle);
+        addIfDifferent(differences, DifferenceType.ZINDEX_CHANGED, labelA, labelB, VersionedLabel::getzIndex);
     }
 
     private void compare(final VersionedPort portA, final VersionedPort portB, final Set<FlowDifference> differences) {
@@ -500,6 +501,7 @@ public class StandardFlowComparator implements FlowComparator {
         addIfDifferent(differences, DifferenceType.PRIORITIZERS_CHANGED, connectionA, connectionB, VersionedConnection::getPrioritizers);
         addIfDifferent(differences, DifferenceType.SELECTED_RELATIONSHIPS_CHANGED, connectionA, connectionB, VersionedConnection::getSelectedRelationships);
         addIfDifferent(differences, DifferenceType.SOURCE_CHANGED, connectionA, connectionB, c -> c.getSource().getId());
+        addIfDifferent(differences, DifferenceType.ZINDEX_CHANGED, connectionA, connectionB, VersionedConnection::getzIndex);
 
         addIfDifferent(differences, DifferenceType.LOAD_BALANCE_STRATEGY_CHANGED, connectionA, connectionB,
                 conn -> conn.getLoadBalanceStrategy() == null ? DEFAULT_LOAD_BALANCE_STRATEGY : conn.getLoadBalanceStrategy());