NIFI-820:

- Creating a context menu item for accessing provenance directly for a selected component.
This commit is contained in:
Matt Gilman 2015-10-26 10:16:01 -04:00
parent 26edab3185
commit f8c3377c84
6 changed files with 96 additions and 22 deletions

View File

@ -15,7 +15,9 @@
limitations under the License. limitations under the License.
--%> --%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %> <%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="provenance"> <div id="provenance">
<span id="intial-component-query" class="hidden"><c:out value="${param.componentId}"/></span>
<span id="nifi-controller-uri" class="hidden"></span> <span id="nifi-controller-uri" class="hidden"></span>
<span id="nifi-content-viewer-url" class="hidden"></span> <span id="nifi-content-viewer-url" class="hidden"></span>
<div id="provenance-header-and-filter"> <div id="provenance-header-and-filter">

View File

@ -57,10 +57,11 @@ div.context-menu-item.hover {
color: #027fd2; color: #027fd2;
} }
img.context-menu-item-img { .context-menu-item-img {
float: left; float: left;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-size: cover;
} }
div.context-menu-item-text { div.context-menu-item-text {
@ -72,6 +73,10 @@ div.context-menu-item-text {
font-size: 11px; font-size: 11px;
} }
div.context-menu-provenance {
background-position: top left;
}
/* /*
General Styles General Styles
*/ */

View File

@ -426,6 +426,22 @@ nf.Actions = (function () {
} }
}, },
/**
* Opens provenance with the component in the specified selection.
*
* @argument {selection} selection The selection
*/
openProvenance: function (selection) {
if (selection.size() === 1) {
var selectionData = selection.datum();
// open the provenance page with the specified component
nf.Shell.showPage('provenance?' + $.param({
componentId: selectionData.component.id
}));
}
},
/** /**
* Starts the components in the specified selection. * Starts the components in the specified selection.
* *

View File

@ -245,6 +245,20 @@ nf.ContextMenu = (function () {
return nf.CanvasUtils.isProcessGroup(selection); return nf.CanvasUtils.isProcessGroup(selection);
}; };
/**
* Determines whether the current selection could have provenance.
*
* @param {selection} selection
*/
var canAccessProvenance = function (selection) {
// ensure the correct number of components are selected
if (selection.size() !== 1) {
return false;
}
return !nf.CanvasUtils.isConnection(selection) && !nf.CanvasUtils.isProcessGroup(selection) && !nf.CanvasUtils.isRemoteProcessGroup(selection) && nf.Common.canAccessProvenance();
};
/** /**
* Determines whether the current selection is a remote process group. * Determines whether the current selection is a remote process group.
* *
@ -313,7 +327,12 @@ nf.ContextMenu = (function () {
$(this).removeClass('hover'); $(this).removeClass('hover');
}).appendTo(contextMenu); }).appendTo(contextMenu);
$('<img class="context-menu-item-img"></img>').attr('src', item['img']).appendTo(menuItem); // create the img and conditionally add the style
var img = $('<div class="context-menu-item-img"></div>').css('background-image', 'url(' + item['img'] + ')').appendTo(menuItem);
if (nf.Common.isDefinedAndNotNull(item['imgStyle'])) {
img.addClass(item['imgStyle']);
}
$('<div class="context-menu-item-text"></div>').text(item['text']).appendTo(menuItem); $('<div class="context-menu-item-text"></div>').text(item['text']).appendTo(menuItem);
$('<div class="clear"></div>').appendTo(menuItem); $('<div class="clear"></div>').appendTo(menuItem);
} }
@ -360,6 +379,7 @@ nf.ContextMenu = (function () {
{condition: canStartTransmission, menuItem: {img: 'images/iconTransmissionActive.png', text: 'Enable transmission', action: 'enableTransmission'}}, {condition: canStartTransmission, menuItem: {img: 'images/iconTransmissionActive.png', text: 'Enable transmission', action: 'enableTransmission'}},
{condition: canStopTransmission, menuItem: {img: 'images/iconTransmissionInactive.png', text: 'Disable transmission', action: 'disableTransmission'}}, {condition: canStopTransmission, menuItem: {img: 'images/iconTransmissionInactive.png', text: 'Disable transmission', action: 'disableTransmission'}},
{condition: supportsStats, menuItem: {img: 'images/iconChart.png', text: 'Stats', action: 'showStats'}}, {condition: supportsStats, menuItem: {img: 'images/iconChart.png', text: 'Stats', action: 'showStats'}},
{condition: canAccessProvenance, menuItem: {img: 'images/iconProvenance.png', imgStyle: 'context-menu-provenance', text: 'Data provenance', action: 'openProvenance'}},
{condition: canMoveToFront, menuItem: {img: 'images/iconToFront.png', text: 'Bring to front', action: 'toFront'}}, {condition: canMoveToFront, menuItem: {img: 'images/iconToFront.png', text: 'Bring to front', action: 'toFront'}},
{condition: isConnection, menuItem: {img: 'images/iconGoTo.png', text: 'Go to source', action: 'showSource'}}, {condition: isConnection, menuItem: {img: 'images/iconGoTo.png', text: 'Go to source', action: 'showSource'}},
{condition: isConnection, menuItem: {img: 'images/iconGoTo.png', text: 'Go to destination', action: 'showDestination'}}, {condition: isConnection, menuItem: {img: 'images/iconGoTo.png', text: 'Go to destination', action: 'showDestination'}},
@ -416,6 +436,7 @@ nf.ContextMenu = (function () {
addMenuItem(contextMenu, { addMenuItem(contextMenu, {
img: menuItem.img, img: menuItem.img,
imgStyle: menuItem.imgStyle,
text: menuItem.text, text: menuItem.text,
click: function (evt) { click: function (evt) {
executeAction(menuItem.action, selection, evt); executeAction(menuItem.action, selection, evt);

View File

@ -258,19 +258,6 @@ nf.ProvenanceTable = (function () {
* @param {boolean} isClustered Whether or not this NiFi clustered * @param {boolean} isClustered Whether or not this NiFi clustered
*/ */
var initSearchDialog = function (isClustered) { var initSearchDialog = function (isClustered) {
$.ajax({
type: 'GET',
url: config.urls.searchOptions,
dataType: 'json'
}).done(function (response) {
var provenanceOptions = response.provenanceOptions;
// load all searchable fields
$.each(provenanceOptions.searchableFields, function (_, field) {
appendSearchableField(field);
});
});
// configure the start and end date picker // configure the start and end date picker
$('#provenance-search-start-date, #provenance-search-end-date').datepicker({ $('#provenance-search-start-date, #provenance-search-end-date').datepicker({
showAnim: '', showAnim: '',
@ -402,6 +389,19 @@ nf.ProvenanceTable = (function () {
} }
}] }]
}); });
return $.ajax({
type: 'GET',
url: config.urls.searchOptions,
dataType: 'json'
}).done(function (response) {
var provenanceOptions = response.provenanceOptions;
// load all searchable fields
$.each(provenanceOptions.searchableFields, function (_, field) {
appendSearchableField(field);
});
});
}; };
/** /**
@ -441,6 +441,11 @@ nf.ProvenanceTable = (function () {
$('<div class="searchable-field-value"><input type="text" class="searchable-field-input"/></div>').appendTo(searchableField); $('<div class="searchable-field-value"><input type="text" class="searchable-field-input"/></div>').appendTo(searchableField);
$('<div class="clear"></div>').appendTo(searchableField); $('<div class="clear"></div>').appendTo(searchableField);
// make the component id accessible for populating
if (field.id === 'ProcessorID') {
searchableField.find('input').addClass('searchable-component-id');
}
// ensure the no searchable fields message is hidden // ensure the no searchable fields message is hidden
$('#no-searchable-fields').hide(); $('#no-searchable-fields').hide();
}; };
@ -949,12 +954,23 @@ nf.ProvenanceTable = (function () {
* @param {boolean} isClustered Whether or not this instance is clustered * @param {boolean} isClustered Whether or not this instance is clustered
*/ */
init: function (isClustered) { init: function (isClustered) {
return loadLineageCapabilities().done(function () { return $.Deferred(function (deferred) {
initDetailsDialog(); // handles init failure
initProvenanceQueryDialog(); var failure = function (xhr, status, error) {
initSearchDialog(isClustered); deferred.reject();
initProvenanceTable(isClustered); nf.Common.handleAjaxError(xhr, status, error);
}).fail(nf.Common.handleAjaxError); };
// load the lineage capabilities
loadLineageCapabilities().done(function () {
initDetailsDialog();
initProvenanceQueryDialog();
initProvenanceTable(isClustered);
initSearchDialog(isClustered).done(function () {
deferred.resolve();
}).fail(failure);
}).fail(failure);
}).promise();
}, },
/** /**

View File

@ -178,8 +178,22 @@ nf.Provenance = (function () {
$.when(loadControllerConfig(), loadAuthorities(), detectedCluster()).done(function () { $.when(loadControllerConfig(), loadAuthorities(), detectedCluster()).done(function () {
// create the provenance table // create the provenance table
nf.ProvenanceTable.init(isClustered).done(function () { nf.ProvenanceTable.init(isClustered).done(function () {
var search;
// look for a processor id in the query search
var initialComponentId = $('#intial-component-query').text();
if ($.trim(initialComponentId) !== '') {
// populate initial search component
$('input.searchable-component-id').val(initialComponentId);
// build the search criteria
search = {
'search[ProcessorID]': initialComponentId
};
}
// load the provenance table // load the provenance table
nf.ProvenanceTable.loadProvenanceTable(); nf.ProvenanceTable.loadProvenanceTable(search);
// once the table is initialized, finish initializing the page // once the table is initialized, finish initializing the page
initializeProvenancePage().done(function () { initializeProvenancePage().done(function () {