NIFI-1781:
- Incorporating updated styles to reflect component level authorization. - Updating canvas for new look and feel. - This closes #417
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.nifi.web.api.entity;
|
package org.apache.nifi.web.api.entity;
|
||||||
|
|
||||||
import org.apache.nifi.web.api.dto.ProcessorDTO;
|
import org.apache.nifi.web.api.dto.ProcessorDTO;
|
||||||
|
import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO;
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
public class ProcessorEntity extends ComponentEntity {
|
public class ProcessorEntity extends ComponentEntity {
|
||||||
|
|
||||||
private ProcessorDTO component;
|
private ProcessorDTO component;
|
||||||
|
private ProcessorStatusDTO status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ProcessorDTO that is being serialized.
|
* The ProcessorDTO that is being serialized.
|
||||||
|
@ -41,4 +43,16 @@ public class ProcessorEntity extends ComponentEntity {
|
||||||
this.component = component;
|
this.component = component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Processor status.
|
||||||
|
*
|
||||||
|
* @return status
|
||||||
|
*/
|
||||||
|
public ProcessorStatusDTO getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(ProcessorStatusDTO status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -634,7 +634,7 @@ public class StatusMerger {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String prettyPrint(final Integer count, final Long bytes) {
|
public static String prettyPrint(final Integer count, final Long bytes) {
|
||||||
return formatCount(count) + " / " + formatDataSize(bytes);
|
return formatCount(count) + " (" + formatDataSize(bytes) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
<md-menu-item layout-align="space-around center">
|
<md-menu-item layout-align="space-around center">
|
||||||
<a id="bulletin-board-link"
|
<a id="bulletin-board-link"
|
||||||
ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.bulletinBoard.shell.launch();"><i
|
ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.bulletinBoard.shell.launch();"><i
|
||||||
class="icon icon-bulletin"></i>Bulletin Board</a>
|
class="fa fa-sticky-note-o"></i>Bulletin Board</a>
|
||||||
</md-menu-item>
|
</md-menu-item>
|
||||||
<md-menu-divider></md-menu-divider>
|
<md-menu-divider></md-menu-divider>
|
||||||
<md-menu-item
|
<md-menu-item
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<div layout="row" layout-align="end center">
|
<div layout="row" layout-align="end center">
|
||||||
<input id="search-field" type="text"/>
|
<input id="search-field" type="text"/>
|
||||||
<button id="search-button"><i class="fa fa-search"></i></button>
|
<button id="search-button"><i class="fa fa-search"></i></button>
|
||||||
<button id="bulletin-button"><i class="icon-bulletin"></i></button>
|
<button id="bulletin-button"><i class="fa fa-sticky-note-o"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="search-flow-results"></div>
|
<div id="search-flow-results"></div>
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
background-color:#728E9B; /*base-color*/
|
background-color:#728E9B; /*base-color*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#bulletin-button i{
|
#bulletin-button i.fa {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size:15px;
|
font-size:15px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,16 +53,78 @@ text.unset {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.component {
|
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 {
|
g.component.selected rect.border {
|
||||||
stroke: #ffcc00;
|
stroke: #004849;
|
||||||
stroke-width: 5;
|
stroke-width: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
g.funnel.selected rect.border {
|
text.stats-label {
|
||||||
stroke-width: 2.5;
|
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
|
Processor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
text.processor-stats-label {
|
text.processor-name {
|
||||||
fill: #fff;
|
fill: #262626;
|
||||||
font-size: 11px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text.processor-stats-value {
|
text.processor-type {
|
||||||
font-size: 11px;
|
fill: #728e9b;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
text.processor-stats-info {
|
text.processor-icon {
|
||||||
fill: #999999;
|
fill: #ad9897;
|
||||||
font-size: 11px;
|
font-family: flowfont;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
text.run-status-icon {
|
||||||
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -108,7 +175,27 @@ text.processor-stats-info {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.connection {
|
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 {
|
path.connector {
|
||||||
|
@ -126,12 +213,6 @@ path.connector.connectable {
|
||||||
stroke-dasharray: 4;
|
stroke-dasharray: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
g.connection rect.connection-label {
|
|
||||||
fill: #ffffff;
|
|
||||||
stroke: #000000;
|
|
||||||
stroke-width: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
g.connection path.connection-path {
|
g.connection path.connection-path {
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke: #000000;
|
stroke: #000000;
|
||||||
|
@ -139,6 +220,21 @@ g.connection path.connection-path {
|
||||||
cursor: pointer;
|
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 */
|
/* grouped connection */
|
||||||
|
|
||||||
g.connection.grouped path.connection-path, g.connection.grouped rect.connection-label {
|
g.connection.grouped path.connection-path, g.connection.grouped rect.connection-label {
|
||||||
|
@ -196,12 +292,6 @@ g.connection rect.endpoint {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
g.connection text.connection-stats-label {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: bold;
|
|
||||||
fill: #598599;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* labels */
|
/* labels */
|
||||||
|
|
||||||
g.label rect.labelpoint {
|
g.label rect.labelpoint {
|
||||||
|
@ -218,8 +308,30 @@ g.label.selected rect.labelpoint {
|
||||||
|
|
||||||
/* funnels */
|
/* funnels */
|
||||||
|
|
||||||
|
text.funnel-icon {
|
||||||
|
fill: #ad9897;
|
||||||
|
font-family: flowfont;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ports */
|
/* 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 */
|
/* active thread count */
|
||||||
|
|
||||||
text.active-thread-count {
|
text.active-thread-count {
|
||||||
|
@ -228,35 +340,55 @@ text.active-thread-count {
|
||||||
|
|
||||||
/* process groups */
|
/* 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 {
|
g.process-group.drop rect.border {
|
||||||
stroke: #0000ff;
|
stroke: #0000ff;
|
||||||
stroke-width: 3;
|
stroke-width: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
text.process-group-contents-count {
|
text.process-group-contents-icon {
|
||||||
font-weight: bold;
|
font-size: 13px;
|
||||||
fill: #294c58;
|
fill: #728e9b;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remote process group */
|
/* 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 {
|
text.remote-process-group-last-refresh {
|
||||||
fill: #cccccc;
|
fill: #728e9b;
|
||||||
font-style: italic;
|
|
||||||
text-anchor: end;
|
text-anchor: end;
|
||||||
}
|
}
|
|
@ -74,12 +74,13 @@ md-toolbar.md-small .md-toolbar-tools {
|
||||||
|
|
||||||
#global-menu-content {
|
#global-menu-content {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 3px 0;
|
padding: 0px 0;
|
||||||
background-color:rgba(249,250,251,0.97); /*tint base-color 96%*/
|
background-color:rgba(249,250,251,0.97); /*tint base-color 96%*/
|
||||||
border:1px solid #004849; /*link-color*/
|
border:1px solid #004849; /*link-color*/
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
box-shadow:0 2px 3px rgba(0,0,0,0.35);
|
box-shadow:0 2px 3px rgba(0,0,0,0.35);
|
||||||
width: 215px;
|
width: 215px;
|
||||||
|
max-height: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#global-menu-content md-menu-item{
|
#global-menu-content md-menu-item{
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Roboto+Slab';
|
font-family: 'Roboto Slab';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src: local('RobotoSlab Regular'),
|
src: local('RobotoSlab Regular'),
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Roboto+Slab';
|
font-family: 'Roboto Slab';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src: local('RobotoSlab Bold'),
|
src: local('RobotoSlab Bold'),
|
||||||
|
|
Before Width: | Height: | Size: 746 B |
Before Width: | Height: | Size: 618 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 585 B |
Before Width: | Height: | Size: 362 B |
Before Width: | Height: | Size: 832 B |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 227 B |
Before Width: | Height: | Size: 356 B |
Before Width: | Height: | Size: 356 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 880 B |
Before Width: | Height: | Size: 495 B |
Before Width: | Height: | Size: 554 B |
Before Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 530 B |
Before Width: | Height: | Size: 551 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 869 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 499 B |
Before Width: | Height: | Size: 435 B |
Before Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 319 B |
Before Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 45 B |
|
@ -152,7 +152,7 @@ nf.Actions = (function () {
|
||||||
url: d.component.uri,
|
url: d.component.uri,
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
var remoteProcessGroup = response.remoteProcessGroup;
|
var remoteProcessGroup = response.component;
|
||||||
|
|
||||||
// the timestamp has not updated yet, poll again
|
// the timestamp has not updated yet, poll again
|
||||||
if (refreshTimestamp === remoteProcessGroup.flowRefreshed) {
|
if (refreshTimestamp === remoteProcessGroup.flowRefreshed) {
|
||||||
|
@ -163,7 +163,7 @@ nf.Actions = (function () {
|
||||||
// reload the group's connections
|
// reload the group's connections
|
||||||
var connections = nf.Connection.getComponentConnections(remoteProcessGroup.id);
|
var connections = nf.Connection.getComponentConnections(remoteProcessGroup.id);
|
||||||
$.each(connections, function (_, connection) {
|
$.each(connections, function (_, connection) {
|
||||||
nf.Connection.reload(connection);
|
nf.Connection.reload(connection.component);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -405,16 +405,12 @@ nf.CanvasUtils = (function () {
|
||||||
.each(function () {
|
.each(function () {
|
||||||
var bBox = this.getBBox();
|
var bBox = this.getBBox();
|
||||||
d3.select(this).attr('x', function () {
|
d3.select(this).attr('x', function () {
|
||||||
return d.dimensions.width - bBox.width - 4;
|
return d.dimensions.width - bBox.width - 15;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// update the background width
|
// update the background width
|
||||||
selection.select('rect.active-thread-count-background')
|
selection.select('text.active-thread-count-icon')
|
||||||
.attr('width', function () {
|
|
||||||
var bBox = activeThreadCount.node().getBBox();
|
|
||||||
return bBox.width + 8;
|
|
||||||
})
|
|
||||||
.attr('x', function () {
|
.attr('x', function () {
|
||||||
var bBox = activeThreadCount.node().getBBox();
|
var bBox = activeThreadCount.node().getBBox();
|
||||||
|
|
||||||
|
@ -423,22 +419,11 @@ nf.CanvasUtils = (function () {
|
||||||
setOffset(bBox.width + 6);
|
setOffset(bBox.width + 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.dimensions.width - bBox.width - 8;
|
return d.dimensions.width - bBox.width - 20;
|
||||||
})
|
|
||||||
.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(' ');
|
|
||||||
})
|
})
|
||||||
.style('display', 'block');
|
.style('display', 'block');
|
||||||
} else {
|
} 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 there are bulletins show them, otherwise hide
|
||||||
if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins)) {
|
if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.bulletins)) {
|
||||||
// update the tooltip
|
// update the tooltip
|
||||||
selection.select('image.bulletin-icon')
|
selection.select('text.bulletin-icon')
|
||||||
.style('display', 'block')
|
|
||||||
.each(function () {
|
.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
|
// if there are bulletins generate a tooltip
|
||||||
tip = getTooltipContainer().append('div')
|
tip = getTooltipContainer().append('div')
|
||||||
.attr('id', function () {
|
.attr('id', function () {
|
||||||
|
@ -505,10 +482,8 @@ nf.CanvasUtils = (function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
// add the tooltip
|
// add the tooltip
|
||||||
nf.CanvasUtils.canvasTooltip(tip, bulletinIcon);
|
nf.CanvasUtils.canvasTooltip(tip, d3.select(this));
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
selection.selectAll('image.bulletin-icon').style('display', 'none');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ nf.Canvas = (function () {
|
||||||
|
|
||||||
// create arrow definitions for the various line types
|
// create arrow definitions for the various line types
|
||||||
defs.selectAll('marker')
|
defs.selectAll('marker')
|
||||||
.data(['normal', 'ghost'])
|
.data(['normal', 'ghost', 'unauthorized'])
|
||||||
.enter().append('marker')
|
.enter().append('marker')
|
||||||
.attr({
|
.attr({
|
||||||
'id': function (d) {
|
'id': function (d) {
|
||||||
|
@ -256,6 +256,8 @@ nf.Canvas = (function () {
|
||||||
'fill': function (d) {
|
'fill': function (d) {
|
||||||
if (d === 'ghost') {
|
if (d === 'ghost') {
|
||||||
return '#aaaaaa';
|
return '#aaaaaa';
|
||||||
|
} else if (d === 'unauthorized') {
|
||||||
|
return '#ba554a';
|
||||||
} else {
|
} else {
|
||||||
return '#000000';
|
return '#000000';
|
||||||
}
|
}
|
||||||
|
@ -264,77 +266,42 @@ nf.Canvas = (function () {
|
||||||
.append('path')
|
.append('path')
|
||||||
.attr('d', 'M2,3 L0,6 L6,3 L0,0 z');
|
.attr('d', 'M2,3 L0,6 L6,3 L0,0 z');
|
||||||
|
|
||||||
// define the gradient for the processor stats background
|
// filter for drop shadow
|
||||||
var processGroupStatsBackground = defs.append('linearGradient')
|
var filter = defs.append('filter')
|
||||||
.attr({
|
.attr('id', 'component-drop-shadow');
|
||||||
'id': 'process-group-stats-background',
|
|
||||||
'x1': '0%',
|
|
||||||
'y1': '100%',
|
|
||||||
'x2': '0%',
|
|
||||||
'y2': '0%'
|
|
||||||
});
|
|
||||||
|
|
||||||
processGroupStatsBackground.append('stop')
|
// blur
|
||||||
.attr({
|
filter.append('feGaussianBlur')
|
||||||
'offset': '0%',
|
.attr('in', 'SourceAlpha')
|
||||||
'stop-color': '#dedede'
|
.attr('stdDeviation', 2)
|
||||||
});
|
.attr('result', 'blur');
|
||||||
|
|
||||||
processGroupStatsBackground.append('stop')
|
// offset
|
||||||
.attr({
|
filter.append('feOffset')
|
||||||
'offset': '50%',
|
.attr('in', 'blur')
|
||||||
'stop-color': '#ffffff'
|
.attr('dx', 0)
|
||||||
});
|
.attr('dy', 1)
|
||||||
|
.attr('result', 'offsetBlur');
|
||||||
|
|
||||||
processGroupStatsBackground.append('stop')
|
// color/opacity
|
||||||
.attr({
|
filter.append('feFlood')
|
||||||
'offset': '100%',
|
.attr('flood-color', '#000000')
|
||||||
'stop-color': '#dedede'
|
.attr('flood-opacity', 0.25)
|
||||||
});
|
.attr('result', 'offsetColor');
|
||||||
|
|
||||||
// define the gradient for the processor stats background
|
// combine
|
||||||
var processorStatsBackground = defs.append('linearGradient')
|
filter.append('feComposite')
|
||||||
.attr({
|
.attr('in', 'offsetColor')
|
||||||
'id': 'processor-stats-background',
|
.attr('in2', 'offsetBlur')
|
||||||
'x1': '0%',
|
.attr('operator', 'in')
|
||||||
'y1': '100%',
|
.attr('result', 'offsetColorBlur');
|
||||||
'x2': '0%',
|
|
||||||
'y2': '0%'
|
|
||||||
});
|
|
||||||
|
|
||||||
processorStatsBackground.append('stop')
|
// stack the effect under the source graph
|
||||||
.attr({
|
var feMerge = filter.append('feMerge');
|
||||||
'offset': '0%',
|
feMerge.append('feMergeNode')
|
||||||
'stop-color': '#6f97ac'
|
.attr('in', 'offsetColorBlur');
|
||||||
});
|
feMerge.append('feMergeNode')
|
||||||
|
.attr('in', 'SourceGraphic');
|
||||||
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'
|
|
||||||
});
|
|
||||||
|
|
||||||
// define the gradient for the expiration icon
|
// define the gradient for the expiration icon
|
||||||
var expirationBackground = defs.append('linearGradient')
|
var expirationBackground = defs.append('linearGradient')
|
||||||
|
@ -636,51 +603,6 @@ nf.Canvas = (function () {
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).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.
|
* Reloads the current status of this flow.
|
||||||
*/
|
*/
|
||||||
|
@ -1172,24 +1094,6 @@ nf.Canvas = (function () {
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).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.
|
* Return whether this instance of NiFi is clustered.
|
||||||
*
|
*
|
||||||
|
|
|
@ -248,29 +248,32 @@ nf.ConnectionConfiguration = (function () {
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.id),
|
url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupData.id),
|
||||||
data: {
|
data: {
|
||||||
verbose: true
|
verbose: true
|
||||||
},
|
},
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
var processGroup = response.component;
|
var processGroup = response.processGroupFlow;
|
||||||
var processGroupContents = processGroup.contents;
|
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
|
// only proceed if there are output ports
|
||||||
if (!nf.Common.isEmpty(processGroupContents.outputPorts)) {
|
if (!nf.Common.isEmpty(options)) {
|
||||||
$('#output-port-source').show();
|
$('#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
|
// sort the options
|
||||||
options.sort(function (a, b) {
|
options.sort(function (a, b) {
|
||||||
return a.text.localeCompare(b.text);
|
return a.text.localeCompare(b.text);
|
||||||
|
@ -331,7 +334,7 @@ nf.ConnectionConfiguration = (function () {
|
||||||
},
|
},
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
var remoteProcessGroup = response.remoteProcessGroup;
|
var remoteProcessGroup = response.component;
|
||||||
var remoteProcessGroupContents = remoteProcessGroup.contents;
|
var remoteProcessGroupContents = remoteProcessGroup.contents;
|
||||||
|
|
||||||
// only proceed if there are output ports
|
// only proceed if there are output ports
|
||||||
|
@ -473,29 +476,29 @@ nf.ConnectionConfiguration = (function () {
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
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'
|
dataType: 'json'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
var processGroup = response.component;
|
var processGroup = response.processGroupFlow;
|
||||||
var processGroupContents = processGroup.contents;
|
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
|
// only proceed if there are output ports
|
||||||
if (!nf.Common.isEmpty(processGroupContents.inputPorts)) {
|
if (!nf.Common.isEmpty(options)) {
|
||||||
$('#input-port-destination').show();
|
$('#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
|
// sort the options
|
||||||
options.sort(function (a, b) {
|
options.sort(function (a, b) {
|
||||||
return a.text.localeCompare(b.text);
|
return a.text.localeCompare(b.text);
|
||||||
|
@ -555,7 +558,7 @@ nf.ConnectionConfiguration = (function () {
|
||||||
},
|
},
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function (response) {
|
}).done(function (response) {
|
||||||
var remoteProcessGroup = response.remoteProcessGroup;
|
var remoteProcessGroup = response.component;
|
||||||
var remoteProcessGroupContents = remoteProcessGroup.contents;
|
var remoteProcessGroupContents = remoteProcessGroup.contents;
|
||||||
|
|
||||||
// only proceed if there are output ports
|
// only proceed if there are output ports
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
nf.Funnel = (function () {
|
nf.Funnel = (function () {
|
||||||
|
|
||||||
var dimensions = {
|
var dimensions = {
|
||||||
width: 61,
|
width: 48,
|
||||||
height: 61
|
height: 48
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
@ -51,7 +51,7 @@ nf.Funnel = (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the funnels in the specified selection.
|
* Renders the funnels in the specified selection.
|
||||||
*
|
*
|
||||||
* @param {selection} entered The selection of funnels to be rendered
|
* @param {selection} entered The selection of funnels to be rendered
|
||||||
* @param {boolean} selected Whether the element should be selected
|
* @param {boolean} selected Whether the element should be selected
|
||||||
*/
|
*/
|
||||||
|
@ -61,40 +61,60 @@ nf.Funnel = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
var funnel = entered.append('g')
|
var funnel = entered.append('g')
|
||||||
.attr({
|
.attr({
|
||||||
'id': function (d) {
|
'id': function (d) {
|
||||||
return 'id-' + d.id;
|
return 'id-' + d.id;
|
||||||
},
|
},
|
||||||
'class': 'funnel component'
|
'class': 'funnel component'
|
||||||
})
|
})
|
||||||
.classed('selected', selected)
|
.classed('selected', selected)
|
||||||
.call(nf.CanvasUtils.position);
|
.call(nf.CanvasUtils.position);
|
||||||
|
|
||||||
// funnel border
|
// funnel border
|
||||||
funnel.append('rect')
|
funnel.append('rect')
|
||||||
.attr({
|
.attr({
|
||||||
'class': 'border',
|
'rx': 2,
|
||||||
'width': function (d) {
|
'ry': 2,
|
||||||
return d.dimensions.width;
|
'class': 'border',
|
||||||
},
|
'width': function (d) {
|
||||||
'height': function (d) {
|
return d.dimensions.width;
|
||||||
return d.dimensions.height;
|
},
|
||||||
},
|
'height': function (d) {
|
||||||
'fill': 'transparent',
|
return d.dimensions.height;
|
||||||
'stroke-opacity': 0.8,
|
},
|
||||||
'stroke-width': 1
|
'fill': 'transparent',
|
||||||
});
|
'stroke': 'transparent'
|
||||||
|
}).classed('unauthorized', function (d) {
|
||||||
|
return d.accessPolicy.canRead === false;
|
||||||
|
});
|
||||||
|
|
||||||
// processor icon
|
// funnel body
|
||||||
funnel.append('image')
|
funnel.append('rect')
|
||||||
.call(nf.CanvasUtils.disableImageHref)
|
.attr({
|
||||||
.attr({
|
'rx': 2,
|
||||||
'xlink:href': 'images/iconFunnel.png',
|
'ry': 2,
|
||||||
'width': 41,
|
'class': 'body',
|
||||||
'height': 41,
|
'width': function (d) {
|
||||||
'x': 10,
|
return d.dimensions.width;
|
||||||
'y': 10
|
},
|
||||||
});
|
'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
|
// always support selection
|
||||||
funnel.call(nf.Selectable.activate).call(nf.ContextMenu.activate);
|
funnel.call(nf.Selectable.activate).call(nf.ContextMenu.activate);
|
||||||
|
@ -109,7 +129,7 @@ nf.Funnel = (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the funnels in the specified selection.
|
* Updates the funnels in the specified selection.
|
||||||
*
|
*
|
||||||
* @param {selection} updated The funnels to be updated
|
* @param {selection} updated The funnels to be updated
|
||||||
*/
|
*/
|
||||||
var updateFunnels = function (updated) {
|
var updateFunnels = function (updated) {
|
||||||
|
@ -117,7 +137,7 @@ nf.Funnel = (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the funnels in the specified selection.
|
* Removes the funnels in the specified selection.
|
||||||
*
|
*
|
||||||
* @param {selection} removed The funnels to be removed
|
* @param {selection} removed The funnels to be removed
|
||||||
*/
|
*/
|
||||||
var removeFunnels = function (removed) {
|
var removeFunnels = function (removed) {
|
||||||
|
@ -133,15 +153,15 @@ nf.Funnel = (function () {
|
||||||
|
|
||||||
// create the funnel container
|
// create the funnel container
|
||||||
funnelContainer = d3.select('#canvas').append('g')
|
funnelContainer = d3.select('#canvas').append('g')
|
||||||
.attr({
|
.attr({
|
||||||
'pointer-events': 'all',
|
'pointer-events': 'all',
|
||||||
'class': 'funnels'
|
'class': 'funnels'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the graph with the specified funnels.
|
* Populates the graph with the specified funnels.
|
||||||
*
|
*
|
||||||
* @argument {object | array} funnelEntities The funnels to add
|
* @argument {object | array} funnelEntities The funnels to add
|
||||||
* @argument {boolean} selectAll Whether or not to select the new contents
|
* @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
|
// apply the selection and handle all new processors
|
||||||
select().enter().call(renderFunnels, selectAll);
|
select().enter().call(renderFunnels, selectAll);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the funnel id is specified it is returned. If no funnel id
|
* If the funnel id is specified it is returned. If no funnel id
|
||||||
* specified, all funnels are returned.
|
* specified, all funnels are returned.
|
||||||
*
|
*
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
*/
|
*/
|
||||||
get: function (id) {
|
get: function (id) {
|
||||||
|
@ -182,11 +202,11 @@ nf.Funnel = (function () {
|
||||||
return funnelMap.get(id);
|
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.
|
* state. If not funnel id is specified, all funnels are refreshed.
|
||||||
*
|
*
|
||||||
* @param {string} id Optional
|
* @param {string} id Optional
|
||||||
*/
|
*/
|
||||||
refresh: function (id) {
|
refresh: function (id) {
|
||||||
|
@ -196,11 +216,11 @@ nf.Funnel = (function () {
|
||||||
d3.selectAll('g.funnel').call(updateFunnels);
|
d3.selectAll('g.funnel').call(updateFunnels);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the funnel state from the server and refreshes the UI.
|
* Reloads the funnel state from the server and refreshes the UI.
|
||||||
* If the funnel is currently unknown, this function just returns.
|
* If the funnel is currently unknown, this function just returns.
|
||||||
*
|
*
|
||||||
* @param {object} funnel The funnel to reload
|
* @param {object} funnel The funnel to reload
|
||||||
*/
|
*/
|
||||||
reload: function (funnel) {
|
reload: function (funnel) {
|
||||||
|
@ -214,21 +234,21 @@ nf.Funnel = (function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Positions the component.
|
* Positions the component.
|
||||||
*
|
*
|
||||||
* @param {string} id The id
|
* @param {string} id The id
|
||||||
*/
|
*/
|
||||||
position: function (id) {
|
position: function (id) {
|
||||||
d3.select('#id-' + id).call(nf.CanvasUtils.position);
|
d3.select('#id-' + id).call(nf.CanvasUtils.position);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the specified funnel(s). If the is an array, it
|
* Sets the specified funnel(s). If the is an array, it
|
||||||
* will set each funnel. If it is not an array, it will
|
* will set each funnel. If it is not an array, it will
|
||||||
* attempt to set the specified funnel.
|
* attempt to set the specified funnel.
|
||||||
*
|
*
|
||||||
* @param {object | array} funnelEntities
|
* @param {object | array} funnelEntities
|
||||||
*/
|
*/
|
||||||
set: function (funnelEntities) {
|
set: function (funnelEntities) {
|
||||||
|
@ -237,7 +257,7 @@ nf.Funnel = (function () {
|
||||||
// update the current entry
|
// update the current entry
|
||||||
var funnelEntry = funnelMap.get(funnelEntity.id);
|
var funnelEntry = funnelMap.get(funnelEntity.id);
|
||||||
$.extend(funnelEntry, funnelEntity);
|
$.extend(funnelEntry, funnelEntity);
|
||||||
|
|
||||||
// update the connection in the UI
|
// update the connection in the UI
|
||||||
d3.select('#id-' + funnelEntity.id).call(updateFunnels);
|
d3.select('#id-' + funnelEntity.id).call(updateFunnels);
|
||||||
}
|
}
|
||||||
|
@ -255,7 +275,7 @@ nf.Funnel = (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the specified funnel.
|
* Removes the specified funnel.
|
||||||
*
|
*
|
||||||
* @param {array|string} funnels The funnel id
|
* @param {array|string} funnels The funnel id
|
||||||
*/
|
*/
|
||||||
remove: function (funnels) {
|
remove: function (funnels) {
|
||||||
|
@ -270,7 +290,7 @@ nf.Funnel = (function () {
|
||||||
// apply the selection and handle all removed funnels
|
// apply the selection and handle all removed funnels
|
||||||
select().exit().call(removeFunnels);
|
select().exit().call(removeFunnels);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all processors.
|
* Removes all processors.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -53,7 +53,9 @@ nf.Label = (function () {
|
||||||
* Selects the labels elements against the current label map.
|
* Selects the labels elements against the current label map.
|
||||||
*/
|
*/
|
||||||
var select = function () {
|
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;
|
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
|
// update the border using the configured color
|
||||||
updated.select('rect.border')
|
updated.select('rect.border')
|
||||||
.attr({
|
.attr({
|
||||||
|
@ -177,10 +164,7 @@ nf.Label = (function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get just the color code part
|
return color;
|
||||||
color = nf.Common.substringAfterLast(color, '#');
|
|
||||||
|
|
||||||
return 'url(#label-background-' + color + ')';
|
|
||||||
},
|
},
|
||||||
'width': function (d) {
|
'width': function (d) {
|
||||||
return d.dimensions.width;
|
return d.dimensions.width;
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
nf.Port = (function () {
|
nf.Port = (function () {
|
||||||
|
|
||||||
var PREVIEW_NAME_LENGTH = 15;
|
var PREVIEW_NAME_LENGTH = 15;
|
||||||
var OFFSET_VALUE = 12;
|
var OFFSET_VALUE = 25;
|
||||||
|
|
||||||
var portDimensions = {
|
var portDimensions = {
|
||||||
width: 160,
|
width: 240,
|
||||||
height: 40
|
height: 50
|
||||||
};
|
};
|
||||||
var remotePortDimensions = {
|
var remotePortDimensions = {
|
||||||
width: 160,
|
width: 240,
|
||||||
height: 56
|
height: 75
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
@ -51,7 +51,9 @@ nf.Port = (function () {
|
||||||
* Selects the port elements against the current port map.
|
* Selects the port elements against the current port map.
|
||||||
*/
|
*/
|
||||||
var select = function () {
|
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')
|
var port = entered.append('g')
|
||||||
.attr({
|
.attr({
|
||||||
'id': function (d) {
|
'id': function (d) {
|
||||||
return 'id-' + d.id;
|
return 'id-' + d.id;
|
||||||
},
|
},
|
||||||
'class': function (d) {
|
'class': function (d) {
|
||||||
if (d.portType === 'INPUT_PORT') {
|
if (d.portType === 'INPUT_PORT') {
|
||||||
return 'input-port component';
|
return 'input-port component';
|
||||||
} else {
|
} else {
|
||||||
return 'output-port component';
|
return 'output-port component';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.classed('selected', selected)
|
})
|
||||||
.call(nf.CanvasUtils.position);
|
.classed('selected', selected)
|
||||||
|
.call(nf.CanvasUtils.position);
|
||||||
|
|
||||||
// port border
|
// port border
|
||||||
port.append('rect')
|
port.append('rect')
|
||||||
.attr({
|
.attr({
|
||||||
'class': 'border',
|
'class': 'border',
|
||||||
'width': function (d) {
|
'width': function (d) {
|
||||||
return d.dimensions.width;
|
return d.dimensions.width;
|
||||||
},
|
},
|
||||||
'height': function (d) {
|
'height': function (d) {
|
||||||
return d.dimensions.height;
|
return d.dimensions.height;
|
||||||
},
|
},
|
||||||
'fill': 'transparent',
|
'fill': 'transparent',
|
||||||
'stroke-opacity': 0.8,
|
'stroke': 'transparent'
|
||||||
'stroke-width': 1,
|
})
|
||||||
'stroke': '#aaaaaa'
|
.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;
|
var offset = 0;
|
||||||
|
|
||||||
|
@ -105,84 +125,47 @@ nf.Port = (function () {
|
||||||
|
|
||||||
// port remote banner
|
// port remote banner
|
||||||
port.append('rect')
|
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({
|
.attr({
|
||||||
'x': 0,
|
'class': 'remote-banner',
|
||||||
'y': offset,
|
|
||||||
'class': 'port-body',
|
|
||||||
'width': function (d) {
|
'width': function (d) {
|
||||||
return d.dimensions.width;
|
return d.dimensions.width;
|
||||||
},
|
},
|
||||||
'height': function (d) {
|
'height': offset,
|
||||||
return d.dimensions.height - offset;
|
'fill': '#e3e8eb'
|
||||||
},
|
|
||||||
'fill': 'url(#port-background)',
|
|
||||||
'fill-opacity': 0.8,
|
|
||||||
'stroke-opacity': 0.8,
|
|
||||||
'stroke-width': 0,
|
|
||||||
'stroke': '#aaaaaa'
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// port icon
|
// port icon
|
||||||
port.append('image')
|
port.append('text')
|
||||||
.call(nf.CanvasUtils.disableImageHref)
|
.attr({
|
||||||
.attr({
|
'class': 'port-icon',
|
||||||
'xlink:href': function (d) {
|
'x': 10,
|
||||||
if (d.portTtype === 'INPUT_PORT') {
|
'y': 38 + offset
|
||||||
return 'images/iconInputPort.png';
|
})
|
||||||
} else {
|
.text(function (d) {
|
||||||
return 'images/iconOutputPort.png';
|
if (d.portType === 'INPUT_PORT') {
|
||||||
}
|
return '\ue832';
|
||||||
},
|
} else {
|
||||||
'width': 46,
|
return '\ue833';
|
||||||
'height': 31,
|
}
|
||||||
'x': function (d) {
|
});
|
||||||
if (d.portType === 'INPUT_PORT') {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 114;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'y': 5 + offset
|
|
||||||
});
|
|
||||||
|
|
||||||
// port name
|
// port name
|
||||||
port.append('text')
|
port.append('text')
|
||||||
.attr({
|
.attr({
|
||||||
'x': function (d) {
|
'x': 70,
|
||||||
if (d.portType === 'INPUT_PORT') {
|
'y': 25 + offset,
|
||||||
return 52;
|
'width': 95,
|
||||||
} else {
|
'height': 30,
|
||||||
return 5;
|
'class': 'port-name'
|
||||||
}
|
});
|
||||||
},
|
|
||||||
'y': 18 + offset,
|
|
||||||
'width': 95,
|
|
||||||
'height': 30,
|
|
||||||
'font-size': '10px',
|
|
||||||
'font-weight': 'bold',
|
|
||||||
'fill': '#294c58',
|
|
||||||
'class': 'port-name'
|
|
||||||
});
|
|
||||||
|
|
||||||
// make ports selectable
|
// make ports selectable
|
||||||
port.call(nf.Selectable.activate).call(nf.ContextMenu.activate);
|
port.call(nf.Selectable.activate).call(nf.ContextMenu.activate);
|
||||||
|
|
||||||
// only activate dragging and connecting if appropriate
|
// only activate dragging and connecting if appropriate
|
||||||
port.filter(function (d) {
|
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(nf.Draggable.activate).call(nf.Connectable.activate);
|
||||||
|
|
||||||
// call update to trigger some rendering
|
// call update to trigger some rendering
|
||||||
|
@ -213,132 +196,85 @@ nf.Port = (function () {
|
||||||
offset = OFFSET_VALUE;
|
offset = OFFSET_VALUE;
|
||||||
|
|
||||||
// port transmitting icon
|
// port transmitting icon
|
||||||
details.append('image')
|
details.append('text')
|
||||||
.call(nf.CanvasUtils.disableImageHref)
|
.attr({
|
||||||
.attr({
|
'class': 'port-transmission-icon',
|
||||||
'class': 'port-transmission-icon',
|
'x': 10,
|
||||||
'width': 10,
|
'y': 15
|
||||||
'height': 10,
|
});
|
||||||
'x': 3,
|
|
||||||
'y': 1
|
// bulletin background
|
||||||
});
|
details.append('rect')
|
||||||
|
.attr({
|
||||||
|
'class': 'bulletin-background',
|
||||||
|
'x': function (d) {
|
||||||
|
return portData.dimensions.width - offset;
|
||||||
|
},
|
||||||
|
'width': offset,
|
||||||
|
'height': offset
|
||||||
|
});
|
||||||
|
|
||||||
// bulletin icon
|
// bulletin icon
|
||||||
details.append('image')
|
details.append('text')
|
||||||
.call(nf.CanvasUtils.disableImageHref)
|
.attr({
|
||||||
.attr({
|
'class': 'bulletin-icon',
|
||||||
'class': 'bulletin-icon',
|
'x': function (d) {
|
||||||
'xlink:href': 'images/iconBulletin.png',
|
return portData.dimensions.width - 18;
|
||||||
'width': 12,
|
},
|
||||||
'height': 12,
|
'y': 18
|
||||||
'x': 147,
|
})
|
||||||
'y': 0
|
.text('\uf24a');
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// run status icon
|
// 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')
|
details.append('text')
|
||||||
.attr({
|
.attr({
|
||||||
'class': 'active-thread-count',
|
'class': 'run-status-icon',
|
||||||
'height': 11,
|
'x': 50,
|
||||||
'y': 9,
|
'y': function () {
|
||||||
'fill': '#000'
|
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) {
|
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 $('<div></div>').append(list).html();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// add the tooltip
|
|
||||||
nf.CanvasUtils.canvasTooltip(tip, d3.select(this));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// update the port name
|
// update the port name
|
||||||
port.select('text.port-name')
|
port.select('text.port-name')
|
||||||
.each(function (d) {
|
.each(function (d) {
|
||||||
var portName = d3.select(this);
|
var portName = d3.select(this);
|
||||||
var name = d.component.name;
|
var name = d.component.name;
|
||||||
var words = name.split(/\s+/);
|
var words = name.split(/\s+/);
|
||||||
|
|
||||||
// reset the port name to handle any previous state
|
// reset the port name to handle any previous state
|
||||||
portName.text(null).selectAll('tspan, title').remove();
|
portName.text(null).selectAll('tspan, title').remove();
|
||||||
|
|
||||||
// handle based on the number of tokens in the port name
|
// handle based on the number of tokens in the port name
|
||||||
if (words.length === 1) {
|
if (words.length === 1) {
|
||||||
// apply ellipsis to the port name as necessary
|
// apply ellipsis to the port name as necessary
|
||||||
nf.CanvasUtils.ellipsis(portName, name);
|
nf.CanvasUtils.ellipsis(portName, name);
|
||||||
} else {
|
} else {
|
||||||
nf.CanvasUtils.multilineEllipsis(portName, 2, name);
|
nf.CanvasUtils.multilineEllipsis(portName, 2, name);
|
||||||
}
|
}
|
||||||
}).append('title').text(function (d) {
|
}).append('title').text(function (d) {
|
||||||
return d.component.name;
|
return d.component.name;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -349,14 +285,14 @@ nf.Port = (function () {
|
||||||
if (portData.accessPolicy.canRead) {
|
if (portData.accessPolicy.canRead) {
|
||||||
// update the port name
|
// update the port name
|
||||||
port.select('text.port-name')
|
port.select('text.port-name')
|
||||||
.text(function (d) {
|
.text(function (d) {
|
||||||
var name = d.component.name;
|
var name = d.component.name;
|
||||||
if (name.length > PREVIEW_NAME_LENGTH) {
|
if (name.length > PREVIEW_NAME_LENGTH) {
|
||||||
return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230);
|
return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230);
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove tooltips if necessary
|
// remove tooltips if necessary
|
||||||
|
@ -372,7 +308,7 @@ nf.Port = (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the port status.
|
* Updates the port status.
|
||||||
*
|
*
|
||||||
* @param {selection} updated The ports to be updated
|
* @param {selection} updated The ports to be updated
|
||||||
*/
|
*/
|
||||||
var updatePortStatus = function (updated) {
|
var updatePortStatus = function (updated) {
|
||||||
|
@ -380,14 +316,82 @@ nf.Port = (function () {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated.select('image.port-transmission-icon')
|
// update the run status
|
||||||
.attr('xlink:href', function (d) {
|
updated.select('text.run-status-icon')
|
||||||
if (d.status.transmitting === true) {
|
.attr({
|
||||||
return 'images/iconPortTransmitting.png';
|
'fill': function (d) {
|
||||||
} else {
|
var fill = '#728e9b';
|
||||||
return 'images/iconPortNotTransmitting.png';
|
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 $('<div></div>').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) {
|
updated.each(function (d) {
|
||||||
var port = d3.select(this);
|
var port = d3.select(this);
|
||||||
|
@ -405,6 +409,10 @@ nf.Port = (function () {
|
||||||
// bulletins
|
// 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 () {
|
nf.CanvasUtils.bulletins(port, d, function () {
|
||||||
return d3.select('#port-tooltips');
|
return d3.select('#port-tooltips');
|
||||||
}, offset);
|
}, offset);
|
||||||
|
@ -426,7 +434,7 @@ nf.Port = (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the tooltips for the ports in the specified selection.
|
* Removes the tooltips for the ports in the specified selection.
|
||||||
*
|
*
|
||||||
* @param {selection} removed
|
* @param {selection} removed
|
||||||
*/
|
*/
|
||||||
var removeTooltips = function (removed) {
|
var removeTooltips = function (removed) {
|
||||||
|
@ -446,12 +454,12 @@ nf.Port = (function () {
|
||||||
|
|
||||||
// create the port container
|
// create the port container
|
||||||
portContainer = d3.select('#canvas').append('g')
|
portContainer = d3.select('#canvas').append('g')
|
||||||
.attr({
|
.attr({
|
||||||
'pointer-events': 'all',
|
'pointer-events': 'all',
|
||||||
'class': 'ports'
|
'class': 'ports'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the graph with the specified ports.
|
* Populates the graph with the specified ports.
|
||||||
*
|
*
|
||||||
|
@ -490,7 +498,7 @@ nf.Port = (function () {
|
||||||
// apply the selection and handle all new ports
|
// apply the selection and handle all new ports
|
||||||
select().enter().call(renderPorts, selectAll);
|
select().enter().call(renderPorts, selectAll);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the port id is specified it is returned. If no port id
|
* If the port id is specified it is returned. If no port id
|
||||||
* specified, all ports are returned.
|
* specified, all ports are returned.
|
||||||
|
@ -504,7 +512,7 @@ nf.Port = (function () {
|
||||||
return portMap.get(id);
|
return portMap.get(id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the port id is specified it is refresh according to the current
|
* If the port id is specified it is refresh according to the current
|
||||||
* state. If not port id is specified, all ports are refreshed.
|
* 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);
|
d3.selectAll('g.input-port, g.output-port').call(updatePorts);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the components necessary after a pan event.
|
* Refreshes the components necessary after a pan event.
|
||||||
*/
|
*/
|
||||||
pan: function () {
|
pan: function () {
|
||||||
d3.selectAll('g.input-port.entering, g.output-port.entering, g.input-port.leaving, g.output-port.leaving').call(updatePorts);
|
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.
|
* Reloads the port state from the server and refreshes the UI.
|
||||||
* If the port is currently unknown, this function just returns.
|
* If the port is currently unknown, this function just returns.
|
||||||
|
@ -547,16 +555,16 @@ nf.Port = (function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Positions the component.
|
* Positions the component.
|
||||||
*
|
*
|
||||||
* @param {string} id The id
|
* @param {string} id The id
|
||||||
*/
|
*/
|
||||||
position: function (id) {
|
position: function (id) {
|
||||||
d3.select('#id-' + id).call(nf.CanvasUtils.position);
|
d3.select('#id-' + id).call(nf.CanvasUtils.position);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the specified port(s). If the is an array, it
|
* Sets the specified port(s). If the is an array, it
|
||||||
* will set each port. If it is not an array, it will
|
* will set each port. If it is not an array, it will
|
||||||
|
@ -585,10 +593,10 @@ nf.Port = (function () {
|
||||||
set(portEntities);
|
set(portEntities);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the port status using the specified status.
|
* Sets the port status using the specified status.
|
||||||
*
|
*
|
||||||
* @param {array} portStatus Port status
|
* @param {array} portStatus Port status
|
||||||
*/
|
*/
|
||||||
setStatus: function (portStatus) {
|
setStatus: function (portStatus) {
|
||||||
|
@ -625,7 +633,7 @@ nf.Port = (function () {
|
||||||
// apply the selection and handle all removed ports
|
// apply the selection and handle all removed ports
|
||||||
select().exit().call(removePorts);
|
select().exit().call(removePorts);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all ports..
|
* Removes all ports..
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -722,6 +722,43 @@ nf.Common = (function () {
|
||||||
return result;
|
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.
|
* Updates the mouse pointer.
|
||||||
*
|
*
|
||||||
|
|