http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js index 8fb73a8..8f8bb6d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-state.js @@ -230,7 +230,7 @@ applyFilter(); }); - // initialize the processor configuration dialog + // initialize the component state dialog $('#component-state-dialog').modal({ scrollableContentStyle: 'scrollable', headerText: 'Component State',
http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-version.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-version.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-version.js index 3110e64..02abac1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-version.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-component-version.js @@ -18,7 +18,7 @@ /* global nf */ /** - * Views state for a given component. + * Handles changing the version of a component bundle. */ (function (root, factory) { if (typeof define === 'function' && define.amd) { http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js index a32a47f..f128086 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js @@ -97,7 +97,7 @@ * @param {selection} selection The selection of currently selected components */ var canCreateTemplate = function (selection) { - return nfCanvasUtils.canWrite() && (selection.empty() || nfCanvasUtils.canRead(selection)); + return nfCanvasUtils.canWriteCurrentGroup() && (selection.empty() || nfCanvasUtils.canRead(selection)); }; /** @@ -106,7 +106,7 @@ * @param {selection} selection The selection of currently selected components */ var canUploadTemplate = function (selection) { - return nfCanvasUtils.canWrite() && selection.empty(); + return nfCanvasUtils.canWriteCurrentGroup() && selection.empty(); }; /** @@ -370,6 +370,89 @@ }; /** + * Determines whether the current selection supports flow versioning. + * + * @param selection + */ + var supportsFlowVersioning = function (selection) { + if (nfCanvasUtils.supportsFlowVersioning() === false) { + return false; + } + + if (selection.empty()) { + return nfCanvasUtils.canReadCurrentGroup() && nfCanvasUtils.canWriteCurrentGroup(); + } + + if (isProcessGroup(selection) === true) { + return nfCanvasUtils.canRead(selection) && nfCanvasUtils.canModify(selection); + } + + return false; + }; + + /** + * Determines whether the current selection supports starting flow versioning. + * + * @param selection + */ + var supportsStartFlowVersioning = function (selection) { + // ensure this selection supports flow versioning above + if (supportsFlowVersioning(selection) === false) { + return false; + } + + if (selection.empty()) { + // check bread crumbs for version control information in the current group + var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs(); + if (breadcrumbEntities.length > 0) { + var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1]; + if (breadcrumbEntity.permissions.canRead) { + return nfCommon.isUndefinedOrNull(breadcrumbEntity.breadcrumb.versionControlInformation); + } else { + return false; + } + } else { + return false; + } + } + + // check the selection for version control information + var processGroupData = selection.datum(); + return nfCommon.isUndefinedOrNull(processGroupData.component.versionControlInformation); + }; + + /** + * Determines whether the current selection supports stopping flow versioning. + * + * @param selection + */ + var supportsStopFlowVersioning = function (selection) { + // ensure this selection supports flow versioning above + if (supportsFlowVersioning(selection) === false) { + return false; + } + + if (selection.empty()) { + // check bread crumbs for version control information in the current group + var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs(); + if (breadcrumbEntities.length > 0) { + var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1]; + if (breadcrumbEntity.permissions.canRead) { + return nfCommon.isDefinedAndNotNull(breadcrumbEntity.breadcrumb.versionControlInformation); + } else { + return false; + } + } else { + return false; + } + } + + // check the selection for version control information + var processGroupData = selection.datum(); + return nfCommon.isDefinedAndNotNull(processGroupData.component.versionControlInformation); + }; + + /** * Determines whether the current selection could have provenance. * * @param {selection} selection @@ -548,6 +631,16 @@ {id: 'show-details-menu-item', condition: hasDetails, menuItem: {clazz: 'fa fa-gear', text: 'View configuration', action: 'showDetails'}}, {id: 'variable-registry-menu-item', condition: hasVariables, menuItem: {clazz: 'fa', text: 'Variables', action: 'openVariableRegistry'}}, {separator: true}, + {id: 'version-menu-item', groupMenuItem: {clazz: 'fa', text: 'Version'}, menuItems: [ + {id: 'start-version-control-menu-item', condition: supportsStartFlowVersioning, menuItem: {clazz: 'fa fa-floppy-o', text: 'Start version control', action: 'saveFlowVersion'}}, + {separator: true}, + {id: 'commit-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-floppy-o', text: 'Commit local changes', action: 'saveFlowVersion'}}, + {id: 'revert-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Revert local changes', action: 'revertFlowChanges'}}, + {id: 'change-version-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Change version', action: 'changeFlowVersion'}}, + {separator: true}, + {id: 'stop-version-control-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Stop version control', action: 'disconnectFlowVersioning'}} + ]}, + {separator: true}, {id: 'enter-group-menu-item', condition: isProcessGroup, menuItem: {clazz: 'fa fa-sign-in', text: 'Enter group', action: 'enterGroup'}}, {separator: true}, {id: 'start-menu-item', condition: isRunnable, menuItem: {clazz: 'fa fa-play', text: 'Start', action: 'start'}}, http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js new file mode 100644 index 0000000..6315d30 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js @@ -0,0 +1,476 @@ +/* + * 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 */ + +/** + * Handles versioning. + */ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery', + 'nf.ng.Bridge', + 'nf.ErrorHandler', + 'nf.Dialog', + 'nf.Common', + 'nf.Client', + 'nf.CanvasUtils', + 'nf.ProcessGroup', + 'nf.Graph'], + function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph) { + return (nf.FlowVersion = factory($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph)); + }); + } else if (typeof exports === 'object' && typeof module === 'object') { + module.exports = (nf.FlowVerison = + factory(require('jquery'), + require('nf.ng.Bridge'), + require('nf.ErrorHandler'), + require('nf.Dialog'), + require('nf.Common'), + require('nf.Client'), + require('nf.CanvasUtils'), + require('nf.ProcessGroup'), + require('nf.Graph'))); + } else { + nf.FlowVersion = factory(root.$, + root.nf.ng.Bridge, + root.nf.ErrorHandler, + root.nf.Dialog, + root.nf.Common, + root.nf.Client, + root.nf.CanvasUtils, + root.nf.ProcessGroup, + root.nf.Graph); + } +}(this, function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph) { + 'use strict'; + + /** + * Reset the dialog. + */ + var resetDialog = function () { + $('#flow-version-registry-combo').combo('destroy').hide(); + $('#flow-version-bucket-combo').combo('destroy').hide(); + + $('#flow-version-registry').text('').hide(); + $('#flow-version-bucket').text('').hide(); + + $('#flow-version-name').val(''); + $('#flow-version-description').val(''); + $('#flow-version-change-comments').val(''); + + $('#flow-version-process-group-id').removeData('versionControlInformation').removeData('revision').text(''); + }; + + /** + * Loads the buckets for the specified registryIdentifier for the current user. + * + * @param registryIdentifier + * @returns {*} + */ + var loadBuckets = function (registryIdentifier) { + return $.ajax({ + type: 'GET', + url: '../nifi-api/flow/registries/' + encodeURIComponent(registryIdentifier) + '/buckets', + dataType: 'json' + }).done(function (response) { + var buckets = []; + + if (nfCommon.isDefinedAndNotNull(response.buckets) && response.buckets.length > 0) { + response.buckets.sort(function (a, b) { + return a.bucket.name > b.bucket.name; + }); + + $.each(response.buckets, function (_, bucketEntity) { + var bucket = bucketEntity.bucket; + buckets.push({ + text: bucket.name, + value: bucket.id, + description: nfCommon.escapeHtml(bucket.description) + }); + }); + } else { + buckets.push({ + text: 'No available buckets', + value: null, + optionClass: 'unset', + disabled: true + }); + } + + // load the buckets + $('#flow-version-bucket-combo').combo('destroy').combo({ + options: buckets, + select: selectBucket + }); + }).fail(function () { + $('#save-flow-version-dialog').modal('refreshButtons'); + }).fail(nfErrorHandler.handleAjaxError); + }; + + /** + * Select handler for the registries combo. + * + * @param selectedOption + */ + var selectRegistry = function (selectedOption) { + if (selectedOption.disabled === true) { + $('#flow-version-bucket-combo').combo('destroy').combo({ + options: [{ + text: 'No available buckets', + value: null, + optionClass: 'unset', + disabled: true + }] + }); + + $('#save-flow-version-dialog').modal('refreshButtons'); + } else { + loadBuckets(selectedOption.value); + } + }; + + /** + * Select handler for the buckets combo. + * + * @param selectedOption + */ + var selectBucket = function (selectedOption) { + $('#save-flow-version-dialog').modal('refreshButtons'); + }; + + /** + * Saves a flow version. + * + * @returns {*} + */ + var saveFlowVersion = function () { + var processGroupId = $('#flow-version-process-group-id').text(); + var processGroupRevision = $('#flow-version-process-group-id').data('revision'); + + var saveFlowVersionRequest = { + processGroupRevision: nfClient.getRevision({ + revision: { + version: processGroupRevision.version + } + }) + }; + + var versionControlInformation = $('#flow-version-process-group-id').data('versionControlInformation'); + if (nfCommon.isDefinedAndNotNull(versionControlInformation)) { + saveFlowVersionRequest['versionedFlow'] = { + registryId: versionControlInformation.registryId, + bucketId: versionControlInformation.bucketId, + flowId: versionControlInformation.flowId, + flowName: $('#flow-version-name').val(), + description: $('#flow-version-description').val(), + comments: $('#flow-version-change-comments').val() + } + } else { + var selectedRegistry = $('#flow-version-registry-combo').combo('getSelectedOption'); + var selectedBucket = $('#flow-version-bucket-combo').combo('getSelectedOption'); + + saveFlowVersionRequest['versionedFlow'] = { + registryId: selectedRegistry.value, + bucketId: selectedBucket.value, + flowName: $('#flow-version-name').val(), + description: $('#flow-version-description').val(), + comments: $('#flow-version-change-comments').val() + } + } + + return $.ajax({ + type: 'POST', + data: JSON.stringify(saveFlowVersionRequest), + url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId), + dataType: 'json', + contentType: 'application/json' + }).fail(nfErrorHandler.handleAjaxError); + }; + + return { + init: function () { + // initialize the flow version dialog + $('#save-flow-version-dialog').modal({ + scrollableContentStyle: 'scrollable', + headerText: 'Save Flow Version', + buttons: [{ + buttonText: 'Save', + color: { + base: '#728E9B', + hover: '#004849', + text: '#ffffff' + }, + disabled: function () { + if ($('#flow-version-registry-combo').is(':visible')) { + var selectedRegistry = $('#flow-version-registry-combo').combo('getSelectedOption'); + var selectedBucket = $('#flow-version-bucket-combo').combo('getSelectedOption'); + + if (nfCommon.isDefinedAndNotNull(selectedRegistry) && nfCommon.isDefinedAndNotNull(selectedBucket)) { + return selectedRegistry.disabled === true || selectedBucket.disabled === true; + } else { + return true; + } + } else { + return false; + } + }, + handler: { + click: function () { + var processGroupId = $('#flow-version-process-group-id').text(); + + saveFlowVersion().done(function (response) { + // refresh either selected PG or bread crumb to reflect connected/tracking status + if (nfCanvasUtils.getGroupId() === processGroupId) { + nfNgBridge.injector.get('breadcrumbsCtrl').updateVersionControlInformation(processGroupId, response.versionControlInformation); + nfNgBridge.digest(); + } else { + nfProcessGroup.reload(processGroupId); + } + + // close the dialog + $('#save-flow-version-dialog').modal('hide'); + }); + } + } + }, { + buttonText: 'Cancel', + color: { + base: '#E3E8EB', + hover: '#C7D2D7', + text: '#004849' + }, + handler: { + click: function () { + $(this).modal('hide'); + } + } + }], + handler: { + close: function () { + resetDialog(); + } + } + }); + }, + + /** + * Shows the flow version dialog. + * + * @param processGroupId + */ + showFlowVersionDialog: function (processGroupId) { + return $.Deferred(function (deferred) { + $.ajax({ + type: 'GET', + url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId), + dataType: 'json' + }).done(function (response) { + // record the revision + $('#flow-version-process-group-id').data('revision', response.processGroupRevision).text(processGroupId); + + if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) { + var versionControlInformation = response.versionControlInformation; + + // update the registry and bucket visibility + $('#flow-version-registry').text(versionControlInformation.registryId).show(); + $('#flow-version-bucket').text(versionControlInformation.bucketId).show(); + + $('#flow-version-name').val(''); + $('#flow-version-description').val(''); + + // record the versionControlInformation + $('#flow-version-process-group-id').data('versionControlInformation', versionControlInformation) + + deferred.resolve(); + } else { + // update the registry and bucket visibility + $('#flow-version-registry-combo').show(); + $('#flow-version-bucket-combo').show(); + + $.ajax({ + type: 'GET', + url: '../nifi-api/flow/registries', + dataType: 'json' + }).done(function (registriesResponse) { + var registries = []; + + if (nfCommon.isDefinedAndNotNull(registriesResponse.registries) && registriesResponse.registries.length > 0) { + registriesResponse.registries.sort(function (a, b) { + return a.component.name > b.component.name; + }); + + $.each(registriesResponse.registries, function (_, registryEntity) { + var registry = registryEntity.component; + registries.push({ + text: registry.name, + value: registry.id, + description: nfCommon.escapeHtml(registry.description) + }); + }); + } else { + registries.push({ + text: 'No available registries', + value: null, + optionClass: 'unset', + disabled: true + }); + } + + // load the registries + $('#flow-version-registry-combo').combo({ + options: registries, + select: selectRegistry + }); + + deferred.resolve(); + }).fail(function () { + deferred.reject(); + }).fail(nfErrorHandler.handleAjaxError); + } + }).fail(nfErrorHandler.handleAjaxError); + }).done(function () { + $('#save-flow-version-dialog').modal('show'); + }).fail(function () { + $('#save-flow-version-dialog').modal('refreshButtons'); + }).promise(); + }, + + /** + * Reverts changes for the specified Process Group. + * + * @param processGroupId + */ + revertFlowChanges: function (processGroupId) { + // prompt the user before reverting + nfDialog.showYesNoDialog({ + headerText: 'Revert Changes', + dialogContent: 'Are you sure you want to revert changes? All flow configuration changes will be reverted to the last version.', + noText: 'Cancel', + yesText: 'Revert', + yesHandler: function () { + $.ajax({ + type: 'GET', + url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId), + dataType: 'json' + }).done(function (response) { + if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) { + var revertFlowVersionRequest = { + processGroupRevision: nfClient.getRevision({ + revision: { + version: response.processGroupRevision.version + } + }), + versionControlInformation: response.versionControlInformation + }; + + $.ajax({ + type: 'POST', + data: JSON.stringify(revertFlowVersionRequest), + url: '../nifi-api/versions/revert-requests/process-groups/' + encodeURIComponent(processGroupId), + dataType: 'json', + contentType: 'application/json' + }).done(function (response) { + // TODO update multi step to show user the ramifications of reverting for confirmation + + if (nfCanvasUtils.getGroupId() === processGroupId) { + // if reverting current PG... reload/refresh this group/canvas + // TODO consider implementing this differently + $.ajax({ + type: 'GET', + url: '../nifi-api/flow/process-groups/' + encodeURIComponent(processGroupId), + dataType: 'json' + }).done(function (response) { + nfGraph.set(response.processGroupFlow.flow); + }).fail(nfErrorHandler.handleAjaxError); + } else { + // if reverting selected PG... reload selected PG to update counts, etc + nfProcessGroup.reload(processGroupId); + } + + nfDialog.showOkDialog({ + headerText: 'Revert Changes', + dialogContent: 'This Process Group has been reverted.' + }); + }).fail(nfErrorHandler.handleAjaxError); + } else { + nfDialog.showOkDialog({ + headerText: 'Revert Changes', + dialogContent: 'This Process Group is not currently under version control.' + }); + } + }).fail(nfErrorHandler.handleAjaxError); + } + }); + }, + + /** + * Disconnects the specified Process Group from flow versioning. + * + * @param processGroupId + */ + disconnectFlowVersioning: function (processGroupId) { + // prompt the user before disconnecting + nfDialog.showYesNoDialog({ + headerText: 'Disconnect', + dialogContent: 'Are you sure you want to disconnect?', + noText: 'Cancel', + yesText: 'Disconnect', + yesHandler: function () { + $.ajax({ + type: 'GET', + url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId), + dataType: 'json' + }).done(function (response) { + if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) { + var revision = nfClient.getRevision({ + revision: { + version: response.processGroupRevision.version + } + }); + + $.ajax({ + type: 'DELETE', + url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId) + '?' + $.param(revision), + dataType: 'json', + contentType: 'application/json' + }).done(function (response) { + // refresh either selected PG or bread crumb to reflect disconnected status + if (nfCanvasUtils.getGroupId() === processGroupId) { + nfNgBridge.injector.get('breadcrumbsCtrl').updateVersionControlInformation(processGroupId, undefined); + nfNgBridge.digest(); + } else { + nfProcessGroup.reload(processGroupId); + } + + nfDialog.showOkDialog({ + headerText: 'Disconnect', + dialogContent: 'This Process Group has been disconnected.' + }); + }).fail(nfErrorHandler.handleAjaxError); + } else { + nfDialog.showOkDialog({ + headerText: 'Disconnect', + dialogContent: 'This Process Group is not currently under version control.' + }) + } + }).fail(nfErrorHandler.handleAjaxError); + } + }); + } + }; +})); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js index 498fbd7..58402df 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js @@ -215,7 +215,7 @@ $('#process-group-configuration').data('process-group', { 'permissions': { canRead: false, - canWrite: nfCanvasUtils.canWrite() + canWrite: nfCanvasUtils.canWriteCurrentGroup() } }); } else { http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js index 13bbc70..17bb069 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js @@ -180,6 +180,15 @@ 'class': 'process-group-name' }); + // process group name + processGroup.append('text') + .attr({ + 'x': 3, + 'y': 17, + 'class': 'version-control' + }) + .text('\uf00c'); + // always support selecting and navigation processGroup.on('dblclick', function (d) { // enter this group on double click @@ -868,12 +877,18 @@ }).append('title').text(function (d) { return d.component.name; }); + + // update version control information + processGroup.select('text.version-control').style('visibility', nfCommon.isDefinedAndNotNull(processGroupData.component.versionControlInformation) ? 'visible' : 'hidden'); } else { // clear the process group comments details.select('text.process-group-comments').text(null); // clear the process group name processGroup.select('text.process-group-name').text(null); + + // update version control information + processGroup.select('text.version-control').style('visibility', false); } // populate the stats http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js ---------------------------------------------------------------------- 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 4da6fc6..0e5a2d7 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 @@ -81,7 +81,9 @@ controllerConfig: '../nifi-api/controller/config', reportingTaskTypes: '../nifi-api/flow/reporting-task-types', createReportingTask: '../nifi-api/controller/reporting-tasks', - reportingTasks: '../nifi-api/flow/reporting-tasks' + reportingTasks: '../nifi-api/flow/reporting-tasks', + createRegistry: '../nifi-api/controller/registries', + registries: '../nifi-api/flow/registries' } }; @@ -465,6 +467,94 @@ }; /** + * Adds the specified entity. + */ + var addRegistry = function () { + var registryEntity = { + 'revision': nfClient.getRevision({ + 'revision': { + 'version': 0 + } + }), + 'component': { + 'name': $('#registry-name').val(), + 'uri': $('#registry-location').val(), + 'description': $('#registry-description').val() + } + }; + + // add the new registry + var addRegistry = $.ajax({ + type: 'POST', + url: config.urls.createRegistry, + data: JSON.stringify(registryEntity), + dataType: 'json', + contentType: 'application/json' + }).done(function (registryEntity) { + // add the item + var registriesGrid = $('#registries-table').data('gridInstance'); + var registriesData = registriesGrid.getData(); + registriesData.addItem($.extend({ + type: 'Registry' + }, registryEntity)); + + // resort + registriesData.reSort(); + registriesGrid.invalidate(); + + // select the new reporting task + var row = registriesData.getRowById(registryEntity.id); + nfFilteredDialogCommon.choseRow(registriesGrid, row); + registriesGrid.scrollRowIntoView(row); + }).fail(nfErrorHandler.handleAjaxError); + + // hide the dialog + $('#registry-configuration-dialog').modal('hide'); + + return addRegistry; + }; + + /** + * Updates the registry with the specified id. + * + * @param registryId + */ + var updateRegistry = function (registryId) { + var registriesGrid = $('#registries-table').data('gridInstance'); + var registriesData = registriesGrid.getData(); + + var registryEntity = registriesData.getItemById(registryId); + var requestRegistryEntity = { + 'revision': nfClient.getRevision(registryEntity), + 'component': { + 'id': registryId, + 'name': $('#registry-name').val(), + 'uri': $('#registry-location').val(), + 'description': $('#registry-description').val() + } + }; + + // add the new reporting task + var updateRegistry = $.ajax({ + type: 'PUT', + url: registryEntity.uri, + data: JSON.stringify(requestRegistryEntity), + dataType: 'json', + contentType: 'application/json' + }).done(function (registryEntity) { + // add the item + registriesData.updateItem(registryId, $.extend({ + type: 'Registry' + }, registryEntity)); + }).fail(nfErrorHandler.handleAjaxError); + + // hide the dialog + $('#registry-configuration-dialog').modal('hide'); + + return updateRegistry; + }; + + /** * Initializes the new reporting task dialog. */ var initNewReportingTaskDialog = function () { @@ -783,6 +873,20 @@ } } }); + + // initialize the registry configuration dialog + $('#registry-configuration-dialog').modal({ + scrollableContentStyle: 'scrollable', + headerText: 'Add Registry', + handler: { + close: function () { + $('#registry-id').text(''); + $('#registry-name').val(''); + $('#registry-location').val(''); + $('#registry-description').val(''); + } + } + }); }; /** @@ -1090,6 +1194,228 @@ }); }; + var initRegistriesTable = function () { + + var locationFormatter = function (row, cell, value, columnDef, dataContext) { + if (!dataContext.permissions.canRead) { + return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>'; + } + + return nfCommon.escapeHtml(dataContext.component.uri); + }; + + var descriptionFormatter = function (row, cell, value, columnDef, dataContext) { + if (!dataContext.permissions.canRead) { + return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>'; + } + + return nfCommon.escapeHtml(dataContext.component.description); + }; + + var registriesActionFormatter = function (row, cell, value, columnDef, dataContext) { + var markup = ''; + + if (nfCommon.canModifyController()) { + // edit registry + markup += '<div title="Edit" class="pointer edit-registry fa fa-pencil" style="margin-top: 2px; margin-right: 3px;" ></div>'; + + // remove registry + markup += '<div title="Remove" class="pointer remove-registry fa fa-trash" style="margin-top: 2px; margin-right: 3px;" ></div>'; + } + + return markup; + }; + + // define the column model for the reporting tasks table + var registriesColumnModel = [ + { + id: 'name', + name: 'Name', + field: 'name', + formatter: nameFormatter, + sortable: true, + resizable: true + }, + { + id: 'uri', + name: 'Location', + field: 'uri', + formatter: locationFormatter, + sortable: true, + resizable: true + }, + { + id: 'description', + name: 'Description', + field: 'description', + formatter: descriptionFormatter, + sortable: true, + resizable: true + } + ]; + + // action column should always be last + registriesColumnModel.push({ + id: 'actions', + name: ' ', + resizable: false, + formatter: registriesActionFormatter, + sortable: false, + width: 90, + maxWidth: 90 + }); + + // initialize the dataview + var registriesData = new Slick.Data.DataView({ + inlineFilters: false + }); + registriesData.setItems([]); + + // initialize the sort + sort({ + columnId: 'name', + sortAsc: true + }, registriesData); + + // initialize the grid + var registriesGrid = new Slick.Grid('#registries-table', registriesData, registriesColumnModel, gridOptions); + registriesGrid.setSelectionModel(new Slick.RowSelectionModel()); + registriesGrid.registerPlugin(new Slick.AutoTooltips()); + registriesGrid.setSortColumn('name', true); + registriesGrid.onSort.subscribe(function (e, args) { + sort({ + columnId: args.sortCol.id, + sortAsc: args.sortAsc + }, registriesData); + }); + + // configure a click listener + registriesGrid.onClick.subscribe(function (e, args) { + var target = $(e.target); + + // get the service at this row + var registryEntity = registriesData.getItem(args.row); + + // determine the desired action + if (registriesGrid.getColumns()[args.cell].id === 'actions') { + if (target.hasClass('edit-registry')) { + editRegistry(registryEntity); + } else if (target.hasClass('remove-registry')) { + promptToRemoveRegistry(registryEntity); + } + } else if (registriesGrid.getColumns()[args.cell].id === 'moreDetails') { + // if (target.hasClass('view-reporting-task')) { + // nfReportingTask.showDetails(reportingTaskEntity); + // } else if (target.hasClass('reporting-task-usage')) { + // // close the settings dialog + // $('#shell-close-button').click(); + // + // // open the documentation for this reporting task + // nfShell.showPage('../nifi-docs/documentation?' + $.param({ + // select: reportingTaskEntity.component.type, + // group: reportingTaskEntity.component.bundle.group, + // artifact: reportingTaskEntity.component.bundle.artifact, + // version: reportingTaskEntity.component.bundle.version + // })).done(function () { + // nfSettings.showSettings(); + // }); + // } + } + }); + + // wire up the dataview to the grid + registriesData.onRowCountChanged.subscribe(function (e, args) { + registriesGrid.updateRowCount(); + registriesGrid.render(); + }); + registriesData.onRowsChanged.subscribe(function (e, args) { + registriesGrid.invalidateRows(args.rows); + registriesGrid.render(); + }); + registriesData.syncGridSelection(registriesGrid, true); + + // hold onto an instance of the grid + $('#registries-table').data('gridInstance', registriesGrid); + }; + + /** + * Edits the specified registry entity. + * + * @param registryEntity + */ + var editRegistry = function (registryEntity) { + // populate the dialog + $('#registry-id').text(registryEntity.id); + $('#registry-name').val(registryEntity.component.name); + $('#registry-location').val(registryEntity.component.uri); + $('#registry-description').val(registryEntity.component.description); + + // show the dialog + $('#registry-configuration-dialog').modal('setButtonModel', [{ + buttonText: 'Update', + color: { + base: '#728E9B', + hover: '#004849', + text: '#ffffff' + }, + handler: { + click: function () { + updateRegistry(registryEntity.id); + } + } + }, { + buttonText: 'Cancel', + color: { + base: '#E3E8EB', + hover: '#C7D2D7', + text: '#004849' + }, + handler: { + click: function () { + $(this).modal('hide'); + } + } + }]).modal('show'); + }; + + /** + * Prompts the user before attempting to delete the specified registry. + * + * @param {object} registryEntity + */ + var promptToRemoveRegistry = function (registryEntity) { + // prompt for deletion + nfDialog.showYesNoDialog({ + headerText: 'Delete Registry', + dialogContent: 'Delete registry \'' + nfCommon.escapeHtml(registryEntity.component.name) + '\'?', + yesHandler: function () { + removeRegistry(registryEntity); + } + }); + }; + + /** + * Deletes the specified registry. + * + * @param {object} registryEntity + */ + var removeRegistry = function (registryEntity) { + var revision = nfClient.getRevision(registryEntity); + $.ajax({ + type: 'DELETE', + url: registryEntity.uri + '?' + $.param({ + version: revision.version, + clientId: revision.clientId + }), + dataType: 'json' + }).done(function (response) { + // remove the task + var registryGrid = $('#registries-table').data('gridInstance'); + var registryData = registryGrid.getData(); + registryData.deleteItem(registryEntity.id); + }).fail(nfErrorHandler.handleAjaxError); + }; + /** * Loads the settings. */ @@ -1158,6 +1484,9 @@ // load the reporting tasks var reportingTasks = loadReportingTasks(); + // load the registries + var registries = loadRegistries(); + // return a deferred for all parts of the settings return $.when(settings, controllerServicesXhr, reportingTasks).done(function (settingsResult, controllerServicesResult) { var controllerServicesResponse = controllerServicesResult[0]; @@ -1199,6 +1528,32 @@ }; /** + * Loads the registries. + */ + var loadRegistries = function () { + return $.ajax({ + type: 'GET', + url: config.urls.registries, + dataType: 'json' + }).done(function (response) { + var registries = []; + $.each(response.registries, function (_, registryEntity) { + registries.push($.extend({ + type: 'Registry' + }, registryEntity)); + }); + + var registriesGrid = $('#registries-table').data('gridInstance'); + var registriesData = registriesGrid.getData(); + + // update the registries + registriesData.setItems(registries); + registriesData.reSort(); + registriesGrid.invalidate(); + }); + }; + + /** * Shows the process group configuration. */ var showSettings = function () { @@ -1241,6 +1596,9 @@ }, { name: 'Reporting Tasks', tabContentId: 'reporting-tasks-tab-content' + }, { + name: 'Registries', + tabContentId: 'registries-tab-content' }], select: function () { var tab = $(this).text(); @@ -1267,6 +1625,9 @@ } else if (tab === 'Reporting Tasks') { $('#settings-save').hide(); return 'Create a new reporting task'; + } else if (tab === 'Registries') { + $('#settings-save').hide(); + return 'Register a new registry'; } }); } else { @@ -1276,7 +1637,7 @@ if (tab === 'Reporting Task Controller Services') { $('#controller-cs-availability').show(); - } else if (tab === 'Reporting Tasks') { + } else if (tab === 'Reporting Tasks' || tab === 'Registries') { $('#controller-cs-availability').hide(); } @@ -1315,6 +1676,32 @@ // set the initial focus $('#reporting-task-type-filter').focus(); + } else if (selectedTab === 'Registries') { + $('#registry-configuration-dialog').modal('setButtonModel', [{ + buttonText: 'Add', + color: { + base: '#728E9B', + hover: '#004849', + text: '#ffffff' + }, + handler: { + click: function () { + addRegistry(); + } + } + }, { + buttonText: 'Cancel', + color: { + base: '#E3E8EB', + hover: '#C7D2D7', + text: '#004849' + }, + handler: { + click: function () { + $(this).modal('hide'); + } + } + }]).modal('show'); } }); @@ -1322,6 +1709,7 @@ initGeneral(); nfControllerServices.init(getControllerServicesTable(), nfSettings.showSettings); initReportingTasks(); + initRegistriesTable(); }, /** http://git-wip-us.apache.org/repos/asf/nifi/blob/7a0a900a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html index 10d36f1..a8b8579 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html @@ -22,6 +22,7 @@ limitations under the License. <span ng-if="separatorFunc(crumb.parentBreadcrumb)" style="margin: 0 12px;"> » </span> + <span ng-if="separatorFunc(crumb.breadcrumb.versionControlInformation)" class="breadcrumb-version-control fa fa-check" style="margin: 0 6px;"></span> <span class="link" ng-class="(highlightCrumbId === crumb.id) ? 'link-bold' : ''" ng-click="clickFunc(crumb.id)">
