blob: dd40e1afdffc73e1c0b3feaea957939b44206e77 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* global top, define, module, require, exports */
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery',
'Slick',
'nf.Common',
'nf.Dialog',
'nf.ErrorHandler',
'nf.HistoryModel'],
function ($, Slick, nfCommon, nfDialog, nfErrorHandler, nfHistoryModel) {
return (nf.HistoryTable = factory($, Slick, nfCommon, nfDialog, nfErrorHandler, nfHistoryModel));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.HistoryTable =
factory(require('jquery'),
require('Slick'),
require('nf.Common'),
require('nf.Dialog'),
require('nf.ErrorHandler'),
require('nf.HistoryModel')));
} else {
nf.HistoryTable = factory(root.$,
root.Slick,
root.nf.Common,
root.nf.Dialog,
root.nf.ErrorHandler,
root.nf.HistoryModel);
}
}(this, function ($, Slick, nfCommon, nfDialog, nfErrorHandler, nfHistoryModel) {
'use strict';
/**
* Configuration object used to hold a number of configuration items.
*/
var config = {
defaultStartTime: '00:00:00',
defaultEndTime: '23:59:59',
styles: {
hidden: 'hidden'
},
urls: {
history: '../nifi-api/controller/history'
}
};
/**
* Initializes the details dialog.
*/
var initDetailsDialog = function () {
$('#action-details-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Action Details',
buttons: [{
buttonText: 'Ok',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
$('#action-details-dialog').modal('hide');
}
}
}],
handler: {
close: function () {
// clear the details
$('#action-details').empty();
}
}
});
};
/**
* Initializes the filter dialog.
*/
var initFilterDialog = function () {
// clear the filter field
$('#history-filter').val('');
// filter type
$('#history-filter-type').combo({
options: [{
text: 'by id',
value: 'by id',
description: 'Filters based on the id of the component that was modified'
}, {
text: 'by user',
value: 'by user',
description: 'Filters based on the user that performed the action'
}]
});
// configure the start and end date picker
$('#history-filter-start-date, #history-filter-end-date').datepicker({
showAnim: '',
showOtherMonths: true,
selectOtherMonths: true
});
$('#history-filter-start-date').datepicker('setDate', '-14d');
$('#history-filter-end-date').datepicker('setDate', '+0d');
// initialize the start and end time
$('#history-filter-start-time').val(config.defaultStartTime);
$('#history-filter-end-time').val(config.defaultEndTime);
// configure the filter dialog
$('#history-filter-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Filter History',
buttons: [{
buttonText: 'Filter',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
$('#history-filter-dialog').modal('hide');
var filter = {};
// extract the filter text
var filterText = $('#history-filter').val();
if (filterText !== '') {
var filterType = $('#history-filter-type').combo('getSelectedOption').text;
if (filterType === 'by id') {
filter['sourceId'] = filterText;
} else if (filterType === 'by user') {
filter['userIdentity'] = filterText;
}
}
// extract the start date time
var startDate = $.trim($('#history-filter-start-date').val());
var startTime = $.trim($('#history-filter-start-time').val());
if (startDate !== '') {
if (startTime === '') {
startTime = config.defaultStartTime;
$('#history-filter-start-time').val(startTime);
}
filter['startDate'] = startDate + ' ' + startTime;
}
// extract the end date time
var endDate = $.trim($('#history-filter-end-date').val());
var endTime = $.trim($('#history-filter-end-time').val());
if (endDate !== '') {
if (endTime === '') {
endTime = config.defaultEndTime;
$('#history-filter-end-time').val(endTime);
}
filter['endDate'] = endDate + ' ' + endTime;
}
// set the filter
var historyGrid = $('#history-table').data('gridInstance');
var historyModel = historyGrid.getData();
historyModel.setFilterArgs(filter);
// reload the table
nfHistoryTable.loadHistoryTable();
}
}
},
{
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$('#history-filter-dialog').modal('hide');
}
}
}]
});
};
/**
* Initializes the purge dialog.
*/
var initPurgeDialog = function () {
// configure the start and end date picker
$('#history-purge-end-date').datepicker({
showAnim: '',
showOtherMonths: true,
selectOtherMonths: true
});
$('#history-purge-end-date').datepicker('setDate', '-1m');
// initialize the start and end time
$('#history-purge-end-time').val(config.defaultStartTime);
// configure the filter dialog
$('#history-purge-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Purge History',
buttons: [{
buttonText: 'Purge',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
// hide the dialog
$('#history-purge-dialog').modal('hide');
// get the purge end date
var endDate = $.trim($('#history-purge-end-date').val());
var endTime = $.trim($('#history-purge-end-time').val());
if (endDate !== '') {
if (endTime === '') {
endTime = config.defaultStartTime;
$('#history-purge-end-time').val(endTime);
}
var endDateTime = endDate + ' ' + endTime;
var timezone = $('.timezone:first').text();
nfDialog.showYesNoDialog({
headerText: 'History',
dialogContent: "Are you sure you want to delete all history before '" + nfCommon.escapeHtml(endDateTime) + " " + nfCommon.escapeHtml(timezone) + "'?",
yesHandler: function () {
purgeHistory(endDateTime);
}
});
} else {
nfDialog.showOkDialog({
headerText: 'History',
dialogContent: 'The end date must be specified.'
});
}
}
}
},
{
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$('#history-purge-dialog').modal('hide');
}
}
}]
});
};
/**
* Initializes the history table.
*/
var initHistoryTable = function () {
// clear the current filter
$('#clear-history-filter').click(function () {
// clear the filter dialog
$('#history-filter').val('');
// hide the overview
$('#history-filter-overview').css('visibility', 'hidden');
// clear the filter
var historyGrid = $('#history-table').data('gridInstance');
var historyModel = historyGrid.getData();
historyModel.setFilterArgs({});
// refresh the table
nfHistoryTable.loadHistoryTable();
});
// add hover effect and click handler for opening the dialog
$('#history-filter-button').click(function () {
$('#history-filter-dialog').modal('show');
});
// define a custom formatter for the more details column
var moreDetailsFormatter = function (row, cell, value, columnDef, dataContext) {
if (dataContext.canRead === true) {
return '<div title="View Details" class="pointer show-action-details fa fa-info-circle"></div>';
}
return "";
};
// define how general values are formatted
var valueFormatter = function (row, cell, value, columnDef, dataContext) {
if (dataContext.canRead !== true) {
return '<span class="unset" style="font-size: 13px; padding-top: 2px;">Not authorized</span>';
}
return nfCommon.formatValue(dataContext.action[columnDef.field]);
};
// initialize the templates table
var historyColumns = [
{
id: 'moreDetails',
name: '&nbsp;',
sortable: false,
resizable: false,
formatter: moreDetailsFormatter,
width: 50,
maxWidth: 50
},
{
id: 'timestamp',
name: 'Date/Time',
field: 'timestamp',
sortable: true,
resizable: true,
formatter: valueFormatter
},
{
id: 'sourceName',
name: 'Name',
field: 'sourceName',
sortable: true,
resizable: true,
formatter: valueFormatter
},
{
id: 'sourceType',
name: 'Type',
field: 'sourceType',
sortable: true,
resizable: true,
formatter: valueFormatter
},
{
id: 'operation',
name: 'Operation',
field: 'operation',
sortable: true,
resizable: true,
formatter: valueFormatter
},
{
id: 'userIdentity',
name: 'User',
field: 'userIdentity',
sortable: true,
resizable: true,
formatter: valueFormatter
}
];
var historyOptions = {
autosizeColsMode: Slick.GridAutosizeColsMode.LegacyForceFit,
enableTextSelectionOnCells: true,
enableCellNavigation: false,
enableColumnReorder: false,
autoEdit: false,
rowHeight: 24
};
// create the remote model
var historyModel = new nfHistoryModel();
// initialize the grid
var historyGrid = new Slick.Grid('#history-table', historyModel, historyColumns, historyOptions);
historyGrid.setSelectionModel(new Slick.RowSelectionModel());
historyGrid.registerPlugin(new Slick.AutoTooltips());
// initialize the grid sorting
historyGrid.onSort.subscribe(function (e, args) {
// set the sort criteria on the model
historyModel.setSort(args.sortCol.field, args.sortAsc ? 1 : -1);
// reload the grid
var vp = historyGrid.getViewport();
historyModel.ensureData(vp.top, vp.bottom);
});
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.action);
}
}
});
// listen for when the viewport changes so we can fetch the appropriate records
historyGrid.onViewportChanged.subscribe(function (e, args) {
var vp = historyGrid.getViewport();
historyModel.ensureData(vp.top, vp.bottom);
});
// listen for when new data has been loaded
historyModel.onDataLoaded.subscribe(function (e, args) {
for (var i = args.from; i <= args.to; i++) {
historyGrid.invalidateRow(i);
}
historyGrid.updateRowCount();
historyGrid.render();
});
// hold onto an instance of the grid
$('#history-table').data('gridInstance', historyGrid);
// add the purge button if appropriate
if (nfCommon.canModifyController()) {
$('#history-purge-button').on('click', function () {
$('#history-purge-dialog').modal('show');
}).show();
}
};
/**
* Purges the history up to the specified end date.
*
* @argument {string} endDateTime The end date time
*/
var purgeHistory = function (endDateTime) {
$.ajax({
type: 'DELETE',
url: config.urls.history + '?' + $.param({
endDate: endDateTime
}),
dataType: 'json'
}).done(function () {
nfHistoryTable.loadHistoryTable();
}).fail(nfErrorHandler.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>' + nfCommon.escapeHtml(action.sourceId) + '</div>'));
// get any component details
var componentDetails = action.componentDetails;
// inspect the operation to determine if there are any component details
if (nfCommon.isDefinedAndNotNull(componentDetails)) {
if (action.sourceType === 'Processor' || action.sourceType === 'ControllerService' || action.sourceType === 'ReportingTask') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Type</div>' + nfCommon.escapeHtml(componentDetails.type) + '</div>'));
} else if (action.sourceType === 'RemoteProcessGroup') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Uri</div>' + nfCommon.formatValue(componentDetails.uri) + '</div>'));
}
}
// get any action details
var actionDetails = action.actionDetails;
// inspect the operation to determine if there are any action details
if (nfCommon.isDefinedAndNotNull(actionDetails)) {
if (action.operation === 'Configure') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Name</div>' + nfCommon.formatValue(actionDetails.name) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Value</div>' + nfCommon.formatValue(actionDetails.value) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Value</div>' + nfCommon.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>' + nfCommon.escapeHtml(actionDetails.sourceId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Source Name</div>' + nfCommon.formatValue(actionDetails.sourceName) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Source Type</div>' + nfCommon.escapeHtml(actionDetails.sourceType) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Relationship(s)</div>' + nfCommon.formatValue(actionDetails.relationship) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Id</div>' + nfCommon.escapeHtml(actionDetails.destinationId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Name</div>' + nfCommon.formatValue(actionDetails.destinationName) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Destination Type</div>' + nfCommon.escapeHtml(actionDetails.destinationType) + '</div>'));
} else if (action.operation === 'Move') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">Group</div>' + nfCommon.formatValue(actionDetails.group) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Group Id</div>' + nfCommon.escapeHtml(actionDetails.groupId) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Group</div>' + nfCommon.formatValue(actionDetails.previousGroup) + '</div>')).append(
$('<div class="action-detail"><div class="history-details-name">Previous Group Id</div>' + nfCommon.escapeHtml(actionDetails.previousGroupId) + '</div>'));
} else if (action.operation === 'Purge') {
detailsMarkup.append(
$('<div class="action-detail"><div class="history-details-name">End Date</div>' + nfCommon.escapeHtml(actionDetails.endDate) + '</div>'));
}
}
// populate the dialog
$('#action-details').append(detailsMarkup);
// show the dialog
$('#action-details-dialog').modal('show');
};
var nfHistoryTable = {
init: function () {
initDetailsDialog();
initFilterDialog();
initPurgeDialog();
initHistoryTable();
},
/**
* Update the size of the grid based on its container's current size.
*/
resetTableSize: function () {
var historyGrid = $('#history-table').data('gridInstance');
if (nfCommon.isDefinedAndNotNull(historyGrid)) {
historyGrid.resizeCanvas();
}
},
/**
* Load the processor status table.
*/
loadHistoryTable: function () {
var historyGrid = $('#history-table').data('gridInstance');
// clear the history model
var historyModel = historyGrid.getData();
historyModel.clear();
// request refresh of the current 'page'
historyGrid.onViewportChanged.notify();
}
};
return nfHistoryTable;
}));