NIFI-1781:

- Incorporating updated styles to reflect component level authorization.
- Updating canvas for new look and feel.
- This closes #417
This commit is contained in:
Matt Gilman 2016-05-06 13:30:49 -04:00
parent 04c41c0654
commit 9db1def6c6
60 changed files with 2992 additions and 2683 deletions

View File

@ -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;
}
}

View File

@ -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) + ")";
}
}

View File

@ -85,7 +85,7 @@
<md-menu-item layout-align="space-around center">
<a id="bulletin-board-link"
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-divider></md-menu-divider>
<md-menu-item

View File

@ -32,7 +32,7 @@
<div layout="row" layout-align="end center">
<input id="search-field" type="text"/>
<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 id="search-flow-results"></div>

View File

@ -78,7 +78,7 @@
background-color:#728E9B; /*base-color*/
}
#bulletin-button i{
#bulletin-button i.fa {
color: #fff;
font-size:15px;
}

View File

@ -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;
}

View File

@ -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{

View File

@ -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'),

View File

@ -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);
});
}
});

View File

@ -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');
}
},

View File

@ -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.
*

View File

@ -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;
// only proceed if there are output ports
if (!nf.Common.isEmpty(processGroupContents.outputPorts)) {
$('#output-port-source').show();
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: outputPort.name,
value: outputPort.id,
description: nf.Common.escapeHtml(outputPort.comments)
text: component.name,
value: component.id,
description: nf.Common.escapeHtml(component.comments)
});
}
});
// only proceed if there are output ports
if (!nf.Common.isEmpty(options)) {
$('#output-port-source').show();
// 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;
// only proceed if there are output ports
if (!nf.Common.isEmpty(processGroupContents.inputPorts)) {
$('#input-port-destination').show();
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: inputPort.name,
value: inputPort.id,
description: nf.Common.escapeHtml(inputPort.comments)
text: component.name,
value: component.id,
description: nf.Common.escapeHtml(component.comments)
});
}
});
// only proceed if there are output ports
if (!nf.Common.isEmpty(options)) {
$('#input-port-destination').show();
// 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

View File

@ -21,7 +21,7 @@ nf.Connection = (function () {
// the dimensions for the connection label
var dimensions = {
width: 188
width: 200
};
/**
@ -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) {
@ -245,6 +247,9 @@ nf.Connection = (function () {
.attr({
'class': 'connection-path',
'pointer-events': 'none'
})
.classed('unauthorized', function (d) {
return d.accessPolicy.canRead === false;
});
// path to show when selection
@ -451,6 +456,8 @@ nf.Connection = (function () {
if (hasUnavailableRelationship(d)) {
marker = 'ghost';
}
} else {
marker = 'unauthorized';
}
return 'url(#' + marker + ')';
@ -476,6 +483,7 @@ nf.Connection = (function () {
// -----
if (d.accessPolicy.canWrite) {
// ------------------
// bends - startpoint
// ------------------
@ -635,14 +643,33 @@ nf.Connection = (function () {
// connection label
connectionLabelContainer.append('rect')
.attr({
'class': 'connection-label',
'class': 'body',
'width': dimensions.width,
'x': 0,
'y': 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) {
@ -661,37 +688,53 @@ nf.Connection = (function () {
'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
'class': 'stats-label',
'x': 5,
'y': 14
})
.text('From');
connectionFrom.append('text')
.attr({
'class': 'connection-stats-value connection-from',
'x': 33,
'y': 10,
'class': 'stats-value connection-from',
'x': 43,
'y': 14,
'width': 130
});
connectionFrom.append('image')
.call(nf.CanvasUtils.disableImageHref)
connectionFrom.append('text')
.attr({
'class': 'connection-from-run-status',
'width': 10,
'height': 10,
'x': 167,
'y': 1
'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
@ -709,14 +752,18 @@ nf.Connection = (function () {
});
// update the label run status
connectionFrom.select('image.connection-from-run-status').attr('xlink:href', function () {
connectionFrom.select('text.connection-from-run-status')
.text(function () {
if (d.component.source.exists === false) {
return 'images/portRemoved.png';
return '\uf071';
} else if (d.component.source.running === true) {
return 'images/portRunning.png';
return '\uf04b';
} else {
return 'images/portStopped.png';
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
@ -741,37 +788,53 @@ nf.Connection = (function () {
'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
'class': 'stats-label',
'x': 5,
'y': 14
})
.text('To');
connectionTo.append('text')
.attr({
'class': 'connection-stats-value connection-to',
'x': 18,
'y': 10,
'class': 'stats-value connection-to',
'x': 25,
'y': 14,
'width': 145
});
connectionTo.append('image')
.call(nf.CanvasUtils.disableImageHref)
connectionTo.append('text')
.attr({
'class': 'connection-to-run-status',
'width': 10,
'height': 10,
'x': 167,
'y': 1
'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
@ -789,14 +852,18 @@ nf.Connection = (function () {
});
// update the label run status
connectionTo.select('image.connection-to-run-status').attr('xlink:href', function () {
connectionTo.select('text.connection-to-run-status')
.text(function () {
if (d.component.destination.exists === false) {
return 'images/portRemoved.png';
return '\uf071';
} else if (d.component.destination.running === true) {
return 'images/portRunning.png';
return '\uf04b';
} else {
return 'images/portStopped.png';
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
@ -823,27 +890,46 @@ nf.Connection = (function () {
'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
'class': 'stats-label',
'x': 5,
'y': 14
})
.text('Name');
connectionName.append('text')
.attr({
'class': 'connection-stats-value connection-name',
'x': 35,
'y': 10,
'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
@ -880,19 +966,47 @@ nf.Connection = (function () {
'class': 'queued-container'
});
queued.append('text')
// background
backgrounds.push(queued.append('rect')
.attr({
'class': 'connection-stats-label',
'x': 0,
'y': 10
})
.text('Queued');
'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')
@ -932,18 +1046,43 @@ nf.Connection = (function () {
});
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')
connectionLabelContainer.select('rect.body')
.attr('height', function () {
return 5 + (15 * labelCount) + 3;
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) {
@ -974,7 +1113,7 @@ 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 label = d3.select(this).select('rect.body');
var position = getLabelPosition(label);
return 'translate(' + position.x + ', ' + position.y + ')';
});
@ -991,12 +1130,23 @@ nf.Connection = (function () {
return;
}
updated.select('text.queued')
// queued count value
updated.select('text.queued tspan.count')
.text(function (d) {
if (nf.Common.isDefinedAndNotNull(d.status)) {
return d.status.queued;
return nf.Common.substringBeforeFirst(d.status.queued, ' ');
} else {
return '- / -';
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 ' (-)';
}
});
};
@ -1264,7 +1414,7 @@ nf.Connection = (function () {
// lazily create the drag selection box
if (drag.empty()) {
var connectionLabel = d3.select(this).select('rect.connection-label');
var connectionLabel = d3.select(this).select('rect.body');
var position = getLabelPosition(connectionLabel);
var width = dimensions.width;
@ -1272,8 +1422,6 @@ nf.Connection = (function () {
// 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')

View File

@ -20,8 +20,8 @@
nf.Funnel = (function () {
var dimensions = {
width: 61,
height: 61
width: 48,
height: 48
};
// -----------------------------
@ -73,6 +73,8 @@ nf.Funnel = (function () {
// funnel border
funnel.append('rect')
.attr({
'rx': 2,
'ry': 2,
'class': 'border',
'width': function (d) {
return d.dimensions.width;
@ -81,21 +83,39 @@ nf.Funnel = (function () {
return d.dimensions.height;
},
'fill': 'transparent',
'stroke-opacity': 0.8,
'stroke-width': 1
'stroke': 'transparent'
}).classed('unauthorized', function (d) {
return d.accessPolicy.canRead === false;
});
// processor icon
funnel.append('image')
.call(nf.CanvasUtils.disableImageHref)
// funnel body
funnel.append('rect')
.attr({
'xlink:href': 'images/iconFunnel.png',
'width': 41,
'height': 41,
'x': 10,
'y': 10
'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);

View File

@ -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;

View File

@ -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;
});
};
/**
@ -92,9 +94,27 @@ nf.Port = (function () {
return d.dimensions.height;
},
'fill': 'transparent',
'stroke-opacity': 0.8,
'stroke-width': 1,
'stroke': '#aaaaaa'
'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;
@ -111,69 +131,32 @@ nf.Port = (function () {
return d.dimensions.width;
},
'height': offset,
'fill': '#294c58',
'fill-opacity': 0.95
'fill': '#e3e8eb'
});
}
// port body
port.append('rect')
.attr({
'x': 0,
'y': offset,
'class': 'port-body',
'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'
});
// port icon
port.append('image')
.call(nf.CanvasUtils.disableImageHref)
port.append('text')
.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) {
'class': 'port-icon',
'x': 10,
'y': 38 + offset
})
.text(function (d) {
if (d.portType === 'INPUT_PORT') {
return 0;
return '\ue832';
} else {
return 114;
return '\ue833';
}
},
'y': 5 + offset
});
// port name
port.append('text')
.attr({
'x': function (d) {
if (d.portType === 'INPUT_PORT') {
return 52;
} else {
return 5;
}
},
'y': 18 + offset,
'x': 70,
'y': 25 + offset,
'width': 95,
'height': 30,
'font-size': '10px',
'font-weight': 'bold',
'fill': '#294c58',
'class': 'port-name'
});
@ -213,114 +196,67 @@ nf.Port = (function () {
offset = OFFSET_VALUE;
// port transmitting icon
details.append('image')
.call(nf.CanvasUtils.disableImageHref)
details.append('text')
.attr({
'class': 'port-transmission-icon',
'width': 10,
'height': 10,
'x': 3,
'y': 1
'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)
details.append('text')
.attr({
'class': 'bulletin-icon',
'xlink:href': 'images/iconBulletin.png',
'width': 12,
'height': 12,
'x': 147,
'y': 0
});
'x': function (d) {
return portData.dimensions.width - 18;
},
'y': 18
})
.text('\uf24a');
}
// run status icon
details.append('image')
.call(nf.CanvasUtils.disableImageHref)
details.append('text')
.attr({
'class': 'port-run-status-icon',
'width': 16,
'height': 16,
'x': function (d) {
if (d.portType === 'INPUT_PORT') {
return 33;
} else {
return 107;
}
},
'class': 'run-status-icon',
'x': 50,
'y': function () {
return 24 + offset;
return 25 + offset;
}
});
// -------------------
// active thread count
// -------------------
// active thread count
details.append('rect')
details.append('text')
.attr({
'class': 'active-thread-count-background',
'height': 11,
'y': 0,
'fill': '#fff',
'fill-opacity': '0.65',
'stroke': '#aaa',
'stroke-width': '1'
});
'class': 'active-thread-count-icon',
'y': 68
})
.text('\ue83f');
// active thread bacground
// active thread icon
details.append('text')
.attr({
'class': 'active-thread-count',
'height': 11,
'y': 9,
'fill': '#000'
'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 $('<div></div>').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) {
@ -380,12 +316,80 @@ nf.Port = (function () {
return;
}
updated.select('image.port-transmission-icon')
.attr('xlink:href', function (d) {
if (d.status.transmitting === true) {
return 'images/iconPortTransmitting.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 'images/iconPortNotTransmitting.png';
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';
}
});
@ -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);

View File

@ -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
@ -77,8 +79,10 @@ nf.Processor = (function () {
return d.dimensions.height;
},
'fill': 'transparent',
'stroke-opacity': 0.8,
'stroke-width': 1
'stroke': 'transparent'
})
.classed('unauthorized', function (d) {
return d.accessPolicy.canRead === false;
});
// processor body
@ -91,40 +95,36 @@ nf.Processor = (function () {
'height': function (d) {
return d.dimensions.height;
},
'fill-opacity': 0.8,
'stroke-opacity': 0.8,
'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,
'x': 62,
'y': 20,
'width': 220,
'height': 16,
'font-size': '10pt',
'font-weight': 'bold',
'fill': 'black',
'class': 'processor-name'
});
// processor icon
processor.append('image')
.call(nf.CanvasUtils.disableImageHref)
processor.append('text')
.attr({
'xlink:href': 'images/iconProcessor.png',
'width': 28,
'height': 26,
'x': 276,
'y': 5
});
'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,
@ -156,35 +156,30 @@ 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)
details.append('text')
.attr({
'class': 'run-status-icon',
'width': 16,
'height': 16,
'x': 5,
'y': 5
'x': 42,
'y': 20
});
if (processorData.accessPolicy.canRead) {
// processor type
details.append('text')
.attr({
'x': 25,
'y': 30,
'class': 'processor-type',
'x': 62,
'y': 35,
'width': 246,
'height': 16,
'font-size': '8pt',
'font-weight': 'normal',
'fill': 'black'
'height': 16
})
.each(function (d) {
var processorType = d3.select(this);
@ -204,32 +199,95 @@ nf.Processor = (function () {
// -----
// draw the processor statistics table
// in
details.append('rect')
.attr({
'width': 294,
'height': 59,
'x': 8,
'y': 35,
'fill': '#ffffff',
'stroke-width': 1,
'stroke': '#6f97ac',
'stroke-opacity': 0.8
'width': function () {
return processorData.dimensions.width;
},
'height': 19,
'x': 0,
'y': 50,
'fill': '#f4f6f7'
});
// border
details.append('rect')
.attr({
'width': 73,
'height': 59,
'x': 8,
'y': 35,
'fill': 'url(#processor-stats-background)',
'stroke-width': 0
'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)'
'transform': 'translate(10, 55)'
});
// in label
@ -237,9 +295,8 @@ nf.Processor = (function () {
.attr({
'width': 73,
'height': 10,
'x': 4,
'y': 4,
'class': 'processor-stats-label'
'y': 9,
'class': 'stats-label'
})
.text('In');
@ -248,9 +305,8 @@ nf.Processor = (function () {
.attr({
'width': 73,
'height': 10,
'x': 4,
'y': 17,
'class': 'processor-stats-label'
'y': 27,
'class': 'stats-label'
})
.text('Read/Write');
@ -259,9 +315,8 @@ nf.Processor = (function () {
.attr({
'width': 73,
'height': 10,
'x': 4,
'y': 30,
'class': 'processor-stats-label'
'y': 46,
'class': 'stats-label'
})
.text('Out');
@ -270,26 +325,36 @@ nf.Processor = (function () {
.attr({
'width': 73,
'height': 10,
'x': 4,
'y': 43,
'class': 'processor-stats-label'
'y': 65,
'class': 'stats-label'
})
.text('Tasks/Time');
// stats value container
var processorStatsValue = details.append('g')
.attr({
'transform': 'translate(80, 45)'
'transform': 'translate(85, 55)'
});
// in value
processorStatsValue.append('text')
var inText = processorStatsValue.append('text')
.attr({
'width': 180,
'height': 10,
'x': 4,
'y': 4,
'class': 'processor-in processor-stats-value'
'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
@ -297,19 +362,29 @@ nf.Processor = (function () {
.attr({
'width': 180,
'height': 10,
'x': 4,
'y': 17,
'class': 'processor-read-write processor-stats-value'
'y': 27,
'class': 'processor-read-write stats-value'
});
// out value
processorStatsValue.append('text')
var outText = processorStatsValue.append('text')
.attr({
'width': 180,
'height': 10,
'x': 4,
'y': 30,
'class': 'processor-out processor-stats-value'
'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
@ -317,145 +392,101 @@ nf.Processor = (function () {
.attr({
'width': 180,
'height': 10,
'x': 4,
'y': 43,
'class': 'processor-tasks-time processor-stats-value'
'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'
'y': 9,
'class': 'stats-info'
})
.text('(5 min)');
.text('5 min');
// read/write info
processorStatsInfo.append('text')
.attr({
'width': 25,
'height': 10,
'x': 4,
'y': 17,
'class': 'processor-stats-info'
'y': 27,
'class': 'stats-info'
})
.text('(5 min)');
.text('5 min');
// out info
processorStatsInfo.append('text')
.attr({
'width': 25,
'height': 10,
'x': 4,
'y': 30,
'class': 'processor-stats-info'
'y': 46,
'class': 'stats-info'
})
.text('(5 min)');
.text('5 min');
// tasks/time info
processorStatsInfo.append('text')
.attr({
'width': 25,
'height': 10,
'x': 4,
'y': 43,
'class': 'processor-stats-info'
'y': 65,
'class': 'stats-info'
})
.text('(5 min)');
.text('5 min');
// -------------------
// active thread count
// -------------------
// active thread count
details.append('rect')
details.append('text')
.attr({
'class': 'active-thread-count-background',
'height': 13,
'y': 0,
'fill': '#fff',
'fill-opacity': '0.65',
'stroke': '#aaa',
'stroke-width': '1'
});
'class': 'active-thread-count-icon',
'y': 42
})
.text('\ue83f');
// active thread bacground
// active thread background
details.append('text')
.attr({
'class': 'active-thread-count',
'height': 13,
'y': 10,
'fill': '#000'
'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)
details.append('text')
.attr({
'class': 'bulletin-icon',
'xlink:href': 'images/iconBulletin.png',
'width': 12,
'height': 12,
'x': 8,
'y': 20
});
'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 $('<div></div>').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) {
@ -503,28 +534,13 @@ 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) {
updated.select('rect.body')
.style('fill', function (d) {
var color = nf.Processor.defaultColor();
if (d.accessPolicy.canRead) {
@ -536,23 +552,6 @@ nf.Processor = (function () {
return color;
});
updated.select('rect.body')
.attr('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'];
}
}
// get just the color code part
color = nf.Common.substringAfterLast(color, '#');
return 'url(#processor-background-' + color + ')';
});
};
/**
@ -565,13 +564,82 @@ nf.Processor = (function () {
return;
}
// in value
updated.select('text.processor-in')
// 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 $('<div></div>').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 d.status.input;
return nf.Common.substringBeforeFirst(d.status.input, ' ');
} else {
return '- / -';
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 ' (-)';
}
});
@ -585,13 +653,23 @@ nf.Processor = (function () {
}
});
// out value
updated.select('text.processor-out')
// out count value
updated.select('text.processor-out tspan.count')
.text(function (d) {
if (nf.Common.isDefinedAndNotNull(d.status)) {
return d.status.output;
return nf.Common.substringBeforeFirst(d.status.output, ' ');
} else {
return '- / -';
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 ' (-)';
}
});
@ -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);
@ -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';
}
};
}());

View File

@ -22,8 +22,8 @@ nf.RemoteProcessGroup = (function () {
var PREVIEW_NAME_LENGTH = 30;
var dimensions = {
width: 365,
height: 140
width: 380,
height: 158
};
// --------------------------------------------
@ -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;
});
};
/**
@ -90,8 +92,6 @@ nf.RemoteProcessGroup = (function () {
// remote process group border
remoteProcessGroup.append('rect')
.attr({
'rx': 6,
'ry': 6,
'class': 'border',
'width': function (d) {
return d.dimensions.width;
@ -100,16 +100,15 @@ nf.RemoteProcessGroup = (function () {
return d.dimensions.height;
},
'fill': 'transparent',
'stroke-opacity': 0.8,
'stroke-width': 2,
'stroke': '#294c58'
'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;
@ -117,29 +116,37 @@ nf.RemoteProcessGroup = (function () {
'height': function (d) {
return d.dimensions.height;
},
'fill': '#294c58',
'fill-opacity': 0.8,
'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,
'x': 30,
'y': 20,
'width': 305,
'height': 16,
'font-size': '10pt',
'font-weight': 'bold',
'fill': '#ffffff',
'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,
@ -182,37 +189,48 @@ 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)
details.append('text')
.attr({
'class': 'remote-process-group-transmission-status',
'width': 16,
'height': 16,
'x': 5,
'y': 5
'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)
details.append('text')
.attr({
'class': 'remote-process-group-transmission-secure',
'width': 14,
'height': 12,
'x': 7,
'y': 23
'x': 10,
'y': 48
});
if (remoteProcessGroupData.accessPolicy.canRead) {
// remote process group uri
details.append('text')
.attr({
'x': 25,
'y': 32,
'x': 30,
'y': 48,
'width': 305,
'height': 12,
'font-size': '8pt',
'fill': '#91b9ce',
'class': 'remote-process-group-uri'
})
.each(function (d) {
@ -232,169 +250,54 @@ nf.RemoteProcessGroup = (function () {
// stats background
// ----------------
// sent
details.append('rect')
.attr({
'x': 6,
'y': 38,
'width': 352,
'height': 89,
'stroke-width': 1,
'stroke': '#6f97ac',
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
'height': 19,
'x': 0,
'y': 66,
'fill': '#f4f6f7'
});
// border
details.append('rect')
.attr({
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
'height': 1,
'x': 0,
'y': 84,
'fill': '#c7d2d7'
});
// received
details.append('rect')
.attr({
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
'height': 19,
'x': 0,
'y': 85,
'fill': '#ffffff'
});
// 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'
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
'height': 1,
'x': 0,
'y': 103,
'fill': '#c7d2d7'
});
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'
});
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'
});
}
// -----
// stats
// -----
@ -402,7 +305,7 @@ nf.RemoteProcessGroup = (function () {
// stats label container
var remoteProcessGroupStatsLabel = details.append('g')
.attr({
'transform': 'translate(6, 70)'
'transform': 'translate(6, 75)'
});
// sent label
@ -411,8 +314,8 @@ nf.RemoteProcessGroup = (function () {
'width': 73,
'height': 10,
'x': 4,
'y': 4,
'class': 'process-group-stats-label'
'y': 5,
'class': 'stats-label'
})
.text('Sent');
@ -422,15 +325,15 @@ nf.RemoteProcessGroup = (function () {
'width': 73,
'height': 10,
'x': 4,
'y': 17,
'class': 'process-group-stats-label'
'y': 23,
'class': 'stats-label'
})
.text('Received');
// stats value container
var remoteProcessGroupStatsValue = details.append('g')
.attr({
'transform': 'translate(95, 70)'
'transform': 'translate(95, 75)'
});
// queued value
@ -439,8 +342,8 @@ nf.RemoteProcessGroup = (function () {
'width': 180,
'height': 10,
'x': 4,
'y': 4,
'class': 'remote-process-group-sent process-group-stats-value'
'y': 5,
'class': 'remote-process-group-sent stats-value'
});
// received value
@ -449,14 +352,14 @@ nf.RemoteProcessGroup = (function () {
'width': 180,
'height': 10,
'x': 4,
'y': 17,
'class': 'remote-process-group-received process-group-stats-value'
'y': 23,
'class': 'remote-process-group-received stats-value'
});
// stats value container
var processGroupStatsInfo = details.append('g')
.attr({
'transform': 'translate(315, 70)'
'transform': 'translate(335, 75)'
});
// sent info
@ -465,10 +368,10 @@ nf.RemoteProcessGroup = (function () {
'width': 25,
'height': 10,
'x': 4,
'y': 4,
'class': 'process-group-stats-info'
'y': 5,
'class': 'stats-info'
})
.text('(5 min)');
.text('5 min');
// received info
processGroupStatsInfo.append('text')
@ -476,10 +379,10 @@ nf.RemoteProcessGroup = (function () {
'width': 25,
'height': 10,
'x': 4,
'y': 17,
'class': 'process-group-stats-info'
'y': 23,
'class': 'stats-info'
})
.text('(5 min)');
.text('5 min');
// --------
// comments
@ -489,7 +392,7 @@ nf.RemoteProcessGroup = (function () {
details.append('text')
.attr({
'x': 10,
'y': 108,
'y': 121,
'width': 342,
'height': 22,
'class': 'remote-process-group-comments'
@ -499,10 +402,23 @@ nf.RemoteProcessGroup = (function () {
// last refreshed time
// -------------------
details.append('rect')
.attr({
'x': 0,
'y': function () {
return remoteProcessGroupData.dimensions.height - 24;
},
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
'height': 24,
'fill': '#e3e8eb'
});
details.append('text')
.attr({
'x': 358,
'y': 137,
'x': 370,
'y': 150,
'class': 'remote-process-group-last-refresh'
});
@ -511,53 +427,59 @@ nf.RemoteProcessGroup = (function () {
// -------------------
// active thread count
details.append('rect')
details.append('text')
.attr({
'class': 'active-thread-count-background',
'height': 13,
'y': 0,
'fill': '#fff',
'fill-opacity': '0.4',
'stroke': '#aaa',
'stroke-width': '1'
});
'class': 'active-thread-count-icon',
'y': 20
})
.text('\ue83f');
// active thread bacground
// active thread icon
details.append('text')
.attr({
'class': 'active-thread-count',
'height': 13,
'y': 10,
'fill': '#000'
'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)
details.append('text')
.attr({
'class': 'bulletin-icon',
'xlink:href': 'images/iconBulletin.png',
'width': 12,
'height': 12,
'y': 2
});
'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 = '';
details.select('text.remote-process-group-transmission-secure')
.text(function (d) {
var icon = '';
if (d.component.targetSecure === true) {
img = 'images/iconSecure.png';
icon = '\uf023';
} else {
img = 'images/iconNotSecure.png';
icon = '\uf09c';
}
return img;
return icon;
})
.each(function (d) {
// remove the existing tip if necessary
@ -688,7 +610,7 @@ nf.RemoteProcessGroup = (function () {
remoteProcessGroupComments.text(null).selectAll('tspan, title').remove();
// apply ellipsis to the port name as necessary
nf.CanvasUtils.multilineEllipsis(remoteProcessGroupComments, 2, getProcessGroupComments(d));
nf.CanvasUtils.ellipsis(remoteProcessGroupComments, getProcessGroupComments(d));
}).classed('unset', function (d) {
return nf.Common.isBlank(d.component.comments);
}).append('title').text(function (d) {
@ -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);

View File

@ -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.
*