NIFI-307:

- Updating how action buttons are invoked in tables throughout the application.
This commit is contained in:
Matt Gilman 2015-02-02 12:44:51 -05:00
parent 037f36dd98
commit 9cd9d126e3
6 changed files with 564 additions and 585 deletions

View File

@ -109,6 +109,22 @@ nf.ClusterTable = (function () {
return nf.Common.escapeHtml(node.address) + ':' + nf.Common.escapeHtml(node.apiPort);
};
/**
* Prompts to verify node connection.
*
* @argument {object} node The node
*/
var promptForConnect = function (node) {
// prompt to connect
nf.Dialog.showYesNoDialog({
dialogContent: 'Connect \'' + formatNodeAddress(node) + '\' to this cluster?',
overlayBackground: false,
yesHandler: function () {
connect(node.nodeId);
}
});
};
/**
* Connects the node in the specified row.
*
@ -132,6 +148,22 @@ nf.ClusterTable = (function () {
}).fail(nf.Common.handleAjaxError);
};
/**
* Prompts to verify node disconnection.
*
* @argument {object} node The node
*/
var promptForDisconnect = function (node) {
// prompt for disconnect
nf.Dialog.showYesNoDialog({
dialogContent: 'Disconnect \'' + formatNodeAddress(node) + '\' from the cluster?',
overlayBackground: false,
yesHandler: function () {
disconnect(node.nodeId);
}
});
};
/**
* Disconnects the node in the specified row.
*
@ -155,6 +187,22 @@ nf.ClusterTable = (function () {
}).fail(nf.Common.handleAjaxError);
};
/**
* Prompts to verify node disconnection.
*
* @argument {object} node The node
*/
var promptForRemoval = function (node) {
// prompt for disconnect
nf.Dialog.showYesNoDialog({
dialogContent: 'Remove \'' + formatNodeAddress(node) + '\' from the cluster?',
overlayBackground: false,
yesHandler: function () {
remove(node.nodeId);
}
});
};
/**
* Disconnects the node in the specified row.
*
@ -230,6 +278,86 @@ nf.ClusterTable = (function () {
// perform the filter
return item[args.property].search(filterExp) >= 0;
};
/**
* Show the node details.
*
* @argument {object} item The item
*/
var showNodeDetails = function (item) {
$.ajax({
type: 'GET',
url: config.urls.nodes + '/' + encodeURIComponent(item.nodeId),
dataType: 'json'
}).done(function (response) {
var node = response.node;
// update the dialog fields
$('#node-id').text(node.nodeId);
$('#node-address').text(formatNodeAddress(node));
// format the events
var events = $('#node-events');
if ($.isArray(node.events) && node.events.length > 0) {
var eventMessages = [];
$.each(node.events, function (i, event) {
eventMessages.push(event.timestamp + ": " + event.message);
});
$('<div></div>').append(nf.Common.formatUnorderedList(eventMessages)).appendTo(events);
} else {
events.append('<div><span class="unset">None</span></div>');
}
// show the dialog
$('#node-details-dialog').modal('show');
}).fail(nf.Common.handleAjaxError);
};
/**
* Makes the specified node the primary node of the cluster.
*
* @argument {object} item The node item
*/
var makePrimary = function (item) {
$.ajax({
type: 'PUT',
url: config.urls.nodes + '/' + encodeURIComponent(item.nodeId),
data: {
primary: true
},
dataType: 'json'
}).done(function (response) {
var grid = $('#cluster-table').data('gridInstance');
var data = grid.getData();
var node = response.node;
// start the update
data.beginUpdate();
data.updateItem(node.nodeId, node);
// need to find the previous primary node
// get the property grid data
var clusterItems = data.getItems();
$.each(clusterItems, function (i, otherNode) {
// attempt to identify the previous primary node
if (node.nodeId !== otherNode.nodeId && otherNode.primary === true) {
// reset its primary status
otherNode.primary = false;
otherNode.status = 'CONNECTED';
// set the new node state
data.updateItem(otherNode.nodeId, otherNode);
// no need to continue processing
return false;
}
});
// end the update
data.endUpdate();
}).fail(nf.Common.handleAjaxError);
};
return {
/**
@ -292,7 +420,7 @@ nf.ClusterTable = (function () {
// define a custom formatter for the more details column
var moreDetailsFormatter = function (row, cell, value, columnDef, dataContext) {
return '<img src="images/iconDetails.png" title="View Details" class="pointer" style="margin-top: 4px;" onclick="javascript:nf.ClusterTable.showNodeDetails(\'' + row + '\');"/>';
return '<img src="images/iconDetails.png" title="View Details" class="pointer show-node-details" style="margin-top: 4px;"/>';
};
// define a custom formatter for the run status column
@ -348,11 +476,11 @@ nf.ClusterTable = (function () {
// return the appropriate markup
if (canConnect) {
return '<img src="images/iconConnect.png" title="Connect" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.ClusterTable.promptForConnect(\'' + row + '\');"/>&nbsp;<img src="images/iconDelete.png" title="Remove" class="pointer" onclick="javascript:nf.ClusterTable.promptForRemoval(\'' + row + '\');"/>';
return '<img src="images/iconConnect.png" title="Connect" class="pointer prompt-for-connect" style="margin-top: 2px;"/>&nbsp;<img src="images/iconDelete.png" title="Remove" class="pointer prompt-for-removal"/>';
} else if (canDisconnect) {
var actions = '<img src="images/iconDisconnect.png" title="Disconnect" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.ClusterTable.promptForDisconnect(\'' + row + '\');"/>';
var actions = '<img src="images/iconDisconnect.png" title="Disconnect" class="pointer prompt-for-disconnect" style="margin-top: 2px;"/>';
if (canBecomePrimary) {
actions += '&nbsp;<img src="images/iconPrimary.png" title="Make Primary" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.ClusterTable.makePrimary(\'' + row + '\');"/>';
actions += '&nbsp;<img src="images/iconPrimary.png" title="Make Primary" class="pointer make-primary" style="margin-top: 2px;"/>';
}
return actions;
} else {
@ -360,7 +488,7 @@ nf.ClusterTable = (function () {
}
};
columnModel.push({id: 'action', label: '&nbsp;', formatter: actionFormatter, resizable: false, sortable: false, width: 80, maxWidth: 80});
columnModel.push({id: 'actions', label: '&nbsp;', formatter: actionFormatter, resizable: false, sortable: false, width: 80, maxWidth: 80});
}
var clusterOptions = {
@ -398,6 +526,31 @@ nf.ClusterTable = (function () {
sortAsc: args.sortAsc
}, clusterData);
});
// configure a click listener
clusterGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var item = clusterData.getItem(args.row);
// determine the desired action
if (clusterGrid.getColumns()[args.cell].id === 'actions') {
if (target.hasClass('prompt-for-connect')) {
promptForConnect(item);
} else if (target.hasClass('prompt-for-removal')) {
promptForRemoval(item);
} else if (target.hasClass('prompt-for-disconnect')) {
promptForDisconnect(item);
} else if (target.hasClass('make-primary')) {
makePrimary(item);
}
} else if (clusterGrid.getColumns()[args.cell].id === 'moreDetails') {
if (target.hasClass('show-node-details')) {
showNodeDetails(item);
}
}
});
// wire up the dataview to the grid
clusterData.onRowCountChanged.subscribe(function (e, args) {
@ -419,122 +572,6 @@ nf.ClusterTable = (function () {
$('#displayed-nodes').text('0');
},
/**
* Prompts to verify node connection.
*
* @argument {string} row The row
*/
promptForConnect: function (row) {
var grid = $('#cluster-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var node = data.getItem(row);
// prompt to connect
nf.Dialog.showYesNoDialog({
dialogContent: 'Connect \'' + formatNodeAddress(node) + '\' to this cluster?',
overlayBackground: false,
yesHandler: function () {
connect(node.nodeId);
}
});
}
},
/**
* Prompts to verify node disconnection.
*
* @argument {string} row The row
*/
promptForDisconnect: function (row) {
var grid = $('#cluster-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var node = data.getItem(row);
// prompt for disconnect
nf.Dialog.showYesNoDialog({
dialogContent: 'Disconnect \'' + formatNodeAddress(node) + '\' from the cluster?',
overlayBackground: false,
yesHandler: function () {
disconnect(node.nodeId);
}
});
}
},
/**
* Makes the specified node the primary node of the cluster.
*
* @argument {string} row The row
*/
makePrimary: function (row) {
var grid = $('#cluster-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
$.ajax({
type: 'PUT',
url: config.urls.nodes + '/' + encodeURIComponent(item.nodeId),
data: {
primary: true
},
dataType: 'json'
}).done(function (response) {
var node = response.node;
// start the update
data.beginUpdate();
data.updateItem(node.nodeId, node);
// need to find the previous primary node
// get the property grid data
var clusterItems = data.getItems();
$.each(clusterItems, function (i, otherNode) {
// attempt to identify the previous primary node
if (node.nodeId !== otherNode.nodeId && otherNode.primary === true) {
// reset its primary status
otherNode.primary = false;
otherNode.status = 'CONNECTED';
// set the new node state
data.updateItem(otherNode.nodeId, otherNode);
// no need to continue processing
return false;
}
});
// end the update
data.endUpdate();
}).fail(nf.Common.handleAjaxError);
}
},
/**
* Prompts to verify node disconnection.
*
* @argument {string} row The row
*/
promptForRemoval: function (row) {
var grid = $('#cluster-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var node = data.getItem(row);
// prompt for disconnect
nf.Dialog.showYesNoDialog({
dialogContent: 'Remove \'' + formatNodeAddress(node) + '\' from the cluster?',
overlayBackground: false,
yesHandler: function () {
remove(node.nodeId);
}
});
}
},
/**
* Update the size of the grid based on its container's current size.
*/
@ -575,46 +612,6 @@ nf.ClusterTable = (function () {
$('#total-nodes').text('0');
}
}).fail(nf.Common.handleAjaxError);
},
/**
* Populate the expanded row.
*
* @argument {string} row The row
*/
showNodeDetails: function (row) {
var grid = $('#cluster-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
$.ajax({
type: 'GET',
url: config.urls.nodes + '/' + encodeURIComponent(item.nodeId),
dataType: 'json'
}).done(function (response) {
var node = response.node;
// update the dialog fields
$('#node-id').text(node.nodeId);
$('#node-address').text(formatNodeAddress(node));
// format the events
var events = $('#node-events');
if ($.isArray(node.events) && node.events.length > 0) {
var eventMessages = [];
$.each(node.events, function (i, event) {
eventMessages.push(event.timestamp + ": " + event.message);
});
$('<div></div>').append(nf.Common.formatUnorderedList(eventMessages)).appendTo(events);
} else {
events.append('<div><span class="unset">None</span></div>');
}
// show the dialog
$('#node-details-dialog').modal('show');
}).fail(nf.Common.handleAjaxError);
}
}
};
}());

View File

@ -110,6 +110,26 @@ nf.CountersTable = (function () {
// perform the filter
return item[args.property].search(filterExp) >= 0;
};
/**
* Resets the specified counter.
*
* @argument {object} item The counter item
*/
var resetCounter = function (item) {
$.ajax({
type: 'PUT',
url: config.urls.counters + '/' + encodeURIComponent(item.id),
dataType: 'json'
}).done(function (response) {
var counter = response.counter;
// get the table and update the row accordingly
var countersGrid = $('#counters-table').data('gridInstance');
var countersData = countersGrid.getData();
countersData.updateItem(counter.id, counter);
}).fail(nf.Common.handleAjaxError);
};
return {
/**
@ -159,7 +179,7 @@ nf.CountersTable = (function () {
if (nf.Common.isDFM()) {
// function for formatting the actions column
var actionFormatter = function (row, cell, value, columnDef, dataContext) {
return '<img src="images/iconResetCounter.png" title="Reset" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.CountersTable.resetCounter(\'' + row + '\');"/>';
return '<img src="images/iconResetCounter.png" title="Reset" class="pointer reset-counter" style="margin-top: 2px;"/>';
};
// add the action column
@ -202,6 +222,21 @@ nf.CountersTable = (function () {
sortAsc: args.sortAsc
}, countersData);
});
// configure a click listener
countersGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var item = countersData.getItem(args.row);
// determine the desired action
if (countersGrid.getColumns()[args.cell].id === 'actions') {
if (target.hasClass('reset-counter')) {
resetCounter(item);
}
}
});
// wire up the dataview to the grid
countersData.onRowCountChanged.subscribe(function (e, args) {
@ -223,32 +258,6 @@ nf.CountersTable = (function () {
$('#displayed-counters').text('0');
},
/**
* Resets the specified counter.
*
* @argument {string} row The row
*/
resetCounter: function (row) {
var grid = $('#counters-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
$.ajax({
type: 'PUT',
url: config.urls.counters + '/' + encodeURIComponent(item.id),
dataType: 'json'
}).done(function (response) {
var counter = response.counter;
// get the table and update the row accordingly
var countersGrid = $('#counters-table').data('gridInstance');
var countersData = countersGrid.getData();
countersData.updateItem(counter.id, counter);
}).fail(nf.Common.handleAjaxError);
}
},
/**
* Update the size of the grid based on its container's current size.
*/

View File

@ -244,7 +244,7 @@ nf.HistoryTable = (function () {
// define a custom formatter for the more details column
var moreDetailsFormatter = function (row, cell, value, columnDef, dataContext) {
return '<img src="images/iconDetails.png" title="View Details" class="pointer" style="margin-top: 4px;" onclick="javascript:nf.HistoryTable.showActionDetails(\'' + row + '\');"/>';
return '<img src="images/iconDetails.png" title="View Details" class="pointer show-action-details" style="margin-top: 4px;"/>';
};
// initialize the templates table
@ -283,6 +283,21 @@ nf.HistoryTable = (function () {
});
historyGrid.setSortColumn('timestamp', false);
// configure a click listener
historyGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var item = historyModel.getItem(args.row);
// determine the desired action
if (historyGrid.getColumns()[args.cell].id === 'moreDetails') {
if (target.hasClass('show-action-details')) {
showActionDetails(item);
}
}
});
// listen for when the viewport changes so we can fetch the appropriate records
historyGrid.onViewportChanged.subscribe(function (e, args) {
var vp = historyGrid.getViewport();
@ -325,6 +340,68 @@ nf.HistoryTable = (function () {
nf.HistoryTable.loadHistoryTable();
}).fail(nf.Common.handleAjaxError);
};
/**
* Shows the details for the specified action.
*
* @param {object} action
*/
var showActionDetails = function (action) {
// create the markup for the dialog
var detailsMarkup = $('<div></div>').append(
$('<div class="action-detail"><div class="history-details-name">Id</div>' + nf.Common.escapeHtml(action.sourceId) + '</div>'));
// get any component details
var componentDetails = action.componentDetails;
// inspect the operation to determine if there are any component details
if (nf.Common.isDefinedAndNotNull(componentDetails)) {
if (action.sourceType === 'Processor') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Type</div>' + nf.Common.escapeHtml(componentDetails.type) + '</div>'));
} else if (action.sourceType === 'RemoteProcessGroup') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Uri</div>' + nf.Common.formatValue(componentDetails.uri) + '</div>'));
}
}
// get any action details
var actionDetails = action.actionDetails;
// inspect the operation to determine if there are any action details
if (nf.Common.isDefinedAndNotNull(actionDetails)) {
if (action.operation === 'Configure') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Name</div>' + nf.Common.formatValue(actionDetails.name) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Value</div>' + nf.Common.formatValue(actionDetails.value) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Value</div>' + nf.Common.formatValue(actionDetails.previousValue) + '</div>'));
} else if (action.operation === 'Connect' || action.operation === 'Disconnect') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Source Id</div>' + nf.Common.escapeHtml(actionDetails.sourceId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Source Name</div>' + nf.Common.formatValue(actionDetails.sourceName) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Source Type</div>' + nf.Common.escapeHtml(actionDetails.sourceType) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Relationship(s)</div>' + nf.Common.formatValue(actionDetails.relationship) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Id</div>' + nf.Common.escapeHtml(actionDetails.destinationId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Name</div>' + nf.Common.formatValue(actionDetails.destinationName) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Type</div>' + nf.Common.escapeHtml(actionDetails.destinationType) + '</div>'));
} else if (action.operation === 'Move') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Group</div>' + nf.Common.formatValue(actionDetails.group) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Group Id</div>' + nf.Common.escapeHtml(actionDetails.groupId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Group</div>' + nf.Common.formatValue(actionDetails.previousGroup) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Group Id</div>' + nf.Common.escapeHtml(actionDetails.previousGroupId) + '</div>'));
} else if (action.operation === 'Purge') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">End Date</div>' + nf.Common.escapeHtml(actionDetails.endDate) + '</div>'));
}
}
// populate the dialog
$('#action-details').append(detailsMarkup);
// show the dialog
$('#action-details-dialog').modal('show');
};
return {
init: function () {
@ -356,74 +433,6 @@ nf.HistoryTable = (function () {
// request refresh of the current 'page'
historyGrid.onViewportChanged.notify();
},
/**
* Shows the details for the specified action.
*
* @param {object} index
*/
showActionDetails: function (index) {
var historyGrid = $('#history-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(historyGrid)) {
var historyModel = historyGrid.getData();
var action = historyModel.getItem(index);
// create the markup for the dialog
var detailsMarkup = $('<div></div>').append(
$('<div class="action-detail"><div class="history-details-name">Id</div>' + nf.Common.escapeHtml(action.sourceId) + '</div>'));
// get any component details
var componentDetails = action.componentDetails;
// inspect the operation to determine if there are any component details
if (nf.Common.isDefinedAndNotNull(componentDetails)) {
if (action.sourceType === 'Processor') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Type</div>' + nf.Common.escapeHtml(componentDetails.type) + '</div>'));
} else if (action.sourceType === 'RemoteProcessGroup') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Uri</div>' + nf.Common.formatValue(componentDetails.uri) + '</div>'));
}
}
// get any action details
var actionDetails = action.actionDetails;
// inspect the operation to determine if there are any action details
if (nf.Common.isDefinedAndNotNull(actionDetails)) {
if (action.operation === 'Configure') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Name</div>' + nf.Common.formatValue(actionDetails.name) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Value</div>' + nf.Common.formatValue(actionDetails.value) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Value</div>' + nf.Common.formatValue(actionDetails.previousValue) + '</div>'));
} else if (action.operation === 'Connect' || action.operation === 'Disconnect') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Source Id</div>' + nf.Common.escapeHtml(actionDetails.sourceId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Source Name</div>' + nf.Common.formatValue(actionDetails.sourceName) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Source Type</div>' + nf.Common.escapeHtml(actionDetails.sourceType) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Relationship(s)</div>' + nf.Common.formatValue(actionDetails.relationship) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Id</div>' + nf.Common.escapeHtml(actionDetails.destinationId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Name</div>' + nf.Common.formatValue(actionDetails.destinationName) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Type</div>' + nf.Common.escapeHtml(actionDetails.destinationType) + '</div>'));
} else if (action.operation === 'Move') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Group</div>' + nf.Common.formatValue(actionDetails.group) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Group Id</div>' + nf.Common.escapeHtml(actionDetails.groupId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Group</div>' + nf.Common.formatValue(actionDetails.previousGroup) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Group Id</div>' + nf.Common.escapeHtml(actionDetails.previousGroupId) + '</div>'));
} else if (action.operation === 'Purge') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">End Date</div>' + nf.Common.escapeHtml(actionDetails.endDate) + '</div>'));
}
}
// populate the dialog
$('#action-details').append(detailsMarkup);
// show the dialog
$('#action-details-dialog').modal('show');
}
}
};
}());

View File

@ -553,7 +553,7 @@ nf.ProvenanceTable = (function () {
// define a custom formatter for the more details column
var moreDetailsFormatter = function (row, cell, value, columnDef, dataContext) {
return '<img src="images/iconDetails.png" title="View Details" class="pointer" style="margin-top: 4px;" onclick="javascript:nf.ProvenanceTable.showEventDetailsByIndex(\'' + row + '\');"/>';
return '<img src="images/iconDetails.png" title="View Details" class="pointer show-event-details" style="margin-top: 4px;"/>';
};
// define how general values are formatted
@ -570,12 +570,12 @@ nf.ProvenanceTable = (function () {
// conditionally include the cluster node id
if (nf.Common.SUPPORTS_SVG) {
markup += '<img src="images/iconLineage.png" title="Show Lineage" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.ProvenanceTable.showLineage(\'' + row + '\');"/>';
markup += '<img src="images/iconLineage.png" title="Show Lineage" class="pointer show-lineage" style="margin-top: 2px;"/>';
}
// conditionally support going to the component
if (isInShell && nf.Common.isDefinedAndNotNull(dataContext.groupId)) {
markup += '&nbsp;<img src="images/iconGoTo.png" title="Go To" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.ProvenanceTable.goTo(\'' + row + '\');"/>';
markup += '&nbsp;<img src="images/iconGoTo.png" title="Go To" class="pointer go-to" style="margin-top: 2px;"/>';
}
return markup;
@ -599,7 +599,7 @@ nf.ProvenanceTable = (function () {
// conditionally show the action column
if (nf.Common.SUPPORTS_SVG || isInShell) {
provenanceColumns.push({id: 'action', name: '&nbsp;', formatter: showLineageFormatter, resizable: false, sortable: false, width: 50, maxWidth: 50});
provenanceColumns.push({id: 'actions', name: '&nbsp;', formatter: showLineageFormatter, resizable: false, sortable: false, width: 50, maxWidth: 50});
}
var provenanceOptions = {
@ -641,6 +641,27 @@ nf.ProvenanceTable = (function () {
sortAsc: args.sortAsc
}, provenanceData);
});
// configure a click listener
provenanceGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var item = provenanceData.getItem(args.row);
// determine the desired action
if (provenanceGrid.getColumns()[args.cell].id === 'actions') {
if (target.hasClass('show-lineage')) {
nf.ProvenanceLineage.showLineage(item.flowFileUuid, item.eventId.toString(), item.clusterNodeId);
} else if (target.hasClass('go-to')) {
goTo(item);
}
} else if (provenanceGrid.getColumns()[args.cell].id === 'moreDetails') {
if (target.hasClass('show-event-details')) {
nf.ProvenanceTable.showEventDetails(item);
}
}
});
// wire up the dataview to the grid
provenanceData.onRowCountChanged.subscribe(function (e, args) {
@ -884,6 +905,25 @@ nf.ProvenanceTable = (function () {
}
};
/**
* Goes to the specified component if possible.
*
* @argument {object} item The event it
*/
var goTo = function (item) {
// ensure the component is still present in the flow
if (nf.Common.isDefinedAndNotNull(item.groupId)) {
// only attempt this if we're within a frame
if (top !== window) {
// and our parent has canvas utils and shell defined
if (nf.Common.isDefinedAndNotNull(parent.nf) && nf.Common.isDefinedAndNotNull(parent.nf.CanvasUtils) && nf.Common.isDefinedAndNotNull(parent.nf.Shell)) {
parent.nf.CanvasUtils.showComponent(item.groupId, item.componentId);
parent.$('#shell-close-button').click();
}
}
}
};
return {
/**
* The max delay between requests.
@ -909,31 +949,6 @@ nf.ProvenanceTable = (function () {
}).fail(nf.Common.handleAjaxError);
},
/**
* Goes to the specified component if possible.
*
* @argument {string} row The row
*/
goTo: function (row) {
var grid = $('#provenance-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// ensure the component is still present in the flow
if (nf.Common.isDefinedAndNotNull(item.groupId)) {
// only attempt this if we're within a frame
if (top !== window) {
// and our parent has canvas utils and shell defined
if (nf.Common.isDefinedAndNotNull(parent.nf) && nf.Common.isDefinedAndNotNull(parent.nf.CanvasUtils) && nf.Common.isDefinedAndNotNull(parent.nf.Shell)) {
parent.nf.CanvasUtils.showComponent(item.groupId, item.componentId);
parent.$('#shell-close-button').click();
}
}
}
}
},
/**
* Update the size of the grid based on its container's current size.
*/
@ -1095,36 +1110,6 @@ nf.ProvenanceTable = (function () {
}).fail(closeDialog);
},
/**
* Shows the lineage for the event in the specified row.
*
* @param {type} row
*/
showLineage: function (row) {
var grid = $('#provenance-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
nf.ProvenanceLineage.showLineage(item.flowFileUuid, item.eventId.toString(), item.clusterNodeId);
}
},
/**
* Gets the event details and shows the details dialog.
*
* @param {long} index
*/
showEventDetailsByIndex: function (index) {
var provenanceGrid = $('#provenance-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(provenanceGrid)) {
var provenanceModel = provenanceGrid.getData();
var event = provenanceModel.getItem(index);
// show the event details
nf.ProvenanceTable.showEventDetails(event);
}
},
/**
* Shows the details for the specified action.
*

View File

@ -53,6 +53,22 @@ nf.TemplatesTable = (function () {
data.sort(comparer, sortDetails.sortAsc);
};
/**
* Prompts the user before attempting to delete the specified template.
*
* @argument {object} template The template
*/
var promptToDeleteTemplate = function (template) {
// prompt for deletion
nf.Dialog.showYesNoDialog({
dialogContent: 'Delete template \'' + nf.Common.escapeHtml(template.name) + '\'?',
overlayBackground: false,
yesHandler: function () {
deleteTemplate(template.id);
}
});
};
/**
* Deletes the template with the specified id.
*
@ -177,11 +193,11 @@ nf.TemplatesTable = (function () {
// function for formatting the actions column
var actionFormatter = function (row, cell, value, columnDef, dataContext) {
var markup = '<img src="images/iconExport.png" title="Download" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.TemplatesTable.exportTemplate(\'' + row + '\');"/>';
var markup = '<img src="images/iconExport.png" title="Download" class="pointer export-template" style="margin-top: 2px;"/>';
// all DFMs to remove templates
if (nf.Common.isDFM()) {
markup += '&nbsp;<img src="images/iconDelete.png" title="Remove Template" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.TemplatesTable.promptToDeleteTemplate(\'' + row + '\');"/>';
markup += '&nbsp;<img src="images/iconDelete.png" title="Remove Template" class="pointer prompt-to-delete-template" style="margin-top: 2px;"/>';
}
return markup;
};
@ -230,6 +246,23 @@ nf.TemplatesTable = (function () {
}, templatesData);
});
// configure a click listener
templatesGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var item = templatesData.getItem(args.row);
// determine the desired action
if (templatesGrid.getColumns()[args.cell].id === 'actions') {
if (target.hasClass('export-template')) {
window.open(config.urls.templates + '/' + encodeURIComponent(item.id));
} else if (target.hasClass('prompt-to-delete-template')) {
promptToDeleteTemplate(item);
}
}
});
// wire up the dataview to the grid
templatesData.onRowCountChanged.subscribe(function (e, args) {
templatesGrid.updateRowCount();
@ -260,42 +293,6 @@ nf.TemplatesTable = (function () {
}
},
/**
* Exports the specified template.
*
* @argument {string} row The row
*/
exportTemplate: function (row) {
var grid = $('#templates-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
window.open(config.urls.templates + '/' + encodeURIComponent(item.id));
}
},
/**
* Prompts the user before attempting to delete the specified template.
*
* @argument {string} row The row
*/
promptToDeleteTemplate: function (row) {
var grid = $('#templates-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var template = data.getItem(row);
// prompt for deletion
nf.Dialog.showYesNoDialog({
dialogContent: 'Delete template \'' + nf.Common.escapeHtml(template.name) + '\'?',
overlayBackground: false,
yesHandler: function () {
deleteTemplate(template.id);
}
});
}
},
/**
* Load the processor templates table.
*/

View File

@ -483,7 +483,7 @@ nf.UsersTable = (function () {
// define a custom formatter for the more details column
var moreDetailsFormatter = function (row, cell, value, columnDef, dataContext) {
return '<img src="images/iconDetails.png" title="View Details" class="pointer" style="margin-top: 4px;" onclick="javascript:nf.UsersTable.showUserDetails(\'' + row + '\');"/>';
return '<img src="images/iconDetails.png" title="View Details" class="pointer show-user-details" style="margin-top: 4px;"/>';
};
// function for formatting the last accessed time
@ -566,20 +566,20 @@ nf.UsersTable = (function () {
// if this represents a grouped row
if (nf.Common.isDefinedAndNotNull(dataContext.userGroup) && grouped) {
var actions = '<img src="images/iconEdit.png" title="Edit Access" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.UsersTable.updateGroupAccess(\'' + row + '\');"/>&nbsp;<img src="images/iconRevoke.png" title="Revoke Access" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.UsersTable.revokeGroupAccess(\'' + row + '\');"/>&nbsp;&nbsp;<img src="images/ungroup.png" title="Ungroup" class="pointer" onclick="javascript:nf.UsersTable.ungroup(\'' + row + '\');"/>';
var actions = '<img src="images/iconEdit.png" title="Edit Access" class="pointer update-group-access" style="margin-top: 2px;"/>&nbsp;<img src="images/iconRevoke.png" title="Revoke Access" class="pointer revoke-group-access" style="margin-top: 2px;"/>&nbsp;&nbsp;<img src="images/ungroup.png" title="Ungroup" class="pointer ungroup"/>';
} else {
// return the appropriate markup for an individual user
var actions = '<img src="images/iconEdit.png" title="Edit Access" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.UsersTable.updateUserAccess(\'' + row + '\');"/>';
var actions = '<img src="images/iconEdit.png" title="Edit Access" class="pointer update-user-access" style="margin-top: 2px;"/>';
if (dataContext.status === 'ACTIVE') {
actions += '&nbsp;<img src="images/iconRevoke.png" title="Revoke Access" class="pointer" onclick="javascript:nf.UsersTable.revokeUserAccess(\'' + row + '\');"/>';
actions += '&nbsp;<img src="images/iconRevoke.png" title="Revoke Access" class="pointer revoke-user-access"/>';
// add an ungroup active if appropriate
if (nf.Common.isDefinedAndNotNull(dataContext.userGroup)) {
actions += '&nbsp;&nbsp;<img src="images/ungroup.png" title="Ungroup" class="pointer" style="margin-top: 2px;" onclick="javascript:nf.UsersTable.ungroupUser(\'' + row + '\');"/>';
actions += '&nbsp;&nbsp;<img src="images/ungroup.png" title="Ungroup" class="pointer ungroup-user" style="margin-top: 2px;"/>';
}
} else {
actions += '&nbsp;<img src="images/iconDelete.png" title="Delete Account" class="pointer" onclick="javascript:nf.UsersTable.deleteUserAccount(\'' + row + '\');"/>';
actions += '&nbsp;<img src="images/iconDelete.png" title="Delete Account" class="pointer delete-user-account"/>';
}
}
@ -632,6 +632,37 @@ nf.UsersTable = (function () {
sortAsc: args.sortAsc
}, usersData);
});
// configure a click listener
usersGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var item = usersData.getItem(args.row);
// determine the desired action
if (usersGrid.getColumns()[args.cell].id === 'actions') {
if (target.hasClass('update-group-access')) {
updateGroupAccess(item);
} else if (target.hasClass('revoke-group-access')) {
revokeGroupAccess(item);
} else if (target.hasClass('ungroup')) {
ungroup(item);
} else if (target.hasClass('update-user-access')) {
updateUserAccess(item);
} else if (target.hasClass('revoke-user-access')) {
revokeUserAccess(item);
} else if (target.hasClass('ungroup-user')) {
ungroupUser(item);
} else if (target.hasClass('delete-user-account')) {
deleteUserAccount(item);
}
} else if (usersGrid.getColumns()[args.cell].id === 'moreDetails') {
if (target.hasClass('show-user-details')) {
showUserDetails(item);
}
}
});
// wire up the dataview to the grid
usersData.onRowCountChanged.subscribe(function (e, args) {
@ -804,6 +835,182 @@ nf.UsersTable = (function () {
}
};
/**
* Shows details for the specified user.
*
* @param {object} user
*/
var showUserDetails = function (user) {
var grouped = $('#group-collaspe-checkbox').hasClass('checkbox-checked');
// update the dialog fields
$('#user-name-details-dialog').text(user.userName);
$('#user-dn-details-dialog').text(user.dn);
// handle fields that could vary for groups
if (nf.Common.isDefinedAndNotNull(user.creation)) {
$('#user-created-details-dialog').text(user.creation);
} else if (grouped && nf.Common.isDefinedAndNotNull(user.userGroup)) {
$('#user-created-details-dialog').html('<span class="unset">Multiple users with different creation timestamps.</span>');
} else {
$('#user-created-details-dialog').html('<span class="unset">No creation timestamp set</span>');
}
if (nf.Common.isDefinedAndNotNull(user.lastVerified)) {
$('#user-verified-details-dialog').text(user.lastVerified);
} else if (grouped && nf.Common.isDefinedAndNotNull(user.userGroup)) {
$('#user-verified-details-dialog').html('<span class="unset">Multiple users with different last verified timestamps.</span>');
} else {
$('#user-verified-details-dialog').html('<span class="unset">No last verified timestamp set.</span>');
}
if (nf.Common.isDefinedAndNotNull(user.justification)) {
$('#user-justification-details-dialog').text(user.justification);
} else if (grouped && nf.Common.isDefinedAndNotNull(user.userGroup)) {
$('#user-justification-details-dialog').html('<span class="unset">Multiple users with different justifications.</span>');
} else {
$('#user-justification-details-dialog').html('<span class="unset">No justification set.</span>');
}
// show the dialog
$('#user-details-dialog').modal('show');
};
/**
* Updates the specified groups level of access.
*
* @argument {object} item The user item
*/
var updateGroupAccess = function (item) {
// record the current group
$('#group-name-roles-dialog').text(item.userGroup);
// show the dialog
$('#group-roles-dialog').modal('show');
};
/**
* Disables the specified group's account.
*
* @argument {object} item The user item
*/
var revokeGroupAccess = function (item) {
// record the current group
$('#group-name-revoke-dialog').text(item.userGroup);
// show the dialog
$('#group-revoke-dialog').modal('show');
};
/**
* Ungroups the specified group.
*
* @argument {object} item The user item
*/
var ungroup = function (item) {
// prompt for ungroup
nf.Dialog.showYesNoDialog({
dialogContent: 'Remove all users from group \'' + nf.Common.escapeHtml(item.userGroup) + '\'?',
overlayBackground: false,
yesHandler: function () {
$.ajax({
type: 'DELETE',
url: config.urls.userGroups + '/' + encodeURIComponent(item.userGroup),
dataType: 'json'
}).done(function (response) {
nf.UsersTable.loadUsersTable();
}).fail(nf.Common.handleAjaxError);
}
});
};
/**
* Updates the specified users's level of access.
*
* @argument {object} item The user item
*/
var updateUserAccess = function (item) {
// populate the user info
$('#user-id-roles-dialog').val(item.id);
$('#user-name-roles-dialog').attr('title', item.dn).text(item.userName);
$('#user-justification-roles-dialog').html(nf.Common.formatValue(item.justification));
// function for checking a checkbox
var check = function (domId) {
$('#' + domId).removeClass('checkbox-unchecked').addClass('checkbox-checked');
};
// go through each user role
$.each(item.authorities, function (i, authority) {
if (authority === 'ROLE_ADMIN') {
check('role-admin-checkbox');
} else if (authority === 'ROLE_DFM') {
check('role-dfm-checkbox');
} else if (authority === 'ROLE_PROVENANCE') {
check('role-provenance-checkbox');
} else if (authority === 'ROLE_MONITOR') {
check('role-monitor-checkbox');
} else if (authority === 'ROLE_NIFI') {
check('role-nifi-checkbox');
} else if (authority === 'ROLE_PROXY') {
check('role-proxy-checkbox');
}
});
// show the dialog
$('#user-roles-dialog').modal('show');
};
/**
* Disables the specified user's account.
*
* @argument {object} item The user item
*/
var revokeUserAccess = function (item) {
// populate the users info
$('#user-id-revoke-dialog').val(item.id);
$('#user-name-revoke-dialog').text(item.userName);
// show the dialog
$('#user-revoke-dialog').modal('show');
};
/**
* Prompts to verify group removal.
*
* @argument {object} item The user item
*/
var ungroupUser = function (item) {
// prompt for ungroup
nf.Dialog.showYesNoDialog({
dialogContent: 'Remove user \'' + nf.Common.escapeHtml(item.userName) + '\' from group \'' + nf.Common.escapeHtml(item.userGroup) + '\'?',
overlayBackground: false,
yesHandler: function () {
$.ajax({
type: 'DELETE',
url: config.urls.userGroups + '/' + encodeURIComponent(item.userGroup) + '/users/' + encodeURIComponent(item.id),
dataType: 'json'
}).done(function (response) {
nf.UsersTable.loadUsersTable();
}).fail(nf.Common.handleAjaxError);
}
});
};
/**
* Delete's the specified user's account.
*
* @argument {object} item The user item
*/
var deleteUserAccount = function (item) {
// populate the users info
$('#user-id-delete-dialog').val(item.id);
$('#user-name-delete-dialog').text(item.userName);
// show the dialog
$('#user-delete-dialog').modal('show');
};
return {
init: function () {
initUserDetailsDialog();
@ -816,183 +1023,6 @@ nf.UsersTable = (function () {
initUsersTable();
},
/**
* Disables the specified user's account.
*
* @argument {string} row The row
*/
revokeUserAccess: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// populate the users info
$('#user-id-revoke-dialog').val(item.id);
$('#user-name-revoke-dialog').text(item.userName);
// show the dialog
$('#user-revoke-dialog').modal('show');
}
},
/**
* Delete's the specified user's account.
*
* @argument {string} row The row
*/
deleteUserAccount: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// populate the users info
$('#user-id-delete-dialog').val(item.id);
$('#user-name-delete-dialog').text(item.userName);
// show the dialog
$('#user-delete-dialog').modal('show');
}
},
/**
* Disables the specified group's account.
*
* @argument {string} row The row
*/
revokeGroupAccess: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// record the current group
$('#group-name-revoke-dialog').text(item.userGroup);
// show the dialog
$('#group-revoke-dialog').modal('show');
}
},
/**
* Updates the specified users's level of access.
*
* @argument {string} row The row
*/
updateUserAccess: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// populate the user info
$('#user-id-roles-dialog').val(item.id);
$('#user-name-roles-dialog').attr('title', item.dn).text(item.userName);
$('#user-justification-roles-dialog').html(nf.Common.formatValue(item.justification));
// function for checking a checkbox
var check = function (domId) {
$('#' + domId).removeClass('checkbox-unchecked').addClass('checkbox-checked');
};
// go through each user role
$.each(item.authorities, function (i, authority) {
if (authority === 'ROLE_ADMIN') {
check('role-admin-checkbox');
} else if (authority === 'ROLE_DFM') {
check('role-dfm-checkbox');
} else if (authority === 'ROLE_PROVENANCE') {
check('role-provenance-checkbox');
} else if (authority === 'ROLE_MONITOR') {
check('role-monitor-checkbox');
} else if (authority === 'ROLE_NIFI') {
check('role-nifi-checkbox');
} else if (authority === 'ROLE_PROXY') {
check('role-proxy-checkbox');
}
});
// show the dialog
$('#user-roles-dialog').modal('show');
}
},
/**
* Updates the specified groups level of access.
*
* @argument {string} row The row
*/
updateGroupAccess: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// record the current group
$('#group-name-roles-dialog').text(item.userGroup);
// show the dialog
$('#group-roles-dialog').modal('show');
}
},
/**
* Prompts to verify group removal.
*
* @argument {string} row The row
*/
ungroupUser: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// prompt for ungroup
nf.Dialog.showYesNoDialog({
dialogContent: 'Remove user \'' + nf.Common.escapeHtml(item.userName) + '\' from group \'' + nf.Common.escapeHtml(item.userGroup) + '\'?',
overlayBackground: false,
yesHandler: function () {
$.ajax({
type: 'DELETE',
url: config.urls.userGroups + '/' + encodeURIComponent(item.userGroup) + '/users/' + encodeURIComponent(item.id),
dataType: 'json'
}).done(function (response) {
nf.UsersTable.loadUsersTable();
}).fail(nf.Common.handleAjaxError);
}
});
}
},
/**
* Ungroups the specified group.
*
* @argument {string} row The row
*/
ungroup: function (row) {
var grid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(grid)) {
var data = grid.getData();
var item = data.getItem(row);
// prompt for ungroup
nf.Dialog.showYesNoDialog({
dialogContent: 'Remove all users from group \'' + nf.Common.escapeHtml(item.userGroup) + '\'?',
overlayBackground: false,
yesHandler: function () {
$.ajax({
type: 'DELETE',
url: config.urls.userGroups + '/' + encodeURIComponent(item.userGroup),
dataType: 'json'
}).done(function (response) {
nf.UsersTable.loadUsersTable();
}).fail(nf.Common.handleAjaxError);
}
});
}
},
/**
* Update the size of the grid based on its container's current size.
*/
@ -1037,54 +1067,6 @@ nf.UsersTable = (function () {
$('#total-users').text('0');
}
}).fail(nf.Common.handleAjaxError);
},
/**
* Shows details for the specified user.
*
* @param {string} row
*/
showUserDetails: function (row) {
var usersGrid = $('#users-table').data('gridInstance');
if (nf.Common.isDefinedAndNotNull(usersGrid)) {
var usersData = usersGrid.getData();
// get the user
var user = usersData.getItem(row);
var grouped = $('#group-collaspe-checkbox').hasClass('checkbox-checked');
// update the dialog fields
$('#user-name-details-dialog').text(user.userName);
$('#user-dn-details-dialog').text(user.dn);
// handle fields that could vary for groups
if (nf.Common.isDefinedAndNotNull(user.creation)) {
$('#user-created-details-dialog').text(user.creation);
} else if (grouped && nf.Common.isDefinedAndNotNull(user.userGroup)) {
$('#user-created-details-dialog').html('<span class="unset">Multiple users with different creation timestamps.</span>');
} else {
$('#user-created-details-dialog').html('<span class="unset">No creation timestamp set</span>');
}
if (nf.Common.isDefinedAndNotNull(user.lastVerified)) {
$('#user-verified-details-dialog').text(user.lastVerified);
} else if (grouped && nf.Common.isDefinedAndNotNull(user.userGroup)) {
$('#user-verified-details-dialog').html('<span class="unset">Multiple users with different last verified timestamps.</span>');
} else {
$('#user-verified-details-dialog').html('<span class="unset">No last verified timestamp set.</span>');
}
if (nf.Common.isDefinedAndNotNull(user.justification)) {
$('#user-justification-details-dialog').text(user.justification);
} else if (grouped && nf.Common.isDefinedAndNotNull(user.userGroup)) {
$('#user-justification-details-dialog').html('<span class="unset">Multiple users with different justifications.</span>');
} else {
$('#user-justification-details-dialog').html('<span class="unset">No justification set.</span>');
}
// show the dialog
$('#user-details-dialog').modal('show');
}
}
};
}());