This commit is contained in:
Mark Payne 2015-02-13 07:20:19 -05:00
commit bf97094b8c
9 changed files with 172 additions and 70 deletions

View File

@ -14,7 +14,7 @@
--> -->
# Apache NiFi # Apache NiFi
Apache NiFi is a dataflow system based on the concepts of flow-based programming. It is currently apart of the Apache Incubator. Apache NiFi is an easy to use, powerful, and reliable system to process and distribute data. It is currently apart of the Apache Incubator.
## Table of Contents ## Table of Contents
@ -28,6 +28,10 @@ Apache NiFi is a dataflow system based on the concepts of flow-based programming
follow the directions found there. follow the directions found there.
- Build nifi. Change directory to 'nifi' and follow the directions found there. - Build nifi. Change directory to 'nifi' and follow the directions found there.
## Documentation
See http://nifi.incubator.apache.org/ for the latest documentation.
## License ## License
Except as otherwise noted this software is licensed under the Except as otherwise noted this software is licensed under the

View File

@ -28,6 +28,7 @@
<a href="#">Documentation</a> <a href="#">Documentation</a>
<ul class="dropdown"> <ul class="dropdown">
<li><a href="faq.html">FAQ</a></li> <li><a href="faq.html">FAQ</a></li>
<li><a href="screencasts.html">Screencasts</a></li>
<li><a href="overview.html">NiFi Overview</a></li> <li><a href="overview.html">NiFi Overview</a></li>
<li><a href="user-guide.html">User Guide</a></li> <li><a href="user-guide.html">User Guide</a></li>
<li><a href="developer-guide.html">Developer Guide</a></li> <li><a href="developer-guide.html">Developer Guide</a></li>

View File

@ -11,5 +11,40 @@ title: Apache NiFi Screencasts
<div class="medium-space"></div> <div class="medium-space"></div>
<div class="row"> <div class="row">
<div class="large-12 columns"> <div class="large-12 columns">
<a href="#" data-reveal-id="toolbar-overview">NiFi Toolbar Overview</a>
<div id="toolbar-overview" class="reveal-modal medium" data-reveal>
<h2>NiFi Toolbar Overview</h2>
<div class="flex-video widescreen" style="display: block;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/LGXRAVUzL4U" frameborder="0" allowfullscreen></iframe>
</div>
<a class="close-reveal-modal">&#215;</a>
</div>
<br/>
<a href="#" data-reveal-id="creating-process-groups">Creating Process Groups</a>
<div id="creating-process-groups" class="reveal-modal medium" data-reveal>
<h2>Creating Process Groups</h2>
<div class="flex-video widescreen" style="display: block;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/hAveiDgDj-8" frameborder="0" allowfullscreen></iframe>
</div>
<a class="close-reveal-modal">&#215;</a>
</div>
<br/>
<a href="#" data-reveal-id="creating-templates">Creating Templates</a>
<div id="creating-templates" class="reveal-modal medium" data-reveal>
<h2>Creating Templates</h2>
<div class="flex-video widescreen" style="display: block;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/PpmL-IMoCnU" frameborder="0" allowfullscreen></iframe>
</div>
<a class="close-reveal-modal">&#215;</a>
</div>
<br/>
<a href="#" data-reveal-id="managing-templates">Managing Templates</a>
<div id="managing-templates" class="reveal-modal medium" data-reveal>
<h2>Managing Templates</h2>
<div class="flex-video widescreen" style="display: block;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/HU5_3PlNmtQ" frameborder="0" allowfullscreen></iframe>
</div>
<a class="close-reveal-modal">&#215;</a>
</div>
</div> </div>
</div> </div>

View File

@ -1065,7 +1065,6 @@ nf.Actions = (function () {
// refresh the birdseye/toolbar // refresh the birdseye/toolbar
nf.Birdseye.refresh(); nf.Birdseye.refresh();
nf.CanvasToolbar.refresh();
// remove the original snippet // remove the original snippet
nf.Snippet.remove(snippet.id).fail(reject); nf.Snippet.remove(snippet.id).fail(reject);
@ -1078,7 +1077,6 @@ nf.Actions = (function () {
// refresh the birdseye/toolbar // refresh the birdseye/toolbar
nf.Birdseye.refresh(); nf.Birdseye.refresh();
nf.CanvasToolbar.refresh();
}); });
// reject the deferred // reject the deferred

View File

@ -373,6 +373,9 @@ nf.CanvasToolbox = (function () {
// show the dialog // show the dialog
$('#new-processor-dialog').modal('show'); $('#new-processor-dialog').modal('show');
// set the focus in the filter field
$('#processor-type-filter').focus();
// adjust the grid canvas now that its been rendered // adjust the grid canvas now that its been rendered
grid.resizeCanvas(); grid.resizeCanvas();
@ -427,12 +430,11 @@ nf.CanvasToolbox = (function () {
*/ */
var promptForInputPortName = function (pt) { var promptForInputPortName = function (pt) {
var addInputPort = function () { var addInputPort = function () {
// hide the dialog
$('#new-port-dialog').modal('hide');
// get the name of the input port and clear the textfield // get the name of the input port and clear the textfield
var portName = $('#new-port-name').val(); var portName = $('#new-port-name').val();
$('#new-port-name').val('');
// hide the dialog
$('#new-port-dialog').modal('hide');
// create the input port // create the input port
createInputPort(portName, pt); createInputPort(portName, pt);
@ -514,12 +516,11 @@ nf.CanvasToolbox = (function () {
*/ */
var promptForOutputPortName = function (pt) { var promptForOutputPortName = function (pt) {
var addOutputPort = function () { var addOutputPort = function () {
// hide the dialog
$('#new-port-dialog').modal('hide');
// get the name of the output port and clear the textfield // get the name of the output port and clear the textfield
var portName = $('#new-port-name').val(); var portName = $('#new-port-name').val();
$('#new-port-name').val('');
// hide the dialog
$('#new-port-dialog').modal('hide');
// create the output port // create the output port
createOutputPort(portName, pt); createOutputPort(portName, pt);
@ -641,12 +642,11 @@ nf.CanvasToolbox = (function () {
*/ */
var promptForRemoteProcessGroupUri = function (pt) { var promptForRemoteProcessGroupUri = function (pt) {
var addRemoteProcessGroup = function () { var addRemoteProcessGroup = function () {
// hide the dialog
$('#new-remote-process-group-dialog').modal('hide');
// get the uri of the controller and clear the textfield // get the uri of the controller and clear the textfield
var remoteProcessGroupUri = $('#new-remote-process-group-uri').val(); var remoteProcessGroupUri = $('#new-remote-process-group-uri').val();
$('#new-remote-process-group-uri').val('');
// hide the dialog
$('#new-remote-process-group-dialog').modal('hide');
// create the remote process group // create the remote process group
createRemoteProcessGroup(remoteProcessGroupUri, pt); createRemoteProcessGroup(remoteProcessGroupUri, pt);
@ -882,7 +882,9 @@ nf.CanvasToolbox = (function () {
nf.Client.setRevision(response.revision); nf.Client.setRevision(response.revision);
// add the label to the graph // add the label to the graph
nf.Label.add(response.label, true); nf.Graph.add({
'labels': [response.label]
}, true);
// update the birdseye // update the birdseye
nf.Birdseye.refresh(); nf.Birdseye.refresh();
@ -1121,19 +1123,34 @@ nf.CanvasToolbox = (function () {
// configure the new port dialog // configure the new port dialog
$('#new-port-dialog').modal({ $('#new-port-dialog').modal({
headerText: 'Add Port', headerText: 'Add Port',
overlayBackground: false overlayBackground: false,
handler: {
close: function () {
$('#new-port-name').val('');
}
}
}); });
// configure the new process group dialog // configure the new process group dialog
$('#new-process-group-dialog').modal({ $('#new-process-group-dialog').modal({
headerText: 'Add Process Group', headerText: 'Add Process Group',
overlayBackground: false overlayBackground: false,
handler: {
close: function () {
$('#new-process-group-name').val('');
}
}
}); });
// configure the new remote process group dialog // configure the new remote process group dialog
$('#new-remote-process-group-dialog').modal({ $('#new-remote-process-group-dialog').modal({
headerText: 'Add Remote Process Group', headerText: 'Add Remote Process Group',
overlayBackground: false overlayBackground: false,
handler: {
close: function () {
$('#new-remote-process-group-uri').val('');
}
}
}); });
// configure the instantiate template dialog // configure the instantiate template dialog
@ -1162,12 +1179,11 @@ nf.CanvasToolbox = (function () {
promptForGroupName: function (pt) { promptForGroupName: function (pt) {
return $.Deferred(function (deferred) { return $.Deferred(function (deferred) {
var addGroup = function () { var addGroup = function () {
// hide the dialog
$('#new-process-group-dialog').modal('hide');
// get the name of the group and clear the textfield // get the name of the group and clear the textfield
var groupName = $('#new-process-group-name').val(); var groupName = $('#new-process-group-name').val();
$('#new-process-group-name').val('');
// hide the dialog
$('#new-process-group-dialog').modal('hide');
// create the group and resolve the deferred accordingly // create the group and resolve the deferred accordingly
createGroup(groupName, pt).done(function (response) { createGroup(groupName, pt).done(function (response) {

View File

@ -393,7 +393,7 @@ nf.CanvasUtils = (function () {
*/ */
disableImageHref: function (selection) { disableImageHref: function (selection) {
selection.on('click.disableImageHref', function () { selection.on('click.disableImageHref', function () {
if (d3.event.ctrlKey) { if (d3.event.ctrlKey || d3.event.shiftKey) {
d3.event.preventDefault(); d3.event.preventDefault();
} }
}); });

View File

@ -409,10 +409,10 @@ nf.Canvas = (function () {
// update the selection box // update the selection box
selectionBox.attr(d); selectionBox.attr(d);
// prevent further propagation (to parents)
d3.event.stopPropagation();
} }
// prevent further propagation (to parents)
d3.event.stopPropagation();
} }
}) })
.on('mouseup.selection', function () { .on('mouseup.selection', function () {
@ -510,12 +510,24 @@ nf.Canvas = (function () {
$(window).on('resize', function () { $(window).on('resize', function () {
updateGraphSize(); updateGraphSize();
}).on('keydown', function (evt) { }).on('keydown', function (evt) {
var isCtrl = evt.ctrlKey || evt.metaKey;
// consider escape, before checking dialogs
if (!isCtrl && evt.keyCode === 27) {
// esc
nf.Actions.hideDialogs();
evt.preventDefault();
return;
}
// if a dialog is open, disable canvas shortcuts // if a dialog is open, disable canvas shortcuts
if ($('.dialog').is(':visible')) { if ($('.dialog').is(':visible')) {
return; return;
} }
if (evt.ctrlKey || evt.metaKey) { // handle shortcuts
if (isCtrl) {
if (evt.keyCode === 82) { if (evt.keyCode === 82) {
// ctrl-r // ctrl-r
nf.Actions.reloadStatus(); nf.Actions.reloadStatus();
@ -543,11 +555,6 @@ nf.Canvas = (function () {
// delete // delete
nf.Actions['delete'](nf.CanvasUtils.getSelection()); nf.Actions['delete'](nf.CanvasUtils.getSelection());
evt.preventDefault();
} else if (evt.keyCode === 27) {
// esc
nf.Actions.hideDialogs();
evt.preventDefault(); evt.preventDefault();
} }
} }

View File

@ -20,6 +20,21 @@ nf.Connectable = (function () {
var canvas; var canvas;
var origin; var origin;
/**
* Determines if we want to allow adding connections in the current state:
*
* 1) When shift is down, we could be adding components to the current selection.
* 2) When the selection box is visible, we are in the process of moving all the
* components currently selected.
* 3) When the drag selection box is visible, we are in the process or selecting components
* using the selection box.
*
* @returns {boolean}
*/
var allowConnection = function () {
return !d3.event.shiftKey && d3.select('rect.drag-selection').empty() && d3.select('rect.selection').empty();
};
return { return {
init: function () { init: function () {
canvas = d3.select('#canvas'); canvas = d3.select('#canvas');
@ -102,17 +117,27 @@ nf.Connectable = (function () {
}).attr('d', function (pathDatum) { }).attr('d', function (pathDatum) {
if (!destination.empty() && destination.classed('connectable-destination')) { if (!destination.empty() && destination.classed('connectable-destination')) {
var destinationData = destination.datum(); var destinationData = destination.datum();
// show the line preview as appropriate
if (pathDatum.sourceId === destinationData.component.id) {
var x = pathDatum.x;
var y = pathDatum.y;
var componentOffset = pathDatum.sourceWidth / 2;
var xOffset = nf.Connection.config.selfLoopXOffset;
var yOffset = nf.Connection.config.selfLoopYOffset;
return 'M' + x + ' ' + y + 'L' + (x + componentOffset + xOffset) + ' ' + (y - yOffset) + 'L' + (x + componentOffset + xOffset) + ' ' + (y + yOffset) + 'Z';
} else {
// get the position on the destination perimeter
var end = nf.CanvasUtils.getPerimeterPoint(pathDatum, {
'x': destinationData.component.position.x,
'y': destinationData.component.position.y,
'width': destinationData.dimensions.width,
'height': destinationData.dimensions.height
});
// get the position on the destination perimeter // direct line between components to provide a 'snap feel'
var end = nf.CanvasUtils.getPerimeterPoint(pathDatum, { return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + end.x + ' ' + end.y;
'x': destinationData.component.position.x, }
'y': destinationData.component.position.y,
'width': destinationData.dimensions.width,
'height': destinationData.dimensions.height
});
// direct line between components to provide a 'snap feel'
return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + end.x + ' ' + end.y;
} else { } else {
return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + d3.event.x + ' ' + d3.event.y; return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + d3.event.x + ' ' + d3.event.y;
} }
@ -122,57 +147,70 @@ nf.Connectable = (function () {
// stop further propagation // stop further propagation
d3.event.sourceEvent.stopPropagation(); d3.event.sourceEvent.stopPropagation();
// get the add connect img
var addConnect = d3.select(this);
// get the connector, if it the current point is not over a new destination // get the connector, if it the current point is not over a new destination
// the connector will be removed. otherwise it will be removed after the // the connector will be removed. otherwise it will be removed after the
// connection has been configured/cancelled // connection has been configured/cancelled
var connector = d3.select('path.connector'); var connector = d3.select('path.connector');
var connectorData = connector.datum();
// get the destination // get the destination
var destination = d3.select('g.connectable-destination'); var destination = d3.select('g.connectable-destination');
// we are not over a new destination // we are not over a new destination
if (destination.empty()) { if (destination.empty()) {
// get the source to determine if we are still over it
var source = d3.select('#id-' + connectorData.sourceId);
var sourceData = source.datum();
// get the mouse position relative to the source
var position = d3.mouse(source.node());
// if the position is outside the component, remove the add connect img
if (position[0] < 0 || position[0] > sourceData.dimensions.width || position[1] < 0 || position[1] > sourceData.dimensions.height) {
addConnect.remove();
} else {
// reset the add connect img by restoring the position and place in the DOM
addConnect.classed('dragging', false).attr('transform', function () {
return 'translate(' + d.origX + ', ' + d.origY + ')';
});
source.node().appendChild(this);
}
// remove the connector
connector.remove(); connector.remove();
} else { } else {
var connectorData = connector.datum(); // remove the add connect img
var destinationData = destination.datum(); addConnect.remove();
// if this is a self loop we need to insert some bend points
if (connectorData.sourceId === destinationData.component.id) {
connector.attr('d', function (pathDatum) {
var x = pathDatum.x;
var y = pathDatum.y;
var componentOffset = pathDatum.sourceWidth / 2;
var xOffset = nf.Connection.config.selfLoopXOffset;
var yOffset = nf.Connection.config.selfLoopYOffset;
return 'M' + x + ' ' + y + 'L' + (x + componentOffset + xOffset) + ' ' + (y - yOffset) + 'L' + (x + componentOffset + xOffset) + ' ' + (y + yOffset) + 'Z';
});
}
// create the connection // create the connection
var destinationData = destination.datum();
nf.ConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.component.id); nf.ConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.component.id);
} }
// remove this component
d3.select(this).remove();
}); });
}, },
activate: function (components) { activate: function (components) {
components components
.on('mouseenter.connectable', function (d) { .on('mouseenter.connectable', function (d) {
if (!d3.event.shiftKey && d3.select('rect.drag-selection').empty()) { if (allowConnection()) {
var selection = d3.select(this); var selection = d3.select(this);
// ensure the current component supports connection source // ensure the current component supports connection source
if (nf.CanvasUtils.isValidConnectionSource(selection)) { if (nf.CanvasUtils.isValidConnectionSource(selection)) {
// see if theres already a connector rendered // see if theres already a connector rendered
var anyConnector = d3.select('image.add-connect'); var addConnect = d3.select('image.add-connect');
if (anyConnector.empty()) { if (addConnect.empty()) {
var x = (d.dimensions.width / 2) - 14; var x = (d.dimensions.width / 2) - 14;
var y = (d.dimensions.height / 2) - 14; var y = (d.dimensions.height / 2) - 14;
selection.append('image') selection.append('image')
.datum({
origX: x,
origY: y
})
.call(connect) .call(connect)
.call(nf.CanvasUtils.disableImageHref) .call(nf.CanvasUtils.disableImageHref)
.attr({ .attr({
@ -188,17 +226,16 @@ nf.Connectable = (function () {
}) })
.on('mouseleave.connectable', function () { .on('mouseleave.connectable', function () {
// conditionally remove the connector // conditionally remove the connector
var connector = d3.select(this).select('image.add-connect'); var addConnect = d3.select(this).select('image.add-connect');
if (!connector.empty() && !connector.classed('dragging')) { if (!addConnect.empty() && !addConnect.classed('dragging')) {
connector.remove(); addConnect.remove();
} }
}) })
// Using mouseover/out to workaround chrome issue #122746 // Using mouseover/out to workaround chrome issue #122746
.on('mouseover.connectable', function () { .on('mouseover.connectable', function () {
// mark that we are hovering when appropriate // mark that we are hovering when appropriate
var selection = d3.select(this); d3.select(this).classed('hover', function () {
selection.classed('hover', function () { return allowConnection();
return !d3.event.shiftKey && !selection.classed('hover') && d3.select('rect.drag-selection').empty();
}); });
}) })
.on('mouseout.connection', function () { .on('mouseout.connection', function () {

View File

@ -67,7 +67,6 @@ nf.Graph = (function () {
// if we are going to select the new components, deselect the previous selection // if we are going to select the new components, deselect the previous selection
if (selectAll) { if (selectAll) {
// deselect the current selection
nf.CanvasUtils.getSelection().classed('selected', false); nf.CanvasUtils.getSelection().classed('selected', false);
} }
@ -96,6 +95,11 @@ nf.Graph = (function () {
if (!nf.Common.isEmpty(processGroupContents.connections)) { if (!nf.Common.isEmpty(processGroupContents.connections)) {
nf.Connection.add(processGroupContents.connections, selectAll); nf.Connection.add(processGroupContents.connections, selectAll);
} }
// trigger the toolbar to refresh if the selection is changing
if (selectAll) {
nf.CanvasToolbar.refresh();
}
}, },
/** /**