You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jw...@apache.org on 2017/01/21 02:42:09 UTC
nifi git commit: NIFI-3301: Provenance UI Cursor Styling - Addressing
inconsistent cursor styling and drag behavior in lineage graph.
Repository: nifi
Updated Branches:
refs/heads/master dc934cbb8 -> 79ca30be4
NIFI-3301: Provenance UI Cursor Styling
- Addressing inconsistent cursor styling and drag behavior in lineage graph.
This closes #1430.
Signed-off-by: James Wing <jv...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/79ca30be
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/79ca30be
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/79ca30be
Branch: refs/heads/master
Commit: 79ca30be4a84cd6c1d218e1a00af7946405b6f30
Parents: dc934cb
Author: Matt Gilman <ma...@gmail.com>
Authored: Fri Jan 20 16:46:12 2017 -0500
Committer: James Wing <jv...@gmail.com>
Committed: Fri Jan 20 18:40:36 2017 -0800
----------------------------------------------------------------------
.../src/main/webapp/css/provenance.css | 17 +-
.../js/nf/provenance/nf-provenance-lineage.js | 537 +++++++++----------
2 files changed, 283 insertions(+), 271 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/79ca30be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/provenance.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/provenance.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/provenance.css
index a1a7ed5..e105348 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/provenance.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/provenance.css
@@ -473,12 +473,19 @@ path.link.selected {
stroke: #ba554a;
}
+g.event {
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
g.event circle.selected {
fill: #ba554a;
}
text.event-type {
- cursor: pointer;
font-family: Roboto;
font-size: 11px;
font-style: normal;
@@ -492,6 +499,14 @@ text.event-type.expand-parents, text.event-type.expand-children {
font-size: 13px;
}
+g.flowfile {
+ cursor: default;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
g.flowfile circle.context, g.event circle.context {
stroke: #004849;
stroke-width: 1.5px;
http://git-wip-us.apache.org/repos/asf/nifi/blob/79ca30be/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
index ddada58..d9586e9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
@@ -553,6 +553,9 @@
// hide the context menu if necessary
d3.selectAll('circle.context').classed('context', false);
$('#provenance-lineage-context-menu').hide().empty();
+
+ // prevents browser from using text cursor
+ d3.event.preventDefault();
})
.on('contextmenu', function () {
var contextMenu = $('#provenance-lineage-context-menu');
@@ -672,7 +675,11 @@
// renders flowfile nodes
var renderFlowFile = function (flowfiles) {
- flowfiles.classed('flowfile', true);
+ flowfiles
+ .classed('flowfile', true)
+ .on('mousedown', function (d) {
+ d3.event.stopPropagation();
+ });
// node
flowfiles.append('circle')
@@ -682,16 +689,6 @@
'stroke': '#000',
'stroke-width': 1.0
})
- .on('mousedown', function (d) {
- // empty context menu if necessary
- $('#provenance-lineage-context-menu').hide().empty();
-
- // prevents the drag event when something other than the
- // left button is clicked
- if (d3.event.button !== 0) {
- d3.event.stopPropagation();
- }
- }, true)
.on('mouseover', function (d) {
links.filter(function (linkDatum) {
return d.id === linkDatum.flowFileUuid;
@@ -725,16 +722,6 @@
return 'translate(0,15)';
}
})
- .on('mousedown', function (d) {
- // empty context menu if necessary
- $('#provenance-lineage-context-menu').hide().empty();
-
- // prevents the drag event when something other than the
- // left button is clicked
- if (d3.event.button !== 0) {
- d3.event.stopPropagation();
- }
- }, true)
.on('mouseover', function (d) {
links.filter(function (linkDatum) {
return d.id === linkDatum.flowFileUuid;
@@ -753,287 +740,297 @@
});
})
.text(function (d) {
- return '\ue808'
+ return '\ue808';
});
};
- // renders event nodes
- var renderEvent = function (events, provenanceTableCtrl) {
- events
- .classed('event', true)
- .append('circle')
- .classed('selected', function (d) {
- return d.id === eventId;
- })
- .attr({
- 'r': 8,
- 'fill': '#aabbc3',
- 'stroke': '#000',
- 'stroke-width': 1.0,
- 'id': function (d) {
- return 'event-node-' + d.id;
- }
- })
- .on('contextmenu', function (d) {
- // select the current node for a visible cue
- d3.select(this).classed('context', true);
+ var showContextMenu = function (d, provenanceTableCtrl) {
+ // empty an previous contents - in case they right click on the
+ // node twice without closing the previous context menu
+ $('#provenance-lineage-context-menu').hide().empty();
- // empty an previous contents - in case they right click on the
- // node twice without closing the previous context menu
- $('#provenance-lineage-context-menu').hide().empty();
+ var menuItems = [{
+ 'class': 'lineage-view-event',
+ 'text': 'View details',
+ 'click': function () {
+ provenanceTableCtrl.showEventDetails(d.id, clusterNodeId);
+ }
+ }];
+
+ // if this is a spawn event show appropriate actions
+ if (d.eventType === 'SPAWN' || d.eventType === 'CLONE' || d.eventType === 'FORK' || d.eventType === 'JOIN' || d.eventType === 'REPLAY') {
+ // starts the lineage expansion process
+ var expandLineage = function (lineageRequest) {
+ var lineageProgress = $('#lineage-percent-complete');
+
+ // add support to cancel outstanding requests - when the button is pressed we
+ // could be in one of two stages, 1) waiting to GET the status or 2)
+ // in the process of GETting the status. Handle both cases by cancelling
+ // the setTimeout (1) and by setting a flag to indicate that a request has
+ // been request so we can ignore the results (2).
+
+ var cancelled = false;
+ var lineage = null;
+ var lineageTimer = null;
+
+ // update the progress bar value
+ provenanceTableCtrl.updateProgress(lineageProgress, 0);
+
+ // show the 'searching...' dialog
+ $('#lineage-query-dialog').modal('setButtonModel', [{
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ cancelled = true;
+
+ // we are waiting for the next poll attempt
+ if (lineageTimer !== null) {
+ // cancel it
+ clearTimeout(lineageTimer);
+
+ // cancel the provenance
+ closeDialog();
+ }
+ }
+ }
+ }]).modal('show');
- var menuItems = [{
- 'class': 'lineage-view-event',
- 'text': 'View details',
- 'click': function () {
- provenanceTableCtrl.showEventDetails(d.id, clusterNodeId);
+
+ // closes the searching dialog and cancels the query on the server
+ var closeDialog = function () {
+ // cancel the provenance results since we've successfully processed the results
+ if (common.isDefinedAndNotNull(lineage)) {
+ cancelLineage(lineage);
}
- }];
-
- // if this is a spawn event show appropriate actions
- if (d.eventType === 'SPAWN' || d.eventType === 'CLONE' || d.eventType === 'FORK' || d.eventType === 'JOIN' || d.eventType === 'REPLAY') {
- // starts the lineage expansion process
- var expandLineage = function (lineageRequest) {
- var lineageProgress = $('#lineage-percent-complete');
-
- // add support to cancel outstanding requests - when the button is pressed we
- // could be in one of two stages, 1) waiting to GET the status or 2)
- // in the process of GETting the status. Handle both cases by cancelling
- // the setTimeout (1) and by setting a flag to indicate that a request has
- // been request so we can ignore the results (2).
-
- var cancelled = false;
- var lineage = null;
- var lineageTimer = null;
-
- // update the progress bar value
- provenanceTableCtrl.updateProgress(lineageProgress, 0);
-
- // show the 'searching...' dialog
- $('#lineage-query-dialog').modal('setButtonModel', [{
- buttonText: 'Cancel',
- color: {
- base: '#E3E8EB',
- hover: '#C7D2D7',
- text: '#004849'
- },
- handler: {
- click: function () {
- cancelled = true;
-
- // we are waiting for the next poll attempt
- if (lineageTimer !== null) {
- // cancel it
- clearTimeout(lineageTimer);
-
- // cancel the provenance
- closeDialog();
- }
- }
- }
- }]).modal('show');
+ // close the dialog
+ $('#lineage-query-dialog').modal('hide');
+ };
- // closes the searching dialog and cancels the query on the server
- var closeDialog = function () {
- // cancel the provenance results since we've successfully processed the results
- if (common.isDefinedAndNotNull(lineage)) {
- cancelLineage(lineage);
- }
+ // polls for the event lineage
+ var pollLineage = function () {
+ getLineage(lineage).done(function (response) {
+ lineage = response.lineage;
- // close the dialog
- $('#lineage-query-dialog').modal('hide');
- };
+ // process the lineage
+ processLineage();
+ }).fail(closeDialog);
+ };
- // polls for the event lineage
- var pollLineage = function () {
- getLineage(lineage).done(function (response) {
- lineage = response.lineage;
+ // processes the event lineage
+ var processLineage = function () {
+ // if the request was cancelled just ignore the current response
+ if (cancelled === true) {
+ closeDialog();
+ return;
+ }
- // process the lineage
- processLineage();
- }).fail(closeDialog);
- };
+ // close the dialog if the results contain an error
+ if (!common.isEmpty(lineage.results.errors)) {
+ var errors = lineage.results.errors;
+ dialog.showOkDialog({
+ headerText: 'Process Lineage',
+ dialogContent: common.formatUnorderedList(errors)
+ });
- // processes the event lineage
- var processLineage = function () {
- // if the request was cancelled just ignore the current response
- if (cancelled === true) {
- closeDialog();
- return;
- }
+ closeDialog();
+ return;
+ }
- // close the dialog if the results contain an error
- if (!common.isEmpty(lineage.results.errors)) {
- var errors = lineage.results.errors;
- dialog.showOkDialog({
- headerText: 'Process Lineage',
- dialogContent: common.formatUnorderedList(errors)
- });
+ // update the precent complete
+ provenanceTableCtrl.updateProgress(lineageProgress, lineage.percentCompleted);
+
+ // process the results if they are finished
+ if (lineage.finished === true) {
+ var results = lineage.results;
+
+ // ensure the events haven't aged off
+ if (results.nodes.length > 0) {
+ // update the lineage graph
+ renderEventLineage(results);
+ } else {
+ // inform the user that no results were found
+ dialog.showOkDialog({
+ headerText: 'Lineage Results',
+ dialogContent: 'The lineage search has completed successfully but there no results were found. The events may have aged off.'
+ });
+ }
- closeDialog();
- return;
- }
+ // close the searching.. dialog
+ closeDialog();
+ } else {
+ lineageTimer = setTimeout(function () {
+ // clear the timer since we've been invoked
+ lineageTimer = null;
- // update the precent complete
- provenanceTableCtrl.updateProgress(lineageProgress, lineage.percentCompleted);
-
- // process the results if they are finished
- if (lineage.finished === true) {
- var results = lineage.results;
-
- // ensure the events haven't aged off
- if (results.nodes.length > 0) {
- // update the lineage graph
- renderEventLineage(results);
- } else {
- // inform the user that no results were found
- dialog.showOkDialog({
- headerText: 'Lineage Results',
- dialogContent: 'The lineage search has completed successfully but there no results were found. The events may have aged off.'
- });
- }
+ // for the lineage
+ pollLineage();
+ }, 2000);
+ }
+ };
- // close the searching.. dialog
- closeDialog();
- } else {
- lineageTimer = setTimeout(function () {
- // clear the timer since we've been invoked
- lineageTimer = null;
-
- // for the lineage
- pollLineage();
- }, 2000);
- }
- };
+ // once the query is submitted wait until its finished
+ submitLineage(lineageRequest).done(function (response) {
+ lineage = response.lineage;
- // once the query is submitted wait until its finished
- submitLineage(lineageRequest).done(function (response) {
- lineage = response.lineage;
+ // process the lineage, if its not done computing wait 1 second before checking again
+ processLineage(1);
+ }).fail(closeDialog);
+ };
- // process the lineage, if its not done computing wait 1 second before checking again
- processLineage(1);
- }).fail(closeDialog);
- };
+ // handles updating the lineage graph
+ var renderEventLineage = function (lineageResults) {
+ addLineage(lineageResults.nodes, lineageResults.links, provenanceTableCtrl);
+ };
- // handles updating the lineage graph
- var renderEventLineage = function (lineageResults) {
- addLineage(lineageResults.nodes, lineageResults.links, provenanceTableCtrl);
+ // collapses the lineage for the specified event in the specified direction
+ var collapseLineage = function (eventId, provenanceTableCtrl) {
+ // get the event in question and collapse in the appropriate direction
+ provenanceTableCtrl.getEventDetails(eventId, clusterNodeId).done(function (response) {
+ var provenanceEvent = response.provenanceEvent;
+ var eventUuid = provenanceEvent.flowFileUuid;
+ var eventUuids = d3.set(provenanceEvent.childUuids);
+
+ // determines if the specified event should be removable based on if the collapsing is fanning in/out
+ var allowEventRemoval = function (fanIn, node) {
+ if (fanIn) {
+ return node.id !== eventId;
+ } else {
+ return node.flowFileUuid !== eventUuid && $.inArray(eventUuid, node.parentUuids) === -1;
+ }
};
- // collapses the lineage for the specified event in the specified direction
- var collapseLineage = function (eventId, provenanceTableCtrl) {
- // get the event in question and collapse in the appropriate direction
- provenanceTableCtrl.getEventDetails(eventId, clusterNodeId).done(function (response) {
- var provenanceEvent = response.provenanceEvent;
- var eventUuid = provenanceEvent.flowFileUuid;
- var eventUuids = d3.set(provenanceEvent.childUuids);
-
- // determines if the specified event should be removable based on if the collapsing is fanning in/out
- var allowEventRemoval = function (fanIn, node) {
- if (fanIn) {
- return node.id !== eventId;
- } else {
- return node.flowFileUuid !== eventUuid && $.inArray(eventUuid, node.parentUuids) === -1;
- }
- };
-
- // determines if the specified link should be removable based on if the collapsing is fanning in/out
- var allowLinkRemoval = function (fanIn, link) {
- if (fanIn) {
- return true;
- } else {
- return link.flowFileUuid !== eventUuid;
- }
- };
-
- // the event is fan in if the flowfile uuid is in the children
- var fanIn = $.inArray(eventUuid, provenanceEvent.childUuids) >= 0;
-
- // collapses the specified uuids
- var collapse = function (uuids) {
- var newUuids = false;
-
- // consider each node for being collapsed
- $.each(nodeLookup.values(), function (_, node) {
- // if this node is in the uuids remove it unless its the original event or is part of this and another lineage
- if (uuids.has(node.flowFileUuid) && allowEventRemoval(fanIn, node)) {
- // remove it from the look lookup
- nodeLookup.remove(node.id);
-
- // include all related outgoing flow file uuids
- $.each(node.outgoing, function (_, outgoing) {
- if (!uuids.has(outgoing.flowFileUuid)) {
- uuids.add(outgoing.flowFileUuid);
- newUuids = true;
- }
- });
- }
- });
+ // determines if the specified link should be removable based on if the collapsing is fanning in/out
+ var allowLinkRemoval = function (fanIn, link) {
+ if (fanIn) {
+ return true;
+ } else {
+ return link.flowFileUuid !== eventUuid;
+ }
+ };
- // update the link data
- $.each(linkLookup.values(), function (_, link) {
- // if this link is in the uuids remove it
- if (uuids.has(link.flowFileUuid) && allowLinkRemoval(fanIn, link)) {
- // remove it from the link lookup
- linkLookup.remove(link.id);
-
- // add a related uuid that needs to be collapse
- var next = link.target;
- if (!uuids.has(next.flowFileUuid)) {
- uuids.add(next.flowFileUuid);
- newUuids = true;
- }
+ // the event is fan in if the flowfile uuid is in the children
+ var fanIn = $.inArray(eventUuid, provenanceEvent.childUuids) >= 0;
+
+ // collapses the specified uuids
+ var collapse = function (uuids) {
+ var newUuids = false;
+
+ // consider each node for being collapsed
+ $.each(nodeLookup.values(), function (_, node) {
+ // if this node is in the uuids remove it unless its the original event or is part of this and another lineage
+ if (uuids.has(node.flowFileUuid) && allowEventRemoval(fanIn, node)) {
+ // remove it from the look lookup
+ nodeLookup.remove(node.id);
+
+ // include all related outgoing flow file uuids
+ $.each(node.outgoing, function (_, outgoing) {
+ if (!uuids.has(outgoing.flowFileUuid)) {
+ uuids.add(outgoing.flowFileUuid);
+ newUuids = true;
}
});
+ }
+ });
- // collapse any related uuids
- if (newUuids) {
- collapse(uuids);
+ // update the link data
+ $.each(linkLookup.values(), function (_, link) {
+ // if this link is in the uuids remove it
+ if (uuids.has(link.flowFileUuid) && allowLinkRemoval(fanIn, link)) {
+ // remove it from the link lookup
+ linkLookup.remove(link.id);
+
+ // add a related uuid that needs to be collapse
+ var next = link.target;
+ if (!uuids.has(next.flowFileUuid)) {
+ uuids.add(next.flowFileUuid);
+ newUuids = true;
}
- };
-
- // collapse the specified uuids
- collapse(eventUuids);
-
- // update the layout
- refresh(provenanceTableCtrl);
+ }
});
- };
- // add menu items
- menuItems.push({
- 'class': 'lineage-view-parents',
- 'text': 'Find parents',
- 'click': function () {
- expandLineage({
- lineageRequestType: 'PARENTS',
- eventId: d.id,
- clusterNodeId: clusterNodeId
- });
- }
- }, {
- 'class': 'lineage-view-children',
- 'text': 'Expand',
- 'click': function () {
- expandLineage({
- lineageRequestType: 'CHILDREN',
- eventId: d.id,
- clusterNodeId: clusterNodeId
- });
- }
- }, {
- 'class': 'lineage-collapse-children',
- 'text': 'Collapse',
- 'click': function () {
- // collapse the children lineage
- collapseLineage(d.id, provenanceTableCtrl);
+ // collapse any related uuids
+ if (newUuids) {
+ collapse(uuids);
}
+ };
+
+ // collapse the specified uuids
+ collapse(eventUuids);
+
+ // update the layout
+ refresh(provenanceTableCtrl);
+ });
+ };
+
+ // add menu items
+ menuItems.push({
+ 'class': 'lineage-view-parents',
+ 'text': 'Find parents',
+ 'click': function () {
+ expandLineage({
+ lineageRequestType: 'PARENTS',
+ eventId: d.id,
+ clusterNodeId: clusterNodeId
});
}
+ }, {
+ 'class': 'lineage-view-children',
+ 'text': 'Expand',
+ 'click': function () {
+ expandLineage({
+ lineageRequestType: 'CHILDREN',
+ eventId: d.id,
+ clusterNodeId: clusterNodeId
+ });
+ }
+ }, {
+ 'class': 'lineage-collapse-children',
+ 'text': 'Collapse',
+ 'click': function () {
+ // collapse the children lineage
+ collapseLineage(d.id, provenanceTableCtrl);
+ }
+ });
+ }
+
+ // show the context menu for an event
+ addContextMenuItems(menuItems);
+ };
+
+ // renders event nodes
+ var renderEvent = function (events, provenanceTableCtrl) {
+ events
+ .on('contextmenu', function (d) {
+ // select the current node for a visible cue
+ d3.select('#event-node-' + d.id).classed('context', true);
+
+ // show the context menu
+ showContextMenu(d, provenanceTableCtrl);
+ })
+ .on('mousedown', function (d) {
+ d3.event.stopPropagation();
+ });
- // show the context menu for an event
- addContextMenuItems(menuItems);
+ events
+ .classed('event', true)
+ .append('circle')
+ .classed('selected', function (d) {
+ return d.id === eventId;
+ })
+ .attr({
+ 'r': 8,
+ 'fill': '#aabbc3',
+ 'stroke': '#000',
+ 'stroke-width': 1.0,
+ 'id': function (d) {
+ return 'event-node-' + d.id;
+ }
});
events