diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java index edf3c5e6ac..89b784ece6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java @@ -17,6 +17,7 @@ package org.apache.nifi.web.api.entity; import org.apache.nifi.web.api.dto.ProcessorDTO; +import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO; import javax.xml.bind.annotation.XmlRootElement; @@ -27,6 +28,7 @@ import javax.xml.bind.annotation.XmlRootElement; public class ProcessorEntity extends ComponentEntity { private ProcessorDTO component; + private ProcessorStatusDTO status; /** * The ProcessorDTO that is being serialized. @@ -41,4 +43,16 @@ public class ProcessorEntity extends ComponentEntity { this.component = component; } + /** + * The Processor status. + * + * @return status + */ + public ProcessorStatusDTO getStatus() { + return status; + } + + public void setStatus(ProcessorStatusDTO status) { + this.status = status; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/StatusMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/StatusMerger.java index 7fc764ace1..d8cead75d3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/StatusMerger.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/StatusMerger.java @@ -634,7 +634,7 @@ public class StatusMerger { } public static String prettyPrint(final Integer count, final Long bytes) { - return formatCount(count) + " / " + formatDataSize(bytes); + return formatCount(count) + " (" + formatDataSize(bytes) + ")"; } } 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 f129d91fd1..8f004298ed 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 @@ -85,7 +85,7 @@ Bulletin Board + class="fa fa-sticky-note-o">Bulletin Board - +
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css index 6ce3538354..f79c8e3424 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css @@ -78,7 +78,7 @@ background-color:#728E9B; /*base-color*/ } -#bulletin-button i{ +#bulletin-button i.fa { color: #fff; font-size:15px; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css index 605a28cdbe..958eb05b6a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css @@ -53,16 +53,78 @@ text.unset { */ g.component { - font-family: Arial, sans-serif; + font-family: Roboto; +} + +g.component rect.body { + fill: #ffffff; +} + +g.component rect.body.unauthorized { + fill: #f4f6f7; +} + +g.component rect.border.unauthorized { + stroke-width: 1.5; + stroke: #ba554a; + stroke-dasharray: 3,3; } g.component.selected rect.border { - stroke: #ffcc00; - stroke-width: 5; + stroke: #004849; + stroke-width: 3; } -g.funnel.selected rect.border { - stroke-width: 2.5; +text.stats-label { + fill: #262626; + font-size: 12px; + font-family: Roboto Slab; +} + +text.stats-value { + fill: #775351; + font-size: 12px; + font-weight: bold; +} + +text.stats-value tspan.size, text.stats-value tspan.size { + font-weight: normal; +} + +text.stats-info { + fill: #728E9B; + font-size: 12px; +} + +text.bulletin-icon { + font-size: 13px; + font-family: FontAwesome; + fill: #ffffff; +} + +rect.bulletin-background { + fill: #728e9b; +} + +rect.bulletin-background.has-bulletins { + fill: #ba554a; +} + +text.process-group-invalid.has-validation-errors { + fill: #ba554a; +} + +text.active-thread-count-icon { + font-family: flowfont; + font-size: 12px; + fill: #728e9b; + text-anchor: end; +} + +text.active-thread-count { + fill: #775351; + font-size: 12px; + font-weight: bold; } /* @@ -88,19 +150,24 @@ image.add-connect { Processor */ -text.processor-stats-label { - fill: #fff; - font-size: 11px; - font-weight: bold; +text.processor-name { + fill: #262626; + font-size: 14px; } -text.processor-stats-value { - font-size: 11px; +text.processor-type { + fill: #728e9b; + font-size: 12px; } -text.processor-stats-info { - fill: #999999; - font-size: 11px; +text.processor-icon { + fill: #ad9897; + font-family: flowfont; + font-size: 30px; +} + +text.run-status-icon { + font-size: 13px; } /* @@ -108,7 +175,27 @@ text.processor-stats-info { */ g.connection { - font-family: Arial, sans-serif; + font-family: Roboto; +} + +g.connection rect.body { + fill: #ffffff; +} + +g.connection rect.body.unauthorized { + fill: #f4f6f7; +} + +g.connection rect.border.unauthorized { + stroke-width: 1.5; + stroke: #ba554a; + stroke-dasharray: 3,3; +} + +g.connection.selected rect.border { + /*stroke: #004849;*/ + stroke: #ffcc00; + stroke-width: 3; } path.connector { @@ -126,12 +213,6 @@ path.connector.connectable { stroke-dasharray: 4; } -g.connection rect.connection-label { - fill: #ffffff; - stroke: #000000; - stroke-width: 2; -} - g.connection path.connection-path { fill: none; stroke: #000000; @@ -139,6 +220,21 @@ g.connection path.connection-path { cursor: pointer; } +g.connection path.connection-path.unauthorized { + stroke: #ba554a; + stroke-dasharray: 3,3; +} + +text.connection-from-run-status, text.connection-to-run-status { + fill: #728e9b; + font-family: FontAwesome; + font-size: 10px; +} + +text.connection-from-run-status.is-missing-port, text.connection-to-run-status.is-missing-port { + fill: #ba554a; +} + /* grouped connection */ g.connection.grouped path.connection-path, g.connection.grouped rect.connection-label { @@ -196,12 +292,6 @@ g.connection rect.endpoint { cursor: pointer; } -g.connection text.connection-stats-label { - font-size: 11px; - font-weight: bold; - fill: #598599; -} - /* labels */ g.label rect.labelpoint { @@ -218,8 +308,30 @@ g.label.selected rect.labelpoint { /* funnels */ +text.funnel-icon { + fill: #ad9897; + font-family: flowfont; + font-size: 30px; +} + /* ports */ +text.port-name { + fill: #262626; + font-size: 14px; +} + +text.port-icon { + fill: #ad9897; + font-family: flowfont; + font-size: 30px; +} + +text.port-transmission-icon { + font-size: 11px; + fill: #728e9b +} + /* active thread count */ text.active-thread-count { @@ -228,35 +340,55 @@ text.active-thread-count { /* process groups */ +text.process-group-name { + fill: #262626; + font-size: 14px; +} + +text.process-group-contents-count { + font-weight: bold; + font-size: 13px; + fill: #294c58; +} + g.process-group.drop rect.border { stroke: #0000ff; stroke-width: 3; } -text.process-group-contents-count { - font-weight: bold; - fill: #294c58; -} - -text.process-group-stats-label { - font-size: 11px; - font-weight: bold; - fill: #598599; -} - -text.process-group-stats-value { - font-size: 11px; -} - -text.process-group-stats-info { - fill: #999999; - font-size: 11px; +text.process-group-contents-icon { + font-size: 13px; + fill: #728e9b; } /* remote process group */ +text.remote-process-group-name { + fill: #262626; + font-size: 14px; +} + +text.remote-process-group-uri { + fill: #004849; + font-size: 12px; +} + +text.remote-process-group-transmission-status { + font-size: 13px; + fill: #728e9b +} + +text.remote-process-group-transmission-status.has-authorization-errors { + fill: #ba554a; +} + +text.remote-process-group-transmission-secure { + font-family: FontAwesome; + font-size: 13px; + fill: #004849; +} + text.remote-process-group-last-refresh { - fill: #cccccc; - font-style: italic; + fill: #728e9b; text-anchor: end; } \ 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/header.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css index f95f78c841..b36914e62c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css @@ -74,12 +74,13 @@ md-toolbar.md-small .md-toolbar-tools { #global-menu-content { font-size: 13px; - padding: 3px 0; + padding: 0px 0; background-color:rgba(249,250,251,0.97); /*tint base-color 96%*/ border:1px solid #004849; /*link-color*/ border-radius:2px; box-shadow:0 2px 3px rgba(0,0,0,0.35); width: 215px; + max-height: inherit; } #global-menu-content md-menu-item{ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css index 4488d62869..83a28303ed 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css @@ -69,7 +69,7 @@ } @font-face { - font-family: 'Roboto+Slab'; + font-family: 'Roboto Slab'; font-style: normal; font-weight: normal; src: local('RobotoSlab Regular'), @@ -78,7 +78,7 @@ } @font-face { - font-family: 'Roboto+Slab'; + font-family: 'Roboto Slab'; font-style: normal; font-weight: bold; src: local('RobotoSlab Bold'), diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgContextMenu.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgContextMenu.png deleted file mode 100755 index 5d3bbf8a9e..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgContextMenu.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgControlsInset.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgControlsInset.png deleted file mode 100755 index ab3b6b7a25..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgControlsInset.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgHeader.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgHeader.png deleted file mode 100755 index 65bc7fed5e..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgHeader.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgNifiLogo.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgNifiLogo.png deleted file mode 100755 index d92c484bdd..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgNifiLogo.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgOutline.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgOutline.png deleted file mode 100755 index 65b3636284..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgOutline.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgPanCenter.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgPanCenter.png deleted file mode 100755 index 0ef3ef2b9e..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgPanCenter.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgPanZoom.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgPanZoom.png deleted file mode 100755 index 9a3f90660e..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgPanZoom.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgProcessGroupDetailsArea.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgProcessGroupDetailsArea.png deleted file mode 100755 index 58dedbd3dd..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgProcessGroupDetailsArea.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgProcessorStatArea.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgProcessorStatArea.png deleted file mode 100755 index 0d8874cb27..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgProcessorStatArea.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgRemoteProcessGroupDetailsArea.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgRemoteProcessGroupDetailsArea.png deleted file mode 100755 index 59e0cd911d..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgRemoteProcessGroupDetailsArea.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgSearchInput.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgSearchInput.png deleted file mode 100755 index 60658e504b..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgSearchInput.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgToolbarBtnBorder.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgToolbarBtnBorder.png deleted file mode 100755 index cb182125c8..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/bgToolbarBtnBorder.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/blueBtnBg-over.jpg b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/blueBtnBg-over.jpg deleted file mode 100755 index dc29c29adf..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/blueBtnBg-over.jpg and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/blueBtnBg.jpg b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/blueBtnBg.jpg deleted file mode 100755 index b11ed7cc2b..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/blueBtnBg.jpg and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonColor.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonColor.png deleted file mode 100755 index 7f0cc06940..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonColor.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonCopy.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonCopy.png deleted file mode 100755 index 584f601c76..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonCopy.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonDelete.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonDelete.png deleted file mode 100755 index dd1cc95c09..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonDelete.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonDisable.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonDisable.png deleted file mode 100755 index 3b2ddbf268..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonDisable.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonEnable.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonEnable.png deleted file mode 100755 index 664a1d69c8..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonEnable.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonGroup.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonGroup.png deleted file mode 100755 index 81f79e1427..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonGroup.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonOutline.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonOutline.png deleted file mode 100755 index 56ec8703fc..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonOutline.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanDown.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanDown.png deleted file mode 100755 index 091ad18ce7..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanDown.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanLeft.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanLeft.png deleted file mode 100755 index 05d746cdec..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanLeft.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanRight.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanRight.png deleted file mode 100755 index befc1fc4a7..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanRight.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanUp.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanUp.png deleted file mode 100755 index c6bae8d4d0..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPanUp.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPaste.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPaste.png deleted file mode 100755 index 7e19a9acc9..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonPaste.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonRun.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonRun.png deleted file mode 100755 index 08aceb548c..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonRun.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonStop.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonStop.png deleted file mode 100755 index 2c6bd279ef..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonStop.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonTemplate.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonTemplate.png deleted file mode 100755 index 2f52861919..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonTemplate.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoom100.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoom100.png deleted file mode 100755 index 7a2e605890..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoom100.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomFit.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomFit.png deleted file mode 100755 index ddecdbddb3..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomFit.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomIn.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomIn.png deleted file mode 100755 index 311da20489..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomIn.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomOut.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomOut.png deleted file mode 100755 index 3ae45261ae..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/buttonZoomOut.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/grayBtnBg-over.jpg b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/grayBtnBg-over.jpg deleted file mode 100755 index b8c463a048..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/grayBtnBg-over.jpg and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/grayBtnBg.jpg b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/grayBtnBg.jpg deleted file mode 100755 index c6668f8f92..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/grayBtnBg.jpg and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/headerTabBg.gif b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/headerTabBg.gif deleted file mode 100755 index 4ad168c1b3..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/headerTabBg.gif and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portRemoved.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portRemoved.png deleted file mode 100755 index cd370e4a83..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portRemoved.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portRunning.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portRunning.png deleted file mode 100755 index 898bdb5383..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portRunning.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portStopped.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portStopped.png deleted file mode 100755 index 514f19f9f9..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/portStopped.png and /dev/null differ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/toolbarBg.gif b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/toolbarBg.gif deleted file mode 100755 index 820730f8fb..0000000000 Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/toolbarBg.gif and /dev/null differ 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 9d90a613c8..54314e970e 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 @@ -152,7 +152,7 @@ nf.Actions = (function () { url: d.component.uri, dataType: 'json' }).done(function (response) { - var remoteProcessGroup = response.remoteProcessGroup; + var remoteProcessGroup = response.component; // the timestamp has not updated yet, poll again if (refreshTimestamp === remoteProcessGroup.flowRefreshed) { @@ -163,7 +163,7 @@ nf.Actions = (function () { // reload the group's connections var connections = nf.Connection.getComponentConnections(remoteProcessGroup.id); $.each(connections, function (_, connection) { - nf.Connection.reload(connection); + nf.Connection.reload(connection.component); }); } }); 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 55c4b49b5b..655dedb71c 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 @@ -405,16 +405,12 @@ nf.CanvasUtils = (function () { .each(function () { var bBox = this.getBBox(); d3.select(this).attr('x', function () { - return d.dimensions.width - bBox.width - 4; + return d.dimensions.width - bBox.width - 15; }); }); // update the background width - selection.select('rect.active-thread-count-background') - .attr('width', function () { - var bBox = activeThreadCount.node().getBBox(); - return bBox.width + 8; - }) + selection.select('text.active-thread-count-icon') .attr('x', function () { var bBox = activeThreadCount.node().getBBox(); @@ -423,22 +419,11 @@ nf.CanvasUtils = (function () { setOffset(bBox.width + 6); } - return d.dimensions.width - bBox.width - 8; - }) - .attr('stroke-dasharray', function() { - var rect = d3.select(this); - var width = parseFloat(rect.attr('width')); - var height = parseFloat(rect.attr('height')); - - var dashArray = []; - dashArray.push(0); - dashArray.push(width + height); - dashArray.push(width + height); - return dashArray.join(' '); + return d.dimensions.width - bBox.width - 20; }) .style('display', 'block'); } else { - selection.selectAll('text.active-thread-count, rect.active-thread-count-background').style('display', 'none'); + selection.selectAll('text.active-thread-count, text.active-thread-count-icon').style('display', 'none'); } }, @@ -475,16 +460,8 @@ nf.CanvasUtils = (function () { // if there are bulletins show them, otherwise hide if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins)) { // update the tooltip - selection.select('image.bulletin-icon') - .style('display', 'block') + selection.select('text.bulletin-icon') .each(function () { - var bBox = this.getBBox(); - var bulletinIcon = d3.select(this); - - bulletinIcon.attr('x', function () { - return d.dimensions.width - offset - bBox.width - 4; - }); - // if there are bulletins generate a tooltip tip = getTooltipContainer().append('div') .attr('id', function () { @@ -505,10 +482,8 @@ nf.CanvasUtils = (function () { }); // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, bulletinIcon); + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); }); - } else { - selection.selectAll('image.bulletin-icon').style('display', 'none'); } }, 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 d5ddbedb77..f82f6c32c2 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 @@ -241,7 +241,7 @@ nf.Canvas = (function () { // create arrow definitions for the various line types defs.selectAll('marker') - .data(['normal', 'ghost']) + .data(['normal', 'ghost', 'unauthorized']) .enter().append('marker') .attr({ 'id': function (d) { @@ -256,6 +256,8 @@ nf.Canvas = (function () { 'fill': function (d) { if (d === 'ghost') { return '#aaaaaa'; + } else if (d === 'unauthorized') { + return '#ba554a'; } else { return '#000000'; } @@ -264,77 +266,42 @@ nf.Canvas = (function () { .append('path') .attr('d', 'M2,3 L0,6 L6,3 L0,0 z'); - // define the gradient for the processor stats background - var processGroupStatsBackground = defs.append('linearGradient') - .attr({ - 'id': 'process-group-stats-background', - 'x1': '0%', - 'y1': '100%', - 'x2': '0%', - 'y2': '0%' - }); + // filter for drop shadow + var filter = defs.append('filter') + .attr('id', 'component-drop-shadow'); - processGroupStatsBackground.append('stop') - .attr({ - 'offset': '0%', - 'stop-color': '#dedede' - }); + // blur + filter.append('feGaussianBlur') + .attr('in', 'SourceAlpha') + .attr('stdDeviation', 2) + .attr('result', 'blur'); - processGroupStatsBackground.append('stop') - .attr({ - 'offset': '50%', - 'stop-color': '#ffffff' - }); + // offset + filter.append('feOffset') + .attr('in', 'blur') + .attr('dx', 0) + .attr('dy', 1) + .attr('result', 'offsetBlur'); - processGroupStatsBackground.append('stop') - .attr({ - 'offset': '100%', - 'stop-color': '#dedede' - }); + // color/opacity + filter.append('feFlood') + .attr('flood-color', '#000000') + .attr('flood-opacity', 0.25) + .attr('result', 'offsetColor'); - // define the gradient for the processor stats background - var processorStatsBackground = defs.append('linearGradient') - .attr({ - 'id': 'processor-stats-background', - 'x1': '0%', - 'y1': '100%', - 'x2': '0%', - 'y2': '0%' - }); + // combine + filter.append('feComposite') + .attr('in', 'offsetColor') + .attr('in2', 'offsetBlur') + .attr('operator', 'in') + .attr('result', 'offsetColorBlur'); - processorStatsBackground.append('stop') - .attr({ - 'offset': '0%', - 'stop-color': '#6f97ac' - }); - - processorStatsBackground.append('stop') - .attr({ - 'offset': '100%', - 'stop-color': '#30505c' - }); - - // define the gradient for the port background - var portBackground = defs.append('linearGradient') - .attr({ - 'id': 'port-background', - 'x1': '0%', - 'y1': '100%', - 'x2': '0%', - 'y2': '0%' - }); - - portBackground.append('stop') - .attr({ - 'offset': '0%', - 'stop-color': '#aaaaaa' - }); - - portBackground.append('stop') - .attr({ - 'offset': '100%', - 'stop-color': '#ffffff' - }); + // stack the effect under the source graph + var feMerge = filter.append('feMerge'); + feMerge.append('feMergeNode') + .attr('in', 'offsetColorBlur'); + feMerge.append('feMergeNode') + .attr('in', 'SourceGraphic'); // define the gradient for the expiration icon var expirationBackground = defs.append('linearGradient') @@ -636,51 +603,6 @@ nf.Canvas = (function () { }).fail(nf.Common.handleAjaxError); }; - /** - * Sets the colors for the specified type. - * - * @param {array} colors The possible colors - * @param {string} type The component type for these colors - */ - var setColors = function (colors, type) { - var defs = d3.select('defs'); - - // update processors - var processorSelection = defs.selectAll('linearGradient.' + type + '-background').data(colors, function (d) { - return d; - }); - - // define the gradient for the processor background - var gradient = processorSelection.enter().append('linearGradient') - .attr({ - 'id': function (d) { - return type + '-background-' + d; - }, - 'class': type + '-background', - 'x1': '0%', - 'y1': '100%', - 'x2': '0%', - 'y2': '0%' - }); - - gradient.append('stop') - .attr({ - 'offset': '0%', - 'stop-color': function (d) { - return '#' + d; - } - }); - - gradient.append('stop') - .attr({ - 'offset': '100%', - 'stop-color': '#ffffff' - }); - - // remove old processor colors - processorSelection.exit().remove(); - }; - /** * Reloads the current status of this flow. */ @@ -1172,24 +1094,6 @@ nf.Canvas = (function () { }).fail(nf.Common.handleAjaxError); }, - /** - * Defines the gradient colors used to render processors. - * - * @param {array} colors The colors - */ - defineProcessorColors: function (colors) { - setColors(colors, 'processor'); - }, - - /** - * Defines the gradient colors used to render label. - * - * @param {array} colors The colors - */ - defineLabelColors: function (colors) { - setColors(colors, 'label'); - }, - /** * Return whether this instance of NiFi is clustered. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js index a316b5d772..e27f43170c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js @@ -248,29 +248,32 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', - url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.id), + url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupData.id), data: { verbose: true }, dataType: 'json' }).done(function (response) { - var processGroup = response.component; - var processGroupContents = processGroup.contents; + var processGroup = response.processGroupFlow; + var processGroupContents = processGroup.flow; + + // show the output port options + var options = []; + $.each(processGroupContents.outputPorts, function (i, outputPort) { + if (outputPort.accessPolicy.canRead && outputPort.accessPolicy.canWrite) { + var component = outputPort.component; + options.push({ + text: component.name, + value: component.id, + description: nf.Common.escapeHtml(component.comments) + }); + } + }); // only proceed if there are output ports - if (!nf.Common.isEmpty(processGroupContents.outputPorts)) { + if (!nf.Common.isEmpty(options)) { $('#output-port-source').show(); - // show the output port options - var options = []; - $.each(processGroupContents.outputPorts, function (i, outputPort) { - options.push({ - text: outputPort.name, - value: outputPort.id, - description: nf.Common.escapeHtml(outputPort.comments) - }); - }); - // sort the options options.sort(function (a, b) { return a.text.localeCompare(b.text); @@ -331,7 +334,7 @@ nf.ConnectionConfiguration = (function () { }, dataType: 'json' }).done(function (response) { - var remoteProcessGroup = response.remoteProcessGroup; + var remoteProcessGroup = response.component; var remoteProcessGroupContents = remoteProcessGroup.contents; // only proceed if there are output ports @@ -473,29 +476,29 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', - url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.id), - data: { - verbose: true - }, + url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupData.id), dataType: 'json' }).done(function (response) { - var processGroup = response.component; - var processGroupContents = processGroup.contents; + var processGroup = response.processGroupFlow; + var processGroupContents = processGroup.flow; + + // show the input port options + var options = []; + $.each(processGroupContents.inputPorts, function (i, inputPort) { + if (inputPort.accessPolicy.canRead && inputPort.accessPolicy.canWrite) { + var component = inputPort.component; + options.push({ + text: component.name, + value: component.id, + description: nf.Common.escapeHtml(component.comments) + }); + } + }); // only proceed if there are output ports - if (!nf.Common.isEmpty(processGroupContents.inputPorts)) { + if (!nf.Common.isEmpty(options)) { $('#input-port-destination').show(); - // show the input port options - var options = []; - $.each(processGroupContents.inputPorts, function (i, inputPort) { - options.push({ - text: inputPort.name, - value: inputPort.id, - description: nf.Common.escapeHtml(inputPort.comments) - }); - }); - // sort the options options.sort(function (a, b) { return a.text.localeCompare(b.text); @@ -555,7 +558,7 @@ nf.ConnectionConfiguration = (function () { }, dataType: 'json' }).done(function (response) { - var remoteProcessGroup = response.remoteProcessGroup; + var remoteProcessGroup = response.component; var remoteProcessGroupContents = remoteProcessGroup.contents; // only proceed if there are output ports diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js index 48f7247f01..1353bbef43 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js @@ -21,12 +21,12 @@ nf.Connection = (function () { // the dimensions for the connection label var dimensions = { - width: 188 + width: 200 }; /** * Gets the position of the label for the specified connection. - * + * * @param {type} connectionLabel The connection label */ var getLabelPosition = function (connectionLabel) { @@ -86,7 +86,7 @@ nf.Connection = (function () { /** * Calculates the distance between the two points specified squared. - * + * * @param {object} v First point * @param {object} w Second point */ @@ -96,7 +96,7 @@ nf.Connection = (function () { /** * Calculates the distance between the two points specified. - * + * * @param {object} v First point * @param {object} w Second point */ @@ -106,7 +106,7 @@ nf.Connection = (function () { /** * Calculates the distance between the point and the line created by s1 and s2. - * + * * @param {object} p The point * @param {object} s1 Segment start * @param {object} s2 Segment end @@ -133,7 +133,7 @@ nf.Connection = (function () { /** * Calculates the index of the bend point that is nearest to the specified point. - * + * * @param {object} p * @param {object} connectionData */ @@ -183,17 +183,17 @@ nf.Connection = (function () { /** * Determines whether the terminal of the connection (source|destination) is * a group. - * + * * @param {object} terminal */ var isGroup = function (terminal) { return terminal.groupId !== nf.Canvas.getGroupId() && (isInputPortType(terminal.type) || isOutputPortType(terminal.type)); }; - + /** * Determines whether expiration is configured for the specified connection. - * - * @param {object} connection + * + * @param {object} connection * @return {boolean} Whether expiration is configured */ var isExpirationConfigured = function (connection) { @@ -210,7 +210,7 @@ nf.Connection = (function () { /** * Sorts the specified connections according to the z index. - * + * * @param {type} connections */ var sort = function (connections) { @@ -223,7 +223,9 @@ nf.Connection = (function () { * Selects the connection elements against the current connection map. */ var select = function () { - return connectionContainer.selectAll('g.connection').data(connectionMap.values()); + return connectionContainer.selectAll('g.connection').data(connectionMap.values(), function (d) { + return d.id; + }); }; var renderConnections = function (entered, selected) { @@ -232,39 +234,42 @@ nf.Connection = (function () { } var connection = entered.append('g') - .attr({ - 'id': function (d) { - return 'id-' + d.id; - }, - 'class': 'connection' - }) - .classed('selected', selected); + .attr({ + 'id': function (d) { + return 'id-' + d.id; + }, + 'class': 'connection' + }) + .classed('selected', selected); // create a connection between the two components connection.append('path') - .attr({ - 'class': 'connection-path', - 'pointer-events': 'none' - }); + .attr({ + 'class': 'connection-path', + 'pointer-events': 'none' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); // path to show when selection connection.append('path') - .attr({ - 'class': 'connection-selection-path', - 'pointer-events': 'none' - }); + .attr({ + 'class': 'connection-selection-path', + 'pointer-events': 'none' + }); // path to make selection easier var selectableConnection = connection.append('path') - .attr({ - 'class': 'connection-path-selectable', - 'pointer-events': 'stroke' - }) - .on('mousedown.selection', function () { - // select the connection when clicking the selectable path - nf.Selectable.select(d3.select(this.parentNode)); - }) - .call(nf.ContextMenu.activate); + .attr({ + 'class': 'connection-path-selectable', + 'pointer-events': 'stroke' + }) + .on('mousedown.selection', function () { + // select the connection when clicking the selectable path + nf.Selectable.select(d3.select(this.parentNode)); + }) + .call(nf.ContextMenu.activate); // only support adding bend points when appropriate selectableConnection.filter(function (d) { @@ -335,29 +340,29 @@ nf.Connection = (function () { if (updatePath === true) { updated.classed('grouped', function (d) { - var grouped = false; + var grouped = false; - if (d.accessPolicy.canRead) { - // if there are more than one selected relationship, mark this as grouped - if (nf.Common.isDefinedAndNotNull(d.component.selectedRelationships) && d.component.selectedRelationships.length > 1) { - grouped = true; + if (d.accessPolicy.canRead) { + // if there are more than one selected relationship, mark this as grouped + if (nf.Common.isDefinedAndNotNull(d.component.selectedRelationships) && d.component.selectedRelationships.length > 1) { + grouped = true; + } } - } - return grouped; - }) - .classed('ghost', function (d) { - var ghost = false; + return grouped; + }) + .classed('ghost', function (d) { + var ghost = false; - if (d.accessPolicy.canRead) { - // if the connection has a relationship that is unavailable, mark it a ghost relationship - if (hasUnavailableRelationship(d)) { - ghost = true; + if (d.accessPolicy.canRead) { + // if the connection has a relationship that is unavailable, mark it a ghost relationship + if (hasUnavailableRelationship(d)) { + ghost = true; + } } - } - return ghost; - }); + return ghost; + }); } updated.each(function (d) { @@ -438,44 +443,47 @@ nf.Connection = (function () { // update the connection paths connection.select('path.connection-path') - .attr({ - 'd': function () { - var datum = [d.start].concat(d.bends, [d.end]); - return lineGenerator(datum); - }, - 'marker-end': function () { - var marker = 'normal'; + .attr({ + 'd': function () { + var datum = [d.start].concat(d.bends, [d.end]); + return lineGenerator(datum); + }, + 'marker-end': function () { + var marker = 'normal'; - if (d.accessPolicy.canRead) { - // if the connection has a relationship that is unavailable, mark it a ghost relationship - if (hasUnavailableRelationship(d)) { - marker = 'ghost'; - } + if (d.accessPolicy.canRead) { + // if the connection has a relationship that is unavailable, mark it a ghost relationship + if (hasUnavailableRelationship(d)) { + marker = 'ghost'; } + } else { + marker = 'unauthorized'; + } - return 'url(#' + marker + ')'; - } - }); + return 'url(#' + marker + ')'; + } + }); connection.select('path.connection-selection-path') - .attr({ - 'd': function () { - var datum = [d.start].concat(d.bends, [d.end]); - return lineGenerator(datum); - } - }); + .attr({ + 'd': function () { + var datum = [d.start].concat(d.bends, [d.end]); + return lineGenerator(datum); + } + }); connection.select('path.connection-path-selectable') - .attr({ - 'd': function () { - var datum = [d.start].concat(d.bends, [d.end]); - return lineGenerator(datum); - } - }); + .attr({ + 'd': function () { + var datum = [d.start].concat(d.bends, [d.end]); + return lineGenerator(datum); + } + }); // ----- // bends // ----- if (d.accessPolicy.canWrite) { + // ------------------ // bends - startpoint // ------------------ @@ -484,17 +492,17 @@ nf.Connection = (function () { // create a point for the start startpoints.enter().append('rect') - .attr({ - 'class': 'startpoint linepoint', - 'pointer-events': 'all', - 'width': 8, - 'height': 8 - }) - .on('mousedown.selection', function () { - // select the connection when clicking the label - nf.Selectable.select(d3.select(this.parentNode)); - }) - .call(nf.ContextMenu.activate); + .attr({ + 'class': 'startpoint linepoint', + 'pointer-events': 'all', + 'width': 8, + 'height': 8 + }) + .on('mousedown.selection', function () { + // select the connection when clicking the label + nf.Selectable.select(d3.select(this.parentNode)); + }) + .call(nf.ContextMenu.activate); // update the start point startpoints.attr('transform', function (p) { @@ -512,18 +520,18 @@ nf.Connection = (function () { // create a point for the end endpoints.enter().append('rect') - .call(endpointDrag) - .attr({ - 'class': 'endpoint linepoint', - 'pointer-events': 'all', - 'width': 8, - 'height': 8 - }) - .on('mousedown.selection', function () { - // select the connection when clicking the label - nf.Selectable.select(d3.select(this.parentNode)); - }) - .call(nf.ContextMenu.activate); + .call(endpointDrag) + .attr({ + 'class': 'endpoint linepoint', + 'pointer-events': 'all', + 'width': 8, + 'height': 8 + }) + .on('mousedown.selection', function () { + // select the connection when clicking the label + nf.Selectable.select(d3.select(this.parentNode)); + }) + .call(nf.ContextMenu.activate); // update the end point endpoints.attr('transform', function (p) { @@ -541,65 +549,65 @@ nf.Connection = (function () { // create a point for the end midpoints.enter().append('rect') - .attr({ - 'class': 'midpoint linepoint', - 'pointer-events': 'all', - 'width': 8, - 'height': 8 - }) - .call(bendPointDrag) - .on('dblclick', function (p) { - // stop even propagation - d3.event.stopPropagation(); + .attr({ + 'class': 'midpoint linepoint', + 'pointer-events': 'all', + 'width': 8, + 'height': 8 + }) + .call(bendPointDrag) + .on('dblclick', function (p) { + // stop even propagation + d3.event.stopPropagation(); - // if this is a self loop prevent removing the last two bends - var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d); - var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d); - if (sourceComponentId === destinationComponentId && d.component.bends.length <= 2) { - nf.Dialog.showOkDialog({ - dialogContent: 'Looping connections must have at least two bend points.', - overlayBackground: false - }); - return; - } - - var newBends = []; - var bendIndex = -1; - - // create a new array of bends without the selected one - $.each(d.component.bends, function (i, bend) { - if (p.x !== bend.x && p.y !== bend.y) { - newBends.push(bend); - } else { - bendIndex = i; - } + // if this is a self loop prevent removing the last two bends + var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d); + var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d); + if (sourceComponentId === destinationComponentId && d.component.bends.length <= 2) { + nf.Dialog.showOkDialog({ + dialogContent: 'Looping connections must have at least two bend points.', + overlayBackground: false }); + return; + } - if (bendIndex < 0) { - return; + var newBends = []; + var bendIndex = -1; + + // create a new array of bends without the selected one + $.each(d.component.bends, function (i, bend) { + if (p.x !== bend.x && p.y !== bend.y) { + newBends.push(bend); + } else { + bendIndex = i; } + }); - var connection = { - id: d.id, - bends: newBends - }; + if (bendIndex < 0) { + return; + } - // update the label index if necessary - var labelIndex = d.component.labelIndex; - if (newBends.length <= 1) { - connection.labelIndex = 0; - } else if (bendIndex <= labelIndex) { - connection.labelIndex = Math.max(0, labelIndex - 1); - } + var connection = { + id: d.id, + bends: newBends + }; - // save the updated connection - save(d, connection); - }) - .on('mousedown.selection', function () { - // select the connection when clicking the label - nf.Selectable.select(d3.select(this.parentNode)); - }) - .call(nf.ContextMenu.activate); + // update the label index if necessary + var labelIndex = d.component.labelIndex; + if (newBends.length <= 1) { + connection.labelIndex = 0; + } else if (bendIndex <= labelIndex) { + connection.labelIndex = Math.max(0, labelIndex - 1); + } + + // save the updated connection + save(d, connection); + }) + .on('mousedown.selection', function () { + // select the connection when clicking the label + nf.Selectable.select(d3.select(this.parentNode)); + }) + .call(nf.ContextMenu.activate); // update the midpoints midpoints.attr('transform', function (p) { @@ -622,27 +630,46 @@ nf.Connection = (function () { if (connectionLabelContainer.empty()) { // connection label container connectionLabelContainer = connection.insert('g', 'rect.startpoint') - .attr({ - 'class': 'connection-label-container', - 'pointer-events': 'all' - }) - .on('mousedown.selection', function () { - // select the connection when clicking the label - nf.Selectable.select(d3.select(this.parentNode)); - }) - .call(nf.ContextMenu.activate); + .attr({ + 'class': 'connection-label-container', + 'pointer-events': 'all' + }) + .on('mousedown.selection', function () { + // select the connection when clicking the label + nf.Selectable.select(d3.select(this.parentNode)); + }) + .call(nf.ContextMenu.activate); // connection label connectionLabelContainer.append('rect') - .attr({ - 'class': 'connection-label', - 'width': dimensions.width, - 'x': 0, - 'y': 0 - }); + .attr({ + 'class': 'body', + 'width': dimensions.width, + 'x': 0, + 'y': 0, + 'filter': 'url(#component-drop-shadow)' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); + + // processor border + connectionLabelContainer.append('rect') + .attr({ + 'class': 'border', + 'width': dimensions.width, + 'fill': 'transparent', + 'stroke': 'transparent' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); } var labelCount = 0; + var rowHeight = 19; + var backgrounds = []; + var borders = []; if (d.accessPolicy.canRead) { @@ -651,73 +678,93 @@ nf.Connection = (function () { // ----------------------- var connectionFrom = connectionLabelContainer.select('g.connection-from-container'); - + // determine if the connection require a from label if (isGroup(d.component.source)) { // see if the connection from label is already rendered if (connectionFrom.empty()) { connectionFrom = connectionLabelContainer.append('g') - .attr({ - 'class': 'connection-from-container' - }); - + .attr({ + 'class': 'connection-from-container' + }); + + // background + backgrounds.push(connectionFrom.append('rect') + .attr({ + 'class': 'connection-label-background', + 'width': dimensions.width, + 'height': rowHeight + })); + + // border + borders.push(connectionFrom.append('rect') + .attr({ + 'class': 'connection-label-border', + 'width': dimensions.width, + 'height': 1 + })); + connectionFrom.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('From'); - + .attr({ + 'class': 'stats-label', + 'x': 5, + 'y': 14 + }) + .text('From'); + connectionFrom.append('text') - .attr({ - 'class': 'connection-stats-value connection-from', - 'x': 33, - 'y': 10, - 'width': 130 - }); - - connectionFrom.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'connection-from-run-status', - 'width': 10, - 'height': 10, - 'x': 167, - 'y': 1 - }); + .attr({ + 'class': 'stats-value connection-from', + 'x': 43, + 'y': 14, + 'width': 130 + }); + + connectionFrom.append('text') + .attr({ + 'class': 'connection-from-run-status', + 'x': 185, + 'y': 14 + }); + } else { + backgrounds.push(connectionFrom.select('rect.connection-label-background')); + borders.push(connectionFrom.select('rect.connection-label-border')); } - + // update the connection from positioning connectionFrom.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; + var y = (rowHeight * labelCount++); + return 'translate(0, ' + y + ')'; }); - + // update the label text connectionFrom.select('text.connection-from') - .each(function () { - var connectionFromLabel = d3.select(this); - - // reset the label name to handle any previous state - connectionFromLabel.text(null).selectAll('title').remove(); - - // apply ellipsis to the label as necessary - nf.CanvasUtils.ellipsis(connectionFromLabel, d.component.source.name); - }).append('title').text(function () { - return d.component.source.name; - }); - - // update the label run status - connectionFrom.select('image.connection-from-run-status').attr('xlink:href', function () { - if (d.component.source.exists === false) { - return 'images/portRemoved.png'; - } else if (d.component.source.running === true) { - return 'images/portRunning.png'; - } else { - return 'images/portStopped.png'; - } + .each(function () { + var connectionFromLabel = d3.select(this); + + // reset the label name to handle any previous state + connectionFromLabel.text(null).selectAll('title').remove(); + + // apply ellipsis to the label as necessary + nf.CanvasUtils.ellipsis(connectionFromLabel, d.component.source.name); + }).append('title').text(function () { + return d.component.source.name; }); + + // update the label run status + connectionFrom.select('text.connection-from-run-status') + .text(function () { + if (d.component.source.exists === false) { + return '\uf071'; + } else if (d.component.source.running === true) { + return '\uf04b'; + } else { + return '\uf04d'; + } + }) + .classed('is-missing-port', function () { + return d.component.source.exists === true; + }); } else { // there is no connection from, but check if the name was previous // rendered so it can be removed @@ -725,79 +772,99 @@ nf.Connection = (function () { connectionFrom.remove(); } } - + // --------------------- // connection label - to // --------------------- - + var connectionTo = connectionLabelContainer.select('g.connection-to-container'); - + // determine if the connection require a to label if (isGroup(d.component.destination)) { // see if the connection to label is already rendered if (connectionTo.empty()) { connectionTo = connectionLabelContainer.append('g') - .attr({ - 'class': 'connection-to-container' - }); - + .attr({ + 'class': 'connection-to-container' + }); + + // background + backgrounds.push(connectionTo.append('rect') + .attr({ + 'class': 'connection-label-background', + 'width': dimensions.width, + 'height': rowHeight + })); + + // border + borders.push(connectionTo.append('rect') + .attr({ + 'class': 'connection-label-border', + 'width': dimensions.width, + 'height': 1 + })); + connectionTo.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('To'); - + .attr({ + 'class': 'stats-label', + 'x': 5, + 'y': 14 + }) + .text('To'); + connectionTo.append('text') - .attr({ - 'class': 'connection-stats-value connection-to', - 'x': 18, - 'y': 10, - 'width': 145 - }); - - connectionTo.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'connection-to-run-status', - 'width': 10, - 'height': 10, - 'x': 167, - 'y': 1 - }); + .attr({ + 'class': 'stats-value connection-to', + 'x': 25, + 'y': 14, + 'width': 145 + }); + + connectionTo.append('text') + .attr({ + 'class': 'connection-to-run-status', + 'x': 185, + 'y': 14 + }); + } else { + backgrounds.push(connectionTo.select('rect.connection-label-background')); + borders.push(connectionTo.select('rect.connection-label-border')); } - + // update the connection to positioning connectionTo.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; + var y = (rowHeight * labelCount++); + return 'translate(0, ' + y + ')'; }); - + // update the label text connectionTo.select('text.connection-to') - .each(function (d) { - var connectionToLabel = d3.select(this); - - // reset the label name to handle any previous state - connectionToLabel.text(null).selectAll('title').remove(); - - // apply ellipsis to the label as necessary - nf.CanvasUtils.ellipsis(connectionToLabel, d.component.destination.name); - }).append('title').text(function (d) { - return d.component.destination.name; - }); - - // update the label run status - connectionTo.select('image.connection-to-run-status').attr('xlink:href', function () { - if (d.component.destination.exists === false) { - return 'images/portRemoved.png'; - } else if (d.component.destination.running === true) { - return 'images/portRunning.png'; - } else { - return 'images/portStopped.png'; - } + .each(function (d) { + var connectionToLabel = d3.select(this); + + // reset the label name to handle any previous state + connectionToLabel.text(null).selectAll('title').remove(); + + // apply ellipsis to the label as necessary + nf.CanvasUtils.ellipsis(connectionToLabel, d.component.destination.name); + }).append('title').text(function (d) { + return d.component.destination.name; }); + + // update the label run status + connectionTo.select('text.connection-to-run-status') + .text(function () { + if (d.component.destination.exists === false) { + return '\uf071'; + } else if (d.component.destination.running === true) { + return '\uf04b'; + } else { + return '\uf04d'; + } + }) + .classed('is-missing-port', function () { + return d.component.destination.exists === false; + }); } else { // there is no connection to, but check if the name was previous // rendered so it can be removed @@ -805,60 +872,79 @@ nf.Connection = (function () { connectionTo.remove(); } } - + // ----------------------- // connection label - name // ----------------------- - + // get the connection name var connectionNameValue = nf.CanvasUtils.formatConnectionName(d.component); var connectionName = connectionLabelContainer.select('g.connection-name-container'); - + // is there a name to render if (!nf.Common.isBlank(connectionNameValue)) { // see if the connection name label is already rendered if (connectionName.empty()) { connectionName = connectionLabelContainer.append('g') - .attr({ - 'class': 'connection-name-container' - }); - + .attr({ + 'class': 'connection-name-container' + }); + + // background + backgrounds.push(connectionName.append('rect') + .attr({ + 'class': 'connection-label-background', + 'width': dimensions.width, + 'height': rowHeight + })); + + // border + borders.push(connectionName.append('rect') + .attr({ + 'class': 'connection-label-border', + 'width': dimensions.width, + 'height': 1 + })); + connectionName.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('Name'); - + .attr({ + 'class': 'stats-label', + 'x': 5, + 'y': 14 + }) + .text('Name'); + connectionName.append('text') - .attr({ - 'class': 'connection-stats-value connection-name', - 'x': 35, - 'y': 10, - 'width': 142 - }); + .attr({ + 'class': 'stats-value connection-name', + 'x': 45, + 'y': 14, + 'width': 142 + }); + } else { + backgrounds.push(connectionName.select('rect.connection-label-background')); + borders.push(connectionName.select('rect.connection-label-border')); } - + // update the connection name positioning connectionName.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; + var y = (rowHeight * labelCount++); + return 'translate(0, ' + y + ')'; }); - + // update the connection name connectionName.select('text.connection-name') - .each(function () { - var connectionToLabel = d3.select(this); - - // reset the label name to handle any previous state - connectionToLabel.text(null).selectAll('title').remove(); - - // apply ellipsis to the label as necessary - nf.CanvasUtils.ellipsis(connectionToLabel, connectionNameValue); - }).append('title').text(function () { - return connectionNameValue; - }); + .each(function () { + var connectionToLabel = d3.select(this); + + // reset the label name to handle any previous state + connectionToLabel.text(null).selectAll('title').remove(); + + // apply ellipsis to the label as necessary + nf.CanvasUtils.ellipsis(connectionToLabel, connectionNameValue); + }).append('title').text(function () { + return connectionNameValue; + }); } else { // there is no connection name, but check if the name was previous // rendered so it can be removed @@ -876,85 +962,138 @@ nf.Connection = (function () { var queued = connectionLabelContainer.select('g.queued-container'); if (queued.empty()) { queued = connectionLabelContainer.append('g') - .attr({ - 'class': 'queued-container' - }); + .attr({ + 'class': 'queued-container' + }); - queued.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('Queued'); + // background + backgrounds.push(queued.append('rect') + .attr({ + 'class': 'connection-label-background', + 'width': dimensions.width, + 'height': rowHeight + })); + + // border + borders.push(queued.append('rect') + .attr({ + 'class': 'connection-label-border', + 'width': dimensions.width, + 'height': 1 + })); queued.append('text') .attr({ - 'class': 'connection-stats-value queued', - 'x': 46, - 'y': 10 + 'class': 'stats-label', + 'x': 5, + 'y': 14 + }) + .text('Queued'); + + var queuedText = queued.append('text') + .attr({ + 'class': 'stats-value queued', + 'x': 55, + 'y': 14 }); - + + // queued count + queuedText.append('tspan') + .attr({ + 'class': 'count' + }); + + // queued size + queuedText.append('tspan') + .attr({ + 'class': 'size' + }); + var expiration = queued.append('g') - .attr({ - 'class': 'expiration-icon', - 'transform': 'translate(167, 2)' - }); - + .attr({ + 'class': 'expiration-icon', + 'transform': 'translate(167, 2)' + }); + expiration.append('circle') - .attr({ - 'cx': 5, - 'cy': 5, - 'r': 4.75, - 'stroke-width': 0.5, - 'stroke': '#87888a', - 'fill': 'url(#expiration)' - }); - + .attr({ + 'cx': 5, + 'cy': 5, + 'r': 4.75, + 'stroke-width': 0.5, + 'stroke': '#87888a', + 'fill': 'url(#expiration)' + }); + expiration.append('line') - .attr({ - 'x1': 6, - 'y1': 5, - 'x2': 3, - 'y2': 4, - 'stroke': '#fff', - 'stroke-width': 1 - }); - + .attr({ + 'x1': 6, + 'y1': 5, + 'x2': 3, + 'y2': 4, + 'stroke': '#fff', + 'stroke-width': 1 + }); + expiration.append('line') - .attr({ - 'x1': 6, - 'y1': 5, - 'x2': 3, - 'y2': 7, - 'stroke': '#fff', - 'stroke-width': 1 - }); - + .attr({ + 'x1': 6, + 'y1': 5, + 'x2': 3, + 'y2': 7, + 'stroke': '#fff', + 'stroke-width': 1 + }); + expiration.append('title'); + } else { + backgrounds.push(queued.select('rect.connection-label-background')); + borders.push(queued.select('rect.connection-label-border')); } // update the queued vertical positioning as necessary queued.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; + var y = (rowHeight * labelCount++); + return 'translate(0, ' + y + ')'; }); // update the height based on the labels being rendered - connectionLabelContainer.select('rect.connection-label') - .attr('height', function () { - return 5 + (15 * labelCount) + 3; - }); - + connectionLabelContainer.select('rect.body') + .attr('height', function () { + return (rowHeight * labelCount); + }); + connectionLabelContainer.select('rect.border') + .attr('height', function () { + return (rowHeight * labelCount); + }); + + // update the coloring of the backgrounds + $.each(backgrounds, function (i, background) { + if (i % 2 === 0) { + background.attr('fill', '#f4f6f7'); + } else { + background.attr('fill', '#ffffff'); + } + }); + + // update the coloring of the label borders + $.each(borders, function (i, border) { + if (i > 0) { + border.attr('fill', '#c7d2d7'); + } else { + border.attr('fill', 'transparent'); + } + }); + if (d.accessPolicy.canRead) { // determine whether or not to show the expiration icon connectionLabelContainer.select('g.expiration-icon') - .classed('hidden', function () { - return !isExpirationConfigured(d.component); - }) - .select('title').text(function () { - return 'Expires FlowFiles older than ' + d.component.flowFileExpiration; - }); + .classed('hidden', function () { + return !isExpirationConfigured(d.component); + }) + .select('title').text(function () { + return 'Expires FlowFiles older than ' + d.component.flowFileExpiration; + }); } if (d.accessPolicy.canWrite) { @@ -973,17 +1112,17 @@ nf.Connection = (function () { // update the position of the label if possible connection.select('g.connection-label-container') - .attr('transform', function () { - var label = d3.select(this).select('rect.connection-label'); - var position = getLabelPosition(label); - return 'translate(' + position.x + ', ' + position.y + ')'; - }); + .attr('transform', function () { + var label = d3.select(this).select('rect.body'); + var position = getLabelPosition(label); + return 'translate(' + position.x + ', ' + position.y + ')'; + }); }); }; /** * Updates the stats of the connections in the specified selection. - * + * * @param {selection} updated The selected connections to update */ var updateConnectionStatus = function (updated) { @@ -991,20 +1130,31 @@ nf.Connection = (function () { return; } - updated.select('text.queued') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.queued; - } else { - return '- / -'; - } - }); + // queued count value + updated.select('text.queued tspan.count') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return nf.Common.substringBeforeFirst(d.status.queued, ' '); + } else { + return '-'; + } + }); + + // queued size value + updated.select('text.queued tspan.size') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return ' ' + nf.Common.substringAfterFirst(d.status.queued, ' '); + } else { + return ' (-)'; + } + }); }; /** * Saves the connection entry specified by d with the new configuration specified * in connection. - * + * * @param {type} d * @param {type} connection */ @@ -1046,7 +1196,7 @@ nf.Connection = (function () { removed.each(function (d) { nf.CanvasUtils.reloadConnectionSourceAndDestination(d.sourceId, d.destinationId); }); - + // remove the connection removed.remove(); }; @@ -1056,323 +1206,321 @@ nf.Connection = (function () { selfLoopXOffset: (dimensions.width / 2) + 5, selfLoopYOffset: 25 }, - + init: function () { connectionMap = d3.map(); // create the connection container connectionContainer = d3.select('#canvas').append('g') - .attr({ - 'pointer-events': 'stroke', - 'class': 'connections' - }); + .attr({ + 'pointer-events': 'stroke', + 'class': 'connections' + }); // define the line generator lineGenerator = d3.svg.line() - .x(function (d) { - return d.x; - }) - .y(function (d) { - return d.y; - }) - .interpolate('linear'); + .x(function (d) { + return d.x; + }) + .y(function (d) { + return d.y; + }) + .interpolate('linear'); // handle bend point drag events bendPointDrag = d3.behavior.drag() - .on('dragstart', function () { - // stop further propagation - d3.event.sourceEvent.stopPropagation(); - }) - .on('drag', function (d) { - d.x = d3.event.x; - d.y = d3.event.y; + .on('dragstart', function () { + // stop further propagation + d3.event.sourceEvent.stopPropagation(); + }) + .on('drag', function (d) { + d.x = d3.event.x; + d.y = d3.event.y; - // redraw this connection - d3.select(this.parentNode).call(updateConnections, true, false); - }) - .on('dragend', function () { - var connection = d3.select(this.parentNode); - var connectionData = connection.datum(); - var bends = connection.selectAll('rect.midpoint').data(); + // redraw this connection + d3.select(this.parentNode).call(updateConnections, true, false); + }) + .on('dragend', function () { + var connection = d3.select(this.parentNode); + var connectionData = connection.datum(); + var bends = connection.selectAll('rect.midpoint').data(); - // ensure the bend lengths are the same - if (bends.length === connectionData.component.bends.length) { - // determine if the bend points have moved - var different = false; - for (var i = 0; i < bends.length && !different; i++) { - if (bends[i].x !== connectionData.component.bends[i].x || bends[i].y !== connectionData.component.bends[i].y) { - different = true; - } - } - - // only save the updated bends if necessary - if (different) { - save(connectionData, { - id: connectionData.id, - bends: bends - }).fail(function () { - // restore the previous bend points - connectionData.bends = $.map(connectionData.component.bends, function (bend) { - return { - x: bend.x, - y: bend.y - }; - }); - - // refresh the connection - connection.call(updateConnections, true, false); - }); + // ensure the bend lengths are the same + if (bends.length === connectionData.component.bends.length) { + // determine if the bend points have moved + var different = false; + for (var i = 0; i < bends.length && !different; i++) { + if (bends[i].x !== connectionData.component.bends[i].x || bends[i].y !== connectionData.component.bends[i].y) { + different = true; } } - // stop further propagation - d3.event.sourceEvent.stopPropagation(); - }); + // only save the updated bends if necessary + if (different) { + save(connectionData, { + id: connectionData.id, + bends: bends + }).fail(function () { + // restore the previous bend points + connectionData.bends = $.map(connectionData.component.bends, function (bend) { + return { + x: bend.x, + y: bend.y + }; + }); + + // refresh the connection + connection.call(updateConnections, true, false); + }); + } + } + + // stop further propagation + d3.event.sourceEvent.stopPropagation(); + }); // handle endpoint drag events endpointDrag = d3.behavior.drag() - .on('dragstart', function (d) { - // indicate that dragging has begun - d.dragging = true; + .on('dragstart', function (d) { + // indicate that dragging has begun + d.dragging = true; - // stop further propagation - d3.event.sourceEvent.stopPropagation(); - }) - .on('drag', function (d) { - d.x = d3.event.x - 8; - d.y = d3.event.y - 8; + // stop further propagation + d3.event.sourceEvent.stopPropagation(); + }) + .on('drag', function (d) { + d.x = d3.event.x - 8; + d.y = d3.event.y - 8; - // ensure the new destination is valid - d3.select('g.hover').classed('connectable-destination', function () { - return nf.CanvasUtils.isValidConnectionDestination(d3.select(this)); - }); + // ensure the new destination is valid + d3.select('g.hover').classed('connectable-destination', function () { + return nf.CanvasUtils.isValidConnectionDestination(d3.select(this)); + }); - // redraw this connection - d3.select(this.parentNode).call(updateConnections, true, false); - }) - .on('dragend', function (d) { - // indicate that dragging as stopped - d.dragging = false; + // redraw this connection + d3.select(this.parentNode).call(updateConnections, true, false); + }) + .on('dragend', function (d) { + // indicate that dragging as stopped + d.dragging = false; - // get the corresponding connection - var connection = d3.select(this.parentNode); - var connectionData = connection.datum(); - var previousDestinationId = connectionData.component.destination.id; + // get the corresponding connection + var connection = d3.select(this.parentNode); + var connectionData = connection.datum(); + var previousDestinationId = connectionData.component.destination.id; - // attempt to select a new destination - var destination = d3.select('g.connectable-destination'); + // attempt to select a new destination + var destination = d3.select('g.connectable-destination'); - // resets the connection if we're not over a new destination - if (destination.empty()) { - connection.call(updateConnections, true, false); + // resets the connection if we're not over a new destination + if (destination.empty()) { + connection.call(updateConnections, true, false); + } else { + // prompt for the new port if appropriate + if (nf.CanvasUtils.isProcessGroup(destination) || nf.CanvasUtils.isRemoteProcessGroup(destination)) { + // user will select new port and updated connect details will be set accordingly + nf.ConnectionConfiguration.showConfiguration(connection, destination).done(function () { + // reload the previous destination + nf.CanvasUtils.reloadConnectionSourceAndDestination(null, previousDestinationId); + }).fail(function () { + // reset the connection + connection.call(updateConnections, true, false); + }); } else { - // prompt for the new port if appropriate - if (nf.CanvasUtils.isProcessGroup(destination) || nf.CanvasUtils.isRemoteProcessGroup(destination)) { - // user will select new port and updated connect details will be set accordingly - nf.ConnectionConfiguration.showConfiguration(connection, destination).done(function () { - // reload the previous destination - nf.CanvasUtils.reloadConnectionSourceAndDestination(null, previousDestinationId); - }).fail(function () { - // reset the connection - connection.call(updateConnections, true, false); - }); - } else { - // get the destination details - var destinationData = destination.datum(); - var destinationType = nf.CanvasUtils.getConnectableTypeForDestination(destination); + // get the destination details + var destinationData = destination.datum(); + var destinationType = nf.CanvasUtils.getConnectableTypeForDestination(destination); - var connectionEntity = { - 'revision': nf.Client.getRevision(), - 'component': { - 'id': connectionData.id, - 'destination': { - 'id': destinationData.id, - 'groupId': nf.Canvas.getGroupId(), - 'type': destinationType - } + var connectionEntity = { + 'revision': nf.Client.getRevision(), + 'component': { + 'id': connectionData.id, + 'destination': { + 'id': destinationData.id, + 'groupId': nf.Canvas.getGroupId(), + 'type': destinationType } - }; - - // if this is a self loop and there are less than 2 bends, add them - if (connectionData.bends.length < 2 && connectionData.component.source.id === destinationData.id) { - var rightCenter = { - x: destinationData.position.x + (destinationData.dimensions.width), - y: destinationData.position.y + (destinationData.dimensions.height / 2) - }; - var xOffset = nf.Connection.config.selfLoopXOffset; - var yOffset = nf.Connection.config.selfLoopYOffset; - - connectionEntity.connection.bends = []; - connectionEntity.connection.bends.push({ - 'x': (rightCenter.x + xOffset), - 'y': (rightCenter.y - yOffset) - }); - connectionEntity.connection.bends.push({ - 'x': (rightCenter.x + xOffset), - 'y': (rightCenter.y + yOffset) - }); } + }; - $.ajax({ - type: 'PUT', - url: connectionData.component.uri, - data: JSON.stringify(connectionEntity), - dataType: 'json', - contentType: 'application/json' - }).done(function (response) { - var updatedConnectionData = response.component; + // if this is a self loop and there are less than 2 bends, add them + if (connectionData.bends.length < 2 && connectionData.component.source.id === destinationData.id) { + var rightCenter = { + x: destinationData.position.x + (destinationData.dimensions.width), + y: destinationData.position.y + (destinationData.dimensions.height / 2) + }; + var xOffset = nf.Connection.config.selfLoopXOffset; + var yOffset = nf.Connection.config.selfLoopYOffset; - // update the revision - nf.Client.setRevision(response.revision); - - // refresh to update the label - nf.Connection.set(response); - - // reload the previous destination and the new source/destination - nf.CanvasUtils.reloadConnectionSourceAndDestination(null, previousDestinationId); - nf.CanvasUtils.reloadConnectionSourceAndDestination(updatedConnectionData.source.id, updatedConnectionData.destination.id); - }).fail(function (xhr, status, error) { - if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) { - nf.Dialog.showOkDialog({ - dialogContent: nf.Common.escapeHtml(xhr.responseText), - overlayBackground: true - }); - - // reset the connection - connection.call(updateConnections, true, false); - } else { - nf.Common.handleAjaxError(xhr, status, error); - } + connectionEntity.connection.bends = []; + connectionEntity.connection.bends.push({ + 'x': (rightCenter.x + xOffset), + 'y': (rightCenter.y - yOffset) + }); + connectionEntity.connection.bends.push({ + 'x': (rightCenter.x + xOffset), + 'y': (rightCenter.y + yOffset) }); } - } - // stop further propagation - d3.event.sourceEvent.stopPropagation(); - }); + $.ajax({ + type: 'PUT', + url: connectionData.component.uri, + data: JSON.stringify(connectionEntity), + dataType: 'json', + contentType: 'application/json' + }).done(function (response) { + var updatedConnectionData = response.component; + + // update the revision + nf.Client.setRevision(response.revision); + + // refresh to update the label + nf.Connection.set(response); + + // reload the previous destination and the new source/destination + nf.CanvasUtils.reloadConnectionSourceAndDestination(null, previousDestinationId); + nf.CanvasUtils.reloadConnectionSourceAndDestination(updatedConnectionData.source.id, updatedConnectionData.destination.id); + }).fail(function (xhr, status, error) { + if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) { + nf.Dialog.showOkDialog({ + dialogContent: nf.Common.escapeHtml(xhr.responseText), + overlayBackground: true + }); + + // reset the connection + connection.call(updateConnections, true, false); + } else { + nf.Common.handleAjaxError(xhr, status, error); + } + }); + } + } + + // stop further propagation + d3.event.sourceEvent.stopPropagation(); + }); // label drag behavior labelDrag = d3.behavior.drag() - .on('dragstart', function (d) { - // stop further propagation - d3.event.sourceEvent.stopPropagation(); - }) - .on('drag', function (d) { - if (d.bends.length > 1) { - // get the dragged component - var drag = d3.select('rect.label-drag'); + .on('dragstart', function (d) { + // stop further propagation + d3.event.sourceEvent.stopPropagation(); + }) + .on('drag', function (d) { + if (d.bends.length > 1) { + // get the dragged component + var drag = d3.select('rect.label-drag'); - // lazily create the drag selection box - if (drag.empty()) { - var connectionLabel = d3.select(this).select('rect.connection-label'); + // lazily create the drag selection box + if (drag.empty()) { + var connectionLabel = d3.select(this).select('rect.body'); - var position = getLabelPosition(connectionLabel); - var width = dimensions.width; - var height = connectionLabel.attr('height'); + var position = getLabelPosition(connectionLabel); + var width = dimensions.width; + var height = connectionLabel.attr('height'); - // create a selection box for the move - drag = d3.select('#canvas').append('rect') - .attr('rx', 6) - .attr('ry', 6) - .attr('x', position.x) - .attr('y', position.y) - .attr('class', 'label-drag') - .attr('width', width) - .attr('height', height) - .attr('stroke-width', function () { - return 1 / nf.Canvas.View.scale(); - }) - .attr('stroke-dasharray', function () { - return 4 / nf.Canvas.View.scale(); - }) - .datum({ - x: position.x, - y: position.y, - width: width, - height: height - }); - } else { - // update the position of the drag selection - drag.attr('x', function (d) { + // create a selection box for the move + drag = d3.select('#canvas').append('rect') + .attr('x', position.x) + .attr('y', position.y) + .attr('class', 'label-drag') + .attr('width', width) + .attr('height', height) + .attr('stroke-width', function () { + return 1 / nf.Canvas.View.scale(); + }) + .attr('stroke-dasharray', function () { + return 4 / nf.Canvas.View.scale(); + }) + .datum({ + x: position.x, + y: position.y, + width: width, + height: height + }); + } else { + // update the position of the drag selection + drag.attr('x', function (d) { d.x += d3.event.dx; return d.x; }) - .attr('y', function (d) { - d.y += d3.event.dy; - return d.y; - }); - } + .attr('y', function (d) { + d.y += d3.event.dy; + return d.y; + }); + } - // calculate the current point - var datum = drag.datum(); - var currentPoint = { - x: datum.x + (datum.width / 2), - y: datum.y + (datum.height / 2) + // calculate the current point + var datum = drag.datum(); + var currentPoint = { + x: datum.x + (datum.width / 2), + y: datum.y + (datum.height / 2) + }; + + var closestBendIndex = -1; + var minDistance; + $.each(d.bends, function (i, bend) { + var bendPoint = { + 'x': bend.x, + 'y': bend.y }; - var closestBendIndex = -1; - var minDistance; - $.each(d.bends, function (i, bend) { - var bendPoint = { - 'x': bend.x, - 'y': bend.y - }; + // get the distance + var distance = distanceBetweenPoints(currentPoint, bendPoint); - // get the distance - var distance = distanceBetweenPoints(currentPoint, bendPoint); + // see if its the minimum + if (closestBendIndex === -1 || distance < minDistance) { + closestBendIndex = i; + minDistance = distance; + } + }); - // see if its the minimum - if (closestBendIndex === -1 || distance < minDistance) { - closestBendIndex = i; - minDistance = distance; - } + // record the closest bend + d.labelIndex = closestBendIndex; + + // refresh the connection + d3.select(this.parentNode).call(updateConnections, true, false); + } + }) + .on('dragend', function (d) { + if (d.bends.length > 1) { + // get the drag selection + var drag = d3.select('rect.label-drag'); + + // ensure we found a drag selection + if (!drag.empty()) { + // remove the drag selection + drag.remove(); + } + + // only save if necessary + if (d.labelIndex !== d.component.labelIndex) { + // get the connection to refresh below + var connection = d3.select(this.parentNode); + + // save the new label index + save(d, { + id: d.id, + labelIndex: d.labelIndex + }).fail(function () { + // restore the previous label index + d.labelIndex = d.component.labelIndex; + + // refresh the connection + connection.call(updateConnections, true, false); }); - - // record the closest bend - d.labelIndex = closestBendIndex; - - // refresh the connection - d3.select(this.parentNode).call(updateConnections, true, false); } - }) - .on('dragend', function (d) { - if (d.bends.length > 1) { - // get the drag selection - var drag = d3.select('rect.label-drag'); + } - // ensure we found a drag selection - if (!drag.empty()) { - // remove the drag selection - drag.remove(); - } - - // only save if necessary - if (d.labelIndex !== d.component.labelIndex) { - // get the connection to refresh below - var connection = d3.select(this.parentNode); - - // save the new label index - save(d, { - id: d.id, - labelIndex: d.labelIndex - }).fail(function () { - // restore the previous label index - d.labelIndex = d.component.labelIndex; - - // refresh the connection - connection.call(updateConnections, true, false); - }); - } - } - - // stop further propagation - d3.event.sourceEvent.stopPropagation(); - }); + // stop further propagation + d3.event.sourceEvent.stopPropagation(); + }); }, - + /** * Populates the graph with the specified connections. - * + * * @argument {object | array} connectionEntities The connections to add * @argument {boolean} selectAll Whether or not to select the new contents */ @@ -1398,17 +1546,17 @@ nf.Connection = (function () { // apply the selection and handle all new connection select().enter().call(renderConnections, selectAll); }, - + /** * Reorders the connections based on their current z index. */ reorder: function () { d3.selectAll('g.connection').call(sort); }, - + /** * Sets the value of the specified connection. - * + * * @param {type} connectionEntities */ set: function (connectionEntities) { @@ -1432,10 +1580,10 @@ nf.Connection = (function () { set(connectionEntities); } }, - + /** * Sets the connection status using the specified status. - * + * * @param {array} connectionStatus */ setStatus: function (connectionStatus) { @@ -1454,10 +1602,10 @@ nf.Connection = (function () { // update the visible connections d3.selectAll('g.connection.visible').call(updateConnectionStatus); }, - + /** * Refreshes the connection in the UI. - * + * * @param {string} connectionId */ refresh: function (connectionId) { @@ -1467,17 +1615,17 @@ nf.Connection = (function () { d3.selectAll('g.connection').call(updateConnections, true, true); } }, - + /** * Refreshes the components necessary after a pan event. */ pan: function () { d3.selectAll('g.connection.entering, g.connection.leaving').call(updateConnections, false, true); }, - + /** * Removes the specified connection. - * + * * @param {array|string} connections The connection id */ remove: function (connections) { @@ -1492,17 +1640,17 @@ nf.Connection = (function () { // apply the selection and handle all removed connections select().exit().call(removeConnections); }, - + /** * Removes all processors. */ removeAll: function () { nf.Connection.remove(connectionMap.keys()); }, - + /** * Reloads the connection state from the server and refreshes the UI. - * + * * @param {object} connection The connection to reload */ reload: function (connection) { @@ -1516,10 +1664,10 @@ nf.Connection = (function () { }); } }, - + /** * Gets the connection that have a source or destination component with the specified id. - * + * * @param {string} id component id * @returns {Array} components connections */ @@ -1533,11 +1681,11 @@ nf.Connection = (function () { }); return connections; }, - + /** * If the connection id is specified it is returned. If no connection id * specified, all connections are returned. - * + * * @param {string} id */ get: function (id) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js index d0422861cd..418d03fa1e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js @@ -20,8 +20,8 @@ nf.Funnel = (function () { var dimensions = { - width: 61, - height: 61 + width: 48, + height: 48 }; // ----------------------------- @@ -51,7 +51,7 @@ nf.Funnel = (function () { /** * Renders the funnels in the specified selection. - * + * * @param {selection} entered The selection of funnels to be rendered * @param {boolean} selected Whether the element should be selected */ @@ -61,40 +61,60 @@ nf.Funnel = (function () { } var funnel = entered.append('g') - .attr({ - 'id': function (d) { - return 'id-' + d.id; - }, - 'class': 'funnel component' - }) - .classed('selected', selected) - .call(nf.CanvasUtils.position); + .attr({ + 'id': function (d) { + return 'id-' + d.id; + }, + 'class': 'funnel component' + }) + .classed('selected', selected) + .call(nf.CanvasUtils.position); // funnel border funnel.append('rect') - .attr({ - 'class': 'border', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': 'transparent', - 'stroke-opacity': 0.8, - 'stroke-width': 1 - }); + .attr({ + 'rx': 2, + 'ry': 2, + 'class': 'border', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'fill': 'transparent', + 'stroke': 'transparent' + }).classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); - // processor icon - funnel.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconFunnel.png', - 'width': 41, - 'height': 41, - 'x': 10, - 'y': 10 - }); + // funnel body + funnel.append('rect') + .attr({ + 'rx': 2, + 'ry': 2, + 'class': 'body', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'filter': 'url(#component-drop-shadow)', + 'stroke-width': 0 + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); + + // funnel icon + funnel.append('text') + .attr({ + 'class': 'funnel-icon', + 'x': 9, + 'y': 34 + }) + .text('\ue803'); // always support selection funnel.call(nf.Selectable.activate).call(nf.ContextMenu.activate); @@ -109,7 +129,7 @@ nf.Funnel = (function () { /** * Updates the funnels in the specified selection. - * + * * @param {selection} updated The funnels to be updated */ var updateFunnels = function (updated) { @@ -117,7 +137,7 @@ nf.Funnel = (function () { /** * Removes the funnels in the specified selection. - * + * * @param {selection} removed The funnels to be removed */ var removeFunnels = function (removed) { @@ -133,15 +153,15 @@ nf.Funnel = (function () { // create the funnel container funnelContainer = d3.select('#canvas').append('g') - .attr({ - 'pointer-events': 'all', - 'class': 'funnels' - }); + .attr({ + 'pointer-events': 'all', + 'class': 'funnels' + }); }, - + /** * Populates the graph with the specified funnels. - * + * * @argument {object | array} funnelEntities The funnels to add * @argument {boolean} selectAll Whether or not to select the new contents */ @@ -168,11 +188,11 @@ nf.Funnel = (function () { // apply the selection and handle all new processors select().enter().call(renderFunnels, selectAll); }, - + /** * If the funnel id is specified it is returned. If no funnel id * specified, all funnels are returned. - * + * * @param {string} id */ get: function (id) { @@ -182,11 +202,11 @@ nf.Funnel = (function () { return funnelMap.get(id); } }, - + /** - * If the funnel id is specified it is refresh according to the current + * If the funnel id is specified it is refresh according to the current * state. If not funnel id is specified, all funnels are refreshed. - * + * * @param {string} id Optional */ refresh: function (id) { @@ -196,11 +216,11 @@ nf.Funnel = (function () { d3.selectAll('g.funnel').call(updateFunnels); } }, - + /** * Reloads the funnel state from the server and refreshes the UI. * If the funnel is currently unknown, this function just returns. - * + * * @param {object} funnel The funnel to reload */ reload: function (funnel) { @@ -214,21 +234,21 @@ nf.Funnel = (function () { }); } }, - + /** * Positions the component. - * + * * @param {string} id The id */ position: function (id) { d3.select('#id-' + id).call(nf.CanvasUtils.position); }, - + /** - * Sets the specified funnel(s). If the is an array, it - * will set each funnel. If it is not an array, it will + * Sets the specified funnel(s). If the is an array, it + * will set each funnel. If it is not an array, it will * attempt to set the specified funnel. - * + * * @param {object | array} funnelEntities */ set: function (funnelEntities) { @@ -237,7 +257,7 @@ nf.Funnel = (function () { // update the current entry var funnelEntry = funnelMap.get(funnelEntity.id); $.extend(funnelEntry, funnelEntity); - + // update the connection in the UI d3.select('#id-' + funnelEntity.id).call(updateFunnels); } @@ -255,7 +275,7 @@ nf.Funnel = (function () { /** * Removes the specified funnel. - * + * * @param {array|string} funnels The funnel id */ remove: function (funnels) { @@ -270,7 +290,7 @@ nf.Funnel = (function () { // apply the selection and handle all removed funnels select().exit().call(removeFunnels); }, - + /** * Removes all processors. */ 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 809b90520f..bb58ff97dc 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 @@ -53,7 +53,9 @@ nf.Label = (function () { * Selects the labels elements against the current label map. */ var select = function () { - return labelContainer.selectAll('g.label').data(labelMap.values()); + return labelContainer.selectAll('g.label').data(labelMap.values(), function (d) { + return d.id; + }); }; /** @@ -126,21 +128,6 @@ nf.Label = (function () { return; } - // reset the colors - var colors = d3.set(); - colors.add(nf.Common.substringAfterLast(nf.Label.defaultColor(), '#')); - - // determine all unique colors - labelMap.forEach(function (id, d) { - if (d.accessPolicy.canRead) { - var color = d.component.style['background-color']; - if (nf.Common.isDefinedAndNotNull(color)) { - colors.add(nf.Common.substringAfterLast(color, '#')); - } - } - }); - nf.Canvas.defineLabelColors(colors.values()); - // update the border using the configured color updated.select('rect.border') .attr({ @@ -177,10 +164,7 @@ nf.Label = (function () { } } - // get just the color code part - color = nf.Common.substringAfterLast(color, '#'); - - return 'url(#label-background-' + color + ')'; + return color; }, 'width': function (d) { return d.dimensions.width; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js index 74c7a77bc1..ba8060adb7 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js @@ -20,15 +20,15 @@ nf.Port = (function () { var PREVIEW_NAME_LENGTH = 15; - var OFFSET_VALUE = 12; + var OFFSET_VALUE = 25; var portDimensions = { - width: 160, - height: 40 + width: 240, + height: 50 }; var remotePortDimensions = { - width: 160, - height: 56 + width: 240, + height: 75 }; // ---------------------------- @@ -51,7 +51,9 @@ nf.Port = (function () { * Selects the port elements against the current port map. */ var select = function () { - return portContainer.selectAll('g.input-port, g.output-port').data(portMap.values()); + return portContainer.selectAll('g.input-port, g.output-port').data(portMap.values(), function (d) { + return d.id; + }); }; /** @@ -66,36 +68,54 @@ nf.Port = (function () { } var port = entered.append('g') - .attr({ - 'id': function (d) { - return 'id-' + d.id; - }, - 'class': function (d) { - if (d.portType === 'INPUT_PORT') { - return 'input-port component'; - } else { - return 'output-port component'; - } + .attr({ + 'id': function (d) { + return 'id-' + d.id; + }, + 'class': function (d) { + if (d.portType === 'INPUT_PORT') { + return 'input-port component'; + } else { + return 'output-port component'; } - }) - .classed('selected', selected) - .call(nf.CanvasUtils.position); + } + }) + .classed('selected', selected) + .call(nf.CanvasUtils.position); // port border port.append('rect') - .attr({ - 'class': 'border', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': 'transparent', - 'stroke-opacity': 0.8, - 'stroke-width': 1, - 'stroke': '#aaaaaa' - }); + .attr({ + 'class': 'border', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'fill': 'transparent', + 'stroke': 'transparent' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); + + // port body + port.append('rect') + .attr({ + 'class': 'body', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'filter': 'url(#component-drop-shadow)', + 'stroke-width': 0 + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); var offset = 0; @@ -105,84 +125,47 @@ nf.Port = (function () { // port remote banner port.append('rect') - .attr({ - 'class': 'remote-banner', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': offset, - 'fill': '#294c58', - 'fill-opacity': 0.95 - }); - } - - // port body - port.append('rect') .attr({ - 'x': 0, - 'y': offset, - 'class': 'port-body', + 'class': 'remote-banner', 'width': function (d) { return d.dimensions.width; }, - 'height': function (d) { - return d.dimensions.height - offset; - }, - 'fill': 'url(#port-background)', - 'fill-opacity': 0.8, - 'stroke-opacity': 0.8, - 'stroke-width': 0, - 'stroke': '#aaaaaa' + 'height': offset, + 'fill': '#e3e8eb' }); + } // port icon - port.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': function (d) { - if (d.portTtype === 'INPUT_PORT') { - return 'images/iconInputPort.png'; - } else { - return 'images/iconOutputPort.png'; - } - }, - 'width': 46, - 'height': 31, - 'x': function (d) { - if (d.portType === 'INPUT_PORT') { - return 0; - } else { - return 114; - } - }, - 'y': 5 + offset - }); + port.append('text') + .attr({ + 'class': 'port-icon', + 'x': 10, + 'y': 38 + offset + }) + .text(function (d) { + if (d.portType === 'INPUT_PORT') { + return '\ue832'; + } else { + return '\ue833'; + } + }); // port name port.append('text') - .attr({ - 'x': function (d) { - if (d.portType === 'INPUT_PORT') { - return 52; - } else { - return 5; - } - }, - 'y': 18 + offset, - 'width': 95, - 'height': 30, - 'font-size': '10px', - 'font-weight': 'bold', - 'fill': '#294c58', - 'class': 'port-name' - }); + .attr({ + 'x': 70, + 'y': 25 + offset, + 'width': 95, + 'height': 30, + 'class': 'port-name' + }); // make ports selectable port.call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only activate dragging and connecting if appropriate port.filter(function (d) { - return d.accessPolicy.canWrite && d.accessPolicy.canRead; + return d.accessPolicy.canWrite && d.accessPolicy.canRead; }).call(nf.Draggable.activate).call(nf.Connectable.activate); // call update to trigger some rendering @@ -213,132 +196,85 @@ nf.Port = (function () { offset = OFFSET_VALUE; // port transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'port-transmission-icon', - 'width': 10, - 'height': 10, - 'x': 3, - 'y': 1 - }); + details.append('text') + .attr({ + 'class': 'port-transmission-icon', + 'x': 10, + 'y': 15 + }); + + // bulletin background + details.append('rect') + .attr({ + 'class': 'bulletin-background', + 'x': function (d) { + return portData.dimensions.width - offset; + }, + 'width': offset, + 'height': offset + }); // bulletin icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'bulletin-icon', - 'xlink:href': 'images/iconBulletin.png', - 'width': 12, - 'height': 12, - 'x': 147, - 'y': 0 - }); + details.append('text') + .attr({ + 'class': 'bulletin-icon', + 'x': function (d) { + return portData.dimensions.width - 18; + }, + 'y': 18 + }) + .text('\uf24a'); } // run status icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'port-run-status-icon', - 'width': 16, - 'height': 16, - 'x': function (d) { - if (d.portType === 'INPUT_PORT') { - return 33; - } else { - return 107; - } - }, - 'y': function () { - return 24 + offset; - } - }); - - // active thread count - details.append('rect') - .attr({ - 'class': 'active-thread-count-background', - 'height': 11, - 'y': 0, - 'fill': '#fff', - 'fill-opacity': '0.65', - 'stroke': '#aaa', - 'stroke-width': '1' - }); - - // active thread bacground details.append('text') - .attr({ - 'class': 'active-thread-count', - 'height': 11, - 'y': 9, - 'fill': '#000' - }); + .attr({ + 'class': 'run-status-icon', + 'x': 50, + 'y': function () { + return 25 + offset; + } + }); + + // ------------------- + // active thread count + // ------------------- + + // active thread count + details.append('text') + .attr({ + 'class': 'active-thread-count-icon', + 'y': 68 + }) + .text('\ue83f'); + + // active thread icon + details.append('text') + .attr({ + 'class': 'active-thread-count', + 'y': 68 + }); } if (portData.accessPolicy.canRead) { - // update the run status - details.select('image.port-run-status-icon') - .attr('xlink:href', function (d) { - var img = ''; - if (d.component.state === 'DISABLED') { - img = 'images/iconDisable.png'; - } else if (!nf.Common.isEmpty(d.component.validationErrors)) { - img = 'images/iconAlert.png'; - } else if (d.component.state === 'RUNNING') { - img = 'images/iconRun.png'; - } else if (d.component.state === 'STOPPED') { - img = 'images/iconStop.png'; - } - return img; - }) - .each(function (d) { - // remove the existing tip if necessary - var tip = d3.select('#run-status-tip-' + d.id); - if (!tip.empty()) { - tip.remove(); - } - - // if there are validation errors generate a tooltip - if (!nf.Common.isEmpty(d.component.validationErrors)) { - tip = d3.select('#port-tooltips').append('div') - .attr('id', function () { - return 'run-status-tip-' + d.id; - }) - .attr('class', 'tooltip nifi-tooltip') - .html(function () { - var list = nf.Common.formatUnorderedList(d.component.validationErrors); - if (list === null || list.length === 0) { - return ''; - } else { - return $('
').append(list).html(); - } - }); - - // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); - } - }); - // update the port name port.select('text.port-name') - .each(function (d) { - var portName = d3.select(this); - var name = d.component.name; - var words = name.split(/\s+/); + .each(function (d) { + var portName = d3.select(this); + var name = d.component.name; + var words = name.split(/\s+/); - // reset the port name to handle any previous state - portName.text(null).selectAll('tspan, title').remove(); + // reset the port name to handle any previous state + portName.text(null).selectAll('tspan, title').remove(); - // handle based on the number of tokens in the port name - if (words.length === 1) { - // apply ellipsis to the port name as necessary - nf.CanvasUtils.ellipsis(portName, name); - } else { - nf.CanvasUtils.multilineEllipsis(portName, 2, name); - } - }).append('title').text(function (d) { + // handle based on the number of tokens in the port name + if (words.length === 1) { + // apply ellipsis to the port name as necessary + nf.CanvasUtils.ellipsis(portName, name); + } else { + nf.CanvasUtils.multilineEllipsis(portName, 2, name); + } + }).append('title').text(function (d) { return d.component.name; }); } @@ -349,14 +285,14 @@ nf.Port = (function () { if (portData.accessPolicy.canRead) { // update the port name port.select('text.port-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); } // remove tooltips if necessary @@ -372,7 +308,7 @@ nf.Port = (function () { /** * Updates the port status. - * + * * @param {selection} updated The ports to be updated */ var updatePortStatus = function (updated) { @@ -380,14 +316,82 @@ nf.Port = (function () { return; } - updated.select('image.port-transmission-icon') - .attr('xlink:href', function (d) { - if (d.status.transmitting === true) { - return 'images/iconPortTransmitting.png'; - } else { - return 'images/iconPortNotTransmitting.png'; + // update the run status + updated.select('text.run-status-icon') + .attr({ + 'fill': function (d) { + var fill = '#728e9b'; + if (d.status.runStatus === 'Invalid') { + fill = '#ba554a'; } - }); + return fill; + }, + 'font-family': function (d) { + var family = 'FontAwesome'; + if (d.status.runStatus === 'Disabled') { + family = 'flowfont'; + } + return family; + } + }) + .text(function (d) { + var img = ''; + if (d.status.runStatus === 'Disabled') { + img = '\ue802'; + } else if (d.status.runStatus === 'Invalid') { + img = '\uf071'; + } else if (d.status.runStatus === 'Running') { + img = '\uf04b'; + } else if (d.status.runStatus === 'Stopped') { + img = '\uf04d'; + } + return img; + }) + .each(function (d) { + // remove the existing tip if necessary + var tip = d3.select('#run-status-tip-' + d.id); + if (!tip.empty()) { + tip.remove(); + } + + // if there are validation errors generate a tooltip + if (d.accessPolicy.canRead && !nf.Common.isEmpty(d.component.validationErrors)) { + tip = d3.select('#port-tooltips').append('div') + .attr('id', function () { + return 'run-status-tip-' + d.id; + }) + .attr('class', 'tooltip nifi-tooltip') + .html(function () { + var list = nf.Common.formatUnorderedList(d.component.validationErrors); + if (list === null || list.length === 0) { + return ''; + } else { + return $('
').append(list).html(); + } + }); + + // add the tooltip + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); + } + }); + + updated.select('text.port-transmission-icon') + .attr({ + 'font-family': function (d) { + if (d.status.transmitting === true) { + return 'FontAwesome'; + } else { + return 'flowfont'; + } + } + }) + .text(function (d) { + if (d.status.transmitting === true) { + return '\uf140'; + } else { + return '\ue80a'; + } + }); updated.each(function (d) { var port = d3.select(this); @@ -405,6 +409,10 @@ nf.Port = (function () { // bulletins // --------- + port.select('rect.bulletin-background').classed('has-bulletins', function () { + return nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins); + }); + nf.CanvasUtils.bulletins(port, d, function () { return d3.select('#port-tooltips'); }, offset); @@ -426,7 +434,7 @@ nf.Port = (function () { /** * Removes the tooltips for the ports in the specified selection. - * + * * @param {selection} removed */ var removeTooltips = function (removed) { @@ -446,12 +454,12 @@ nf.Port = (function () { // create the port container portContainer = d3.select('#canvas').append('g') - .attr({ - 'pointer-events': 'all', - 'class': 'ports' - }); + .attr({ + 'pointer-events': 'all', + 'class': 'ports' + }); }, - + /** * Populates the graph with the specified ports. * @@ -490,7 +498,7 @@ nf.Port = (function () { // apply the selection and handle all new ports select().enter().call(renderPorts, selectAll); }, - + /** * If the port id is specified it is returned. If no port id * specified, all ports are returned. @@ -504,7 +512,7 @@ nf.Port = (function () { return portMap.get(id); } }, - + /** * If the port id is specified it is refresh according to the current * state. If not port id is specified, all ports are refreshed. @@ -518,14 +526,14 @@ nf.Port = (function () { d3.selectAll('g.input-port, g.output-port').call(updatePorts); } }, - + /** * Refreshes the components necessary after a pan event. */ pan: function () { d3.selectAll('g.input-port.entering, g.output-port.entering, g.input-port.leaving, g.output-port.leaving').call(updatePorts); }, - + /** * Reloads the port state from the server and refreshes the UI. * If the port is currently unknown, this function just returns. @@ -547,16 +555,16 @@ nf.Port = (function () { }); } }, - + /** * Positions the component. - * + * * @param {string} id The id */ position: function (id) { d3.select('#id-' + id).call(nf.CanvasUtils.position); }, - + /** * Sets the specified port(s). If the is an array, it * will set each port. If it is not an array, it will @@ -585,10 +593,10 @@ nf.Port = (function () { set(portEntities); } }, - + /** * Sets the port status using the specified status. - * + * * @param {array} portStatus Port status */ setStatus: function (portStatus) { @@ -625,7 +633,7 @@ nf.Port = (function () { // apply the selection and handle all removed ports select().exit().call(removePorts); }, - + /** * Removes all ports.. */ 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.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js index 5af7a45389..4a2da5ed31 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js @@ -22,8 +22,8 @@ nf.ProcessGroup = (function () { var PREVIEW_NAME_LENGTH = 30; var dimensions = { - width: 365, - height: 142 + width: 380, + height: 172 }; // ---------------------------- @@ -44,8 +44,8 @@ nf.ProcessGroup = (function () { /** * Gets the process group comments. - * - * @param {object} d + * + * @param {object} d */ var getProcessGroupComments = function (d) { if (nf.Common.isBlank(d.component.comments)) { @@ -59,7 +59,9 @@ nf.ProcessGroup = (function () { * Selects the process group elements against the current process group map. */ var select = function () { - return processGroupContainer.selectAll('g.process-group').data(processGroupMap.values()); + return processGroupContainer.selectAll('g.process-group').data(processGroupMap.values(), function (d) { + return d.id; + }); }; /** @@ -74,14 +76,14 @@ nf.ProcessGroup = (function () { } var processGroup = entered.append('g') - .attr({ - 'id': function (d) { - return 'id-' + d.id; - }, - 'class': 'process-group component' - }) - .classed('selected', selected) - .call(nf.CanvasUtils.position); + .attr({ + 'id': function (d) { + return 'id-' + d.id; + }, + 'class': 'process-group component' + }) + .classed('selected', selected) + .call(nf.CanvasUtils.position); // ---- // body @@ -89,74 +91,78 @@ nf.ProcessGroup = (function () { // process group border processGroup.append('rect') - .attr({ - 'rx': 6, - 'ry': 6, - 'class': 'border', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': 'transparent', - 'stroke-opacity': 0.8, - 'stroke-width': 2, - 'stroke': '#294c58' - }); + .attr({ + 'class': 'border', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'fill': 'transparent', + 'stroke': 'transparent' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); // process group body processGroup.append('rect') - .attr({ - 'rx': 6, - 'ry': 6, - 'class': 'body', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': '#294c58', - 'fill-opacity': 0.8, - 'stroke-width': 0 - }); + .attr({ + 'class': 'body', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'filter': 'url(#component-drop-shadow)', + 'stroke-width': 0 + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); + + // process group name background + processGroup.append('rect') + .attr({ + 'width': function (d) { + return d.dimensions.width; + }, + 'height': 32, + 'fill': '#b8c6cd' + }); // process group name processGroup.append('text') - .attr({ - 'x': 10, - 'y': 15, - 'width': 316, - 'height': 16, - 'font-size': '10pt', - 'font-weight': 'bold', - 'fill': '#ffffff', - 'class': 'process-group-name' - }); + .attr({ + 'x': 10, + 'y': 20, + 'width': 316, + 'height': 16, + 'class': 'process-group-name' + }); // process group preview processGroup.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/bgProcessGroupDetailsArea.png', - 'width': 352, - 'height': 113, - 'x': 6, - 'y': 22, - 'class': 'process-group-preview' - }); + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'width': 352, + 'height': 113, + 'x': 6, + 'y': 22, + 'class': 'process-group-preview' + }); // always support selecting and navigation processGroup.on('dblclick', function (d) { - // enter this group on double click - nf.CanvasUtils.enterGroup(d.id); - }) - .call(nf.Selectable.activate).call(nf.ContextMenu.activate); + // enter this group on double click + nf.CanvasUtils.enterGroup(d.id); + }) + .call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only support dragging, connection, and drag and drop if appropriate - if (nf.Common.isDFM()) { - processGroup.filter(function (d) { + processGroup.filter(function (d) { return d.accessPolicy.canWrite && d.accessPolicy.canRead; }) .on('mouseover.drop', function (d) { @@ -171,7 +177,7 @@ nf.ProcessGroup = (function () { var drag = d3.select('rect.drag-selection'); if (!drag.empty()) { // filter the current selection by this group - var selection = nf.CanvasUtils.getSelection().filter(function(d) { + var selection = nf.CanvasUtils.getSelection().filter(function (d) { return targetData.id === d.id; }); @@ -192,14 +198,13 @@ nf.ProcessGroup = (function () { }) .call(nf.Draggable.activate) .call(nf.Connectable.activate); - } // call update to trigger some rendering processGroup.call(updateProcessGroups); }; // attempt of space between component count and icon for process group contents - var CONTENTS_SPACER = 5; + var CONTENTS_SPACER = 10; /** * Updates the process groups in the specified selection. @@ -220,333 +225,388 @@ nf.ProcessGroup = (function () { if (details.empty()) { details = processGroup.append('g').attr('class', 'process-group-details'); - // ---------------- - // stats background - // ---------------- + // ------------------- + // contents background + // ------------------- details.append('rect') - .attr({ - 'x': 6, - 'y': 22, - 'width': 352, - 'height': 113, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': '#ffffff' - }); - - details.append('rect') - .attr({ - 'x': 6, - 'y': 22, - 'width': 352, - 'height': 22, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': 'url(#process-group-stats-background)', - 'class': 'process-group-contents-container' - }); - - details.append('rect') - .attr({ - 'x': 6, - 'y': 104, - 'width': 352, - 'height': 33, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': 'url(#process-group-stats-background)' - }); + .attr({ + 'x': 0, + 'y': 32, + 'width': function () { + return processGroupData.dimensions.width + }, + 'height': 24, + 'fill': '#e3e8eb' + }); // -------- // contents // -------- if (processGroupData.accessPolicy.canRead) { - // input ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconInputPortSmall.png', - 'width': 16, - 'height': 16, - 'x': 10, - 'y': 25 - }); - - // input ports count - details.append('text') - .attr({ - 'x': 29, - 'y': 37, - 'class': 'process-group-input-port-count process-group-contents-count' - }); - - // output ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconOutputPortSmall.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-output-port' - }); - - // output ports count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-output-port-count process-group-contents-count' - }); // transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionActive.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-transmitting' - }); + details.append('text') + .attr({ + 'x': 10, + 'y': 49, + 'class': 'process-group-transmitting process-group-contents-icon', + 'font-family': 'FontAwesome' + }) + .text('\uf140'); // transmitting count details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-transmitting-count process-group-contents-count' - }); + .attr({ + 'x': 28, + 'y': 49, + 'class': 'process-group-transmitting-count process-group-contents-count' + }); // not transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionInactive.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-not-transmitting' - }); + details.append('text') + .attr({ + 'y': 49, + 'class': 'process-group-not-transmitting process-group-contents-icon', + 'font-family': 'flowfont' + }) + .text('\ue80a'); // not transmitting count details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-not-transmitting-count process-group-contents-count' - }); + .attr({ + 'y': 49, + 'class': 'process-group-not-transmitting-count process-group-contents-count' + }); // running icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconRun.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-running' - }); + details.append('text') + .attr({ + 'y': 49, + 'class': 'process-group-running process-group-contents-icon', + 'font-family': 'FontAwesome' + }) + .text('\uf04b'); // running count details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-running-count process-group-contents-count' - }); + .attr({ + 'y': 49, + 'class': 'process-group-running-count process-group-contents-count' + }); // stopped icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconStop.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-stopped' - }); + details.append('text') + .attr({ + 'y': 49, + 'class': 'process-group-stopped process-group-contents-icon', + 'font-family': 'FontAwesome' + }) + .text('\uf04d'); // stopped count details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-stopped-count process-group-contents-count' - }); + .attr({ + 'y': 49, + 'class': 'process-group-stopped-count process-group-contents-count' + }); // invalid icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconAlert.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-invalid' - }); + details.append('text') + .attr({ + 'y': 49, + 'class': 'process-group-invalid process-group-contents-icon', + 'font-family': 'FontAwesome' + }) + .text('\uf071'); // invalid count details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-invalid-count process-group-contents-count' - }); + .attr({ + 'y': 49, + 'class': 'process-group-invalid-count process-group-contents-count' + }); // disabled icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconDisable.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-disabled' - }); + details.append('text') + .attr({ + 'y': 49, + 'class': 'process-group-disabled process-group-contents-icon', + 'font-family': 'flowfont' + }) + .text('\ue802'); // disabled count details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-disabled-count process-group-contents-count' - }); + .attr({ + 'y': 49, + 'class': 'process-group-disabled-count process-group-contents-count' + }); } + // ---------------- + // stats background + // ---------------- + + // queued + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 66, + 'fill': '#f4f6f7' + }); + + // border + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 84, + 'fill': '#c7d2d7' + }); + + // in + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 85, + 'fill': '#ffffff' + }); + + // border + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 103, + 'fill': '#c7d2d7' + }); + + // read/write + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 104, + 'fill': '#f4f6f7' + }); + + // border + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 122, + 'fill': '#c7d2d7' + }); + + // out + details.append('rect') + .attr({ + 'width': function () { + return processGroupData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 123, + 'fill': '#ffffff' + }); + // ----- // stats // ----- // stats label container var processGroupStatsLabel = details.append('g') - .attr({ - 'transform': 'translate(6, 54)' - }); + .attr({ + 'transform': 'translate(6, 75)' + }); // queued label processGroupStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'process-group-stats-label' - }) - .text('Queued'); + .attr({ + 'width': 73, + 'height': 10, + 'x': 4, + 'y': 5, + 'class': 'stats-label' + }) + .text('Queued'); // in label processGroupStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'process-group-stats-label' - }) - .text('In'); + .attr({ + 'width': 73, + 'height': 10, + 'x': 4, + 'y': 24, + 'class': 'stats-label' + }) + .text('In'); // read/write label processGroupStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 30, - 'class': 'process-group-stats-label' - }) - .text('Read/Write'); + .attr({ + 'width': 73, + 'height': 10, + 'x': 4, + 'y': 42, + 'class': 'stats-label' + }) + .text('Read/Write'); // out label processGroupStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 43, - 'class': 'process-group-stats-label' - }) - .text('Out'); + .attr({ + 'width': 73, + 'height': 10, + 'x': 4, + 'y': 60, + 'class': 'stats-label' + }) + .text('Out'); // stats value container var processGroupStatsValue = details.append('g') - .attr({ - 'transform': 'translate(95, 54)' - }); + .attr({ + 'transform': 'translate(95, 75)' + }); // queued value - processGroupStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'process-group-queued process-group-stats-value' - }); + var queuedText = processGroupStatsValue.append('text') + .attr({ + 'width': 180, + 'height': 10, + 'x': 4, + 'y': 5, + 'class': 'process-group-queued stats-value' + }); + + // queued count + queuedText.append('tspan') + .attr({ + 'class': 'count' + }); + + // queued size + queuedText.append('tspan') + .attr({ + 'class': 'size' + }); // in value - processGroupStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'process-group-in process-group-stats-value' - }); + var inText = processGroupStatsValue.append('text') + .attr({ + 'width': 180, + 'height': 10, + 'x': 4, + 'y': 24, + 'class': 'process-group-in stats-value' + }); + + // in count + inText.append('tspan') + .attr({ + 'class': 'count' + }); + + // in size + inText.append('tspan') + .attr({ + 'class': 'size' + }); // read/write value processGroupStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 30, - 'class': 'process-group-read-write process-group-stats-value' - }); + .attr({ + 'width': 180, + 'height': 10, + 'x': 4, + 'y': 42, + 'class': 'process-group-read-write stats-value' + }); // out value - processGroupStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 43, - 'class': 'process-group-out process-group-stats-value' - }); + var outText = processGroupStatsValue.append('text') + .attr({ + 'width': 180, + 'height': 10, + 'x': 4, + 'y': 60, + 'class': 'process-group-out stats-value' + }); + + // in count + outText.append('tspan') + .attr({ + 'class': 'count' + }); + + // in size + outText.append('tspan') + .attr({ + 'class': 'size' + }); // stats value container var processGroupStatsInfo = details.append('g') - .attr({ - 'transform': 'translate(314, 54)' - }); + .attr({ + 'transform': 'translate(335, 75)' + }); // in info processGroupStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'process-group-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'x': 4, + 'y': 24, + 'class': 'stats-info' + }) + .text('5 min'); // read/write info processGroupStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 30, - 'class': 'process-group-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'x': 4, + 'y': 42, + 'class': 'stats-info' + }) + .text('5 min'); // out info processGroupStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 43, - 'class': 'process-group-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'x': 4, + 'y': 60, + 'class': 'stats-info' + }) + .text('5 min'); // -------- // comments @@ -554,189 +614,158 @@ nf.ProcessGroup = (function () { // process group comments details.append('text') - .attr({ - 'x': 10, - 'y': 118, - 'width': 342, - 'height': 22, - 'class': 'process-group-comments' - }); + .attr({ + 'x': 10, + 'y': 160, + 'width': 342, + 'height': 22, + 'class': 'process-group-comments' + }); // ------------------- // active thread count // ------------------- // active thread count - details.append('rect') - .attr({ - 'class': 'active-thread-count-background', - 'height': 13, - 'y': 0, - 'fill': '#fff', - 'fill-opacity': '0.4', - 'stroke': '#aaa', - 'stroke-width': '1' - }); - - // active thread bacground details.append('text') - .attr({ - 'class': 'active-thread-count', - 'height': 13, - 'y': 10, - 'fill': '#000' - }); + .attr({ + 'class': 'active-thread-count-icon', + 'y': 20 + }) + .text('\ue83f'); + + // active thread icon + details.append('text') + .attr({ + 'class': 'active-thread-count', + 'y': 20 + }); // --------- // bulletins // --------- + // bulletin background + details.append('rect') + .attr({ + 'class': 'bulletin-background', + 'x': function () { + return processGroupData.dimensions.width - 24; + }, + 'y': 32, + 'width': 24, + 'height': 24 + }); + // bulletin icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'bulletin-icon', - 'xlink:href': 'images/iconBulletin.png', - 'width': 12, - 'height': 12, - 'y': 2 - }); + details.append('text') + .attr({ + 'class': 'bulletin-icon', + 'x': function () { + return processGroupData.dimensions.width - 17; + }, + 'y': 50 + }) + .text('\uf24a'); } if (processGroupData.accessPolicy.canRead) { - // update the input ports - var inputPortCount = details.select('text.process-group-input-port-count') - .text(function (d) { - return d.component.inputPortCount; - }); - - // update the output ports - var outputPort = details.select('image.process-group-output-port') - .attr('x', function () { - var inputPortCountX = parseInt(inputPortCount.attr('x'), 10); - return inputPortCountX + inputPortCount.node().getComputedTextLength() + CONTENTS_SPACER; - }); - details.select('text.process-group-output-port-count') - .attr('x', function () { - var outputPortImageX = parseInt(outputPort.attr('x'), 10); - var outputPortImageWidth = parseInt(outputPort.attr('width'), 10); - return outputPortImageX + outputPortImageWidth + CONTENTS_SPACER; - }) - .text(function (d) { - return d.component.outputPortCount; - }); - - // get the container to help right align - var container = details.select('rect.process-group-contents-container'); - - // update disabled - var disabledCount = details.select('text.process-group-disabled-count') - .text(function (d) { - return d.component.disabledCount; - }) - .attr('x', function () { - var containerX = parseInt(container.attr('x'), 10); - var containerWidth = parseInt(container.attr('width'), 10); - return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var disabled = details.select('image.process-group-disabled') - .attr('x', function () { - var disabledCountX = parseInt(disabledCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return disabledCountX - width - CONTENTS_SPACER; - }); - - // update invalid - var invalidCount = details.select('text.process-group-invalid-count') - .text(function (d) { - return d.component.invalidCount; - }) - .attr('x', function () { - var disabledX = parseInt(disabled.attr('x'), 10); - return disabledX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var invalid = details.select('image.process-group-invalid') - .attr('x', function () { - var invalidCountX = parseInt(invalidCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return invalidCountX - width - CONTENTS_SPACER; - }); - - // update stopped - var stoppedCount = details.select('text.process-group-stopped-count') - .text(function (d) { - return d.component.stoppedCount; - }) - .attr('x', function () { - var invalidX = parseInt(invalid.attr('x'), 10); - return invalidX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var stopped = details.select('image.process-group-stopped') - .attr('x', function () { - var stoppedCountX = parseInt(stoppedCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return stoppedCountX - width - CONTENTS_SPACER; - }); - - // update running - var runningCount = details.select('text.process-group-running-count') - .text(function (d) { - return d.component.runningCount; - }) - .attr('x', function () { - var stoppedX = parseInt(stopped.attr('x'), 10); - return stoppedX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var running = details.select('image.process-group-running') - .attr('x', function () { - var runningCountX = parseInt(runningCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return runningCountX - width - CONTENTS_SPACER; - }); - - // update not transmitting - var notTransmittingCount = details.select('text.process-group-not-transmitting-count') - .text(function (d) { - return d.component.inactiveRemotePortCount; - }) - .attr('x', function () { - var runningX = parseInt(running.attr('x'), 10); - return runningX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var notTransmitting = details.select('image.process-group-not-transmitting') - .attr('x', function () { - var notTransmittingCountX = parseInt(notTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return notTransmittingCountX - width - CONTENTS_SPACER; - }); // update transmitting var transmittingCount = details.select('text.process-group-transmitting-count') - .text(function (d) { - return d.component.activeRemotePortCount; - }) - .attr('x', function () { - var notTransmittingX = parseInt(notTransmitting.attr('x'), 10); - return notTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - details.select('image.process-group-transmitting') - .attr('x', function () { - var transmittingCountX = parseInt(transmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return transmittingCountX - width - CONTENTS_SPACER; - }); + .text(function (d) { + return d.component.activeRemotePortCount; + }); + + // update not transmitting + var notTransmitting = details.select('text.process-group-not-transmitting') + .attr('x', function () { + var transmittingX = parseInt(transmittingCount.attr('x'), 10); + return transmittingX + transmittingCount.node().getComputedTextLength() + CONTENTS_SPACER; + }); + var notTransmittingCount = details.select('text.process-group-not-transmitting-count') + .attr('x', function () { + var notTransmittingCountX = parseInt(notTransmitting.attr('x'), 10); + return notTransmittingCountX + notTransmitting.node().getComputedTextLength() + CONTENTS_SPACER; + }) + .text(function (d) { + return d.component.inactiveRemotePortCount; + }); + + // update running + var running = details.select('text.process-group-running') + .attr('x', function () { + var notTransmittingX = parseInt(notTransmittingCount.attr('x'), 10); + return notTransmittingX + notTransmittingCount.node().getComputedTextLength() + CONTENTS_SPACER; + }); + var runningCount = details.select('text.process-group-running-count') + .attr('x', function () { + var runningCountX = parseInt(running.attr('x'), 10); + return runningCountX + running.node().getComputedTextLength() + CONTENTS_SPACER; + }) + .text(function (d) { + return d.component.runningCount; + }); + + // update stopped + var stopped = details.select('text.process-group-stopped') + .attr('x', function () { + var runningX = parseInt(runningCount.attr('x'), 10); + return runningX + runningCount.node().getComputedTextLength() + CONTENTS_SPACER; + }); + var stoppedCount = details.select('text.process-group-stopped-count') + .attr('x', function () { + var stoppedCountX = parseInt(stopped.attr('x'), 10); + return stoppedCountX + stopped.node().getComputedTextLength() + CONTENTS_SPACER; + }) + .text(function (d) { + return d.component.stoppedCount; + }); + + // update invalid + var invalid = details.select('text.process-group-invalid') + .attr('x', function () { + var stoppedX = parseInt(stoppedCount.attr('x'), 10); + return stoppedX + stoppedCount.node().getComputedTextLength() + CONTENTS_SPACER; + }) + .classed('has-validation-errors', function (d) { + return d.accessPolicy.canRead && d.component.invalidCount > 0; + }); + var invalidCount = details.select('text.process-group-invalid-count') + .attr('x', function () { + var invalidCountX = parseInt(invalid.attr('x'), 10); + return invalidCountX + invalid.node().getComputedTextLength() + CONTENTS_SPACER; + }) + .text(function (d) { + return d.component.invalidCount; + }); + + // update disabled + var disabled = details.select('text.process-group-disabled') + .attr('x', function () { + var invalidX = parseInt(invalidCount.attr('x'), 10); + return invalidX + invalidCount.node().getComputedTextLength() + CONTENTS_SPACER; + }); + details.select('text.process-group-disabled-count') + .attr('x', function () { + var disabledCountX = parseInt(disabled.attr('x'), 10); + return disabledCountX + disabled.node().getComputedTextLength() + CONTENTS_SPACER; + }) + .text(function (d) { + return d.component.disabledCount; + }); // update the process group comments details.select('text.process-group-comments') - .each(function (d) { - var processGroupComments = d3.select(this); + .each(function (d) { + var processGroupComments = d3.select(this); - // reset the process group name to handle any previous state - processGroupComments.text(null).selectAll('tspan, title').remove(); + // reset the process group name to handle any previous state + processGroupComments.text(null).selectAll('tspan, title').remove(); - // apply ellipsis to the port name as necessary - nf.CanvasUtils.multilineEllipsis(processGroupComments, 2, getProcessGroupComments(d)); - }).classed('unset', function (d) { + // apply ellipsis to the port name as necessary + nf.CanvasUtils.ellipsis(processGroupComments, getProcessGroupComments(d)); + }).classed('unset', function (d) { return nf.Common.isBlank(d.component.comments); }).append('title').text(function (d) { return getProcessGroupComments(d); @@ -744,15 +773,15 @@ nf.ProcessGroup = (function () { // update the process group name processGroup.select('text.process-group-name') - .each(function (d) { - var processGroupName = d3.select(this); + .each(function (d) { + var processGroupName = d3.select(this); - // reset the process group name to handle any previous state - processGroupName.text(null).selectAll('title').remove(); + // reset the process group name to handle any previous state + processGroupName.text(null).selectAll('title').remove(); - // apply ellipsis to the process group name as necessary - nf.CanvasUtils.ellipsis(processGroupName, d.component.name); - }).append('title').text(function (d) { + // apply ellipsis to the process group name as necessary + nf.CanvasUtils.ellipsis(processGroupName, d.component.name); + }).append('title').text(function (d) { return d.component.name; }); } @@ -766,14 +795,14 @@ nf.ProcessGroup = (function () { if (processGroupData.accessPolicy.canRead) { // update the process group name processGroup.select('text.process-group-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); } // show the preview @@ -792,7 +821,7 @@ nf.ProcessGroup = (function () { /** * Updates the process group status. - * + * * @param {selection} updated The process groups to be updated */ var updateProcessGroupStatus = function (updated) { @@ -800,45 +829,75 @@ nf.ProcessGroup = (function () { return; } - // queued value - updated.select('text.process-group-queued') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.queued; - } else { - return '- / -'; - } - }); + // queued count value + updated.select('text.process-group-queued tspan.count') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return nf.Common.substringBeforeFirst(d.status.queued, ' '); + } else { + return '-'; + } + }); - // in value - updated.select('text.process-group-in') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.input; - } else { - return '- / -'; - } - }); + // queued size value + updated.select('text.process-group-queued tspan.size') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return ' ' + nf.Common.substringAfterFirst(d.status.queued, ' '); + } else { + return ' (-)'; + } + }); + + // in count value + updated.select('text.process-group-in tspan.count') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return nf.Common.substringBeforeFirst(d.status.input, ' '); + } else { + return '-'; + } + }); + + // in size value + updated.select('text.process-group-in tspan.size') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return ' ' + nf.Common.substringAfterFirst(d.status.input, ' '); + } else { + return ' (-)'; + } + }); // read/write value updated.select('text.process-group-read-write') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.read + ' / ' + d.status.written; - } else { - return '- / -'; - } - }); + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return d.status.read + ' / ' + d.status.written; + } else { + return '- / -'; + } + }); - // out value - updated.select('text.process-group-out') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.output; - } else { - return '- / -'; - } - }); + // out count value + updated.select('text.process-group-out tspan.count') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return nf.Common.substringBeforeFirst(d.status.output, ' '); + } else { + return '-'; + } + }); + + // out size value + updated.select('text.process-group-out tspan.size') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return ' ' + nf.Common.substringAfterFirst(d.status.output, ' '); + } else { + return ' (-)'; + } + }); updated.each(function (d) { var processGroup = d3.select(this); @@ -856,6 +915,10 @@ nf.ProcessGroup = (function () { // bulletins // --------- + processGroup.select('rect.bulletin-background').classed('has-bulletins', function () { + return nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins); + }); + nf.CanvasUtils.bulletins(processGroup, d, function () { return d3.select('#process-group-tooltips'); }, offset); @@ -877,7 +940,7 @@ nf.ProcessGroup = (function () { /** * Removes the tooltips for the process groups in the specified selection. - * + * * @param {selection} removed */ var removeTooltips = function (removed) { @@ -896,12 +959,12 @@ nf.ProcessGroup = (function () { // create the process group container processGroupContainer = d3.select('#canvas').append('g') - .attr({ - 'pointer-events': 'all', - 'class': 'process-groups' - }); + .attr({ + 'pointer-events': 'all', + 'class': 'process-groups' + }); }, - + /** * Populates the graph with the specified process groups. * @@ -931,7 +994,7 @@ nf.ProcessGroup = (function () { // apply the selection and handle all new process group select().enter().call(renderProcessGroups, selectAll); }, - + /** * If the process group id is specified it is returned. If no process group id * specified, all process groups are returned. @@ -945,7 +1008,7 @@ nf.ProcessGroup = (function () { return processGroupMap.get(id); } }, - + /** * If the process group id is specified it is refresh according to the current * state. If no process group id is specified, all process groups are refreshed. @@ -959,14 +1022,14 @@ nf.ProcessGroup = (function () { d3.selectAll('g.process-group').call(updateProcessGroups); } }, - + /** * Refreshes the components necessary after a pan event. */ pan: function () { d3.selectAll('g.process-group.entering, g.process-group.leaving').call(updateProcessGroups); }, - + /** * Reloads the process group state from the server and refreshes the UI. * If the process group is currently unknown, this function just returns. @@ -984,16 +1047,16 @@ nf.ProcessGroup = (function () { }); } }, - + /** * Positions the component. - * + * * @param {string} id The id */ position: function (id) { d3.select('#id-' + id).call(nf.CanvasUtils.position); }, - + /** * Sets the specified process group(s). If the is an array, it * will set each process group. If it is not an array, it will @@ -1007,7 +1070,7 @@ nf.ProcessGroup = (function () { // update the current entry var processGroupEntry = processGroupMap.get(processGroupEntity.id); $.extend(processGroupEntry, processGroupEntity); - + // update the process group in the UI d3.select('#id-' + processGroupEntry.id).call(updateProcessGroups); } @@ -1022,10 +1085,10 @@ nf.ProcessGroup = (function () { set(processGroupEntities); } }, - + /** * Sets the process group status using the specified status. - * + * * @param {array} processGroupStatus Process group status */ setStatus: function (processGroupStatus) { @@ -1062,7 +1125,7 @@ nf.ProcessGroup = (function () { // apply the selection and handle all removed process groups select().exit().call(removeProcessGroups); }, - + /** * Removes all process groups. */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js index dbe52464a5..6ed968f1bf 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js @@ -23,8 +23,8 @@ nf.Processor = (function () { // default dimensions for each type of component var dimensions = { - width: 310, - height: 100 + width: 350, + height: 130 }; // --------------------------------- @@ -47,7 +47,9 @@ nf.Processor = (function () { * Selects the processor elements against the current processor map. */ var select = function () { - return processorContainer.selectAll('g.processor').data(processorMap.values()); + return processorContainer.selectAll('g.processor').data(processorMap.values(), function (d) { + return d.id; + }); }; // renders the processors @@ -57,80 +59,78 @@ nf.Processor = (function () { } var processor = entered.append('g') - .attr({ - 'id': function (d) { - return 'id-' + d.id; - }, - 'class': 'processor component' - }) - .classed('selected', selected) - .call(nf.CanvasUtils.position); + .attr({ + 'id': function (d) { + return 'id-' + d.id; + }, + 'class': 'processor component' + }) + .classed('selected', selected) + .call(nf.CanvasUtils.position); // processor border processor.append('rect') - .attr({ - 'class': 'border', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': 'transparent', - 'stroke-opacity': 0.8, - 'stroke-width': 1 - }); + .attr({ + 'class': 'border', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'fill': 'transparent', + 'stroke': 'transparent' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); // processor body processor.append('rect') - .attr({ - 'class': 'body', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill-opacity': 0.8, - 'stroke-opacity': 0.8, - 'stroke-width': 0 - }); + .attr({ + 'class': 'body', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'filter': 'url(#component-drop-shadow)', + 'stroke-width': 0 + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); // processor name processor.append('text') - .attr({ - 'x': 25, - 'y': 18, - 'width': 220, - 'height': 16, - 'font-size': '10pt', - 'font-weight': 'bold', - 'fill': 'black', - 'class': 'processor-name' - }); + .attr({ + 'x': 62, + 'y': 20, + 'width': 220, + 'height': 16, + 'class': 'processor-name' + }); // processor icon - processor.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconProcessor.png', - 'width': 28, - 'height': 26, - 'x': 276, - 'y': 5 - }); + processor.append('text') + .attr({ + 'x': 6, + 'y': 32, + 'class': 'processor-icon' + }) + .text('\ue807'); // processor stats preview processor.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/bgProcessorStatArea.png', - 'width': 294, - 'height': 58, - 'x': 8, - 'y': 35, - 'class': 'processor-stats-preview' - }); + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'width': 294, + 'height': 58, + 'x': 8, + 'y': 35, + 'class': 'processor-stats-preview' + }); // make processors selectable processor.call(nf.Selectable.activate).call(nf.ContextMenu.activate); @@ -146,7 +146,7 @@ nf.Processor = (function () { /** * Updates the processors in the specified selection. - * + * * @param {selection} updated The processors to update */ var updateProcessors = function (updated) { @@ -156,45 +156,40 @@ nf.Processor = (function () { updated.each(function (processorData) { var processor = d3.select(this); - var details = processor.select('g.processor-details'); + var details = processor.select('g.processor-canvas-details'); // if this processor is visible, render everything if (processor.classed('visible')) { if (details.empty()) { - details = processor.append('g').attr('class', 'processor-details'); + details = processor.append('g').attr('class', 'processor-canvas-details'); // run status icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'run-status-icon', - 'width': 16, - 'height': 16, - 'x': 5, - 'y': 5 - }); + details.append('text') + .attr({ + 'class': 'run-status-icon', + 'x': 42, + 'y': 20 + }); if (processorData.accessPolicy.canRead) { // processor type details.append('text') - .attr({ - 'x': 25, - 'y': 30, - 'width': 246, - 'height': 16, - 'font-size': '8pt', - 'font-weight': 'normal', - 'fill': 'black' - }) - .each(function (d) { - var processorType = d3.select(this); + .attr({ + 'class': 'processor-type', + 'x': 62, + 'y': 35, + 'width': 246, + 'height': 16 + }) + .each(function (d) { + var processorType = d3.select(this); - // reset the processor type to handle any previous state - processorType.text(null).selectAll('title').remove(); + // reset the processor type to handle any previous state + processorType.text(null).selectAll('title').remove(); - // apply ellipsis to the processor type as necessary - nf.CanvasUtils.ellipsis(processorType, nf.Common.substringAfterLast(d.component.type, '.')); - }).append('title').text(function (d) { + // apply ellipsis to the processor type as necessary + nf.CanvasUtils.ellipsis(processorType, nf.Common.substringAfterLast(d.component.type, '.')); + }).append('title').text(function (d) { return nf.Common.substringAfterLast(d.component.type, '.'); }); } @@ -204,269 +199,305 @@ nf.Processor = (function () { // ----- // draw the processor statistics table - details.append('rect') - .attr({ - 'width': 294, - 'height': 59, - 'x': 8, - 'y': 35, - 'fill': '#ffffff', - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'stroke-opacity': 0.8 - }); + // in details.append('rect') - .attr({ - 'width': 73, - 'height': 59, - 'x': 8, - 'y': 35, - 'fill': 'url(#processor-stats-background)', - 'stroke-width': 0 - }); + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 50, + 'fill': '#f4f6f7' + }); + + // border + details.append('rect') + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 68, + 'fill': '#c7d2d7' + }); + + // read/write + details.append('rect') + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 69, + 'fill': '#ffffff' + }); + + // border + details.append('rect') + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 87, + 'fill': '#c7d2d7' + }); + + // out + details.append('rect') + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 20, + 'x': 0, + 'y': 88, + 'fill': '#f4f6f7' + }); + + // border + details.append('rect') + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 106, + 'fill': '#c7d2d7' + }); + + // tasks/time + details.append('rect') + .attr({ + 'width': function () { + return processorData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 107, + 'fill': '#ffffff' + }); // stats label container var processorStatsLabel = details.append('g') - .attr({ - 'transform': 'translate(8, 45)' - }); + .attr({ + 'transform': 'translate(10, 55)' + }); // in label processorStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'processor-stats-label' - }) - .text('In'); + .attr({ + 'width': 73, + 'height': 10, + 'y': 9, + 'class': 'stats-label' + }) + .text('In'); // read/write label processorStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'processor-stats-label' - }) - .text('Read/Write'); + .attr({ + 'width': 73, + 'height': 10, + 'y': 27, + 'class': 'stats-label' + }) + .text('Read/Write'); // out label processorStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 30, - 'class': 'processor-stats-label' - }) - .text('Out'); + .attr({ + 'width': 73, + 'height': 10, + 'y': 46, + 'class': 'stats-label' + }) + .text('Out'); // tasks/time label processorStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 43, - 'class': 'processor-stats-label' - }) - .text('Tasks/Time'); + .attr({ + 'width': 73, + 'height': 10, + 'y': 65, + 'class': 'stats-label' + }) + .text('Tasks/Time'); // stats value container var processorStatsValue = details.append('g') - .attr({ - 'transform': 'translate(80, 45)' - }); + .attr({ + 'transform': 'translate(85, 55)' + }); // in value - processorStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'processor-in processor-stats-value' - }); + var inText = processorStatsValue.append('text') + .attr({ + 'width': 180, + 'height': 9, + 'y': 9, + 'class': 'processor-in stats-value' + }); + + // in count + inText.append('tspan') + .attr({ + 'class': 'count' + }); + + // in size + inText.append('tspan') + .attr({ + 'class': 'size' + }); // read/write value processorStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'processor-read-write processor-stats-value' - }); + .attr({ + 'width': 180, + 'height': 10, + 'y': 27, + 'class': 'processor-read-write stats-value' + }); // out value - processorStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 30, - 'class': 'processor-out processor-stats-value' - }); + var outText = processorStatsValue.append('text') + .attr({ + 'width': 180, + 'height': 10, + 'y': 46, + 'class': 'processor-out stats-value' + }); + + // out count + outText.append('tspan') + .attr({ + 'class': 'count' + }); + + // out size + outText.append('tspan') + .attr({ + 'class': 'size' + }); // tasks/time value processorStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 43, - 'class': 'processor-tasks-time processor-stats-value' - }); + .attr({ + 'width': 180, + 'height': 10, + 'y': 65, + 'class': 'processor-tasks-time stats-value' + }); // stats value container var processorStatsInfo = details.append('g') - .attr('transform', 'translate(258, 45)'); + .attr('transform', 'translate(305, 55)'); // in info processorStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'processor-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'y': 9, + 'class': 'stats-info' + }) + .text('5 min'); // read/write info processorStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'processor-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'y': 27, + 'class': 'stats-info' + }) + .text('5 min'); // out info processorStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 30, - 'class': 'processor-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'y': 46, + 'class': 'stats-info' + }) + .text('5 min'); // tasks/time info processorStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 43, - 'class': 'processor-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'y': 65, + 'class': 'stats-info' + }) + .text('5 min'); // ------------------- // active thread count // ------------------- // active thread count - details.append('rect') - .attr({ - 'class': 'active-thread-count-background', - 'height': 13, - 'y': 0, - 'fill': '#fff', - 'fill-opacity': '0.65', - 'stroke': '#aaa', - 'stroke-width': '1' - }); - - // active thread bacground details.append('text') - .attr({ - 'class': 'active-thread-count', - 'height': 13, - 'y': 10, - 'fill': '#000' - }); + .attr({ + 'class': 'active-thread-count-icon', + 'y': 42 + }) + .text('\ue83f'); + + // active thread background + details.append('text') + .attr({ + 'class': 'active-thread-count', + 'y': 42 + }); // --------- // bulletins // --------- + // bulletin background + details.append('rect') + .attr({ + 'class': 'bulletin-background', + 'x': function (d) { + return processorData.dimensions.width - 24; + }, + 'width': 24, + 'height': 24 + }); + // bulletin icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'bulletin-icon', - 'xlink:href': 'images/iconBulletin.png', - 'width': 12, - 'height': 12, - 'x': 8, - 'y': 20 - }); + details.append('text') + .attr({ + 'class': 'bulletin-icon', + 'x': function (d) { + return processorData.dimensions.width - 18; + }, + 'y': 18 + }) + .text('\uf24a'); } if (processorData.accessPolicy.canRead) { - // update the run status - details.select('image.run-status-icon') - .attr('xlink:href', function (d) { - var img = ''; - if (d.component.state === 'DISABLED') { - img = 'images/iconDisable.png'; - } else if (!nf.Common.isEmpty(d.component.validationErrors)) { - img = 'images/iconAlert.png'; - } else if (d.component.state === 'RUNNING') { - img = 'images/iconRun.png'; - } else if (d.component.state === 'STOPPED') { - img = 'images/iconStop.png'; - } - return img; - }) - .each(function (d) { - // remove the existing tip if necessary - var tip = d3.select('#run-status-tip-' + d.id); - if (!tip.empty()) { - tip.remove(); - } - - // if there are validation errors generate a tooltip - if (!nf.Common.isEmpty(d.component.validationErrors)) { - tip = d3.select('#processor-tooltips').append('div') - .attr('id', function () { - return 'run-status-tip-' + d.id; - }) - .attr('class', 'tooltip nifi-tooltip') - .html(function () { - var list = nf.Common.formatUnorderedList(d.component.validationErrors); - if (list === null || list.length === 0) { - return ''; - } else { - return $('
').append(list).html(); - } - }); - - // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); - } - }); - // update the processor name processor.select('text.processor-name') - .each(function (d) { - var processorName = d3.select(this); + .each(function (d) { + var processorName = d3.select(this); - // reset the processor name to handle any previous state - processorName.text(null).selectAll('title').remove(); + // reset the processor name to handle any previous state + processorName.text(null).selectAll('title').remove(); - // apply ellipsis to the processor name as necessary - nf.CanvasUtils.ellipsis(processorName, d.component.name); - }).append('title').text(function (d) { + // apply ellipsis to the processor name as necessary + nf.CanvasUtils.ellipsis(processorName, d.component.name); + }).append('title').text(function (d) { return d.component.name; }); } @@ -480,14 +511,14 @@ nf.Processor = (function () { if (processorData.accessPolicy.canRead) { // update the processor name processor.select('text.processor-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); } // show the preview @@ -503,61 +534,29 @@ nf.Processor = (function () { } }); - // ----------------------------------------------------------------- - // ensure there is a linear gradient defined for each possible color - // ----------------------------------------------------------------- - - // reset the colors - var colors = d3.set(); - colors.add(nf.Common.substringAfterLast(nf.Processor.defaultColor(), '#')); - - // determine all unique colors - processorMap.forEach(function (id, d) { - if (d.accessPolicy.canRead) { - var color = d.component.style['background-color']; - if (nf.Common.isDefinedAndNotNull(color)) { - colors.add(nf.Common.substringAfterLast(color, '#')); - } - } - }); - nf.Canvas.defineProcessorColors(colors.values()); + // --------------- + // processor color + // --------------- // update the processor color - updated.select('rect.border') - .attr('stroke', function (d) { - var color = nf.Processor.defaultColor(); - - if (d.accessPolicy.canRead) { - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; - } - } - - return color; - }); - updated.select('rect.body') - .attr('fill', function (d) { - var color = nf.Processor.defaultColor(); + .style('fill', function (d) { + var color = nf.Processor.defaultColor(); - if (d.accessPolicy.canRead) { - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; - } + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; } + } - // get just the color code part - color = nf.Common.substringAfterLast(color, '#'); - - return 'url(#processor-background-' + color + ')'; - }); + return color; + }); }; /** * Updates the stats for the processors in the specified selection. - * + * * @param {selection} updated The processors to update */ var updateProcessorStatus = function (updated) { @@ -565,45 +564,124 @@ nf.Processor = (function () { return; } - // in value - updated.select('text.processor-in') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.input; - } else { - return '- / -'; + // update the run status + updated.select('text.run-status-icon') + .attr({ + 'fill': function (d) { + var fill = '#728e9b'; + if (d.status && d.status.runStatus === 'Invalid') { + fill = '#ba554a'; } - }); + return fill; + }, + 'font-family': function (d) { + var family = 'FontAwesome'; + if (d.status && d.status.runStatus === 'Disabled') { + family = 'flowfont'; + } + return family; + } + }) + .text(function (d) { + var img = ''; + if (d.status && d.status.runStatus === 'Disabled') { + img = '\ue802'; + } else if (d.status && d.status.runStatus === 'Invalid') { + img = '\uf071'; + } else if (d.status && d.status.runStatus === 'Running') { + img = '\uf04b'; + } else if (d.status && d.status.runStatus === 'Stopped') { + img = '\uf04d'; + } + return img; + }) + .each(function (d) { + // remove the existing tip if necessary + var tip = d3.select('#run-status-tip-' + d.id); + if (!tip.empty()) { + tip.remove(); + } + + // if there are validation errors generate a tooltip + if (d.accessPolicy.canRead && !nf.Common.isEmpty(d.component.validationErrors)) { + tip = d3.select('#processor-tooltips').append('div') + .attr('id', function () { + return 'run-status-tip-' + d.id; + }) + .attr('class', 'tooltip nifi-tooltip') + .html(function () { + var list = nf.Common.formatUnorderedList(d.component.validationErrors); + if (list === null || list.length === 0) { + return ''; + } else { + return $('
').append(list).html(); + } + }); + + // add the tooltip + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); + } + }); + + // in count value + updated.select('text.processor-in tspan.count') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return nf.Common.substringBeforeFirst(d.status.input, ' '); + } else { + return '-'; + } + }); + + // in size value + updated.select('text.processor-in tspan.size') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return ' ' + nf.Common.substringAfterFirst(d.status.input, ' '); + } else { + return ' (-)'; + } + }); // read/write value updated.select('text.processor-read-write') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.read + ' / ' + d.status.written; - } else { - return '- / -'; - } - }); + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return d.status.read + ' / ' + d.status.written; + } else { + return '- / -'; + } + }); - // out value - updated.select('text.processor-out') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.output; - } else { - return '- / -'; - } - }); + // out count value + updated.select('text.processor-out tspan.count') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return nf.Common.substringBeforeFirst(d.status.output, ' '); + } else { + return '-'; + } + }); + + // out size value + updated.select('text.processor-out tspan.size') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return ' ' + nf.Common.substringAfterFirst(d.status.output, ' '); + } else { + return ' (-)'; + } + }); // tasks/time value updated.select('text.processor-tasks-time') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.tasks + ' / ' + d.status.tasksDuration; - } else { - return '- / -'; - } - }); + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return d.status.tasks + ' / ' + d.status.tasksDuration; + } else { + return '- / -'; + } + }); updated.each(function (d) { var processor = d3.select(this); @@ -618,6 +696,10 @@ nf.Processor = (function () { // bulletins // --------- + processor.select('rect.bulletin-background').classed('has-bulletins', function () { + return nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins); + }); + nf.CanvasUtils.bulletins(processor, d, function () { return d3.select('#processor-tooltips'); }, 286); @@ -626,7 +708,7 @@ nf.Processor = (function () { /** * Removes the processors in the specified selection. - * + * * @param {selection} removed */ var removeProcessors = function (removed) { @@ -639,7 +721,7 @@ nf.Processor = (function () { /** * Removes the tooltips for the processors in the specified selection. - * + * * @param {selection} removed */ var removeTooltips = function (removed) { @@ -659,15 +741,15 @@ nf.Processor = (function () { // create the processor container processorContainer = d3.select('#canvas').append('g') - .attr({ - 'pointer-events': 'all', - 'class': 'processors' - }); + .attr({ + 'pointer-events': 'all', + 'class': 'processors' + }); }, - + /** * Populates the graph with the specified processors. - * + * * @argument {object | array} processorEntities The processors to add * @argument {boolean} selectAll Whether or not to select the new contents */ @@ -694,11 +776,11 @@ nf.Processor = (function () { // apply the selection and handle all new processors select().enter().call(renderProcessors, selectAll); }, - + /** * If the processor id is specified it is returned. If no processor id * specified, all processors are returned. - * + * * @param {string} id */ get: function (id) { @@ -708,11 +790,11 @@ nf.Processor = (function () { return processorMap.get(id); } }, - + /** - * If the processor id is specified it is refresh according to the current + * If the processor id is specified it is refresh according to the current * state. If not processor id is specified, all processors are refreshed. - * + * * @param {string} id Optional */ refresh: function (id) { @@ -722,27 +804,27 @@ nf.Processor = (function () { d3.selectAll('g.processor').call(updateProcessors); } }, - + /** * Positions the component. - * + * * @param {string} id The id */ position: function (id) { d3.select('#id-' + id).call(nf.CanvasUtils.position); }, - + /** * Refreshes the components necessary after a pan event. */ pan: function () { d3.selectAll('g.processor.entering, g.processor.leaving').call(updateProcessors); }, - + /** * Reloads the processor state from the server and refreshes the UI. * If the processor is currently unknown, this function just returns. - * + * * @param {object} processor The processor to reload */ reload: function (processor) { @@ -756,12 +838,12 @@ nf.Processor = (function () { }); } }, - + /** - * Sets the specified processor(s). If the is an array, it - * will set each processor. If it is not an array, it will + * Sets the specified processor(s). If the is an array, it + * will set each processor. If it is not an array, it will * attempt to set the specified processor. - * + * * @param {object | array} processorEntities */ set: function (processorEntities) { @@ -770,7 +852,7 @@ nf.Processor = (function () { // update the current entry var processorEntry = processorMap.get(processorEntity.id); $.extend(processorEntry, processorEntity); - + // update the processor in the UI d3.select('#id-' + processorEntry.id).call(updateProcessors); } @@ -785,10 +867,10 @@ nf.Processor = (function () { set(processorEntities); } }, - + /** * Removes the specified processor. - * + * * @param {array|string} processors The processors */ remove: function (processors) { @@ -803,17 +885,17 @@ nf.Processor = (function () { // apply the selection and handle all removed processors select().exit().call(removeProcessors); }, - + /** * Removes all processors. */ removeAll: function () { nf.Processor.remove(processorMap.keys()); }, - + /** * Sets the processor status using the specified status. - * + * * @param {array} processorStatus Processor status */ setStatus: function (processorStatus) { @@ -837,7 +919,7 @@ nf.Processor = (function () { * Returns the default color that should be used when drawing a processor. */ defaultColor: function () { - return '#aaaaaa'; + return '#ffffff'; } }; }()); \ 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-remote-process-group.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js index 27fa46170d..9cfa194767 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js @@ -22,8 +22,8 @@ nf.RemoteProcessGroup = (function () { var PREVIEW_NAME_LENGTH = 30; var dimensions = { - width: 365, - height: 140 + width: 380, + height: 158 }; // -------------------------------------------- @@ -44,8 +44,8 @@ nf.RemoteProcessGroup = (function () { /** * Gets the process group comments. - * - * @param {object} d + * + * @param {object} d */ var getProcessGroupComments = function (d) { if (nf.Common.isBlank(d.component.comments)) { @@ -59,7 +59,9 @@ nf.RemoteProcessGroup = (function () { * Selects the remote process group elements against the current remote process group map. */ var select = function () { - return remoteProcessGroupContainer.selectAll('g.remote-process-group').data(remoteProcessGroupMap.values()); + return remoteProcessGroupContainer.selectAll('g.remote-process-group').data(remoteProcessGroupMap.values(), function (d) { + return d.id; + }); }; /** @@ -74,14 +76,14 @@ nf.RemoteProcessGroup = (function () { } var remoteProcessGroup = entered.append('g') - .attr({ - 'id': function (d) { - return 'id-' + d.id; - }, - 'class': 'remote-process-group component' - }) - .classed('selected', selected) - .call(nf.CanvasUtils.position); + .attr({ + 'id': function (d) { + return 'id-' + d.id; + }, + 'class': 'remote-process-group component' + }) + .classed('selected', selected) + .call(nf.CanvasUtils.position); // ---- // body @@ -89,63 +91,68 @@ nf.RemoteProcessGroup = (function () { // remote process group border remoteProcessGroup.append('rect') - .attr({ - 'rx': 6, - 'ry': 6, - 'class': 'border', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': 'transparent', - 'stroke-opacity': 0.8, - 'stroke-width': 2, - 'stroke': '#294c58' - }); + .attr({ + 'class': 'border', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'fill': 'transparent', + 'stroke': 'transparent' + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); // remote process group body remoteProcessGroup.append('rect') - .attr({ - 'rx': 6, - 'ry': 6, - 'class': 'body', - 'width': function (d) { - return d.dimensions.width; - }, - 'height': function (d) { - return d.dimensions.height; - }, - 'fill': '#294c58', - 'fill-opacity': 0.8, - 'stroke-width': 0 - }); + .attr({ + 'class': 'body', + 'width': function (d) { + return d.dimensions.width; + }, + 'height': function (d) { + return d.dimensions.height; + }, + 'filter': 'url(#component-drop-shadow)', + 'stroke-width': 0 + }) + .classed('unauthorized', function (d) { + return d.accessPolicy.canRead === false; + }); + + // remote process group name background + remoteProcessGroup.append('rect') + .attr({ + 'width': function (d) { + return d.dimensions.width; + }, + 'height': 32, + 'fill': '#b8c6cd' + }); // remote process group name remoteProcessGroup.append('text') - .attr({ - 'x': 25, - 'y': 17, - 'width': 305, - 'height': 16, - 'font-size': '10pt', - 'font-weight': 'bold', - 'fill': '#ffffff', - 'class': 'remote-process-group-name' - }); + .attr({ + 'x': 30, + 'y': 20, + 'width': 305, + 'height': 16, + 'class': 'remote-process-group-name' + }); - // process group icon + // remote process group icon remoteProcessGroup.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/bgRemoteProcessGroupDetailsArea.png', - 'width': 352, - 'height': 89, - 'x': 6, - 'y': 38, - 'class': 'remote-process-group-preview' - }); + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'width': 352, + 'height': 89, + 'x': 6, + 'y': 38, + 'class': 'remote-process-group-preview' + }); // always support selection remoteProcessGroup.call(nf.Selectable.activate).call(nf.ContextMenu.activate); @@ -182,48 +189,59 @@ nf.RemoteProcessGroup = (function () { details = remoteProcessGroup.append('g').attr('class', 'remote-process-group-details'); // remote process group transmission status - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'remote-process-group-transmission-status', - 'width': 16, - 'height': 16, - 'x': 5, - 'y': 5 - }); + details.append('text') + .attr({ + 'class': 'remote-process-group-transmission-status', + 'x': 10, + 'y': 20 + }); + + // ------------------ + // details background + // ------------------ + + details.append('rect') + .attr({ + 'x': 0, + 'y': 32, + 'width': function () { + return remoteProcessGroupData.dimensions.width + }, + 'height': 24, + 'fill': '#e3e8eb' + }); + + // ------- + // details + // ------- // remote process group secure transfer - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'remote-process-group-transmission-secure', - 'width': 14, - 'height': 12, - 'x': 7, - 'y': 23 - }); + details.append('text') + .attr({ + 'class': 'remote-process-group-transmission-secure', + 'x': 10, + 'y': 48 + }); if (remoteProcessGroupData.accessPolicy.canRead) { // remote process group uri details.append('text') - .attr({ - 'x': 25, - 'y': 32, - 'width': 305, - 'height': 12, - 'font-size': '8pt', - 'fill': '#91b9ce', - 'class': 'remote-process-group-uri' - }) - .each(function (d) { - var remoteProcessGroupUri = d3.select(this); + .attr({ + 'x': 30, + 'y': 48, + 'width': 305, + 'height': 12, + 'class': 'remote-process-group-uri' + }) + .each(function (d) { + var remoteProcessGroupUri = d3.select(this); - // reset the remote process group name to handle any previous state - remoteProcessGroupUri.text(null).selectAll('title').remove(); + // reset the remote process group name to handle any previous state + remoteProcessGroupUri.text(null).selectAll('title').remove(); - // apply ellipsis to the remote process group name as necessary - nf.CanvasUtils.ellipsis(remoteProcessGroupUri, d.component.targetUri); - }).append('title').text(function (d) { + // apply ellipsis to the remote process group name as necessary + nf.CanvasUtils.ellipsis(remoteProcessGroupUri, d.component.targetUri); + }).append('title').text(function (d) { return d.component.name; }); } @@ -232,168 +250,53 @@ nf.RemoteProcessGroup = (function () { // stats background // ---------------- + // sent details.append('rect') - .attr({ - 'x': 6, - 'y': 38, - 'width': 352, - 'height': 89, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': '#ffffff' - }); + .attr({ + 'width': function () { + return remoteProcessGroupData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 66, + 'fill': '#f4f6f7' + }); + // border details.append('rect') - .attr({ - 'x': 6, - 'y': 38, - 'width': 176, - 'height': 22, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': 'url(#process-group-stats-background)', - 'class': 'remote-process-group-input-container' - }); + .attr({ + 'width': function () { + return remoteProcessGroupData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 84, + 'fill': '#c7d2d7' + }); + // received details.append('rect') - .attr({ - 'x': 182, - 'y': 38, - 'width': 176, - 'height': 22, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': 'url(#process-group-stats-background)', - 'class': 'remote-process-group-output-container' - }); + .attr({ + 'width': function () { + return remoteProcessGroupData.dimensions.width; + }, + 'height': 19, + 'x': 0, + 'y': 85, + 'fill': '#ffffff' + }); + // border details.append('rect') - .attr({ - 'x': 6, - 'y': 94, - 'width': 352, - 'height': 33, - 'stroke-width': 1, - 'stroke': '#6f97ac', - 'fill': 'url(#process-group-stats-background)' - }); - - // -------- - // contents - // -------- - - if (remoteProcessGroupData.accessPolicy.canRead) { - // input ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconInputPortSmall.png', - 'width': 16, - 'height': 16, - 'x': 10, - 'y': 41 - }); - - // input ports count - details.append('text') - .attr({ - 'x': 30, - 'y': 53, - 'class': 'remote-process-group-input-port-count process-group-contents-count' - }); - - // input transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionActive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-input-transmitting' - }); - - // input transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-input-transmitting-count process-group-contents-count' - }); - - // input not transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionInactive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-input-not-transmitting' - }); - - // input not transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-input-not-transmitting-count process-group-contents-count' - }); - - // output ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconOutputPortSmall.png', - 'width': 16, - 'height': 16, - 'x': 186, - 'y': 41, - 'class': 'remote-process-group-output-port' - }); - - // output ports count - details.append('text') - .attr({ - 'x': 206, - 'y': 53, - 'class': 'remote-process-group-output-port-count process-group-contents-count' - }); - - // output transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionActive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-output-transmitting' - }); - - // output transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-output-transmitting-count process-group-contents-count' - }); - - // output not transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionInactive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-output-not-transmitting' - }); - - // output not transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-output-not-transmitting-count process-group-contents-count' - }); - } + .attr({ + 'width': function () { + return remoteProcessGroupData.dimensions.width; + }, + 'height': 1, + 'x': 0, + 'y': 103, + 'fill': '#c7d2d7' + }); // ----- // stats @@ -401,85 +304,85 @@ nf.RemoteProcessGroup = (function () { // stats label container var remoteProcessGroupStatsLabel = details.append('g') - .attr({ - 'transform': 'translate(6, 70)' - }); + .attr({ + 'transform': 'translate(6, 75)' + }); // sent label remoteProcessGroupStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'process-group-stats-label' - }) - .text('Sent'); + .attr({ + 'width': 73, + 'height': 10, + 'x': 4, + 'y': 5, + 'class': 'stats-label' + }) + .text('Sent'); // received label remoteProcessGroupStatsLabel.append('text') - .attr({ - 'width': 73, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'process-group-stats-label' - }) - .text('Received'); + .attr({ + 'width': 73, + 'height': 10, + 'x': 4, + 'y': 23, + 'class': 'stats-label' + }) + .text('Received'); // stats value container var remoteProcessGroupStatsValue = details.append('g') - .attr({ - 'transform': 'translate(95, 70)' - }); + .attr({ + 'transform': 'translate(95, 75)' + }); // queued value remoteProcessGroupStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'remote-process-group-sent process-group-stats-value' - }); + .attr({ + 'width': 180, + 'height': 10, + 'x': 4, + 'y': 5, + 'class': 'remote-process-group-sent stats-value' + }); // received value remoteProcessGroupStatsValue.append('text') - .attr({ - 'width': 180, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'remote-process-group-received process-group-stats-value' - }); + .attr({ + 'width': 180, + 'height': 10, + 'x': 4, + 'y': 23, + 'class': 'remote-process-group-received stats-value' + }); // stats value container var processGroupStatsInfo = details.append('g') - .attr({ - 'transform': 'translate(315, 70)' - }); + .attr({ + 'transform': 'translate(335, 75)' + }); // sent info processGroupStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 4, - 'class': 'process-group-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'x': 4, + 'y': 5, + 'class': 'stats-info' + }) + .text('5 min'); // received info processGroupStatsInfo.append('text') - .attr({ - 'width': 25, - 'height': 10, - 'x': 4, - 'y': 17, - 'class': 'process-group-stats-info' - }) - .text('(5 min)'); + .attr({ + 'width': 25, + 'height': 10, + 'x': 4, + 'y': 23, + 'class': 'stats-info' + }) + .text('5 min'); // -------- // comments @@ -487,101 +390,120 @@ nf.RemoteProcessGroup = (function () { // process group comments details.append('text') - .attr({ - 'x': 10, - 'y': 108, - 'width': 342, - 'height': 22, - 'class': 'remote-process-group-comments' - }); + .attr({ + 'x': 10, + 'y': 121, + 'width': 342, + 'height': 22, + 'class': 'remote-process-group-comments' + }); // ------------------- // last refreshed time // ------------------- - details.append('text') - .attr({ - 'x': 358, - 'y': 137, - 'class': 'remote-process-group-last-refresh' - }); - - // ------------------- - // active thread count - // ------------------- - - // active thread count details.append('rect') - .attr({ - 'class': 'active-thread-count-background', - 'height': 13, - 'y': 0, - 'fill': '#fff', - 'fill-opacity': '0.4', - 'stroke': '#aaa', - 'stroke-width': '1' - }); + .attr({ + 'x': 0, + 'y': function () { + return remoteProcessGroupData.dimensions.height - 24; + }, + 'width': function () { + return remoteProcessGroupData.dimensions.width; + }, + 'height': 24, + 'fill': '#e3e8eb' + }); - // active thread bacground details.append('text') - .attr({ - 'class': 'active-thread-count', - 'height': 13, - 'y': 10, - 'fill': '#000' - }); + .attr({ + 'x': 370, + 'y': 150, + 'class': 'remote-process-group-last-refresh' + }); + + // ------------------- + // active thread count + // ------------------- + + // active thread count + details.append('text') + .attr({ + 'class': 'active-thread-count-icon', + 'y': 20 + }) + .text('\ue83f'); + + // active thread icon + details.append('text') + .attr({ + 'class': 'active-thread-count', + 'y': 20 + }); // --------- // bulletins // --------- + // bulletin background + details.append('rect') + .attr({ + 'class': 'bulletin-background', + 'x': function () { + return remoteProcessGroupData.dimensions.width - 24; + }, + 'y': 32, + 'width': 24, + 'height': 24 + }); + // bulletin icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'bulletin-icon', - 'xlink:href': 'images/iconBulletin.png', - 'width': 12, - 'height': 12, - 'y': 2 - }); + details.append('text') + .attr({ + 'class': 'bulletin-icon', + 'x': function () { + return remoteProcessGroupData.dimensions.width - 17; + }, + 'y': 50 + }) + .text('\uf24a'); } if (remoteProcessGroupData.accessPolicy.canRead) { // update the process groups transmission status - details.select('image.remote-process-group-transmission-secure') - .attr('xlink:href', function (d) { - var img = ''; - if (d.component.targetSecure === true) { - img = 'images/iconSecure.png'; - } else { - img = 'images/iconNotSecure.png'; - } - return img; - }) - .each(function (d) { - // remove the existing tip if necessary - var tip = d3.select('#transmission-secure-' + d.id); - if (!tip.empty()) { - tip.remove(); - } + details.select('text.remote-process-group-transmission-secure') + .text(function (d) { + var icon = ''; + if (d.component.targetSecure === true) { + icon = '\uf023'; + } else { + icon = '\uf09c'; + } + return icon; + }) + .each(function (d) { + // remove the existing tip if necessary + var tip = d3.select('#transmission-secure-' + d.id); + if (!tip.empty()) { + tip.remove(); + } - tip = d3.select('#remote-process-group-tooltips').append('div') - .attr('id', function () { - return 'transmission-secure-' + d.id; - }) - .attr('class', 'tooltip nifi-tooltip') - .text(function () { - if (d.component.targetSecure === true) { - return 'Site-to-Site is secure.'; - } else { - return 'Site-to-Site is NOT secure.'; - } - }); + tip = d3.select('#remote-process-group-tooltips').append('div') + .attr('id', function () { + return 'transmission-secure-' + d.id; + }) + .attr('class', 'tooltip nifi-tooltip') + .text(function () { + if (d.component.targetSecure === true) { + return 'Site-to-Site is secure.'; + } else { + return 'Site-to-Site is NOT secure.'; + } + }); - // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); - }); + // add the tooltip + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); + }); // ---------------------- // update the input ports @@ -589,45 +511,45 @@ nf.RemoteProcessGroup = (function () { // input port count details.select('text.remote-process-group-input-port-count') - .text(function (d) { - return d.component.inputPortCount; - }); + .text(function (d) { + return d.component.inputPortCount; + }); // get the input port container to help right align var inputContainer = details.select('rect.remote-process-group-input-container'); // update input not transmitting var inputNotTransmittingCount = details.select('text.remote-process-group-input-not-transmitting-count') - .text(function (d) { - return d.component.inactiveRemoteInputPortCount; - }) - .attr('x', function () { - var containerX = parseInt(inputContainer.attr('x'), 10); - var containerWidth = parseInt(inputContainer.attr('width'), 10); - return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; - }); + .text(function (d) { + return d.component.inactiveRemoteInputPortCount; + }) + .attr('x', function () { + var containerX = parseInt(inputContainer.attr('x'), 10); + var containerWidth = parseInt(inputContainer.attr('width'), 10); + return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; + }); var inputNotTransmitting = details.select('image.remote-process-group-input-not-transmitting') - .attr('x', function () { - var inputNotTransmittingCountX = parseInt(inputNotTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return inputNotTransmittingCountX - width - CONTENTS_SPACER; - }); + .attr('x', function () { + var inputNotTransmittingCountX = parseInt(inputNotTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return inputNotTransmittingCountX - width - CONTENTS_SPACER; + }); // update input transmitting var inputTransmittingCount = details.select('text.remote-process-group-input-transmitting-count') - .text(function (d) { - return d.component.activeRemoteInputPortCount; - }) - .attr('x', function () { - var inputNotTransmittingX = parseInt(inputNotTransmitting.attr('x'), 10); - return inputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; - }); + .text(function (d) { + return d.component.activeRemoteInputPortCount; + }) + .attr('x', function () { + var inputNotTransmittingX = parseInt(inputNotTransmitting.attr('x'), 10); + return inputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; + }); details.select('image.remote-process-group-input-transmitting') - .attr('x', function () { - var inputTransmittingCountX = parseInt(inputTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return inputTransmittingCountX - width - CONTENTS_SPACER; - }); + .attr('x', function () { + var inputTransmittingCountX = parseInt(inputTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return inputTransmittingCountX - width - CONTENTS_SPACER; + }); // ----------------------- // update the output ports @@ -635,45 +557,45 @@ nf.RemoteProcessGroup = (function () { // output port count details.select('text.remote-process-group-output-port-count') - .text(function (d) { - return d.component.outputPortCount; - }); + .text(function (d) { + return d.component.outputPortCount; + }); // get the output port container to help right align var outputContainer = details.select('rect.remote-process-group-output-container'); // update input not transmitting var outputNotTransmittingCount = details.select('text.remote-process-group-output-not-transmitting-count') - .text(function (d) { - return d.component.inactiveRemoteOutputPortCount; - }) - .attr('x', function () { - var containerX = parseInt(outputContainer.attr('x'), 10); - var containerWidth = parseInt(outputContainer.attr('width'), 10); - return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; - }); + .text(function (d) { + return d.component.inactiveRemoteOutputPortCount; + }) + .attr('x', function () { + var containerX = parseInt(outputContainer.attr('x'), 10); + var containerWidth = parseInt(outputContainer.attr('width'), 10); + return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; + }); var outputNotTransmitting = details.select('image.remote-process-group-output-not-transmitting') - .attr('x', function () { - var outputNotTransmittingCountX = parseInt(outputNotTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return outputNotTransmittingCountX - width - CONTENTS_SPACER; - }); + .attr('x', function () { + var outputNotTransmittingCountX = parseInt(outputNotTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return outputNotTransmittingCountX - width - CONTENTS_SPACER; + }); // update output transmitting var outputTransmittingCount = details.select('text.remote-process-group-output-transmitting-count') - .text(function (d) { - return d.component.activeRemoteOutputPortCount; - }) - .attr('x', function () { - var outputNotTransmittingX = parseInt(outputNotTransmitting.attr('x'), 10); - return outputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; - }); + .text(function (d) { + return d.component.activeRemoteOutputPortCount; + }) + .attr('x', function () { + var outputNotTransmittingX = parseInt(outputNotTransmitting.attr('x'), 10); + return outputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; + }); details.select('image.remote-process-group-output-transmitting') - .attr('x', function () { - var outputTransmittingCountX = parseInt(outputTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return outputTransmittingCountX - width - CONTENTS_SPACER; - }); + .attr('x', function () { + var outputTransmittingCountX = parseInt(outputTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return outputTransmittingCountX - width - CONTENTS_SPACER; + }); // --------------- // update comments @@ -681,15 +603,15 @@ nf.RemoteProcessGroup = (function () { // update the process group comments details.select('text.remote-process-group-comments') - .each(function (d) { - var remoteProcessGroupComments = d3.select(this); + .each(function (d) { + var remoteProcessGroupComments = d3.select(this); - // reset the processor name to handle any previous state - remoteProcessGroupComments.text(null).selectAll('tspan, title').remove(); + // reset the processor name to handle any previous state + remoteProcessGroupComments.text(null).selectAll('tspan, title').remove(); - // apply ellipsis to the port name as necessary - nf.CanvasUtils.multilineEllipsis(remoteProcessGroupComments, 2, getProcessGroupComments(d)); - }).classed('unset', function (d) { + // apply ellipsis to the port name as necessary + nf.CanvasUtils.ellipsis(remoteProcessGroupComments, getProcessGroupComments(d)); + }).classed('unset', function (d) { return nf.Common.isBlank(d.component.comments); }).append('title').text(function (d) { return getProcessGroupComments(d); @@ -700,25 +622,25 @@ nf.RemoteProcessGroup = (function () { // -------------- details.select('text.remote-process-group-last-refresh') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.component.flowRefreshed)) { - return d.component.flowRefreshed; - } else { - return 'Remote flow not current'; - } - }); + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.component.flowRefreshed)) { + return d.component.flowRefreshed; + } else { + return 'Remote flow not current'; + } + }); // update the process group name remoteProcessGroup.select('text.remote-process-group-name') - .each(function (d) { - var remoteProcessGroupName = d3.select(this); + .each(function (d) { + var remoteProcessGroupName = d3.select(this); - // reset the remote process group name to handle any previous state - remoteProcessGroupName.text(null).selectAll('title').remove(); + // reset the remote process group name to handle any previous state + remoteProcessGroupName.text(null).selectAll('title').remove(); - // apply ellipsis to the remote process group name as necessary - nf.CanvasUtils.ellipsis(remoteProcessGroupName, d.component.name); - }).append('title').text(function (d) { + // apply ellipsis to the remote process group name as necessary + nf.CanvasUtils.ellipsis(remoteProcessGroupName, d.component.name); + }).append('title').text(function (d) { return d.component.name; }); } @@ -732,14 +654,14 @@ nf.RemoteProcessGroup = (function () { if (remoteProcessGroupData.accessPolicy.canRead) { // update the process group name remoteProcessGroup.select('text.remote-process-group-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); } // show the preview @@ -758,7 +680,7 @@ nf.RemoteProcessGroup = (function () { /** * Updates the process group status. - * + * * @param {selection} updated The process groups to be updated */ var updateProcessGroupStatus = function (updated) { @@ -768,23 +690,23 @@ nf.RemoteProcessGroup = (function () { // sent value updated.select('text.remote-process-group-sent') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.sent; - } else { - return '- / -'; - } - }); + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return d.status.sent; + } else { + return '- / -'; + } + }); // received value updated.select('text.remote-process-group-received') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.status)) { - return d.status.received; - } else { - return '- / -'; - } - }); + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.status)) { + return d.status.received; + } else { + return '- / -'; + } + }); // -------------------- // authorization issues @@ -792,19 +714,31 @@ nf.RemoteProcessGroup = (function () { // TODO - only consider state from the status // update the process groups transmission status - updated.select('image.remote-process-group-transmission-status') - .attr('xlink:href', function (d) { - var img = ''; + updated.select('text.remote-process-group-transmission-status') + .text(function (d) { + var icon = ''; if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.authorizationIssues)) { - img = 'images/iconAlert.png'; + icon = '\uf071'; } else if (d.accessPolicy.canRead) { if (d.component.transmitting === true) { - img = 'images/iconTransmissionActive.png'; + icon = '\uf140'; } else { - img = 'images/iconTransmissionInactive.png'; + icon = '\ue80a'; } } - return img; + return icon; + }) + .attr('font-family', function (d) { + var family = ''; + if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.authorizationIssues) || (d.accessPolicy.canRead && d.component.transmitting)) { + family = 'FontAwesome'; + } else { + family = 'flowfont'; + } + return family; + }) + .classed('has-authorization-errors', function (d) { + return nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.authorizationIssues); }) .each(function (d) { // remove the existing tip if necessary @@ -850,6 +784,10 @@ nf.RemoteProcessGroup = (function () { // bulletins // --------- + remoteProcessGroup.select('rect.bulletin-background').classed('has-bulletins', function () { + return nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins); + }); + nf.CanvasUtils.bulletins(remoteProcessGroup, d, function () { return d3.select('#remote-process-group-tooltips'); }, offset); @@ -871,7 +809,7 @@ nf.RemoteProcessGroup = (function () { /** * Removes the tooltips for the remote process groups in the specified selection. - * + * * @param {type} removed */ var removeTooltips = function (removed) { @@ -892,12 +830,12 @@ nf.RemoteProcessGroup = (function () { // create the process group container remoteProcessGroupContainer = d3.select('#canvas').append('g') - .attr({ - 'pointer-events': 'all', - 'class': 'remote-process-groups' - }); + .attr({ + 'pointer-events': 'all', + 'class': 'remote-process-groups' + }); }, - + /** * Populates the graph with the specified remote process groups. * @@ -927,9 +865,9 @@ nf.RemoteProcessGroup = (function () { // apply the selection and handle all new remote process groups select().enter().call(renderRemoteProcessGroups, selectAll); }, - + /** - * If the remote process group id is specified it is returned. If no remote process + * If the remote process group id is specified it is returned. If no remote process * group id specified, all remote process groups are returned. * * @param {string} id @@ -941,7 +879,7 @@ nf.RemoteProcessGroup = (function () { return remoteProcessGroupMap.get(id); } }, - + /** * If the remote process group id is specified it is refresh according to the current * state. If no remote process group id is specified, all remote process groups are refreshed. @@ -955,14 +893,14 @@ nf.RemoteProcessGroup = (function () { d3.selectAll('g.remote-process-group').call(updateRemoteProcessGroups); } }, - + /** * Refreshes the components necessary after a pan event. */ pan: function () { d3.selectAll('g.remote-process-group.entering, g.remote-process-group.leaving').call(updateRemoteProcessGroups); }, - + /** * Reloads the remote process group state from the server and refreshes the UI. * If the remote process group is currently unknown, this function just returns. @@ -986,16 +924,16 @@ nf.RemoteProcessGroup = (function () { }); } }, - + /** * Positions the component. - * + * * @param {string} id The id */ position: function (id) { d3.select('#id-' + id).call(nf.CanvasUtils.position); }, - + /** * Sets the specified remote process group(s). If the is an array, it * will set each remote process group. If it is not an array, it will @@ -1009,7 +947,7 @@ nf.RemoteProcessGroup = (function () { // update the current entry var remoteProcessGroupEntry = remoteProcessGroupMap.get(remoteProcessGroupEntity.id); $.extend(remoteProcessGroupEntry, remoteProcessGroupEntity); - + // update the remote process group in the UI d3.select('#id-' + remoteProcessGroupEntry.id).call(updateRemoteProcessGroups); } @@ -1024,10 +962,10 @@ nf.RemoteProcessGroup = (function () { set(remoteProcessGroupEntities); } }, - + /** * Sets the remote process group status using the specified status. - * + * * @param {array | object} remoteProcessGroupStatus Remote process group status */ setStatus: function (remoteProcessGroupStatus) { @@ -1064,7 +1002,7 @@ nf.RemoteProcessGroup = (function () { // apply the selection and handle all removed remote process groups select().exit().call(removeRemoteProcessGroups); }, - + /** * Removes all remote process groups. */ 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 879fb56ffe..882667199a 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 @@ -722,6 +722,43 @@ nf.Common = (function () { return result; }, + /** + * Extracts the contents of the specified str after the strToFind. If the + * strToFind is not found or the last part of the str, an empty string is + * returned. + * + * @argument {string} str The full string + * @argument {string} strToFind The substring to find + */ + substringAfterFirst: function (str, strToFind) { + var result = ''; + var indexOfStrToFind = str.indexOf(strToFind); + if (indexOfStrToFind >= 0) { + var indexAfterStrToFind = indexOfStrToFind + strToFind.length; + if (indexAfterStrToFind < str.length) { + result = str.substr(indexAfterStrToFind); + } + } + return result; + }, + + /** + * Extracts the contents of the specified str before the strToFind. If the + * strToFind is not found or the first part of the str, an empty string is + * returned. + * + * @argument {string} str The full string + * @argument {string} strToFind The substring to find + */ + substringBeforeFirst: function(str, strToFind) { + var result = ''; + var indexOfStrToFind = str.indexOf(strToFind); + if (indexOfStrToFind >= 0) { + result = str.substr(0, indexOfStrToFind); + } + return result + }, + /** * Updates the mouse pointer. *