diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml index c227c9b7e7..4f2cc8ebce 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml @@ -475,6 +475,7 @@ ${staging.dir}/js/nf/canvas/nf-draggable.js ${staging.dir}/js/nf/canvas/nf-connectable.js ${staging.dir}/js/nf/canvas/nf-graph.js + ${staging.dir}/js/nf/nf-filtered-dialog-common.js ${staging.dir}/js/nf/nf-status-history.js ${staging.dir}/js/nf/canvas/nf-queue-listing.js ${staging.dir}/js/nf/canvas/nf-policy-management.js diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties index 9b04ecec9e..413c6c2f83 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties @@ -57,6 +57,7 @@ nf.canvas.script.tags=\n\ \n\ \n\ +\n\ \n\ \n\ \n\ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js index c9f80f3862..3af00da597 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js @@ -26,10 +26,11 @@ 'nf.Graph', 'nf.CanvasUtils', 'nf.ErrorHandler', + 'nf.FilteredDialogCommon', 'nf.Dialog', 'nf.Common'], - function ($, Slick, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon) { - return (nf.ng.ProcessorComponent = factory($, Slick, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon)); + function ($, Slick, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfFilteredDialogCommon, nfDialog, nfCommon) { + return (nf.ng.ProcessorComponent = factory($, Slick, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfFilteredDialogCommon, nfDialog, nfCommon)); }); } else if (typeof exports === 'object' && typeof module === 'object') { module.exports = (nf.ng.ProcessorComponent = @@ -40,6 +41,7 @@ require('nf.Graph'), require('nf.CanvasUtils'), require('nf.ErrorHandler'), + require('nf.FilteredDialogCommon'), require('nf.Dialog'), require('nf.Common'))); } else { @@ -50,10 +52,11 @@ root.nf.Graph, root.nf.CanvasUtils, root.nf.ErrorHandler, + root.nf.FilteredDialogCommon, root.nf.Dialog, root.nf.Common); } -}(this, function ($, Slick, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon) { +}(this, function ($, Slick, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfFilteredDialogCommon, nfDialog, nfCommon) { 'use strict'; return function (serviceProvider) { @@ -81,7 +84,9 @@ // update the selection if possible if (processorTypesData.getLength() > 0) { - processorTypesGrid.setSelectedRows([0]); + nfFilteredDialogCommon.choseFirstRow(processorTypesGrid); + // make the first row visible + processorTypesGrid.scrollRowToTop(0); } } }; @@ -722,9 +727,17 @@ // show the dialog this.modal.show(); + var navigationKeys = [$.ui.keyCode.UP, $.ui.keyCode.PAGE_UP, $.ui.keyCode.DOWN, $.ui.keyCode.PAGE_DOWN]; + // setup the filter - $('#processor-type-filter').focus().off('keyup').on('keyup', function (e) { + $('#processor-type-filter').off('keyup').on('keyup', function (e) { var code = e.keyCode ? e.keyCode : e.which; + + // ignore navigation keys + if ($.inArray(code, navigationKeys) !== -1) { + return; + } + if (code === $.ui.keyCode.ENTER) { var selected = grid.getSelectedRows(); @@ -740,13 +753,19 @@ } }); + // setup row navigation + nfFilteredDialogCommon.addKeydownListener('#processor-type-filter', grid, dataview); + // adjust the grid canvas now that its been rendered grid.resizeCanvas(); // auto select the first row if possible if (dataview.getLength() > 0) { - grid.setSelectedRows([0]); + nfFilteredDialogCommon.choseFirstRow(grid); } + + // set the initial focus + $('#processor-type-filter').focus() } }; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js index 86bec682b4..59041c4769 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js @@ -27,6 +27,7 @@ 'nf.ProcessGroupConfiguration', 'nf.CanvasUtils', 'nf.ErrorHandler', + 'nf.FilteredDialogCommon', 'nf.Dialog', 'nf.Common', 'nf.ControllerService', @@ -35,8 +36,8 @@ 'nf.ComponentState', 'nf.ComponentVersion', 'nf.ng.Bridge'], - function ($, d3, Slick, nfClient, nfShell, nfProcessGroupConfiguration, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon, nfControllerService, nfProcessGroup, nfPolicyManagement, nfComponentState, nfComponentVersion, nfNgBridge) { - return (nf.ControllerServices = factory($, d3, Slick, nfClient, nfShell, nfProcessGroupConfiguration, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon, nfControllerService, nfProcessGroup, nfPolicyManagement, nfComponentState, nfComponentVersion, nfNgBridge)); + function ($, d3, Slick, nfClient, nfShell, nfProcessGroupConfiguration, nfCanvasUtils, nfErrorHandler, nfFilteredDialogCommon, nfDialog, nfCommon, nfControllerService, nfProcessGroup, nfPolicyManagement, nfComponentState, nfComponentVersion, nfNgBridge) { + return (nf.ControllerServices = factory($, d3, Slick, nfClient, nfShell, nfProcessGroupConfiguration, nfCanvasUtils, nfErrorHandler, nfFilteredDialogCommon, nfDialog, nfCommon, nfControllerService, nfProcessGroup, nfPolicyManagement, nfComponentState, nfComponentVersion, nfNgBridge)); }); } else if (typeof exports === 'object' && typeof module === 'object') { module.exports = (nf.ControllerServices = @@ -48,6 +49,7 @@ require('nf.ProcessGroupConfiguration'), require('nf.CanvasUtils'), require('nf.ErrorHandler'), + require('nf.FilteredDialogCommon'), require('nf.Dialog'), require('nf.Common'), require('nf.ControllerService'), @@ -65,6 +67,7 @@ root.nf.ProcessGroupConfiguration, root.nf.CanvasUtils, root.nf.ErrorHandler, + root.nf.FilteredDialogCommon, root.nf.Dialog, root.nf.Common, root.nf.ControllerService, @@ -74,7 +77,7 @@ root.nf.ComponentVersion, root.nf.ng.Bridge); } -}(this, function ($, d3, Slick, nfClient, nfShell, nfProcessGroupConfiguration, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon, nfControllerService, nfProcessGroup, nfPolicyManagement, nfComponentState, nfComponentVersion, nfNgBridge) { +}(this, function ($, d3, Slick, nfClient, nfShell, nfProcessGroupConfiguration, nfCanvasUtils, nfErrorHandler, nfFilteredDialogCommon, nfDialog, nfCommon, nfControllerService, nfProcessGroup, nfPolicyManagement, nfComponentState, nfComponentVersion, nfNgBridge) { 'use strict'; var dblClick = null; @@ -137,7 +140,9 @@ // update the selection if possible if (controllerServiceTypesData.getLength() > 0) { - controllerServiceTypesGrid.setSelectedRows([0]); + nfFilteredDialogCommon.choseFirstRow(controllerServiceTypesGrid); + // make the first row visible + controllerServiceTypesGrid.scrollRowToTop(0); } } }; @@ -324,7 +329,7 @@ // select the new controller service var row = controllerServicesData.getRowById(controllerServiceEntity.id); - controllerServicesGrid.setSelectedRows([row]); + nfFilteredDialogCommon.choseRow(controllerServicesGrid, row); controllerServicesGrid.scrollRowIntoView(row); }).fail(nfErrorHandler.handleAjaxError); @@ -1191,9 +1196,17 @@ var grid = $('#controller-service-types-table').data('gridInstance'); var dataview = grid.getData(); + var navigationKeys = [$.ui.keyCode.UP, $.ui.keyCode.PAGE_UP, $.ui.keyCode.DOWN, $.ui.keyCode.PAGE_DOWN]; + // update the keyhandler $('#controller-service-type-filter').off('keyup').on('keyup', function (e) { var code = e.keyCode ? e.keyCode : e.which; + + // ignore navigation keys + if ($.inArray(code, navigationKeys) !== -1) { + return; + } + if (code === $.ui.keyCode.ENTER) { var selected = grid.getSelectedRows(); @@ -1209,6 +1222,9 @@ } }); + // setup row navigation + nfFilteredDialogCommon.addKeydownListener('#controller-service-type-filter', grid, dataview); + // update the button model and show the dialog $('#new-controller-service-dialog').modal('setButtonModel', [{ buttonText: 'Add', @@ -1267,7 +1283,7 @@ // auto select the first row if possible if (dataview.getLength() > 0) { - grid.setSelectedRows([0]); + nfFilteredDialogCommon.choseFirstRow(grid); } // set the initial focus diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js index ee2dfda9da..4da6fc65c3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js @@ -28,13 +28,14 @@ 'nf.CanvasUtils', 'nf.ControllerServices', 'nf.ErrorHandler', + 'nf.FilteredDialogCommon', 'nf.ReportingTask', 'nf.Shell', 'nf.ComponentState', 'nf.ComponentVersion', 'nf.PolicyManagement'], - function ($, Slick, d3, nfClient, nfDialog, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) { - return (nf.Settings = factory($, Slick, d3, nfClient, nfDialog, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement)); + function ($, Slick, d3, nfClient, nfDialog, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) { + return (nf.Settings = factory($, Slick, d3, nfClient, nfDialog, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement)); }); } else if (typeof exports === 'object' && typeof module === 'object') { module.exports = (nf.Settings = @@ -47,6 +48,7 @@ require('nf.CanvasUtils'), require('nf.ControllerServices'), require('nf.ErrorHandler'), + require('nf.FilteredDialogCommon'), require('nf.ReportingTask'), require('nf.Shell'), require('nf.ComponentState'), @@ -62,13 +64,14 @@ root.nf.CanvasUtils, root.nf.ControllerServices, root.nf.ErrorHandler, + root.nf.FilteredDialogCommon, root.nf.ReportingTask, root.nf.Shell, root.nf.ComponentState, root.nf.ComponentVersion, root.nf.PolicyManagement); } -}(this, function ($, Slick, d3, nfClient, nfDialog, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) { +}(this, function ($, Slick, d3, nfClient, nfDialog, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) { 'use strict'; @@ -321,7 +324,7 @@ // update the selection if possible if (reportingTaskTypesData.getLength() > 0) { - reportingTaskTypesGrid.setSelectedRows([0]); + nfFilteredDialogCommon.choseFirstRow(reportingTaskTypesGrid); } } }; @@ -451,7 +454,7 @@ // select the new reporting task var row = reportingTaskData.getRowById(reportingTaskEntity.id); - reportingTaskGrid.setSelectedRows([row]); + nfFilteredDialogCommon.choseRow(reportingTaskGrid, row); reportingTaskGrid.scrollRowIntoView(row); }).fail(nfErrorHandler.handleAjaxError); @@ -465,26 +468,6 @@ * Initializes the new reporting task dialog. */ var initNewReportingTaskDialog = function () { - // define the function for filtering the list - $('#reporting-task-type-filter').on('keyup', function (e) { - var code = e.keyCode ? e.keyCode : e.which; - if (code === $.ui.keyCode.ENTER) { - // get the grid reference - var grid = $('#reporting-task-types-table').data('gridInstance'); - var selected = grid.getSelectedRows(); - - if (selected.length > 0) { - // grid configured with multi-select = false - var item = grid.getDataItem(selected[0]); - if (isSelectable(item)) { - addSelectedReportingTask(); - } - } - } else { - applyReportingTaskTypeFilter(); - } - }); - // initialize the reporting task type table var reportingTaskTypesColumns = [ { @@ -698,6 +681,35 @@ }); }).fail(nfErrorHandler.handleAjaxError); + var navigationKeys = [$.ui.keyCode.UP, $.ui.keyCode.PAGE_UP, $.ui.keyCode.DOWN, $.ui.keyCode.PAGE_DOWN]; + + // define the function for filtering the list + $('#reporting-task-type-filter').off('keyup').on('keyup', function (e) { + var code = e.keyCode ? e.keyCode : e.which; + + // ignore navigation keys + if ($.inArray(code, navigationKeys) !== -1) { + return; + } + + if (code === $.ui.keyCode.ENTER) { + var selected = reportingTaskTypesGrid.getSelectedRows(); + + if (selected.length > 0) { + // grid configured with multi-select = false + var item = reportingTaskTypesGrid.getDataItem(selected[0]); + if (isSelectable(item)) { + addSelectedReportingTask(); + } + } + } else { + applyReportingTaskTypeFilter(); + } + }); + + // setup row navigation + nfFilteredDialogCommon.addKeydownListener('#reporting-task-type-filter', reportingTaskTypesGrid, reportingTaskTypesGrid.getData()); + // initialize the reporting task dialog $('#new-reporting-task-dialog').modal({ scrollableContentStyle: 'scrollable', @@ -1297,7 +1309,7 @@ // select the first row if possible if (reportingTaskTypesData.getLength() > 0) { - reportingTaskTypesGrid.setSelectedRows([0]); + nfFilteredDialogCommon.choseFirstRow(reportingTaskTypesGrid); } } @@ -1349,7 +1361,7 @@ // select the desired service var row = controllerServiceData.getRowById(controllerServiceId); - controllerServiceGrid.setSelectedRows([row]); + nfFilteredDialogCommon.choseRow(controllerServiceGrid, row); controllerServiceGrid.scrollRowIntoView(row); // select the controller services tab @@ -1367,7 +1379,7 @@ // select the desired service var row = reportingTaskData.getRowById(reportingTaskId); - reportingTaskGrid.setSelectedRows([row]); + nfFilteredDialogCommon.choseRow(reportingTaskGrid, row); reportingTaskGrid.scrollRowIntoView(row); // select the controller services tab diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-filtered-dialog-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-filtered-dialog-common.js new file mode 100644 index 0000000000..d4194cf7e6 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-filtered-dialog-common.js @@ -0,0 +1,105 @@ +/* + * 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 define, module, require, exports */ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery'], function ($) { + return (nf.FilteredDialogCommon = factory($)); + }); + } else if (typeof exports === 'object' && typeof module === 'object') { + module.exports = (nf.FilteredDialogCommon = factory(require('jquery'))); + } else { + nf.FilteredDialogCommon = factory(root.$); + } +}(this, function ($) { + 'use strict'; + + var nfFilteredDialogCommon = { + + /** + * Registers keydown event on dialog's filter input in order to navigate the grid's rows via keyboard arrow keys. + * + * @argument {string} filter Filter input box selector + * @argument {object} grid SlickGrid reference + * @argument {object} dataview Current grid dataset + */ + addKeydownListener: function (filter, grid, dataview) { + var navigationKeys = [$.ui.keyCode.UP, $.ui.keyCode.PAGE_UP, $.ui.keyCode.DOWN, $.ui.keyCode.PAGE_DOWN]; + + // setup the navigation + $(filter).off('keydown').on('keydown', function(e) { + var code = e.keyCode ? e.keyCode : e.which; + + // nonmodified navigation keys only + if ($.inArray(code, navigationKeys) === -1 || e.shiftKey || e.altKey || e.ctrlKey) { + return; + } + + var selected = grid.getSelectedRows(); + + if (selected.length > 0) { + if (code === $.ui.keyCode.PAGE_UP) { + grid.navigatePageUp(); + return; + } + if (code === $.ui.keyCode.PAGE_DOWN) { + grid.navigatePageDown(); + return; + } + + // grid multi-select = false + var nextIndex = selected[0]; + + // get the following/previous row + if (code === $.ui.keyCode.UP) { + nextIndex = Math.max(nextIndex - 1, 0); + } else { + nextIndex = Math.min(nextIndex + 1, dataview.getLength() - 1); + } + + nfFilteredDialogCommon.choseRow(grid, nextIndex); + // ensure the newly selected row is visible + grid.scrollRowIntoView(nextIndex, false); + } + }); + }, + + /** + * Selects the first row and activates the first cell within given SlickGrid. + * + * @argument {object} grid SlickGrid reference + */ + choseFirstRow: function (grid) { + nfFilteredDialogCommon.choseRow(grid, 0); + }, + + /** + * Selects given row and activates the first cell in the row within given SlickGrid. + * + * @argument {object} grid SlickGrid reference + * @argument {int} index Row index + */ + choseRow: function (grid, index) { + grid.setSelectedRows([index]); + grid.setActiveCell(index, 0); + } + }; + + return nfFilteredDialogCommon; +})); \ No newline at end of file