mirror of https://github.com/apache/nifi.git
NIFI-115:
- Code clean up. - Showing an expiration icon on the connection label when appropriate. - Allowing the user to search for connections that have expiration and back pressure configured.
This commit is contained in:
parent
22596080c9
commit
bda9985d6a
|
@ -113,6 +113,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.admin.service.UserService;
|
import org.apache.nifi.admin.service.UserService;
|
||||||
import org.apache.nifi.authorization.DownloadAuthorization;
|
import org.apache.nifi.authorization.DownloadAuthorization;
|
||||||
|
import org.apache.nifi.processor.DataUnit;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
@ -1254,6 +1255,28 @@ public class ControllerFacade implements ControllerServiceProvider {
|
||||||
for (final FlowFilePrioritizer comparator : queue.getPriorities()) {
|
for (final FlowFilePrioritizer comparator : queue.getPriorities()) {
|
||||||
addIfAppropriate(searchStr, comparator.getClass().getName(), "Prioritizer", matches);
|
addIfAppropriate(searchStr, comparator.getClass().getName(), "Prioritizer", matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search expiration
|
||||||
|
if (StringUtils.containsIgnoreCase("expires", searchStr) || StringUtils.containsIgnoreCase("expiration", searchStr)) {
|
||||||
|
final int expirationMillis = connection.getFlowFileQueue().getFlowFileExpiration(TimeUnit.MILLISECONDS);
|
||||||
|
if (expirationMillis > 0) {
|
||||||
|
matches.add("FlowFile expiration: " + connection.getFlowFileQueue().getFlowFileExpiration());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search back pressure
|
||||||
|
if (StringUtils.containsIgnoreCase("back pressure", searchStr) || StringUtils.containsIgnoreCase("pressure", searchStr)) {
|
||||||
|
final String backPressureDataSize = connection.getFlowFileQueue().getBackPressureDataSizeThreshold();
|
||||||
|
final Double backPressureBytes = DataUnit.parseDataSize(backPressureDataSize, DataUnit.B);
|
||||||
|
if (backPressureBytes > 0) {
|
||||||
|
matches.add("Back pressure data size: " + backPressureDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long backPressureCount = connection.getFlowFileQueue().getBackPressureObjectThreshold();
|
||||||
|
if (backPressureCount > 0) {
|
||||||
|
matches.add("Back pressure count: " + backPressureCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// search the source
|
// search the source
|
||||||
final Connectable source = connection.getSource();
|
final Connectable source = connection.getSource();
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="setting">
|
<div class="setting">
|
||||||
<div class="setting-name">
|
<div class="setting-name">
|
||||||
File expiration
|
FlowFile expiration
|
||||||
<img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum amount of time an object may be in the flow before it will be automatically aged out of the flow."/>
|
<img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum amount of time an object may be in the flow before it will be automatically aged out of the flow."/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-field">
|
<div class="setting-field">
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="setting">
|
<div class="setting">
|
||||||
<div class="setting-name">
|
<div class="setting-name">
|
||||||
File expiration
|
FlowFile expiration
|
||||||
<img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum amount of time an object may be in the flow before it will be automatically aged out of the flow."/>
|
<img class="setting-icon icon-info" src="images/iconInfo.png" alt="Info" title="The maximum amount of time an object may be in the flow before it will be automatically aged out of the flow."/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-field">
|
<div class="setting-field">
|
||||||
|
|
|
@ -311,6 +311,28 @@ nf.Canvas = (function () {
|
||||||
'offset': '100%',
|
'offset': '100%',
|
||||||
'stop-color': '#ffffff'
|
'stop-color': '#ffffff'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// define the gradient for the expiration icon
|
||||||
|
var expirationBackground = defs.append('linearGradient')
|
||||||
|
.attr({
|
||||||
|
'id': 'expiration',
|
||||||
|
'x1': '0%',
|
||||||
|
'y1': '0%',
|
||||||
|
'x2': '0%',
|
||||||
|
'y2': '100%'
|
||||||
|
});
|
||||||
|
|
||||||
|
expirationBackground.append('stop')
|
||||||
|
.attr({
|
||||||
|
'offset': '0%',
|
||||||
|
'stop-color': '#aeafb1'
|
||||||
|
});
|
||||||
|
|
||||||
|
expirationBackground.append('stop')
|
||||||
|
.attr({
|
||||||
|
'offset': '100%',
|
||||||
|
'stop-color': '#87888a'
|
||||||
|
});
|
||||||
|
|
||||||
// create the canvas element
|
// create the canvas element
|
||||||
canvas = svg.append('g')
|
canvas = svg.append('g')
|
||||||
|
@ -322,135 +344,135 @@ nf.Canvas = (function () {
|
||||||
|
|
||||||
// handle canvas events
|
// handle canvas events
|
||||||
svg.on('mousedown.selection', function () {
|
svg.on('mousedown.selection', function () {
|
||||||
canvasClicked = true;
|
canvasClicked = true;
|
||||||
|
|
||||||
if (d3.event.button !== 0) {
|
if (d3.event.button !== 0) {
|
||||||
// prevent further propagation (to parents and others handlers
|
// prevent further propagation (to parents and others handlers
|
||||||
// on the same element to prevent zoom behavior)
|
// on the same element to prevent zoom behavior)
|
||||||
d3.event.stopImmediatePropagation();
|
d3.event.stopImmediatePropagation();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// show selection box if shift is held down
|
||||||
|
if (d3.event.shiftKey) {
|
||||||
|
var position = d3.mouse(canvas.node());
|
||||||
|
canvas.append('rect')
|
||||||
|
.attr('rx', 6)
|
||||||
|
.attr('ry', 6)
|
||||||
|
.attr('x', position[0])
|
||||||
|
.attr('y', position[1])
|
||||||
|
.attr('class', 'selection')
|
||||||
|
.attr('width', 0)
|
||||||
|
.attr('height', 0)
|
||||||
|
.attr('stroke-width', function () {
|
||||||
|
return 1 / nf.Canvas.View.scale();
|
||||||
|
})
|
||||||
|
.attr('stroke-dasharray', function () {
|
||||||
|
return 4 / nf.Canvas.View.scale();
|
||||||
|
})
|
||||||
|
.datum(position);
|
||||||
|
|
||||||
|
// prevent further propagation (to parents)
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('mousemove.selection', function () {
|
||||||
|
// update selection box if shift is held down
|
||||||
|
if (d3.event.shiftKey) {
|
||||||
|
// get the selection box
|
||||||
|
var selectionBox = d3.select('rect.selection');
|
||||||
|
if (!selectionBox.empty()) {
|
||||||
|
// get the original position
|
||||||
|
var originalPosition = selectionBox.datum();
|
||||||
|
var position = d3.mouse(canvas.node());
|
||||||
|
|
||||||
|
var d = {};
|
||||||
|
if (originalPosition[0] < position[0]) {
|
||||||
|
d.x = originalPosition[0];
|
||||||
|
d.width = position[0] - originalPosition[0];
|
||||||
|
} else {
|
||||||
|
d.x = position[0];
|
||||||
|
d.width = originalPosition[0] - position[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// show selection box if shift is held down
|
if (originalPosition[1] < position[1]) {
|
||||||
if (d3.event.shiftKey) {
|
d.y = originalPosition[1];
|
||||||
var position = d3.mouse(canvas.node());
|
d.height = position[1] - originalPosition[1];
|
||||||
canvas.append('rect')
|
} else {
|
||||||
.attr('rx', 6)
|
d.y = position[1];
|
||||||
.attr('ry', 6)
|
d.height = originalPosition[1] - position[1];
|
||||||
.attr('x', position[0])
|
|
||||||
.attr('y', position[1])
|
|
||||||
.attr('class', 'selection')
|
|
||||||
.attr('width', 0)
|
|
||||||
.attr('height', 0)
|
|
||||||
.attr('stroke-width', function () {
|
|
||||||
return 1 / nf.Canvas.View.scale();
|
|
||||||
})
|
|
||||||
.attr('stroke-dasharray', function () {
|
|
||||||
return 4 / nf.Canvas.View.scale();
|
|
||||||
})
|
|
||||||
.datum(position);
|
|
||||||
|
|
||||||
// prevent further propagation (to parents)
|
|
||||||
d3.event.stopPropagation();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on('mousemove.selection', function () {
|
|
||||||
// update selection box if shift is held down
|
|
||||||
if (d3.event.shiftKey) {
|
|
||||||
// get the selection box
|
|
||||||
var selectionBox = d3.select('rect.selection');
|
|
||||||
if (!selectionBox.empty()) {
|
|
||||||
// get the original position
|
|
||||||
var originalPosition = selectionBox.datum();
|
|
||||||
var position = d3.mouse(canvas.node());
|
|
||||||
|
|
||||||
var d = {};
|
|
||||||
if (originalPosition[0] < position[0]) {
|
|
||||||
d.x = originalPosition[0];
|
|
||||||
d.width = position[0] - originalPosition[0];
|
|
||||||
} else {
|
|
||||||
d.x = position[0];
|
|
||||||
d.width = originalPosition[0] - position[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originalPosition[1] < position[1]) {
|
|
||||||
d.y = originalPosition[1];
|
|
||||||
d.height = position[1] - originalPosition[1];
|
|
||||||
} else {
|
|
||||||
d.y = position[1];
|
|
||||||
d.height = originalPosition[1] - position[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the selection box
|
|
||||||
selectionBox.attr(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
d3.event.stopPropagation();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on('mouseup.selection', function () {
|
|
||||||
// ensure this originated from clicking the canvas, not a component.
|
|
||||||
// when clicking on a component, the event propagation is stopped so
|
|
||||||
// it never reaches the canvas. we cannot do this however on up events
|
|
||||||
// since the drag events break down
|
|
||||||
if (canvasClicked === false) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the canvas click flag
|
// update the selection box
|
||||||
canvasClicked = false;
|
selectionBox.attr(d);
|
||||||
|
}
|
||||||
|
|
||||||
// hide the context menu if necessary
|
d3.event.stopPropagation();
|
||||||
nf.ContextMenu.hide();
|
}
|
||||||
|
})
|
||||||
|
.on('mouseup.selection', function () {
|
||||||
|
// ensure this originated from clicking the canvas, not a component.
|
||||||
|
// when clicking on a component, the event propagation is stopped so
|
||||||
|
// it never reaches the canvas. we cannot do this however on up events
|
||||||
|
// since the drag events break down
|
||||||
|
if (canvasClicked === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get the selection box
|
// reset the canvas click flag
|
||||||
var selectionBox = d3.select('rect.selection');
|
canvasClicked = false;
|
||||||
if (!selectionBox.empty()) {
|
|
||||||
var selectionBoundingBox = {
|
|
||||||
x: parseInt(selectionBox.attr('x'), 10),
|
|
||||||
y: parseInt(selectionBox.attr('y'), 10),
|
|
||||||
width: parseInt(selectionBox.attr('width'), 10),
|
|
||||||
height: parseInt(selectionBox.attr('height'), 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
// see if a component should be selected or not
|
// hide the context menu if necessary
|
||||||
d3.selectAll('g.component').classed('selected', function (d) {
|
nf.ContextMenu.hide();
|
||||||
// consider it selected if its already selected or enclosed in the bounding box
|
|
||||||
return d3.select(this).classed('selected') ||
|
|
||||||
d.component.position.x >= selectionBoundingBox.x && (d.component.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
|
|
||||||
d.component.position.y >= selectionBoundingBox.y && (d.component.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height);
|
|
||||||
});
|
|
||||||
|
|
||||||
// see if a connection should be selected or not
|
// get the selection box
|
||||||
d3.selectAll('g.connection').classed('selected', function (d) {
|
var selectionBox = d3.select('rect.selection');
|
||||||
// consider all points
|
if (!selectionBox.empty()) {
|
||||||
var points = [d.start].concat(d.bends, [d.end]);
|
var selectionBoundingBox = {
|
||||||
|
x: parseInt(selectionBox.attr('x'), 10),
|
||||||
|
y: parseInt(selectionBox.attr('y'), 10),
|
||||||
|
width: parseInt(selectionBox.attr('width'), 10),
|
||||||
|
height: parseInt(selectionBox.attr('height'), 10)
|
||||||
|
};
|
||||||
|
|
||||||
// determine the bounding box
|
// see if a component should be selected or not
|
||||||
var x = d3.extent(points, function (pt) {
|
d3.selectAll('g.component').classed('selected', function (d) {
|
||||||
return pt.x;
|
// consider it selected if its already selected or enclosed in the bounding box
|
||||||
});
|
return d3.select(this).classed('selected') ||
|
||||||
var y = d3.extent(points, function (pt) {
|
d.component.position.x >= selectionBoundingBox.x && (d.component.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
|
||||||
return pt.y;
|
d.component.position.y >= selectionBoundingBox.y && (d.component.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height);
|
||||||
});
|
|
||||||
|
|
||||||
// consider it selected if its already selected or enclosed in the bounding box
|
|
||||||
return d3.select(this).classed('selected') ||
|
|
||||||
x[0] >= selectionBoundingBox.x && x[1] <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
|
|
||||||
y[0] >= selectionBoundingBox.y && y[1] <= (selectionBoundingBox.y + selectionBoundingBox.height);
|
|
||||||
});
|
|
||||||
|
|
||||||
// remove the selection box
|
|
||||||
selectionBox.remove();
|
|
||||||
} else if (panning === false) {
|
|
||||||
// deselect as necessary if we are not panning
|
|
||||||
nf.CanvasUtils.getSelection().classed('selected', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the toolbar
|
|
||||||
nf.CanvasToolbar.refresh();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// see if a connection should be selected or not
|
||||||
|
d3.selectAll('g.connection').classed('selected', function (d) {
|
||||||
|
// consider all points
|
||||||
|
var points = [d.start].concat(d.bends, [d.end]);
|
||||||
|
|
||||||
|
// determine the bounding box
|
||||||
|
var x = d3.extent(points, function (pt) {
|
||||||
|
return pt.x;
|
||||||
|
});
|
||||||
|
var y = d3.extent(points, function (pt) {
|
||||||
|
return pt.y;
|
||||||
|
});
|
||||||
|
|
||||||
|
// consider it selected if its already selected or enclosed in the bounding box
|
||||||
|
return d3.select(this).classed('selected') ||
|
||||||
|
x[0] >= selectionBoundingBox.x && x[1] <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
|
||||||
|
y[0] >= selectionBoundingBox.y && y[1] <= (selectionBoundingBox.y + selectionBoundingBox.height);
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove the selection box
|
||||||
|
selectionBox.remove();
|
||||||
|
} else if (panning === false) {
|
||||||
|
// deselect as necessary if we are not panning
|
||||||
|
nf.CanvasUtils.getSelection().classed('selected', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the toolbar
|
||||||
|
nf.CanvasToolbar.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
// define a function for update the graph dimensions
|
// define a function for update the graph dimensions
|
||||||
var updateGraphSize = function () {
|
var updateGraphSize = function () {
|
||||||
// get the location of the bottom of the graph
|
// get the location of the bottom of the graph
|
||||||
|
@ -802,17 +824,21 @@ nf.Canvas = (function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
CANVAS_OFFSET: 0,
|
CANVAS_OFFSET: 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the current broswer supports SVG.
|
* Determines if the current broswer supports SVG.
|
||||||
*/
|
*/
|
||||||
SUPPORTS_SVG: !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect,
|
SUPPORTS_SVG: !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides the splash that is displayed while the application is loading.
|
* Hides the splash that is displayed while the application is loading.
|
||||||
*/
|
*/
|
||||||
hideSplash: function () {
|
hideSplash: function () {
|
||||||
$('#splash').fadeOut();
|
$('#splash').fadeOut();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop polling for revision.
|
* Stop polling for revision.
|
||||||
*/
|
*/
|
||||||
|
@ -820,6 +846,7 @@ nf.Canvas = (function () {
|
||||||
// set polling flag
|
// set polling flag
|
||||||
revisionPolling = false;
|
revisionPolling = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the status poller.
|
* Remove the status poller.
|
||||||
*/
|
*/
|
||||||
|
@ -827,6 +854,7 @@ nf.Canvas = (function () {
|
||||||
// set polling flag
|
// set polling flag
|
||||||
statusPolling = false;
|
statusPolling = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the flow from the server based on the currently specified group id.
|
* Reloads the flow from the server based on the currently specified group id.
|
||||||
* To load another group, update nf.Canvas.setGroupId and call nf.Canvas.reload.
|
* To load another group, update nf.Canvas.setGroupId and call nf.Canvas.reload.
|
||||||
|
@ -865,6 +893,7 @@ nf.Canvas = (function () {
|
||||||
});
|
});
|
||||||
}).promise();
|
}).promise();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the status.
|
* Reloads the status.
|
||||||
*/
|
*/
|
||||||
|
@ -878,6 +907,7 @@ nf.Canvas = (function () {
|
||||||
});
|
});
|
||||||
}).promise();
|
}).promise();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize NiFi.
|
* Initialize NiFi.
|
||||||
*/
|
*/
|
||||||
|
@ -999,6 +1029,7 @@ nf.Canvas = (function () {
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).fail(nf.Common.handleAjaxError);
|
||||||
}).fail(nf.Common.handleAjaxError);
|
}).fail(nf.Common.handleAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the gradient colors used to render processors.
|
* Defines the gradient colors used to render processors.
|
||||||
*
|
*
|
||||||
|
@ -1007,6 +1038,7 @@ nf.Canvas = (function () {
|
||||||
defineProcessorColors: function (colors) {
|
defineProcessorColors: function (colors) {
|
||||||
setColors(colors, 'processor');
|
setColors(colors, 'processor');
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the gradient colors used to render label.
|
* Defines the gradient colors used to render label.
|
||||||
*
|
*
|
||||||
|
@ -1015,6 +1047,7 @@ nf.Canvas = (function () {
|
||||||
defineLabelColors: function (colors) {
|
defineLabelColors: function (colors) {
|
||||||
setColors(colors, 'label');
|
setColors(colors, 'label');
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether this instance of NiFi is clustered.
|
* Return whether this instance of NiFi is clustered.
|
||||||
*
|
*
|
||||||
|
@ -1023,12 +1056,14 @@ nf.Canvas = (function () {
|
||||||
isClustered: function () {
|
isClustered: function () {
|
||||||
return clustered === true;
|
return clustered === true;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether site to site communications is secure.
|
* Returns whether site to site communications is secure.
|
||||||
*/
|
*/
|
||||||
isSecureSiteToSite: function () {
|
isSecureSiteToSite: function () {
|
||||||
return secureSiteToSite;
|
return secureSiteToSite;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the group id.
|
* Set the group id.
|
||||||
*
|
*
|
||||||
|
@ -1043,6 +1078,7 @@ nf.Canvas = (function () {
|
||||||
getGroupId: function () {
|
getGroupId: function () {
|
||||||
return groupId;
|
return groupId;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the group name.
|
* Set the group name.
|
||||||
*
|
*
|
||||||
|
@ -1051,12 +1087,14 @@ nf.Canvas = (function () {
|
||||||
setGroupName: function (gn) {
|
setGroupName: function (gn) {
|
||||||
groupName = gn;
|
groupName = gn;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the group name.
|
* Get the group name.
|
||||||
*/
|
*/
|
||||||
getGroupName: function () {
|
getGroupName: function () {
|
||||||
return groupName;
|
return groupName;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the parent group id.
|
* Set the parent group id.
|
||||||
*
|
*
|
||||||
|
@ -1065,13 +1103,16 @@ nf.Canvas = (function () {
|
||||||
setParentGroupId: function (pgi) {
|
setParentGroupId: function (pgi) {
|
||||||
parentGroupId = pgi;
|
parentGroupId = pgi;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parent group id.
|
* Get the parent group id.
|
||||||
*/
|
*/
|
||||||
getParentGroupId: function () {
|
getParentGroupId: function () {
|
||||||
return parentGroupId;
|
return parentGroupId;
|
||||||
},
|
},
|
||||||
|
|
||||||
View: (function () {
|
View: (function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates component visibility based on their proximity to the screen's viewport.
|
* Updates component visibility based on their proximity to the screen's viewport.
|
||||||
*/
|
*/
|
||||||
|
@ -1138,8 +1179,8 @@ nf.Canvas = (function () {
|
||||||
.classed('entering', function () {
|
.classed('entering', function () {
|
||||||
return visible && !wasVisible;
|
return visible && !wasVisible;
|
||||||
}).classed('leaving', function () {
|
}).classed('leaving', function () {
|
||||||
return !visible && wasVisible;
|
return !visible && wasVisible;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the all components
|
// get the all components
|
||||||
|
|
|
@ -186,6 +186,24 @@ nf.Connection = (function () {
|
||||||
var isGroup = function (terminal) {
|
var isGroup = function (terminal) {
|
||||||
return terminal.groupId !== nf.Canvas.getGroupId() && (isInputPortType(terminal.type) || isOutputPortType(terminal.type));
|
return terminal.groupId !== nf.Canvas.getGroupId() && (isInputPortType(terminal.type) || isOutputPortType(terminal.type));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether expiration is configured for the specified connection.
|
||||||
|
*
|
||||||
|
* @param {object} connection
|
||||||
|
* @return {boolean} Whether expiration is configured
|
||||||
|
*/
|
||||||
|
var isExpirationConfigured = function (connection) {
|
||||||
|
if (nf.Common.isDefinedAndNotNull(connection.flowFileExpiration)) {
|
||||||
|
var match = connection.flowFileExpiration.match(/^(\d+).*/);
|
||||||
|
if (match !== null && match.length > 0) {
|
||||||
|
if (parseInt(match[0], 10) > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the specified connections according to the z index.
|
* Sorts the specified connections according to the z index.
|
||||||
|
@ -325,16 +343,16 @@ nf.Connection = (function () {
|
||||||
|
|
||||||
return grouped;
|
return grouped;
|
||||||
})
|
})
|
||||||
.classed('ghost', function (d) {
|
.classed('ghost', function (d) {
|
||||||
var ghost = false;
|
var ghost = false;
|
||||||
|
|
||||||
// if the connection has a relationship that is unavailable, mark it a ghost relationship
|
// if the connection has a relationship that is unavailable, mark it a ghost relationship
|
||||||
if (hasUnavailableRelationship(d)) {
|
if (hasUnavailableRelationship(d)) {
|
||||||
ghost = true;
|
ghost = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost;
|
return ghost;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updated.each(function (d) {
|
updated.each(function (d) {
|
||||||
|
@ -669,7 +687,7 @@ nf.Connection = (function () {
|
||||||
|
|
||||||
// update the label text
|
// update the label text
|
||||||
connectionFrom.select('text.connection-from')
|
connectionFrom.select('text.connection-from')
|
||||||
.each(function (d) {
|
.each(function () {
|
||||||
var connectionFromLabel = d3.select(this);
|
var connectionFromLabel = d3.select(this);
|
||||||
|
|
||||||
// reset the label name to handle any previous state
|
// reset the label name to handle any previous state
|
||||||
|
@ -677,9 +695,9 @@ nf.Connection = (function () {
|
||||||
|
|
||||||
// apply ellipsis to the label as necessary
|
// apply ellipsis to the label as necessary
|
||||||
nf.CanvasUtils.ellipsis(connectionFromLabel, d.component.source.name);
|
nf.CanvasUtils.ellipsis(connectionFromLabel, d.component.source.name);
|
||||||
}).append('title').text(function (d) {
|
}).append('title').text(function () {
|
||||||
return d.component.source.name;
|
return d.component.source.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
// update the label run status
|
// update the label run status
|
||||||
connectionFrom.select('image.connection-from-run-status').attr('xlink:href', function () {
|
connectionFrom.select('image.connection-from-run-status').attr('xlink:href', function () {
|
||||||
|
@ -758,8 +776,8 @@ nf.Connection = (function () {
|
||||||
// apply ellipsis to the label as necessary
|
// apply ellipsis to the label as necessary
|
||||||
nf.CanvasUtils.ellipsis(connectionToLabel, d.component.destination.name);
|
nf.CanvasUtils.ellipsis(connectionToLabel, d.component.destination.name);
|
||||||
}).append('title').text(function (d) {
|
}).append('title').text(function (d) {
|
||||||
return d.component.destination.name;
|
return d.component.destination.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
// update the label run status
|
// update the label run status
|
||||||
connectionTo.select('image.connection-to-run-status').attr('xlink:href', function () {
|
connectionTo.select('image.connection-to-run-status').attr('xlink:href', function () {
|
||||||
|
@ -821,7 +839,7 @@ nf.Connection = (function () {
|
||||||
|
|
||||||
// update the connection name
|
// update the connection name
|
||||||
connectionName.select('text.connection-name')
|
connectionName.select('text.connection-name')
|
||||||
.each(function (d) {
|
.each(function () {
|
||||||
var connectionToLabel = d3.select(this);
|
var connectionToLabel = d3.select(this);
|
||||||
|
|
||||||
// reset the label name to handle any previous state
|
// reset the label name to handle any previous state
|
||||||
|
@ -829,9 +847,9 @@ nf.Connection = (function () {
|
||||||
|
|
||||||
// apply ellipsis to the label as necessary
|
// apply ellipsis to the label as necessary
|
||||||
nf.CanvasUtils.ellipsis(connectionToLabel, connectionNameValue);
|
nf.CanvasUtils.ellipsis(connectionToLabel, connectionNameValue);
|
||||||
}).append('title').text(function (d) {
|
}).append('title').text(function () {
|
||||||
return connectionNameValue;
|
return connectionNameValue;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// there is no connection name, but check if the name was previous
|
// there is no connection name, but check if the name was previous
|
||||||
// rendered so it can be removed
|
// rendered so it can be removed
|
||||||
|
@ -861,11 +879,49 @@ nf.Connection = (function () {
|
||||||
.text('Queued');
|
.text('Queued');
|
||||||
|
|
||||||
queued.append('text')
|
queued.append('text')
|
||||||
|
.attr({
|
||||||
|
'class': 'connection-stats-value queued',
|
||||||
|
'x': 46,
|
||||||
|
'y': 10
|
||||||
|
});
|
||||||
|
|
||||||
|
var expiration = queued.append('g')
|
||||||
.attr({
|
.attr({
|
||||||
'class': 'connection-stats-value queued',
|
'class': 'expiration-icon',
|
||||||
'x': 46,
|
'transform': 'translate(167, 2)'
|
||||||
'y': 10
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expiration.append('circle')
|
||||||
|
.attr({
|
||||||
|
'cx': 5,
|
||||||
|
'cy': 5,
|
||||||
|
'r': 4.75,
|
||||||
|
'stroke-width': 0.5,
|
||||||
|
'stroke': '#87888a',
|
||||||
|
'fill': 'url(#expiration)'
|
||||||
|
});
|
||||||
|
|
||||||
|
expiration.append('line')
|
||||||
|
.attr({
|
||||||
|
'x1': 6,
|
||||||
|
'y1': 5,
|
||||||
|
'x2': 3,
|
||||||
|
'y2': 4,
|
||||||
|
'stroke': '#fff',
|
||||||
|
'stroke-width': 1
|
||||||
|
});
|
||||||
|
|
||||||
|
expiration.append('line')
|
||||||
|
.attr({
|
||||||
|
'x1': 6,
|
||||||
|
'y1': 5,
|
||||||
|
'x2': 3,
|
||||||
|
'y2': 7,
|
||||||
|
'stroke': '#fff',
|
||||||
|
'stroke-width': 1
|
||||||
|
});
|
||||||
|
|
||||||
|
expiration.append('title');
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the queued vertical positioning as necessary
|
// update the queued vertical positioning as necessary
|
||||||
|
@ -879,6 +935,15 @@ nf.Connection = (function () {
|
||||||
.attr('height', function () {
|
.attr('height', function () {
|
||||||
return 5 + (15 * labelCount) + 3;
|
return 5 + (15 * labelCount) + 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// determine whether or not to show the expiration icon
|
||||||
|
connectionLabelContainer.select('g.expiration-icon')
|
||||||
|
.classed('hidden', function () {
|
||||||
|
return !isExpirationConfigured(d.component);
|
||||||
|
})
|
||||||
|
.select('title').text(function () {
|
||||||
|
return 'Expires FlowFiles older than ' + d.component.flowFileExpiration;
|
||||||
|
});
|
||||||
|
|
||||||
if (nf.Common.isDFM()) {
|
if (nf.Common.isDFM()) {
|
||||||
// only support dragging the label when appropriate
|
// only support dragging the label when appropriate
|
||||||
|
|
Loading…
Reference in New Issue