http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/index.html ---------------------------------------------------------------------- diff --git a/falcon-ui/app/index.html b/falcon-ui/app/index.html index 13fbe35..89ca4a9 100644 --- a/falcon-ui/app/index.html +++ b/falcon-ui/app/index.html @@ -18,12 +18,14 @@ */ --> <!DOCTYPE html> -<html ng-app="app"> +<html ng-app="app" data-ng-controller="ThemeController"> <head> <title>Falcon Web UI</title> <meta charset="utf-8"> <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> - <link rel="stylesheet" href="css/main.css"/> + <link rel="stylesheet" ng-href="css/{{theme}}-theme.css"/> + <link rel="stylesheet" href="css/jquery-ui.css"> + <link rel="icon" type="image/x-icon" href="data:image/png;base64,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"/> </head> @@ -34,11 +36,11 @@ </section> <section class="container-fluid"> - <div class="row mainUIView" ui-view id="mainUIView"></div> + <div ng-if="!httpError" class="row mainUIView" ui-view id="mainUIView"></div> + <div ng-if="httpError" class="row mainUIView" error-nav id="errorView"></div> </section> <script src="js/vendor.min.js"></script> <script src="js/main.min.js"></script> - </body> </html>
http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/app.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/app.js b/falcon-ui/app/js/app.js index 5ae7eb6..1d781bc 100644 --- a/falcon-ui/app/js/app.js +++ b/falcon-ui/app/js/app.js @@ -23,26 +23,36 @@ 'ui.router', 'ngCookies', 'ngAnimate', + 'ngStorage', 'ngMessages', 'checklist-model', 'app.controllers', 'app.directives', 'app.services', 'ngTagsInput', - 'nsPopover', 'ngAnimate', 'ngMask', 'dateHelper' + 'nsPopover', + 'ngMask', + 'dateHelper', + 'focus-if', + 'routeHelper' ]); - - app.config(["$stateProvider", "$urlRouterProvider", "$httpProvider", function ($stateProvider, $urlRouterProvider, $httpProvider) { + app.constant('APP_CONSTANTS',{ + enableXSRFHeader : true + }); + app.config(["$stateProvider", "$urlRouterProvider", "$httpProvider", 'APP_CONSTANTS', function ($stateProvider, $urlRouterProvider, $httpProvider, AppConstants) { $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content'); + if (AppConstants.enableXSRFHeader ){ + $httpProvider.defaults.headers.common['X-XSRF-HEADER'] = Math.round(Math.random()*100000); + } $httpProvider.defaults.headers.common["X-Requested-By"] = 'X-Requested-By'; $urlRouterProvider.otherwise("/"); $stateProvider .state('main', { - url: '/', + url: '/?fromAction', templateUrl: 'html/mainTpl.html', controller: 'DashboardCtrl' }) @@ -61,8 +71,16 @@ templateUrl: 'html/formsTpl.html' }) .state('forms.cluster', { + url : '/cluster?name&action', controller: 'ClusterFormCtrl', - templateUrl: 'html/cluster/clusterFormTpl.html' + templateUrl: 'html/cluster/clusterFormTpl.html', + resolve : { + ClusterModel : ['$stateParams', 'EntityDetails', function($stateParams, EntityDetails){ + if($stateParams.name !== null){ + return EntityDetails.getEntityDefinition("cluster", $stateParams.name); + } + }] + } }) .state('forms.cluster.general', { templateUrl: 'html/cluster/clusterFormGeneralStepTpl.html' @@ -71,12 +89,50 @@ templateUrl: 'html/cluster/clusterFormSummaryStepTpl.html' }) .state('forms.feed', { + url : '/feed?name&action', templateUrl: 'html/feed/feedFormTpl.html', - controller: 'FeedController' + controller: 'FeedController', + resolve : { + FeedModel : ['$stateParams', 'EntityDetails', 'FileApi','X2jsService', function($stateParams, EntityDetails, FileApi, X2jsService){ + if($stateParams.action === 'import'){ + var feedJson = X2jsService.xml_str2json(FileApi.fileRaw); + return feedJson; + } + if($stateParams.name !== null){ + var modelPromise = EntityDetails.getEntityDefinition("feed", $stateParams.name); + return modelPromise.then(function(model){ + if($stateParams.action === "edit"){ + model.edit = true; + }else if($stateParams.action === "clone"){ + model.clone = true; + } + return model; + }); + } + }], + datasourcesList: ['Falcon', function (Falcon) { + return Falcon.getEntities('datasource').then( + function (response) { + return response.data; + }); + }] + } }) .state('forms.feed.general', { templateUrl: 'html/feed/feedFormGeneralStepTpl.html', - controller: 'FeedGeneralInformationController' + controller: 'FeedGeneralInformationController', + resolve: { + clustersList: ['Falcon', function (Falcon) { + return Falcon.getEntities('cluster').then( + function (response) { + return response.data; + }); + }] + } + }) + .state('forms.feed.advanced', { + templateUrl: 'html/feed/feedFormAdvancedStepTpl.html', + controller: 'FeedAdvancedController' }) .state('forms.feed.properties', { templateUrl: 'html/feed/feedFormPropertiesStepTpl.html', @@ -103,33 +159,39 @@ controller: 'FeedSummaryController' }) .state('forms.process', { + url : '/process?name&action', templateUrl: 'html/process/processFormTpl.html', - controller: 'ProcessRootCtrl' + controller: 'ProcessRootCtrl', + resolve : { + ProcessModel : ['$stateParams', 'EntityDetails', 'FileApi','X2jsService', function($stateParams, EntityDetails, FileApi, X2jsService){ + if($stateParams.action === 'import'){ + var processJson = X2jsService.xml_str2json(FileApi.fileRaw); + return processJson; + } + if($stateParams.name !== null){ + var modelPromise = EntityDetails.getEntityDefinition("process", $stateParams.name); + return modelPromise.then(function(model){ + if($stateParams.action === "edit"){ + model.edit = true; + }else if($stateParams.action === "clone"){ + model.clone = true; + } + return model; + }); + } + }] + } }) .state('forms.process.general', { templateUrl: 'html/process/processFormGeneralStepTpl.html', - controller: 'ProcessGeneralInformationCtrl' - }) - .state('forms.process.properties', { - templateUrl: 'html/process/processFormPropertiesStepTpl.html', - controller: 'ProcessPropertiesCtrl' - }) - .state('forms.process.clusters', { - templateUrl: 'html/process/processFormClustersStepTpl.html', - controller: 'ProcessClustersCtrl', + controller: 'ProcessGeneralInformationCtrl', resolve: { clustersList: ['Falcon', function (Falcon) { return Falcon.getEntities('cluster').then( function (response) { return response.data; }); - }] - } - }) - .state('forms.process.io', { - templateUrl: 'html/process/processFormInputsAndOutputsStepTpl.html', - controller: 'ProcessInputsAndOutputsCtrl', - resolve: { + }], feedsList: ['Falcon', function (Falcon) { return Falcon.getEntities('feed').then( function (response) { @@ -138,11 +200,16 @@ }] } }) + .state('forms.process.advanced', { + templateUrl: 'html/process/processFormAdvancedStepTpl.html', + controller: 'ProcessAdvancedCtrl' + }) .state('forms.process.summary', { templateUrl: 'html/process/processFormSummaryStepTpl.html', controller: 'ProcessSummaryCtrl' }) .state('entityDetails', { + url : '/entity?name&type', views: { '': { controller: 'EntityDetailsCtrl', @@ -153,10 +220,25 @@ }, 'processSummary@entityDetails': { templateUrl: 'html/process/processSummary.html' + }, + 'clusterSummary@entityDetails': { + templateUrl: 'html/cluster/clusterSummary.html' + }, + 'snapshotSummary@entityDetails': { + templateUrl: 'html/snapshot/snapshotSummary.html' + }, + 'datasetSummary@entityDetails': { + templateUrl: 'html/dataset/datasetSummary.html' } + }, + resolve : { + entity : ['$stateParams', 'EntityDetails', function($stateParams, EntityDetails){ + return EntityDetails.getEntityDetails($stateParams.name, $stateParams.type.toLowerCase()); + }] } }) .state('forms.dataset', { + url : '/dataset?name&action', controller: 'DatasetCtrl', templateUrl: 'html/dataset/datasetFormTpl.html', resolve: { @@ -165,6 +247,19 @@ function (response) { return response.data.entity; }); + }], + DatasetModel : ['$stateParams', 'EntityDetails', function($stateParams, EntityDetails){ + if($stateParams.name !== null){ + var modelPromise = EntityDetails.getEntityDefinition("process", $stateParams.name); + return modelPromise.then(function(model){ + if($stateParams.action === "edit"){ + model.edit = true; + }else if($stateParams.action === "clone"){ + model.clone = true; + } + return model; + }); + } }] } }) @@ -174,10 +269,81 @@ .state('forms.dataset.summary', { templateUrl: 'html/dataset/datasetFormSummaryStepTpl.html' }) + .state('forms.snapshot', { + url : '/snapshot?name&action', + controller: 'SnapshotController', + templateUrl: 'html/snapshot/snapshotFormTpl.html', + resolve: { + clustersList: ['Falcon', function (Falcon) { + return Falcon.getEntities('cluster').then( + function (response) { + return response.data; + }); + }], + SnapshotModel : ['$stateParams', 'EntityDetails', function($stateParams, EntityDetails){ + if ($stateParams.name !== null) { + var modelPromise = EntityDetails.getEntityDefinition("process", $stateParams.name); + return modelPromise.then(function(model){ + if ($stateParams.action === "edit") { + model.edit = true; + } else if($stateParams.action === "clone") { + model.clone = true; + } + return model; + }); + } + }] + } + }) + .state('forms.snapshot.general', { + templateUrl: 'html/snapshot/snapshotFormGeneralStepTpl.html' + }) + .state('forms.snapshot.advanced', { + templateUrl: 'html/snapshot/snapshotFormAdvancedStepTpl.html' + }) + .state('forms.snapshot.summary', { + templateUrl: 'html/snapshot/snapshotFormSummaryStepTpl.html' + }) .state('instanceDetails', { templateUrl: 'html/instanceDetails.html', controller: 'InstanceDetailsCtrl' }) + .state('forms.datasource', { + url : '/datasource?name&action', + templateUrl: 'html/datasource/datasourceFormTpl.html', + controller: 'DatasourceController', + resolve : { + DatasourceModel : ['$stateParams', 'EntityDetails', 'FileApi', 'X2jsService', function($stateParams, EntityDetails, FileApi, X2jsService){ + if($stateParams.action === 'import'){ + var dataSourceJson = X2jsService.xml_str2json(FileApi.fileRaw); + return dataSourceJson; + } + if($stateParams.name !== null){ + var modelPromise = EntityDetails.getEntityDefinition("datasource", $stateParams.name); + return modelPromise.then(function(model){ + if($stateParams.action === "edit"){ + model.edit = true; + } else if($stateParams.action === "clone"){ + model.clone = true; + } + return model; + }); + } + }] + } + }) + .state('forms.datasource.general', { + templateUrl: 'html/datasource/datasourceFormGeneralStepTpl.html', + controller: 'DatasourceGeneralInformationController' + }) + .state('forms.datasource.advanced', { + templateUrl: 'html/datasource/datasourceFormAdvancedStepTpl.html', + controller: 'DatasourceAdvancedController' + }) + .state('forms.datasource.summary', { + templateUrl: 'html/datasource/datasourceFormSummaryStepTpl.html', + controller: 'DatasourceSummaryController' + }) ; }]); @@ -185,6 +351,25 @@ app.run(['$rootScope', '$state', '$location', '$http', '$stateParams', '$cookieStore', 'SpinnersFlag', 'ServerAPI', '$timeout', '$interval', function ($rootScope, $state, $location, $http, $stateParams, $cookieStore, SpinnersFlag, ServerAPI, $timeout, $interval) { + $rootScope.ambariView = function () { + var location_call = $location.absUrl(); + var index_call = location_call.indexOf("views/"); + if (index_call !== -1) { + return true; + } else { + return false; + } + }; + + var location = $location.absUrl(); + var index = location.indexOf("views/"); + if (index !== -1) { + index = index + 6; + var path = location.substring(index); + var servicePaths = path.split("/"); + $rootScope.serviceURI = '/api/v1/views/' + servicePaths[0] + '/versions/' + servicePaths[1] + '/instances/' + servicePaths[2] + '/resources/proxy'; + } + if(!$rootScope.secureModeDefined){ $rootScope.secureMode = false; ServerAPI.clearUser().then(function() { @@ -196,6 +381,13 @@ $rootScope.secureMode = true; } } + if (property.key == 'safemode') { + if (property.value == 'true') { + $rootScope.safeMode = true; + } else { + $rootScope.safeMode = false; + } + } }); } $rootScope.secureModeDefined = true; @@ -203,25 +395,6 @@ }); } - var location = $location.absUrl(); - var index = location.indexOf("views/"); - if (index !== -1) { - index = index + 6; - var path = location.substring(index); - var servicePaths = path.split("/"); - $rootScope.serviceURI = '/api/v1/views/' + servicePaths[0] + '/versions/' + servicePaths[1] + '/instances/' + servicePaths[2] + '/resources/proxy'; - } - - $rootScope.ambariView = function () { - var location_call = $location.absUrl(); - var index_call = location_call.indexOf("views/"); - if (index_call !== -1) { - return true; - } else { - return false; - } - }; - $rootScope.isSecureMode = function () { if(!$rootScope.secureModeDefined){ return false; @@ -233,14 +406,10 @@ }; $rootScope.userLogged = function () { - if($rootScope.ambariView()){ + if (angular.isDefined($cookieStore.get('userToken')) && $cookieStore.get('userToken') !== null) { return true; } else { - if (angular.isDefined($cookieStore.get('userToken')) && $cookieStore.get('userToken') !== null) { - return true; - } else { - return false; - } + return false; } }; @@ -338,4 +507,4 @@ }]); -})(); \ No newline at end of file +})(); http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/cluster/cluster-module.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/cluster/cluster-module.js b/falcon-ui/app/js/controllers/cluster/cluster-module.js index d0fdf86..1f54756 100644 --- a/falcon-ui/app/js/controllers/cluster/cluster-module.js +++ b/falcon-ui/app/js/controllers/cluster/cluster-module.js @@ -26,19 +26,58 @@ */ var clusterModule = angular.module('app.controllers.cluster', [ 'app.services' ]); - clusterModule.controller('ClusterFormCtrl', [ "$scope", "$interval", "Falcon", "EntityModel", "$state", - "X2jsService", "ValidationService", "SpinnersFlag", "$timeout", "$rootScope", "$cookieStore", - function ($scope, $interval, Falcon, EntityModel, $state, - X2jsService, validationService, SpinnersFlag, $timeout, $rootScope, $cookieStore) { + clusterModule.controller('ClusterFormCtrl', [ + "$scope", "$interval", "Falcon", "EntityModel", "$state", "FileApi", "X2jsService", "ValidationService", + "SpinnersFlag", "$timeout", "$rootScope", "$cookieStore", "$stateParams", "ClusterModel", + function ($scope, $interval, Falcon, EntityModel, $state, FileApi, X2jsService, validationService, + SpinnersFlag, $timeout, $rootScope, $cookieStore, $stateParams, clusterModel) { + + if (clusterModel && $stateParams.action === 'clone') { + $scope.cloningMode = true; + $scope.editingMode = false; + $scope.clusterEntity = { 'clusterModel' : clusterModel }; + $scope.clusterEntity.clusterModel.name = ""; + } else if(clusterModel && $stateParams.action === 'edit') { + $scope.editingMode = true; + $scope.cloningMode = false; + $scope.clusterEntity = { 'clusterModel' : clusterModel }; + } else{ + $scope.editingMode = false; + $scope.cloningMode = false; + $scope.clusterEntity = EntityModel; + } + + if ($rootScope.secureMode) { + $scope.clusterEntity.clusterModel.cluster.properties.property[0] + = {_name : 'dfs.namenode.kerberos.principal', _value : 'nn/[email protected]'} + } + $scope.$watch("clusterEntity.clusterModel.cluster._name",function(){ + if ($scope.editingMode) { + return; + } + $scope.clusterEntity.clusterModel.cluster.locations.location.forEach (function(loc, index) { + if (loc._name === "staging") { + loc._path = "/apps/falcon/" + + ($scope.clusterEntity.clusterModel.cluster._name ? $scope.clusterEntity.clusterModel.cluster._name + "/" : "") + + "staging"; + } else if (loc._name === "working") { + loc._path = "/apps/falcon/" + + ($scope.clusterEntity.clusterModel.cluster._name ? $scope.clusterEntity.clusterModel.cluster._name + "/" : "") + + "working"; + } + }); + }); - $scope.clusterEntity = EntityModel; $scope.xmlPreview = { edit: false }; $scope.secondStep = false; + $scope.enableCustomSparkInterface = function() { + $scope.customSparkInterfaceEnabled = !$scope.customSparkInterfaceEnabled; + } function normalizeModel() { //------------INTERFACE-----------// - var requiredInterfaceFields = ["readonly", "write", "execute", "workflow", "messaging", "registry"], - requiredLocationFields = ["staging", "temp", "working", ""], + var requiredInterfaceFields = ["readonly", "write", "execute", "workflow", "messaging", "registry", "spark"], + requiredLocationFields = ["staging", "temp", "working"], modelInterfaceArray = $scope.clusterEntity.clusterModel.cluster.interfaces.interface, modelLocationsArray = $scope.clusterEntity.clusterModel.cluster.locations.location; @@ -47,10 +86,12 @@ if (element._type === requiredField) { requiredInterfaceFields.splice(requiredField, 1); } }); }); - $scope.registry = { check: true }; + $scope.registry = { check: false }; + $scope.spark = { check: false }; + $scope.customSparkInterfaceEnabled = false; requiredInterfaceFields.forEach(function (fieldToPush) { var fieldObject = { _type: fieldToPush, _endpoint: "", _version: "" }; - if (fieldToPush === "registry") { $scope.registry = { check: false }; } + //if (fieldToPush === "registry") { $scope.registry = { check: true }; } modelInterfaceArray.push(fieldObject); }); //--------------TAGS--------------// @@ -64,15 +105,17 @@ //-------------ACL----------------// if (!$scope.clusterEntity.clusterModel.cluster.ACL) { angular.copy(EntityModel.defaultValues.cluster.cluster.ACL, $scope.clusterEntity.clusterModel.cluster.ACL); - $scope.clusterEntity.clusterModel.cluster.ACL._owner = $cookieStore.get('userToken').user; /*$scope.clusterEntity.clusterModel.cluster.ACL = { _owner: "", _group: "", _permission: "" };*/ } + if ($cookieStore.get('userToken') && !$scope.clusterEntity.clusterModel.cluster.ACL._owner) { + $scope.clusterEntity.clusterModel.cluster.ACL._owner = $cookieStore.get('userToken').user; + } //------------Location------------// modelLocationsArray.forEach(function(element) { - requiredLocationFields.forEach(function(requiredField) { - if(element._name === requiredField) { requiredLocationFields.splice(requiredField, 1); } + requiredLocationFields.forEach(function(requiredField, index) { + if(element._name === requiredField) { requiredLocationFields.splice(index, 1); } }); }); requiredLocationFields.forEach(function(fieldToPush) { @@ -87,8 +130,13 @@ } function cleanModel() { + + if (!$scope.clusterEntity.clusterModel.cluster._description) { + $scope.clusterEntity.clusterModel.cluster._description = ''; + } + //if registry check is false backups the object and removes it from array - if (!$scope.registry.check) { + if ($scope.registry && !$scope.registry.check) { $scope.clusterEntity.clusterModel.cluster.interfaces.interface.forEach(function(registry, index) { if (registry._type === "registry") { $scope.backupRegistryObject = $scope.clusterEntity.clusterModel.cluster.interfaces.interface[index]; @@ -96,20 +144,31 @@ } }); } - //deletes property empty last object and array if empty - var lastOne = $scope.clusterEntity.clusterModel.cluster.properties.property.length - 1; - if ( - $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._name === "" || - $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._name === undefined || - $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._value === "" || - $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._value === undefined - ) { - - $scope.removeProperty(lastOne); + if ($scope.spark && !$scope.spark.check) { + $scope.clusterEntity.clusterModel.cluster.interfaces.interface.forEach(function(spark, index) { + if (spark._type === "spark") { + $scope.backupSparkObject = $scope.clusterEntity.clusterModel.cluster.interfaces.interface[index]; + $scope.clusterEntity.clusterModel.cluster.interfaces.interface.splice(index, 1); + } + }); } - if ($scope.clusterEntity.clusterModel.cluster.properties.property.length === 0) { - delete $scope.clusterEntity.clusterModel.cluster.properties; + //deletes property empty last object and array if empty + if($scope.clusterEntity.clusterModel.cluster.properties){ + var lastOne = $scope.clusterEntity.clusterModel.cluster.properties.property.length - 1; + if ( + $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._name === "" || + $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._name === undefined || + $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._value === "" || + $scope.clusterEntity.clusterModel.cluster.properties.property[lastOne]._value === undefined + ) { + + $scope.removeProperty(lastOne); + } + if ($scope.clusterEntity.clusterModel.cluster.properties.property.length === 0) { + delete $scope.clusterEntity.clusterModel.cluster.properties; + } } + var lastLocationIndex = $scope.clusterEntity.clusterModel.cluster.locations.location.length - 1; if ( $scope.clusterEntity.clusterModel.cluster.locations.location[lastLocationIndex]._name === "" || @@ -161,11 +220,13 @@ $scope.convertTags = function () { var result = []; - $scope.tagsArray.forEach(function(element) { - if(element.key && element.value) { - result.push(element.key + "=" + element.value); - } - }); + if($scope.tagsArray) { + $scope.tagsArray.forEach(function(element) { + if(element.key && element.value) { + result.push(element.key + "=" + element.value); + } + }); + } result = result.join(","); $scope.clusterEntity.clusterModel.cluster.tags = result; }; @@ -188,6 +249,14 @@ $scope.convertTags(); } }; + $scope.toggleclick = function () { + $('.formBoxContainer').toggleClass('col-xs-14 '); + $('.xmlPreviewContainer ').toggleClass('col-xs-10 hide'); + $('.preview').toggleClass('pullOver pullOverXml'); + ($('.preview').hasClass('pullOver')) ? $('.preview').find('button').html('Preview XML') : $('.preview').find('button').html('Hide XML'); + ($($("textarea")[0]).attr("ng-model") == "prettyXml" ) ? $($("textarea")[0]).css("min-height", $(".formBoxContainer").height() - 40 ) : ''; + }; + //-------------------------------------// //----------LOCATION-------------------// @@ -219,10 +288,45 @@ $scope.clusterEntity.clusterModel.cluster.properties.property.splice(index, 1); } }; - //--------------------------------------// + + $scope.isActive = function (route) { + return route === $state.current.name; + }; + + $scope.isCompleted = function (route) { + return $state.get(route).data && $state.get(route).data.completed; + }; + + $scope.validateLocations = function(){ + var stagingLoc; + var workingLoc; + $scope.clusterEntity.clusterModel.cluster.locations.location.forEach(function(location){ + if(location._name == "staging"){ + stagingLoc = location._path; + } + if(location._name == "working"){ + workingLoc = location._path; + } + }); + if(stagingLoc && workingLoc && stagingLoc == workingLoc){ + $scope.locationsEqualError = true; + }else{ + $scope.locationsEqualError = false; + } + return $scope.locationsEqualError; + }; + //--------------------------------------// $scope.goSummaryStep = function (formInvalid) { - SpinnersFlag.show = true; - if (!$scope.validations.nameAvailable || formInvalid) { + $state.current.data = $state.current.data || {}; + $state.current.data.completed = !formInvalid; + + SpinnersFlag.show = true; + if($scope.validateLocations()){ + SpinnersFlag.show = false; + return; + } + + if (!$scope.validations.nameAvailable || formInvalid) { validationService.displayValidations.show = true; validationService.displayValidations.nameShow = true; SpinnersFlag.show = false; @@ -236,6 +340,12 @@ }, 500); }; + + $scope.hideMessage = function (){ + angular.element('.nameValidationMessage').hide(); + }; + + $scope.goGeneralStep = function () { SpinnersFlag.backShow = true; $scope.secondStep = false; @@ -244,7 +354,15 @@ $scope.validations.nameAvailable = true; if(!$scope.registry.check) { //recovers previously deleted registry object - $scope.clusterEntity.clusterModel.cluster.interfaces.interface.push($scope.backupRegistryObject); + if($scope.backupRegistryObject){ + $scope.clusterEntity.clusterModel.cluster.interfaces.interface.push($scope.backupRegistryObject); + } + } + if(!$scope.spark.check) { + //recovers previously deleted spark object + if($scope.backupSparkObject){ + $scope.clusterEntity.clusterModel.cluster.interfaces.interface.push($scope.backupSparkObject); + } } if(!$scope.clusterEntity.clusterModel.cluster.tags) { $scope.clusterEntity.clusterModel.cluster.tags = ""; @@ -261,23 +379,48 @@ SpinnersFlag.show = true; $scope.saveModelBuffer(); Falcon.logRequest(); - Falcon.postSubmitEntity($scope.jsonString, "cluster").success(function (response) { - $scope.skipUndo = true; - Falcon.logResponse('success', response, false); - $state.go('main'); - }).error(function (err) { - SpinnersFlag.show = false; - Falcon.logResponse('error', err, false); - angular.element('body, html').animate({scrollTop: 0}, 300); - }); + if($scope.editingMode) { + Falcon.postUpdateEntity($scope.jsonString, "cluster", $scope.clusterEntity.clusterModel.cluster._name) + .success(function (response) { + $scope.skipUndo = true; + Falcon.logResponse('success', response, false); + $state.go('main'); + }) + .error(function(err) { + SpinnersFlag.show = false; + Falcon.logResponse('error', err, false); + angular.element('body, html').animate({scrollTop: 0}, 300); + }); + } else { + Falcon.postSubmitEntity($scope.jsonString, "cluster") + .success(function (response) { + $scope.skipUndo = true; + Falcon.logResponse('success', response, false); + $state.go('main'); + }) + .error(function(err) { + SpinnersFlag.show = false; + Falcon.logResponse('error', err, false); + angular.element('body, html').animate({scrollTop: 0}, 300); + }); + } }; //--------------------------------------// //----------XML preview-----------------// $scope.xmlPreview.editXML = function () { - $scope.xmlPreview.edit = !$scope.xmlPreview.edit; + $scope.xmlPreview.edit = !$scope.xmlPreview.edit; + }; + + $scope.revertXml = function() { + if($scope.clusterEntity.clusterModel.cluster.tags !== undefined) { + $scope.convertTags(); + } + $scope.showInPreview(); + $scope.invalidXml = false; }; + $scope.showInPreview = function() { var xmlStr = X2jsService.json2xml_str(angular.copy($scope.clusterEntity.clusterModel)); $scope.prettyXml = X2jsService.prettifyXml(xmlStr); @@ -290,6 +433,7 @@ if (!xmlObj.cluster.ACL || !xmlObj.cluster.ACL._owner || !xmlObj.cluster.ACL._group || !xmlObj.cluster.ACL._permission) { xmlObj.cluster.ACL = angular.copy(EntityModel.defaultValues.cluster.cluster.ACL); + xmlObj.cluster.ACL._owner = EntityModel.getUserNameFromCookie(); } $scope.arrangeFieldsOrder(xmlObj); @@ -297,8 +441,10 @@ if($scope.clusterEntity.clusterModel.cluster.properties && $scope.clusterEntity.clusterModel.cluster.properties.property[0] === '') { $scope.clusterEntity.clusterModel.cluster.properties.property=[]; } + $scope.invalidXml = false; } catch(err) { + $scope.invalidXml = true; console.log('xml malformed'); } @@ -310,9 +456,6 @@ $scope.jsonString = X2jsService.json2xml_str($scope.jsonString); }; function xmlPreviewCallback() { - if ($state.current.name !== 'forms.cluster.general' && $state.current.name !== 'forms.cluster.summary') { - $interval.cancel(refresher); - } if(!$scope.xmlPreview.edit) { if($scope.clusterEntity.clusterModel.cluster.tags !== undefined) { $scope.convertTags(); } $scope.showInPreview(); @@ -322,7 +465,9 @@ $scope.transformBack(); } } - var refresher = $interval(xmlPreviewCallback, 1000); + $scope.$watch('clusterEntity.clusterModel.cluster', xmlPreviewCallback, true); + $scope.$watch('tagsArray', xmlPreviewCallback, true); + $scope.$watch('prettyXml', xmlPreviewCallback, true); $scope.skipUndo = false; $scope.$on('$destroy', function () { @@ -338,17 +483,29 @@ model = angular.toJson(model); if (!$scope.skipUndo && !angular.equals(model, defaultModel)) { - $interval.cancel(refresher); $scope.$parent.cancel('cluster', $rootScope.previousState); } }); //------------init------------// - normalizeModel(); - } - ]); -})(); - + if($state.params && $state.params.action === 'import'){ + $scope.prettyXml = FileApi.fileRaw; + $scope.transformBack(); + }else{ + normalizeModel(); + } + if($state.current.name !=="forms.cluster.general"){ + $state.go("forms.cluster.general"); + } + $scope.capitalize = function(input) { + return input ? input.charAt(0).toUpperCase() + input.slice(1) : ""; + }; + $scope.upperCase = function(input) { + return input ? input.toUpperCase() : ""; + }; + } + ]); +})(); http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/controllers.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/controllers.js b/falcon-ui/app/js/controllers/controllers.js index 4867851..869e055 100644 --- a/falcon-ui/app/js/controllers/controllers.js +++ b/falcon-ui/app/js/controllers/controllers.js @@ -19,6 +19,7 @@ 'use strict'; angular.module('app.controllers', [ + 'app.controllers.theme', 'app.controllers.login', 'app.controllers.navHeader', 'app.controllers.rootCtrl', @@ -29,7 +30,9 @@ 'app.controllers.process', 'app.controllers.entity', 'app.controllers.instance', - 'app.controllers.dataset' + 'app.controllers.dataset', + 'app.controllers.snapshot', + 'app.controllers.datasource' ]); })(); http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/dashboard-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/dashboard-controller.js b/falcon-ui/app/js/controllers/dashboard-controller.js index 7a8d1b4..66e3aa9 100644 --- a/falcon-ui/app/js/controllers/dashboard-controller.js +++ b/falcon-ui/app/js/controllers/dashboard-controller.js @@ -20,11 +20,29 @@ var dashboardCtrlModule = angular.module('app.controllers.dashboardCtrl', ['app.services']); - dashboardCtrlModule.controller('DashboardCtrl', [ "$scope", "Falcon", "EntityModel", "FileApi", "$state", "X2jsService", - "$timeout", function ($scope, Falcon, EntityModel, FileApi, $state, X2jsService, $timeout) { + dashboardCtrlModule.controller('DashboardCtrl', [ "$scope", "$q", "Falcon", "EntityFalcon", "EntityModel", + "EntityScheduler", "FileApi", "$state", "X2jsService", "$timeout", "ServerAPI", + function ($scope, $q, Falcon, EntityFalcon, EntityModel, + EntityScheduler, FileApi, $state, X2jsService, $timeout, ServerAPI) { - $scope.$parent.refreshList(); + ServerAPI.getRuntimeConfig(EntityModel.getUserNameFromCookie()); + if(!($state.params && $state.params.fromAction === 'listEntities')){ + $scope.$parent.refreshList($scope.tags); + } + var searchPromise = $scope.$parent.goPage(1, 'list'); + searchPromise.then(function(){ + if($scope.$parent.searchList.length > 0){ + return; + } + EntityFalcon.searchEntities('', '', 'cluster', 0).then(function(){ + if(EntityFalcon.data !== null && EntityFalcon.data.entity && EntityFalcon.data.entity.length >0){ + $scope.$parent.hasClusters = true; + }else{ + $scope.$parent.hasClusters = false; + } + }); + }); $timeout(function() { angular.element('#nsPopover').trigger('click'); }, 1000); @@ -33,77 +51,24 @@ $scope.$parent.refreshList($scope.tags); }; - $scope.deleteEntity = function (type, name) { - type = type.toLowerCase(); //new sandbox returns uppercase type - Falcon.logRequest(); - Falcon.deleteEntity(type, name) - .success(function (data) { - Falcon.logResponse('success', data, type); - $scope.$parent.refreshList($scope.tags); - }) - .error(function (err) { - - Falcon.logResponse('error', err, type); - }); - }; - $scope.cloneEntity = function (type, name) { - type = type.toLowerCase(); //new sandbox returns uppercase type + $scope.backToListing = function(type){ + if($scope.tags && $scope.tags.length > 0){ + $scope.$parent.refreshList($scope.tags); + }else if(type === 'cluster'){ + $scope.$parent.goPage($scope.$parent.currentPage, 'cluster'); + }else{ + $scope.$parent.goPage($scope.$parent.currentPage, 'list'); + } + } - Falcon.logRequest(); - Falcon.getEntityDefinition(type, name) - .success(function (data) { - Falcon.logResponse('success', data, false, true); - var modelName = type + "Model", - entityModel = X2jsService.xml_str2json(data); - - if (entityModel.process && entityModel.process.tags && entityModel.process.tags.search('_falcon_mirroring_type') !== -1) { - - entityModel.process.name = ""; - EntityModel.datasetModel.toImportModel = entityModel; - $scope.$parent.cloningMode = true; - $state.go('forms.dataset.general'); - - } else { - EntityModel[modelName] = entityModel; - EntityModel[modelName][type]._name = ""; - $scope.models[modelName] = angular.copy(entityModel); - $scope.cloningMode = true; // dont know utility of this - $scope.$parent.cloningMode = true; - $state.go('forms.' + type + ".general"); + $scope.deleteEntity = function (type, name) { + EntityScheduler.deleteEntity(type, name).then(function(status){ + if(status === "DELETED"){ + $scope.backToListing(type); } - }) - .error(function (err) { - Falcon.logResponse('error', err, false, true); - }); + }); }; - $scope.editEntity = function (type, name) { - type = type.toLowerCase(); //new sandbox returns uppercase type - Falcon.logRequest(); - Falcon.getEntityDefinition(type, name) - .success(function (data) { - Falcon.logResponse('success', data, false, true); - var entityModel = X2jsService.xml_str2json(data); - var modelName = type + "Model"; - - if (entityModel.process && entityModel.process.tags.search('_falcon_mirroring_type') !== -1) { - - EntityModel.datasetModel.toImportModel = entityModel; - $scope.$parent.cloningMode = false; - $state.go('forms.dataset.general'); - - } else { - EntityModel[modelName] = entityModel; - $scope.models[modelName] = angular.copy(entityModel); - $scope.editingMode = true;// dont know utility of this - $scope.$parent.cloningMode = false; - $state.go('forms.' + type + ".general"); - } - }) - .error(function (err) { - Falcon.logResponse('error', err, false, true); - }); - }; //-----------------------------------------// $scope.entityDefinition = function (name, type) { @@ -125,37 +90,27 @@ }; //----------------------------------------// $scope.resumeEntity = function (type, name) { - Falcon.logRequest(); - Falcon.postResumeEntity(type, name).success(function (data) { - Falcon.logResponse('success', data, type); - $scope.$parent.refreshList($scope.tags); - }) - .error(function (err) { - Falcon.logResponse('error', err, type); + EntityScheduler.resumeEntity(type, name).then(function(status){ + if(status === "RUNNING"){ + $scope.backToListing(type); + } }); }; + $scope.scheduleEntity = function (type, name) { - Falcon.logRequest(); - Falcon.postScheduleEntity(type, name).success(function (data) { - Falcon.logResponse('success', data, type); - $scope.$parent.refreshList($scope.tags); - }) - .error(function (err) { - Falcon.logResponse('error', err, type); + EntityScheduler.scheduleEntity(type, name).then(function(status){ + if(status === "RUNNING"){ + $scope.backToListing(type); + } }); }; $scope.suspendEntity = function (type, name) { - Falcon.logRequest(); - Falcon.postSuspendEntity(type, name) - .success(function (message) { - Falcon.logResponse('success', message, type); - $scope.$parent.refreshList($scope.tags); - }) - .error(function (err) { - Falcon.logResponse('error', err, type); - - }); + EntityScheduler.suspendEntity(type, name).then(function(status){ + if(status === "SUSPENDED"){ + $scope.backToListing(type); + } + }); }; $scope.loadTags = function(query) { @@ -196,18 +151,21 @@ type = type.toLowerCase(); //new sandbox returns uppercase type Falcon.logRequest(); - Falcon.getEntityDefinition(type, name) - .success(function (data) { - Falcon.logResponse('success', data, false, true); - var entityModel = X2jsService.xml_str2json(data); + var entityDetailsPromise = Falcon.getEntityDefinition(type, name); + var entityStatusPromise = Falcon.getEntityStatus(type, name); + $q.all([entityDetailsPromise,entityStatusPromise]).then(function(responses){ + Falcon.logResponse('success', responses[0].data, false, true); + Falcon.logResponse('success', responses[1].data, false, true); + var entityModel = X2jsService.xml_str2json(responses[0].data); EntityModel.type = type; EntityModel.name = name; + var status = responses[1].data.message; + EntityModel.status = status.substr(status.indexOf("/") + 1, status.length - 1).trim(); EntityModel.model = entityModel; $state.go('entityDetails'); - }) - .error(function (err) { - Falcon.logResponse('error', err, false, true); - }); + },function(err){ + Falcon.logResponse('error', err, type); + }); }; $scope.clearTags = function(){ @@ -217,4 +175,4 @@ }]); -})(); \ No newline at end of file +})(); http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/dataset/dataset-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/dataset/dataset-controller.js b/falcon-ui/app/js/controllers/dataset/dataset-controller.js index a28cd77..2dafbe0 100644 --- a/falcon-ui/app/js/controllers/dataset/dataset-controller.js +++ b/falcon-ui/app/js/controllers/dataset/dataset-controller.js @@ -21,20 +21,47 @@ var datasetModule = angular.module('app.controllers.dataset', [ 'app.services' ]); datasetModule.controller('DatasetCtrl', [ - "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", "DateHelper", - "ValidationService", "SpinnersFlag", "$timeout", "$rootScope", "clustersList", "$cookieStore", - function ($scope, $interval, Falcon, EntityModel, $state, X2jsService, DateHelper, - validationService, SpinnersFlag, $timeout, $rootScope, clustersList, $cookieStore) { - + "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", "DateHelper", "RouteHelper", + "ValidationService", "SpinnersFlag", "$timeout", "$rootScope", "clustersList", "$cookieStore", "DatasetModel", + "ExtensionSerializer", + function ($scope, $interval, Falcon, EntityModel, $state, X2jsService, DateHelper, RouteHelper, + validationService, SpinnersFlag, $timeout, $rootScope, clustersList, $cookieStore, datasetModel, + extensionSerializer) { + + var stateMatrix = { + general : {previous : '', next : 'summary'}, + summary : {previous : 'general', next : ''} + }; $scope.skipUndo = false; + $scope.secureMode = $rootScope.secureMode; + $scope.clusterErrorMessage = ''; $scope.$on('$destroy', function () { if (!$scope.skipUndo && !angular.equals($scope.UIModel, EntityModel.defaultValues.MirrorUIModel)) { + if($scope.clone){ + EntityModel.datasetModel.UIModel.clone = true; + } + if($scope.editingMode){ + EntityModel.datasetModel.UIModel.edit = true; + } $scope.$parent.cancel('dataset', $rootScope.previousState); } }); + $scope.isFrequencyValid = true; + $scope.checkMininumFrequency = function(quantity, unit, field) { + $scope.isFrequencyValid = quantity ? true : false; + if (quantity && unit === 'minutes') { + $scope.isFrequencyValid = validationService.checkMininum(quantity); + } else if (unit !== 'minutes' && quantity && parseInt(quantity) === 0) { + $scope.isFrequencyValid = false; + } + if (field) { + field.$setValidity('required', $scope.isFrequencyValid); + } + }; + $scope.isActive = function (route) { return route === $state.current.name; }; @@ -43,8 +70,6 @@ return $state.get(route).data && $state.get(route).data.completed; }; - $scope.clone = $scope.$parent.cloningMode; - if (!clustersList) { $scope.clustersList = []; } else if (clustersList.type) { // is an object @@ -55,23 +80,33 @@ $scope.switchModel = function (type) { $scope.model = EntityModel.datasetModel[type].process; - $scope.UIModel.formType = type; + $scope.UIModel.type = type; $scope.completeModel = EntityModel.datasetModel[type]; - switchTag(type); checkClusters(); }; $scope.model = EntityModel.datasetModel.HDFS.process; $scope.UIModel = EntityModel.datasetModel.UIModel; $scope.completeModel = EntityModel.datasetModel.HDFS; - $scope.UIModel.acl.owner = $cookieStore.get('userToken').user; + if($scope.UIModel.clone === true || (datasetModel && datasetModel.clone === true)){ + $scope.clone = true; + $scope.editingMode = false; + }else if($scope.UIModel.edit === true || (datasetModel && datasetModel.edit === true)){ + $scope.editingMode = true; + $scope.clone = false; + }else{ + $scope.editingMode = false; + $scope.clone = false; + } + + $scope.UIModel.ACL.owner = $cookieStore.get('userToken').user; //-------------------------// function checkClusters() { - if ($scope.UIModel.source.cluster && $scope.UIModel.formType === 'HIVE') { + if ($scope.UIModel.source.cluster && $scope.UIModel.type === 'HIVE') { $scope.getSourceDefinition(); } - if ($scope.UIModel.target.cluster && $scope.UIModel.formType === 'HIVE') { + if ($scope.UIModel.target.cluster && $scope.UIModel.type === 'HIVE') { $scope.getTargetDefinition(); } } @@ -89,51 +124,24 @@ }; //----------------TAGS---------------------// $scope.addTag = function () { - if ($scope.UIModel.tags.newTag.value === "_falcon_mirroring_type") { - return; - } - $scope.UIModel.tags.tagsArray.push($scope.UIModel.tags.newTag); - $scope.UIModel.tags.newTag = {value: "", key: ""}; - $scope.convertTags(); + $scope.UIModel.tags.push({key: null, value: null}); }; $scope.removeTag = function (index) { - $scope.UIModel.tags.tagsArray.splice(index, 1); - $scope.convertTags(); - }; - function switchTag (type) { - $scope.UIModel.tags.tagsArray.forEach(function (item) { - if (item.key === "_falcon_mirroring_type") { - item.value = type; - } - }); - } - $scope.convertTags = function () { - var result = []; - $scope.UIModel.tags.tagsArray.forEach(function (element) { - if (element.key && element.value) { - result.push(element.key + "=" + element.value); - } - }); - result = result.join(","); - $scope.UIModel.tags.tagsString = result; - }; - $scope.splitTags = function () { - $scope.UIModel.tags.tagsArray = []; - $scope.UIModel.tags.tagsString.split(",").forEach(function (fieldToSplit) { - var splittedString = fieldToSplit.split("="); - $scope.UIModel.tags.tagsArray.push({key: splittedString[0], value: splittedString[1]}); - }); + if (index >= 0 && $scope.UIModel.tags.length > 1) { + $scope.UIModel.tags.splice(index, 1); + } }; //----------- Alerts -----------// $scope.addAlert = function () { - $scope.UIModel.alerts.alertsArray.push($scope.UIModel.alerts.alert.email); - $scope.UIModel.alerts.alert = {email: ""}; + $scope.UIModel.alerts.push($scope.UIModel.alert.email); + $scope.UIModel.alert = {email: ""}; }; $scope.removeAlert = function (index) { - $scope.UIModel.alerts.alertsArray.splice(index, 1); + $scope.UIModel.alerts.splice(index, 1); }; + //----------------- DATE INPUTS -------------------// - $scope.dateFormat = 'MM/dd/yyyy'; + $scope.dateFormat = DateHelper.getLocaleDateFormat(); $scope.openStartDatePicker = function ($event) { $event.preventDefault(); @@ -148,21 +156,21 @@ $scope.constructDate = function () { - if ($scope.UIModel.validity.start && $scope.UIModel.validity.end && $scope.UIModel.validity.startTime && $scope.UIModel.validity.endTime) { - $scope.UIModel.validity.startISO = DateHelper.createISO($scope.UIModel.validity.start, $scope.UIModel.validity.startTime, $scope.UIModel.validity.tz); - $scope.UIModel.validity.endISO = DateHelper.createISO($scope.UIModel.validity.end, $scope.UIModel.validity.endTime, $scope.UIModel.validity.tz); + if ($scope.UIModel.validity.start.date && $scope.UIModel.validity.end.date && $scope.UIModel.validity.start.time && $scope.UIModel.validity.end.time) { + $scope.UIModel.validity.startISO = DateHelper.createISO($scope.UIModel.validity.start.date, $scope.UIModel.validity.start.time, $scope.UIModel.validity.timezone); + $scope.UIModel.validity.endISO = DateHelper.createISO($scope.UIModel.validity.end.date, $scope.UIModel.validity.end.time, $scope.UIModel.validity.timezone); } }; $scope.$watch(function () { - return $scope.UIModel.validity.tz; + return $scope.UIModel.validity.timezone; }, function () { return $scope.constructDate(); }); //-------------------------------------// - $scope.goNext = function (formInvalid, stateName) { + $scope.goNext = function (formInvalid) { $state.current.data = $state.current.data || {}; $state.current.data.completed = !formInvalid; @@ -171,22 +179,25 @@ validationService.displayValidations.show = true; validationService.displayValidations.nameShow = true; SpinnersFlag.show = false; - angular.element('body, html').animate({scrollTop: 0}, 500); return; } + + if ($scope.clusterErrorMessage !== '') { + SpinnersFlag.show = false; + return; + } + validationService.displayValidations.show = false; validationService.displayValidations.nameShow = false; - $scope.convertTags(); - createXML(); - $state.go(stateName); + $state.go(RouteHelper.getNextState($state.current.name, stateMatrix)); angular.element('body, html').animate({scrollTop: 0}, 500); }; - $scope.goBack = function (stateName) { + $scope.goBack = function () { SpinnersFlag.backShow = true; validationService.displayValidations.show = false; validationService.displayValidations.nameShow = false; - $state.go(stateName); + $state.go(RouteHelper.getPreviousState($state.current.name, stateMatrix)); angular.element('body, html').animate({scrollTop: 0}, 500); }; @@ -197,34 +208,49 @@ Falcon.getEntityDefinition("cluster", $scope.UIModel.source.cluster) .success(function (data) { $scope.sourceClusterModel = X2jsService.xml_str2json(data); - if (!EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath && EntityModel.datasetModel.UIModel.formType === 'HIVE') { - EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath = findLocation($scope.sourceClusterModel.cluster.locations.location, 'staging'); + if (EntityModel.datasetModel.UIModel.type === 'HIVE') { + EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath + = findLocation($scope.sourceClusterModel.cluster.locations.location, 'staging'); + EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint + = replaceHive(findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'registry')); } - if (!EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint && EntityModel.datasetModel.UIModel.formType === 'HIVE') { - EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint = replaceHive(findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'registry')); - } - }) .error(function (err) { $scope.UIModel.source.cluster = ""; Falcon.logResponse('error', err, false, true); }); + + if ($scope.UIModel.source.cluster === $scope.UIModel.target.cluster) { + $scope.clusterErrorMessage = 'Target cannot be the same as the Source'; + } else { + $scope.clusterErrorMessage = ''; + return; + } }; $scope.getTargetDefinition = function () { Falcon.getEntityDefinition("cluster", $scope.UIModel.target.cluster) .success(function (data) { $scope.targetClusterModel = X2jsService.xml_str2json(data); - if (!EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath && EntityModel.datasetModel.UIModel.formType === 'HIVE') { - EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath = findLocation($scope.targetClusterModel.cluster.locations.location, 'staging'); + if (EntityModel.datasetModel.UIModel.type === 'HIVE') { + EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath + = findLocation($scope.targetClusterModel.cluster.locations.location, 'staging'); } - if (!EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint && EntityModel.datasetModel.UIModel.formType === 'HIVE') { - EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint = replaceHive(findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'registry')); + if (EntityModel.datasetModel.UIModel.type === 'HIVE') { + EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint + = replaceHive(findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'registry')); } }) .error(function (err) { $scope.UIModel.target.cluster = ""; Falcon.logResponse('error', err, false, true); }); + + if ($scope.UIModel.source.cluster === $scope.UIModel.target.cluster) { + $scope.clusterErrorMessage = 'Target cannot be the same as the Source'; + } else { + $scope.clusterErrorMessage = ''; + return; + } }; function findLocation (array, locationString) { @@ -254,177 +280,13 @@ } } - function createXML() { - $scope.model._name = $scope.UIModel.name; - $scope.model.tags = $scope.UIModel.tags.tagsString; - $scope.model.retry._policy = $scope.UIModel.retry.policy; - $scope.model.retry._delay = $scope.UIModel.retry.delay.unit + '(' + $scope.UIModel.retry.delay.number + ')'; - $scope.model.retry._attempts = $scope.UIModel.retry.attempts; - $scope.model.ACL._owner = $scope.UIModel.acl.owner; - $scope.model.ACL._group = $scope.UIModel.acl.group; - $scope.model.ACL._permission = $scope.UIModel.acl.permissions; - $scope.model.frequency = $scope.UIModel.frequency.unit + '(' + $scope.UIModel.frequency.number + ')'; - $scope.model.clusters.cluster[0].validity._start = $scope.UIModel.validity.startISO; - $scope.model.clusters.cluster[0].validity._end = $scope.UIModel.validity.endISO; - $scope.model.timezone = $scope.UIModel.validity.tz; - if ($scope.UIModel.formType === 'HDFS') { - - if ($scope.UIModel.runOn === "source") { - $scope.model.clusters.cluster[0]._name = $scope.UIModel.source.cluster; - } else { - $scope.model.clusters.cluster[0]._name = $scope.UIModel.target.cluster; - } - - $scope.model.workflow._name = $scope.UIModel.name + '-WF'; - - $scope.model.properties.property.forEach(function (item) { - if (item._name === 'distcpMaxMaps') { - item._value = $scope.UIModel.allocation.hdfs.maxMaps; - } - if (item._name === 'distcpMapBandwidth') { - item._value = $scope.UIModel.allocation.hdfs.maxBandwidth; - } - if (item._name === 'drSourceDir') { - item._value = $scope.UIModel.source.path; - } - if (item._name === 'drTargetDir') { - item._value = $scope.UIModel.target.path; - } - if (item._name === 'drSourceClusterFS') { - if ($scope.UIModel.source.location === 'HDFS') { - item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'write'); - } else { - item._value = $scope.UIModel.source.url; - } - } - if (item._name === 'drTargetClusterFS') { - if ($scope.UIModel.target.location === 'HDFS') { - item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'write'); - } else { - item._value = $scope.UIModel.target.url; - } - } - if (item._name === 'drNotificationReceivers') { - item._value = (function () { - if ($scope.UIModel.alerts.alertsArray.length === 0) { - return "NA"; - } else { - return $scope.UIModel.alerts.alertsArray.join(); - } - }()); - } - if (item._name === 'sourceCluster') { - if ($scope.UIModel.source.location === 'HDFS') { item._value = $scope.UIModel.source.cluster; } - else { item._value = ""; } - } - if (item._name === 'targetCluster') { - if ($scope.UIModel.target.location === 'HDFS') { item._value = $scope.UIModel.target.cluster; } - else { item._value = ""; } - } - }); - - } else if ($scope.UIModel.formType === 'HIVE') { - - $scope.model.clusters.cluster[0]._name = $scope.UIModel.source.cluster; - $scope.model.properties.property.forEach(function (item) { - if (item._name === 'distcpMaxMaps') { - item._value = $scope.UIModel.allocation.hive.maxMapsDistcp; - } - if (item._name === 'distcpMapBandwidth') { - item._value = $scope.UIModel.allocation.hive.maxBandwidth; - } - if (item._name === 'sourceCluster') { - item._value = $scope.UIModel.source.cluster; - } - if (item._name === 'targetCluster') { - item._value = $scope.UIModel.target.cluster; - } - if (item._name === 'sourceHiveServer2Uri') { - item._value = $scope.UIModel.hiveOptions.source.hiveServerToEndpoint; - } - if (item._name === 'targetHiveServer2Uri') { - item._value = $scope.UIModel.hiveOptions.target.hiveServerToEndpoint; - } - if (item._name === 'sourceStagingPath') { - item._value = $scope.UIModel.hiveOptions.source.stagingPath; - } - if (item._name === 'targetStagingPath') { - item._value = $scope.UIModel.hiveOptions.target.stagingPath; - } - if (item._name === 'sourceNN') { - item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'write'); - } - if (item._name === 'targetNN') { - item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'write'); - } - if (item._name === 'sourceMetastoreUri') { - item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'registry'); - } - if (item._name === 'targetMetastoreUri') { - item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'registry'); - } - if (item._name === 'sourceTable') { - if ($scope.UIModel.source.hiveDatabaseType === "databases") { - item._value = "*"; - } else { - item._value = $scope.UIModel.source.hiveTables; - } - } - if (item._name === 'sourceDatabase') { - if ($scope.UIModel.source.hiveDatabaseType === "databases") { - item._value = $scope.UIModel.source.hiveDatabases; - } else { - item._value = $scope.UIModel.source.hiveDatabase; - } - } - if (item._name === 'maxEvents') { - item._value = $scope.UIModel.allocation.hive.maxMapsEvents; - } - if (item._name === 'replicationMaxMaps') { - item._value = $scope.UIModel.allocation.hive.maxMapsMirror; - } - if (item._name === 'clusterForJobRun') { - if ($scope.UIModel.runOn === "source") { - item._value = $scope.UIModel.source.cluster; - } else { - item._value = $scope.UIModel.target.cluster; - } - } - if (item._name === 'clusterForJobRunWriteEP') { - if ($scope.UIModel.runOn === "source") { - item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'write'); - } else { - item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'write'); - } - } - if (item._name === 'drJobName') { - item._value = $scope.UIModel.name; - } - if (item._name === 'drNotificationReceivers') { - item._value = (function () { - if ($scope.UIModel.alerts.alertsArray.length === 0) { - return "NA"; - } else { - return $scope.UIModel.alerts.alertsArray.join(); - } - }()); - } - - }); - - } else { - console.log('error in form type'); - } - - $scope.xmlString = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + X2jsService.json2xml_str($scope.completeModel); - - } - $scope.save = function () { SpinnersFlag.show = true; + var extensionData = extensionSerializer.convertObjectToString( + extensionSerializer.serializeExtensionProperties($scope.UIModel, $scope.UIModel.type + '-MIRROR')); - if(!$scope.$parent.cloningMode) { - Falcon.postUpdateEntity($scope.xmlString, 'process', $scope.model._name) + if($scope.editingMode) { + Falcon.postUpdateExtension(extensionData, $scope.UIModel.type + '-MIRRORING') .success(function (response) { $scope.skipUndo = true; Falcon.logResponse('success', response, false); @@ -437,7 +299,7 @@ angular.element('body, html').animate({scrollTop: 0}, 300); }); } else { - Falcon.postSubmitEntity($scope.xmlString, 'process') + Falcon.postSubmitExtension(extensionData, $scope.UIModel.type + '-MIRRORING') .success(function (response) { $scope.skipUndo = true; Falcon.logResponse('success', response, false); @@ -462,181 +324,27 @@ } } - function importModel(model) { - - var mirrorType; - - if (model.process.tags.search('_falcon_mirroring_type=HDFS') !== -1) { - mirrorType = 'HDFS'; - } else { - mirrorType = 'HIVE'; - } - $scope.switchModel(mirrorType); - EntityModel.datasetModel.UIModel.formType = mirrorType; - EntityModel.datasetModel.UIModel.name = (function () { if (!$scope.clone) { return model.process._name; } else { return ""; } }()); - EntityModel.datasetModel.UIModel.retry.policy = model.process.retry._policy; - EntityModel.datasetModel.UIModel.retry.attempts = model.process.retry._attempts; - EntityModel.datasetModel.UIModel.retry.delay.number = (function () { - return parseInt(model.process.retry._delay.split('(')[1]); - }()); - EntityModel.datasetModel.UIModel.retry.delay.unit = (function () { - return model.process.retry._delay.split('(')[0]; - }()); - EntityModel.datasetModel.UIModel.frequency.number = (function () { - return parseInt(model.process.frequency.split('(')[1]); - }()); - EntityModel.datasetModel.UIModel.frequency.unit = (function () { - return model.process.frequency.split('(')[0]; - }()); - EntityModel.datasetModel.UIModel.acl.owner = model.process.ACL._owner; - EntityModel.datasetModel.UIModel.acl.group = model.process.ACL._group; - EntityModel.datasetModel.UIModel.acl.permissions = model.process.ACL._permission; - - EntityModel.datasetModel.UIModel.validity.startISO = model.process.clusters.cluster[0].validity._start; - EntityModel.datasetModel.UIModel.validity.endISO = model.process.clusters.cluster[0].validity._end; - EntityModel.datasetModel.UIModel.validity.tz = model.process.timezone; - EntityModel.datasetModel.UIModel.validity.start = DateHelper.importDate (model.process.clusters.cluster[0].validity._start, model.process.timezone); - EntityModel.datasetModel.UIModel.validity.startTime = DateHelper.importDate (model.process.clusters.cluster[0].validity._start, model.process.timezone); - EntityModel.datasetModel.UIModel.validity.end = DateHelper.importDate (model.process.clusters.cluster[0].validity._end, model.process.timezone); - EntityModel.datasetModel.UIModel.validity.endTime = DateHelper.importDate (model.process.clusters.cluster[0].validity._end, model.process.timezone); - - EntityModel.datasetModel.UIModel.tags.tagsString = model.process.tags; - EntityModel.datasetModel.UIModel.tags.tagsArray = (function () { - var array = []; - model.process.tags.split(',').forEach(function (fieldToSplit) { - var splittedString = fieldToSplit.split("="); - array.push({key: splittedString[0], value: splittedString[1]}); - }); - return array; - }()); - - if (mirrorType === 'HDFS') { - model.process.properties.property.forEach(function (item) { - if (item._name === 'distcpMaxMaps') { - EntityModel.datasetModel.UIModel.allocation.hdfs.maxMaps = item._value; - } - if (item._name === 'distcpMapBandwidth') { - EntityModel.datasetModel.UIModel.allocation.hdfs.maxBandwidth = item._value; - } - if (item._name === 'drSourceDir') { - EntityModel.datasetModel.UIModel.source.path = item._value; - } - if (item._name === 'drTargetDir') { - EntityModel.datasetModel.UIModel.target.path = item._value; - } - if (item._name === 'drNotificationReceivers') { - EntityModel.datasetModel.UIModel.alerts.alertsArray = (function () { - if (item._value !== "NA") { - return item._value.split(','); - } else { - return []; - } - }()); - } - if (item._name === 'targetCluster') { - EntityModel.datasetModel.UIModel.target.cluster = item._value; - } - if (item._name === 'sourceCluster') { - EntityModel.datasetModel.UIModel.source.cluster = item._value; - } - if (item._name === 'drSourceClusterFS') { - EntityModel.datasetModel.UIModel.source.url = item._value; - } - if (item._name === 'drTargetClusterFS') { - EntityModel.datasetModel.UIModel.target.url = item._value; - } - }); - - if (EntityModel.datasetModel.UIModel.source.cluster === model.process.clusters.cluster[0]._name) { - EntityModel.datasetModel.UIModel.runOn = "source"; - } - if (EntityModel.datasetModel.UIModel.target.cluster === model.process.clusters.cluster[0]._name) { - EntityModel.datasetModel.UIModel.runOn = "target"; - } - - EntityModel.datasetModel.UIModel.source.location = identifyLocationType(EntityModel.datasetModel.UIModel.source.url); - EntityModel.datasetModel.UIModel.target.location = identifyLocationType(EntityModel.datasetModel.UIModel.target.url); - - } else if (mirrorType === 'HIVE') { - - model.process.properties.property.forEach(function (item) { - if (item._name === 'distcpMaxMaps') { - EntityModel.datasetModel.UIModel.allocation.hive.maxMapsDistcp = item._value; - } - if (item._name === 'distcpMapBandwidth') { - EntityModel.datasetModel.UIModel.allocation.hive.maxBandwidth = item._value; - } - if (item._name === 'sourceCluster') { - EntityModel.datasetModel.UIModel.source.cluster = item._value; - } - if (item._name === 'targetCluster') { - EntityModel.datasetModel.UIModel.target.cluster = item._value; - } - if (item._name === 'sourceStagingPath') { - EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath = item._value; - } - if (item._name === 'targetStagingPath') { - EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath = item._value; - if (item._value === "*") { - EntityModel.datasetModel.UIModel.source.hiveDatabaseType = "databases"; - } else { - EntityModel.datasetModel.UIModel.source.hiveDatabaseType = "tables"; - } - } - if (item._name === 'sourceHiveServer2Uri') { - EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint = item._value; - } - if (item._name === 'targetHiveServer2Uri') { - EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint = item._value; - } - if (item._name === 'sourceTable') { - EntityModel.datasetModel.UIModel.source.hiveTables = item._value; - if (EntityModel.datasetModel.UIModel.source.hiveDatabaseType === "databases") { - EntityModel.datasetModel.UIModel.source.hiveTables = "*"; - } - else { - EntityModel.datasetModel.UIModel.source.hiveTables = item._value; - } - } - if (item._name === 'sourceDatabase') { - if (EntityModel.datasetModel.UIModel.source.hiveDatabaseType === "databases") { - EntityModel.datasetModel.UIModel.source.hiveDatabases = item._value; - } else { - EntityModel.datasetModel.UIModel.source.hiveDatabase = item._value; - } - } - if (item._name === 'maxEvents') { - EntityModel.datasetModel.UIModel.allocation.hive.maxMapsEvents = item._value; - } - if (item._name === 'replicationMaxMaps') { - EntityModel.datasetModel.UIModel.allocation.hive.maxMapsMirror = item._value; - } - if (item._name === 'clusterForJobRun') { - if (EntityModel.datasetModel.UIModel.source.cluster === item._value) { - EntityModel.datasetModel.UIModel.runOn = "source"; - } else { - EntityModel.datasetModel.UIModel.runOn = "target"; - } - } - if (item._name === 'drNotificationReceivers') { - EntityModel.datasetModel.UIModel.alerts.alertsArray = (function () { - if (item._value !== "NA") { - return item._value.split(','); - } else { - return []; - } - }()); - } - - }); + var extensionModel; + if (datasetModel) { + extensionModel = datasetModel; + } else if (EntityModel.datasetModel.toImportModel) { + extensionModel = EntityModel.datasetModel.toImportModel; + } + if (extensionModel && extensionModel.process.tags) { + var datasetType; + if (extensionModel.process.tags.indexOf('_falcon_extension_name=HDFS-MIRRORING') !== -1) { + datasetType = 'hdfs-mirror'; + $scope.UIModel = extensionSerializer.serializeExtensionModel(extensionModel, datasetType, $scope.secureMode); + } else if (extensionModel.process.tags.indexOf('_falcon_extension_name=HIVE-MIRRORING') !== -1) { + datasetType = 'hive-mirror'; + $scope.UIModel = extensionSerializer.serializeExtensionModel(extensionModel, datasetType, $scope.secureMode); } - - if(EntityModel.datasetModel.UIModel.source.cluster) { $scope.getSourceDefinition(); } - if(EntityModel.datasetModel.UIModel.target.cluster) { $scope.getTargetDefinition(); } - } - if (EntityModel.datasetModel.toImportModel) { - importModel(EntityModel.datasetModel.toImportModel); + if ($scope.clone) { + $scope.UIModel.name = ""; + } + if($state.current.name !== "forms.dataset.general"){ + $state.go("forms.dataset.general"); } }]); }());
