http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/entity/entity-details.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/entity/entity-details.js b/falcon-ui/app/js/controllers/entity/entity-details.js new file mode 100644 index 0000000..217bb9b --- /dev/null +++ b/falcon-ui/app/js/controllers/entity/entity-details.js @@ -0,0 +1,169 @@ +/** + * 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. + */ +(function () { + 'use strict'; + + /*** + * @ngdoc controller + * @name app.controllers.feed.FeedController + * @requires EntityModel the entity model to copy the feed entity from + * @requires Falcon the falcon service to talk with the Falcon REST API + */ + var clusterModule = angular.module('app.controllers.view', [ 'app.services' ]); + + clusterModule.controller('EntityDetailsCtrl', [ + "$scope", "$timeout", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", 'EntitySerializer', 'InstanceFalcon', + function ($scope, $timeout, $interval, Falcon, EntityModel, $state, X2jsService, serializer, InstanceFalcon) { + + $scope.entity = EntityModel; + + var resultsPerPage = 10; + var visiblePages = 3; + $scope.entityName = $scope.entity.name; + $scope.entityType = $scope.entity.type; + + $scope.pages = []; + $scope.nextPages = false; + $scope.mirrorTag = "_falcon_mirroring_type"; + + $scope.isMirror = function(tags){ + var flag = false; + if(tags !== undefined && tags.indexOf($scope.mirrorTag) !== -1){ + flag = true; + } + return flag; + }; + + if($scope.entity.type === "feed"){ + $scope.feed = serializer.preDeserialize($scope.entity.model, "feed"); + $scope.feed.name = $scope.entity.name; + $scope.feed.type = $scope.entity.type; + $scope.entity.start = $scope.entity.model.feed.clusters.cluster[0].validity._start; + $scope.entity.end = $scope.entity.model.feed.clusters.cluster[0].validity._end; + }else{ + var tags = $scope.entity.model.process.tags; + if($scope.isMirror(tags)){ + $scope.entityTypeLabel = "Mirror"; + } + $scope.process = serializer.preDeserialize($scope.entity.model, "process"); + $scope.process.name = $scope.entity.name; + $scope.process.type = $scope.entity.type; + $scope.entity.start = $scope.entity.model.process.clusters.cluster[0].validity._start; + $scope.entity.end = $scope.entity.model.process.clusters.cluster[0].validity._end; + } + + $scope.capitalize = function(input) { + return input.charAt(0).toUpperCase() + input.slice(1); + }; + + $scope.dateFormatter = function (date) { + var dates = date.split('T')[0], + time = date.split('T')[1].split('Z')[0].split('.')[0]; + return dates + ' ' + time; + }; + + $scope.refreshInstanceList = function (type, name, start, end, status, orderBy, sortOrder) { + $scope.instancesList = []; + changePagesSet(0, 0, 0, start, end, status, orderBy, sortOrder); + }; + + var consultPage = function(offset, page, defaultPage, start, end, status, orderBy, sortOrder){ + Falcon.responses.listLoaded = false; + InstanceFalcon.searchInstances($scope.entityType, $scope.entityName, offset, start, end, status, orderBy, sortOrder).then(function() { + if (InstanceFalcon.data) { + $scope.pages[page] = {}; + $scope.pages[page].index = page; + $scope.pages[page].data = InstanceFalcon.data.instances; + $scope.pages[page].show = true; + $scope.pages[page].enabled = true; + $scope.pages[page].label = "" + ((offset/resultsPerPage)+1); + if($scope.pages[page].data.length > resultsPerPage){ + offset = offset + resultsPerPage; + $scope.nextPages = true; + if(page < visiblePages-1){ + consultPage(offset, page+1, defaultPage, start, end, status, orderBy, sortOrder); + }else{ + $scope.goPage(defaultPage); + } + }else{ + $scope.nextPages = false; + $scope.goPage(defaultPage); + } + } + }); + }; + + var changePagesSet = function(offset, page, defaultPage, start, end, status, orderBy, sortOrder){ + $scope.pages = []; + consultPage(offset, page, defaultPage, start, end, status, orderBy, sortOrder); + }; + + $scope.goPage = function (page) { + $scope.pages.forEach(function(pag) { + pag.enabled = true; + }); + $scope.pages[page].enabled = false; + $scope.instancesList = $scope.pages[page].data; + if($scope.instancesList.length > resultsPerPage){ + $scope.instancesList.pop(); + } + $scope.prevPages = parseInt($scope.pages[page].label) > visiblePages ? true : false; + Falcon.responses.listLoaded = true; + }; + + $scope.changePagesSet = function(offset, page, defaultPage, start, end, status, orderBy, sortOrder){ + changePagesSet(offset, page, defaultPage, start, end, status, orderBy, sortOrder); + }; + + $scope.instanceDetails = function (instance) { + EntityModel.model = instance; + EntityModel.type = $scope.entity.type; + EntityModel.name = $scope.entity.name; + $state.go("instanceDetails"); + }; + + $scope.displayIcon = function (type, model) { + if(type === "FEED"){ + $scope.entityTypeLabel = "Feed"; + return "entypo download"; + }else if(type === "PROCESS"){ + var tags = model.process.tags; + if($scope.isMirror(tags)){ + $scope.entityTypeLabel = "Mirror"; + return "glyphicon glyphicon-duplicate"; + }else{ + $scope.entityTypeLabel = "Process"; + return "entypo cycle"; + } + }else{ + $scope.entityTypeLabel = "Process"; + return "entypo cycle"; + } + }; + + } + ]); + + clusterModule.filter('titleCase', function() { + return function(input) { + input = input || ''; + return input.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); + }; + }); + +})();
http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/entity/entity-view.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/entity/entity-view.js b/falcon-ui/app/js/controllers/entity/entity-view.js deleted file mode 100644 index d58f7f6..0000000 --- a/falcon-ui/app/js/controllers/entity/entity-view.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * 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. - */ -(function () { - 'use strict'; - - /*** - * @ngdoc controller - * @name app.controllers.feed.FeedController - * @requires EntityModel the entity model to copy the feed entity from - * @requires Falcon the falcon service to talk with the Falcon REST API - */ - var clusterModule = angular.module('app.controllers.view', [ 'app.services' ]); - - clusterModule.controller('EntityDetailsCtrl', [ - "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", - function ($scope, $interval, Falcon, EntityModel, $state, X2jsService) { - - $scope.clusterEntity = EntityModel; - $scope.xmlPreview = { edit: false }; - $scope.secondStep = false; - - function normalizeModel() { - //------------INTERFACE-----------// - var requiredInterfaceFields = ["readonly", "write", "execute", "workflow", "messaging", "registry"], - requiredLocationFields = ["staging", "temp", "working", ""], - modelInterfaceArray = $scope.clusterEntity.clusterModel.cluster.interfaces.interface, - modelLocationsArray = $scope.clusterEntity.clusterModel.cluster.locations.location; - - modelInterfaceArray.forEach(function (element) { - requiredInterfaceFields.forEach(function (requiredField) { - if (element._type === requiredField) { requiredInterfaceFields.splice(requiredField, 1); } - }); - }); - $scope.registry = { check: true }; - requiredInterfaceFields.forEach(function (fieldToPush) { - var fieldObject = { _type: fieldToPush, _endpoint: "", _version: "" }; - if (fieldToPush === "registry") { $scope.registry = { check: false }; } - modelInterfaceArray.push(fieldObject); - }); - //--------------TAGS--------------// - if ($scope.clusterEntity.clusterModel.cluster.tags === "" || - $scope.clusterEntity.clusterModel.cluster.tags === undefined) { - $scope.clusterEntity.clusterModel.cluster.tags = ""; - $scope.tagsArray = [{key: null, value: null}]; - } else { - $scope.splitTags(); - } - //-------------ACL----------------// - if (!$scope.clusterEntity.clusterModel.cluster.ACL) { - $scope.clusterEntity.clusterModel.cluster.ACL = { - _owner: "", _group: "", _permission: "" - }; - } - //------------Location------------// - modelLocationsArray.forEach(function(element) { - requiredLocationFields.forEach(function(requiredField) { - if(element._name === requiredField) { requiredLocationFields.splice(requiredField, 1); } - }); - }); - requiredLocationFields.forEach(function(fieldToPush) { - var fieldObject = {_name: fieldToPush, _path: ""}; - modelLocationsArray.push(fieldObject); - }); - //----------Properties -------------// - if(!$scope.clusterEntity.clusterModel.cluster.properties) { - $scope.clusterEntity.clusterModel.cluster.properties = { property : [{ _name: "", _value: ""}] }; - } - - } - - $scope.arrangeFieldsOrder = function () { - var BK = $scope.clusterEntity.clusterModel.cluster, - orderedObj = {}; - - orderedObj._xmlns = 'uri:falcon:cluster:0.1'; - orderedObj._name = BK._name; - orderedObj._description = BK._description; - orderedObj._colo = BK._colo; - - if (BK.tags) { orderedObj.tags = BK.tags; } - if (BK.interfaces) { orderedObj.interfaces = BK.interfaces; } - if (BK.locations) { orderedObj.locations = BK.locations; } - if (BK.ACL) { orderedObj.ACL = BK.ACL; } - if (BK.properties) { orderedObj.properties = BK.properties; } - - delete $scope.clusterEntity.clusterModel.cluster; - $scope.clusterEntity.clusterModel.cluster = orderedObj; - - }; - //--------------TAGS------------------------// - - $scope.convertTags = function () { - var result = []; - $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; - }; - $scope.splitTags = function () { - $scope.tagsArray = []; - $scope.clusterEntity.clusterModel.cluster.tags.split(",").forEach(function (fieldToSplit) { - var splittedString = fieldToSplit.split("="); - $scope.tagsArray.push({key: splittedString[0], value: splittedString[1]}); - }); - }; - $scope.addTag = function () { - $scope.tagsArray.push({key: null, value: null}); - }; - $scope.removeTag = function (index) { - if (!isNaN(index) && index !== undefined && index !== null) { - $scope.tagsArray.splice(index, 1); - $scope.convertTags(); - } - }; - //-------------------------------------// - //----------LOCATION-------------------// - - $scope.addLocation = function () { - var lastOneIndex = $scope.clusterEntity.clusterModel.cluster.locations.location.length - 1; - - if (!$scope.clusterEntity.clusterModel.cluster.locations.location[lastOneIndex]._name || - !$scope.clusterEntity.clusterModel.cluster.locations.location[lastOneIndex]._path) { - //console.log('location empty'); - } else { - $scope.clusterEntity.clusterModel.cluster.locations.location.push({_name: "", _path: ""}); - } - }; - $scope.removeLocation = function (index) { - if(!isNaN(index) && index !== undefined && index !== null) { - $scope.clusterEntity.clusterModel.cluster.locations.location.splice(index, 1); - } - }; - //-----------PROPERTIES----------------// - $scope.addProperty = function () { - 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]._value){ - $scope.clusterEntity.clusterModel.cluster.properties.property.push({ _name: "", _value: ""}); - // $scope.tempPropModel = { _name: "", _value: ""}; - } - }; - $scope.removeProperty = function(index) { - if(index !== null && $scope.clusterEntity.clusterModel.cluster.properties.property[index]) { - $scope.clusterEntity.clusterModel.cluster.properties.property.splice(index, 1); - } - }; - - //--------------------------------------// - //----------XML preview-----------------// - - $scope.xmlPreview.editXML = function () { - $scope.xmlPreview.edit = !$scope.xmlPreview.edit; - }; - $scope.showInPreview = function() { - var xmlStr = X2jsService.json2xml_str(angular.copy($scope.clusterEntity.clusterModel)); - $scope.prettyXml = X2jsService.prettifyXml(xmlStr); - $scope.xml = xmlStr; - }; - $scope.transformBack = function() { - try { - var xmlObj = X2jsService.xml_str2json($scope.prettyXml); - $scope.clusterEntity.clusterModel = xmlObj; - - if($scope.clusterEntity.clusterModel.cluster.properties && $scope.clusterEntity.clusterModel.cluster.properties.property[0] === '') { - $scope.clusterEntity.clusterModel.cluster.properties.property=[]; - } - } - catch(err) { - console.log('xml malformed'); - } - }; - $scope.saveModelBuffer = function () { - $scope.jsonString = angular.toJson($scope.clusterEntity.clusterModel); - //goes back to js to have x2js parse it correctly - $scope.jsonString = JSON.parse($scope.jsonString); - $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(); - } - else { - $scope.splitTags(); - $scope.transformBack(); - } - } - var refresher = $interval(xmlPreviewCallback, 1000); - - //xmlPreviewCallback(); - - - //------------init------------// - normalizeModel(); - } - ]); -})(); - - - - http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/entity/instance-details.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/entity/instance-details.js b/falcon-ui/app/js/controllers/entity/instance-details.js new file mode 100644 index 0000000..0775d61 --- /dev/null +++ b/falcon-ui/app/js/controllers/entity/instance-details.js @@ -0,0 +1,131 @@ +/** + * 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. + */ +(function () { + 'use strict'; + + /*** + * @ngdoc controller + * @name app.controllers.feed.FeedController + * @requires EntityModel the entity model to copy the feed entity from + * @requires Falcon the falcon service to talk with the Falcon REST API + */ + var clusterModule = angular.module('app.controllers.instance', ['app.services']); + + clusterModule.controller('InstanceDetailsCtrl', [ + "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", 'EntitySerializer', + function ($scope, $interval, Falcon, EntityModel, $state, X2jsService) { + + $scope.instance = EntityModel.model; + $scope.instance.type = EntityModel.type; + $scope.instance.name = EntityModel.name; + + $scope.backToEntity = function () { + var type = $scope.instance.type.toLowerCase(); + var name = $scope.instance.name; + Falcon.logRequest(); + Falcon.getEntityDefinition(type, name) + .success(function (data) { + Falcon.logResponse('success', data, false, true); + var entityModel = X2jsService.xml_str2json(data); + EntityModel.type = type; + EntityModel.name = name; + EntityModel.model = entityModel; + $state.go('entityDetails'); + }) + .error(function (err) { + Falcon.logResponse('error', err, false, true); + }); + }; + + $scope.resumeInstance = function () { + Falcon.logRequest(); + var start = $scope.instance.instance; + var end = addOneMin(start); + Falcon.postResumeInstance($scope.instance.type, $scope.instance.name, start, end) + .success(function (message) { + Falcon.logResponse('success', message, $scope.instance.type); + $scope.instance.status = "RUNNING"; + }) + .error(function (err) { + Falcon.logResponse('error', err, $scope.instance.type); + + }); + }; + + $scope.reRunInstance = function () { + Falcon.logRequest(); + var start = $scope.instance.instance; + var end = addOneMin(start); + Falcon.postReRunInstance($scope.instance.type, $scope.instance.name, start, end) + .success(function (message) { + Falcon.logResponse('success', message, $scope.instance.type); + $scope.instance.status = "RUNNING"; + }) + .error(function (err) { + Falcon.logResponse('error', err, $scope.instance.type); + + }); + }; + + $scope.suspendInstance = function () { + Falcon.logRequest(); + var start = $scope.instance.instance; + var end = addOneMin(start); + Falcon.postSuspendInstance($scope.instance.type, $scope.instance.name, start, end) + .success(function (message) { + Falcon.logResponse('success', message, $scope.instance.type); + $scope.instance.status = "SUSPENDED"; + }) + .error(function (err) { + Falcon.logResponse('error', err, $scope.instance.type); + + }); + }; + + $scope.killInstance = function () { + Falcon.logRequest(); + var start = $scope.instance.instance; + var end = addOneMin(start); + Falcon.postKillInstance($scope.instance.type, $scope.instance.name, start, end) + .success(function (message) { + Falcon.logResponse('success', message, $scope.instance.type); + $scope.instance.status = "KILLED"; + }) + .error(function (err) { + Falcon.logResponse('error', err, $scope.instance.type); + + }); + }; + + var addOneMin = function (time) { + var newtime = parseInt(time.substring(time.length - 3, time.length - 1)); + if (newtime === 59) { + newtime = 0; + } else { + newtime++; + } + if (newtime < 10) { + newtime = "0" + newtime; + } + return time.substring(0, time.length - 3) + newtime + "Z"; + } + + } + ]); + +})(); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js b/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js index 55a5651..64c6892 100644 --- a/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js +++ b/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js @@ -27,9 +27,15 @@ */ var feedModule = angular.module('app.controllers.feed'); - feedModule.controller('FeedClustersController', ["$scope","clustersList", "EntityFactory", + feedModule.controller('FeedClustersController', [ "$scope", "clustersList", "EntityFactory", "$timeout", + function($scope, clustersList, entityFactory, $timeout) { - function($scope, clustersList, entityFactory) { + function focusOnElement () { + $timeout(function () { + angular.element('#clusterNameSelect').trigger('focus'); + }, 500); + } + focusOnElement(); unwrapClusters(clustersList); @@ -93,18 +99,30 @@ }; function unwrapClusters(clusters) { - $scope.clusterList = []; - var typeOfData = Object.prototype.toString.call(clusters.entity); - if(typeOfData === "[object Array]") { - $scope.clusterList = clusters.entity; - } else if(typeOfData === "[object Object]") { - $scope.clusterList = [clusters.entity]; - } else { - //console.log("type of data not recognized"); - } + if(clusters !== undefined && clusters !== null && clusters !== "null"){ + $scope.clusterList = []; + var typeOfData = Object.prototype.toString.call(clusters.entity); + if(typeOfData === "[object Array]") { + $scope.clusterList = clusters.entity; + } else if(typeOfData === "[object Object]") { + $scope.clusterList = [clusters.entity]; + } else { + //console.log("type of data not recognized"); + } + } } + $scope.clusterLocationsPlaceHolders = (function () { + var obj = {}; + $scope.feed.storage.fileSystem.locations.forEach(function (item) { + obj[item.type] = item.path; + }); + return obj; + }()); + + + $scope.selectedCluster = $scope.selectedCluster || $scope.feed.clusters[0]; $scope.sourceCluster = $scope.sourceCluster || $scope.feed.clusters[0]; $scope.archiveCluster = $scope.newCluster(false); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/feed/feed-location-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/feed/feed-location-controller.js b/falcon-ui/app/js/controllers/feed/feed-location-controller.js index bbb488b..055436d 100644 --- a/falcon-ui/app/js/controllers/feed/feed-location-controller.js +++ b/falcon-ui/app/js/controllers/feed/feed-location-controller.js @@ -27,11 +27,24 @@ */ var feedModule = angular.module('app.controllers.feed'); - feedModule.controller('FeedLocationController', [ "$scope",function($scope) { + feedModule.controller('FeedLocationController', [ "$scope", "$timeout", function ($scope, $timeout) { + + function focusOnElement () { + $timeout(function () { + if ($scope.feed.storage.catalog.active) { + angular.element('.catalogStorageInput').trigger('focus'); + } + else { + angular.element('.firstInput').trigger('focus'); + } + }, 500); + } + focusOnElement(); $scope.toggleStorage = function() { toggle($scope.feed.storage.fileSystem); toggle($scope.feed.storage.catalog); + focusOnElement(); }; function toggle(storage) { http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/feed/feed-properties-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/feed/feed-properties-controller.js b/falcon-ui/app/js/controllers/feed/feed-properties-controller.js index 0f10ac9..8bf6a0d 100644 --- a/falcon-ui/app/js/controllers/feed/feed-properties-controller.js +++ b/falcon-ui/app/js/controllers/feed/feed-properties-controller.js @@ -28,6 +28,7 @@ var feedModule = angular.module('app.controllers.feed'); feedModule.controller('FeedPropertiesController', [ "$scope",function($scope) { + $scope.addCustomProperty = function () { $scope.feed.customProperties.push({key: null, value: null}); }; @@ -37,6 +38,22 @@ $scope.feed.customProperties.splice(index, 1); } }; + + $scope.propPlaceholders = { + queueName: 'default', + jobPriority: '', + parallel: 3, + maxMaps: 8, + mapBandwidthKB: 1024 + }; + + /*new Entry('queueName', 'default'), + new Entry('jobPriority', ''), + new Entry('timeout', new Frequency(1, 'hours')), + new Entry('parallel', 3), + new Entry('maxMaps', 8), + new Entry('mapBandwidthKB', 1024)*/ + }]); })(); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js b/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js index 27dad77..9282ea4 100644 --- a/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js +++ b/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js @@ -33,9 +33,11 @@ 'JsonTransformerFactory', 'EntityFactory', 'EntitySerializer', '$interval', '$controller', "ValidationService", + "SpinnersFlag", "$rootScope", function($scope, $state, $timeout, Falcon, X2jsService, transformerFactory, entityFactory, - serializer, $interval, $controller, validationService) { + serializer, $interval, $controller, + validationService, SpinnersFlag, $rootScope) { $scope.entityType = 'feed'; @@ -55,7 +57,7 @@ $scope.baseInit(); var type = $scope.entityType; $scope[type] = $scope.loadOrCreateEntity(); - $scope.dateFormat ='dd-MMMM-yyyy'; + $scope.dateFormat ='MM/dd/yyyy'; }; $scope.openDatePicker = function($event, container) { @@ -76,25 +78,35 @@ $scope.saveEntity = function() { var type = $scope.entityType; + var cleanedXml = cleanXml($scope.xml); + SpinnersFlag.show = true; + if(!$scope.$parent.cloningMode) { Falcon.logRequest(); - Falcon.postUpdateEntity($scope.xml, $scope.entityType, $scope[type].name) + + Falcon.postUpdateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + cleanedXml, $scope.entityType, $scope[type].name) .success(function (response) { - Falcon.logResponse('success', response, false); + $scope.skipUndo = true; + Falcon.logResponse('success', response, false); $state.go('main'); }) .error(function(err) { Falcon.logResponse('error', err, false); + SpinnersFlag.show = false; + angular.element('body, html').animate({scrollTop: 0}, 300); }); } else { Falcon.logRequest(); - Falcon.postSubmitEntity($scope.xml, $scope.entityType) + Falcon.postSubmitEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + cleanedXml, $scope.entityType) .success(function (response) { - Falcon.logResponse('success', response, false); + $scope.skipUndo = true; + Falcon.logResponse('success', response, false); $state.go('main'); }) .error(function(err) { Falcon.logResponse('error', err, false); + SpinnersFlag.show = false; + angular.element('body, html').animate({scrollTop: 0}, 300); }); } @@ -145,34 +157,92 @@ }; var xmlPreviewWorker = $interval(xmlPreviewCallback, 1000); - + $scope.skipUndo = false; $scope.$on('$destroy', function () { + + var defaultFeed = entityFactory.newEntity('feed'), + + nameIsEqual = ($scope.feed.name == null || $scope.feed.name === ""), + groupsIsEqual = ($scope.feed.groups == null || $scope.feed.groups === ""), + descriptionIsEqual = ($scope.feed.description === null || $scope.feed.description === ""), + ACLIsEqual = angular.equals($scope.feed.ACL, defaultFeed.ACL), + schemaIsEqual = angular.equals($scope.feed.schema, defaultFeed.schema); + $interval.cancel(xmlPreviewWorker); - }); - //$scope.nameValid = $scope.$parent.nameValid; - /* - * needed for validation - * */ + if (!$scope.skipUndo && (!nameIsEqual || !groupsIsEqual || !descriptionIsEqual || !ACLIsEqual || !schemaIsEqual)) { + $scope.$parent.models.feedModel = angular.copy(X2jsService.xml_str2json($scope.xml)); + $scope.$parent.cancel('feed', $rootScope.previousState); + } + }); $scope.goNext = function (formInvalid, stateName) { + + SpinnersFlag.show = true; + if (!validationService.nameAvailable || formInvalid) { validationService.displayValidations.show = true; validationService.displayValidations.nameShow = true; + SpinnersFlag.show = false; return; } validationService.displayValidations.show = false; validationService.displayValidations.nameShow = false; + $state.go(stateName); + + }; $scope.goBack = function (stateName) { + SpinnersFlag.backShow = true; validationService.displayValidations.show = false; validationService.displayValidations.nameShow = false; $state.go(stateName); }; - }]); - + function cleanXml (xml) { + + var obj = X2jsService.xml_str2json(xml), + clusterLocationsArray = [], + feedLocationsArray = []; + + // cluster locations + obj.feed.clusters.cluster[0].locations.location.forEach(function (item) { + if (item._path) { + clusterLocationsArray.push(item); + } + }); + + if (clusterLocationsArray.length === 0) { + delete obj.feed.clusters.cluster[0].locations; + } else { + obj.feed.clusters.cluster[0].locations.location = clusterLocationsArray; + } + + // feed locations + obj.feed.locations.location.forEach(function (item) { + if (item._path) { + feedLocationsArray.push(item); + } + }); + + if (feedLocationsArray.length === 0) { + delete obj.feed.locations; + } else { + obj.feed.locations.location = feedLocationsArray; + } + + //feed properties + if (obj.feed.properties.property.length === 1 && obj.feed.properties.property[0] === "") { + delete obj.feed.properties; + } + + return X2jsService.json2xml_str(obj); + + } + + }]); + })(); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/feed/feed-summary-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/feed/feed-summary-controller.js b/falcon-ui/app/js/controllers/feed/feed-summary-controller.js index 77e1dcc..249b8da 100644 --- a/falcon-ui/app/js/controllers/feed/feed-summary-controller.js +++ b/falcon-ui/app/js/controllers/feed/feed-summary-controller.js @@ -27,7 +27,12 @@ */ var feedModule = angular.module('app.controllers.feed'); - feedModule.controller('FeedSummaryController', [ "$scope", "$filter", function($scope, $filter) { + feedModule.controller('FeedSummaryController', [ "$scope", "$filter", "$timeout", + function($scope, $filter, $timeout) { + + $timeout(function () { + angular.element('.nextBtn').trigger('focus'); + }, 500); if($scope.transform) { $scope.transform(); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/header-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/header-controller.js b/falcon-ui/app/js/controllers/header-controller.js index 5039b99..b2dcaea 100644 --- a/falcon-ui/app/js/controllers/header-controller.js +++ b/falcon-ui/app/js/controllers/header-controller.js @@ -25,35 +25,92 @@ ]); navHeaderModule.controller('HeaderController', [ - '$rootScope', '$scope', '$state', '$cookieStore', 'EntityModel', 'ValidationService', - function ($rootScope, $scope, $state, $cookieStore, EntityModel, validationService) { + '$rootScope', '$scope', '$state', '$cookieStore', '$timeout', 'EntityModel', 'ValidationService', 'Falcon', + function ($rootScope, $scope, $state, $cookieStore, $timeout, EntityModel, validationService, Falcon) { + + $scope.fake = { focus: false }; //used in upload button to fake the focus borders + $scope.notifs = false; + $scope.responses = Falcon.responses; + + $scope.isInForm = function (type) { + if($rootScope.currentState) { + var currState = $rootScope.currentState.split('.'), + formType = currState[1]; + return type === formType; + } + }; $scope.resetCluster = function () { validationService.displayValidations = {show: false, nameShow: false}; - EntityModel.clusterModel = { cluster: { tags: "", interfaces: { interface: [ - { _type: "readonly", _endpoint: "hftp://sandbox.hortonworks.com:50070", _version: "2.2.0"}, - { _type: "write", _endpoint: "hdfs://sandbox.hortonworks.com:8020", _version: "2.2.0"}, - { _type: "execute", _endpoint: "sandbox.hortonworks.com:8050", _version: "2.2.0"}, - { _type: "workflow", _endpoint: "http://sandbox.hortonworks.com:11000/oozie/", _version: "4.0.0"}, - { _type: "messaging", _endpoint: "tcp://sandbox.hortonworks.com:61616?daemon=true", _version: "5.1.6"} - ]}, locations: { location: [{ _name: "staging", _path: ""}, { _name: "temp", _path: ""}, { _name: "working", _path: ""}]}, - ACL: { _owner: "", _group: "", _permission: ""}, properties: { property: [{ _name: "", _value: ""}]}, - _xmlns: "uri:falcon:cluster:0.1", _name: "", _description: "", _colo: ""}}; + angular.copy(EntityModel.defaultValues.cluster, EntityModel.clusterModel); $state.go("forms.cluster.general"); }; $scope.resetProcess = function () { validationService.displayValidations = {show: false, nameShow: false}; $scope.cloningMode = true; + $scope.models.processModel = null; $state.go("forms.process.general"); }; $scope.resetFeed = function () { validationService.displayValidations = {show: false, nameShow: false}; $scope.cloningMode = true; + $scope.models.feedModel = null; $state.go("forms.feed.general"); }; - + + $scope.resetDataset = function () { + validationService.displayValidations = {show: false, nameShow: false}; + EntityModel.datasetModel.toImportModel = undefined; + angular.copy(EntityModel.defaultValues.MirrorUIModel, EntityModel.datasetModel.UIModel); + $scope.cloningMode = true; + $scope.models.feedModel = null; + $state.go("forms.dataset.general"); + }; + + $scope.userLogged = function () { + if($rootScope.isSecureMode()){ + return true; + }else if($rootScope.userLogged()){ + if(angular.isDefined($cookieStore.get('userToken')) && $cookieStore.get('userToken') !== null){ + $scope.userToken = $cookieStore.get('userToken').user; + return true; + }else{ + return false; + } + }else{ + return false; + } + }; + + $scope.isSecureMode = function () { + return $rootScope.isSecureMode(); + }; + + $scope.logOut = function() { + $cookieStore.put('userToken', null); + $state.transitionTo('login'); + }; + + $scope.restore = function(state) { + $state.go(state); + }; + + $scope.notify = function() { + Falcon.notify(true); + }; + + $scope.hideNotifs = function() { + Falcon.hideNotifs(); + }; + }]); + navHeaderModule.filter('reverse', function() { + return function(items) { + return items.slice().reverse(); + }; + }); + })(); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/login.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/login.js b/falcon-ui/app/js/controllers/login.js new file mode 100644 index 0000000..2a86676 --- /dev/null +++ b/falcon-ui/app/js/controllers/login.js @@ -0,0 +1,72 @@ +/** + * 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. + */ +(function () { + 'use strict'; + + /*** + * @ngdoc controller + * @name app.controllers.feed.FeedController + * @requires EntityModel the entity model to copy the feed entity from + * @requires Falcon the falcon service to talk with the Falcon REST API + */ + var loginModule = angular.module('app.controllers.login', ['ngMessages', 'app.services']); + + loginModule.controller('LoginFormCtrl', ['$scope', '$state', '$cookieStore', '$http', 'ServerAPI', + function ($scope, $state, $cookieStore, $http, ServerAPI) { + $scope.showLoginVal = {show: false, userPassInvalid: false}; + + //$scope.loggUser = function(form) { + //if(form.$valid){ + // $http.get('config/loginData.json').success(function(data) { + // var user = data.user; + // var password = data.password; + // if($scope.login.user === user && $scope.login.password === password){ + // var userToken = {}; + // userToken.timeOutLimit = $scope.login.timeOut; + // userToken.user = $scope.login.user; + // userToken.timeOut = new Date().getTime(); + // $cookieStore.put('userToken', userToken); + // $state.go('main'); + // }else{ + // $scope.showLoginVal.show = true; + // $scope.showLoginVal.userPassInvalid = true; + // } + // }); + //}else{ + // $scope.showLoginVal.show = true; + //} + //}; + + $scope.loggUser = function (form) { + if (form.$valid) { + ServerAPI.clearUser().then(function() { + var userToken = {}; + userToken.timeOutLimit = $scope.login.timeOut; + userToken.user = $scope.login.user; + userToken.timeOut = new Date().getTime(); + $cookieStore.put('userToken', userToken); + $state.go('main'); + }); + } else { + $scope.showLoginVal.show = true; + } + }; + + }]); + +}()); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js b/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js index b588c84..5605268 100644 --- a/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js +++ b/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js @@ -27,11 +27,15 @@ */ var feedModule = angular.module('app.controllers.process'); - feedModule.controller('ProcessClustersCtrl', - ['$scope', 'clustersList', 'EntityFactory', function($scope, clustersList, entityFactory) { + feedModule.controller('ProcessClustersCtrl', ['$scope', 'clustersList', 'EntityFactory', '$timeout', + function($scope, clustersList, entityFactory, $timeout) { + + $timeout(function () { + angular.element('.firstSelectClusterStep').trigger('focus'); + }, 500); $scope.init = function() { - $scope.dateFormat = 'dd-MMMM-yyyy'; + $scope.dateFormat = 'MM/dd/yyyy'; }; $scope.openDatePicker = function($event, container) { @@ -60,7 +64,7 @@ } else if(typeOfData === "[object Object]") { $scope.clusterList = [clusters.entity]; } else { - //console.log("type of data not recognized"); + //console.log("type of data not recognized"); } } http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/process/process-general-information-ctrl.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/process/process-general-information-ctrl.js b/falcon-ui/app/js/controllers/process/process-general-information-ctrl.js index ee5ab12..bda465d 100644 --- a/falcon-ui/app/js/controllers/process/process-general-information-ctrl.js +++ b/falcon-ui/app/js/controllers/process/process-general-information-ctrl.js @@ -29,9 +29,9 @@ feedModule.controller('ProcessGeneralInformationCtrl', [ '$scope', function($scope) { var availableVerions = { - oozie: ['4.2.0', '4.1.0', '4.0.1', '4.0.0'], - pig: ['pig-0.13.0', 'pig-0.12.1', 'pig-0.12.0', 'pig-0.11.1', 'pig-0.11.0', 'pig-0.10.1'], - hive: ['hive-0.13.1', 'hive-0.13.0', 'hive-0.12.0', 'hive-0.11.0', 'hive-0.10.0'] + oozie: ['3.1.3-incubating', '3.2.0-incubating', '3.3.0', '3.3.1', '3.3.2', '4.0.0', '4.0.1'], + pig: ['pig-0.10.0', 'pig-0.10.1', 'pig-0.11.0', 'pig-0.11.1', 'pig-0.12.0', 'pig-0.12.1', 'pig-0.13.0', 'pig-0.8.0', 'pig-0.8.1', ' pig-0.9.0', ' pig-0.9.1', 'pig-0.9.2'], + hive: ['hive-0.10.0', 'hive-0.11.0', 'hive-0.12.0', 'hive-0.13.0', 'hive-0.13.1', 'hive-0.6.0', 'hive-0.7.0', 'hive-0.8.0', 'hive-0.8.1', 'hive-0.9.0'] }; $scope.nameValid = false; @@ -50,10 +50,9 @@ }; $scope.selectWorkflow = function() { - if($scope.process.workflow) { var engine = $scope.process.workflow.engine; - $scope.process.workflow.version = null; + $scope.process.workflow.version = ""; $scope.versions = availableVerions[engine]; } }; http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/process/process-inputs-and-outputs-ctrl.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/process/process-inputs-and-outputs-ctrl.js b/falcon-ui/app/js/controllers/process/process-inputs-and-outputs-ctrl.js index c9b22d0..a113a49 100644 --- a/falcon-ui/app/js/controllers/process/process-inputs-and-outputs-ctrl.js +++ b/falcon-ui/app/js/controllers/process/process-inputs-and-outputs-ctrl.js @@ -27,50 +27,73 @@ */ var feedModule = angular.module('app.controllers.process'); - feedModule.controller('ProcessInputsAndOutputsCtrl', + feedModule.controller('ProcessInputsAndOutputsCtrl', ['$scope', 'EntityFactory', 'feedsList', '$timeout', + function ($scope, entityFactory, feedsList, $timeout) { - ['$scope', 'EntityFactory', 'feedsList', function($scope, entityFactory, feedsList) { + $timeout(function () { + if ($scope.process.inputs.length > 0) { + angular.element('.firstInput').trigger('focus'); + } + else if ($scope.process.outputs.length > 0) { + angular.element('.firstOutput').trigger('focus'); + } + else { + angular.element('.addInputButton').trigger('focus'); + } + }, 500); - $scope.init = function() { + $scope.init = function () { }; - $scope.addInput = function() { + $scope.addInput = function () { $scope.process.inputs.push(entityFactory.newInput()); }; - $scope.removeInput = function(index) { - if(index >= 0) { + $scope.removeInput = function (index) { + if (index >= 0) { $scope.process.inputs.splice(index, 1); } }; - $scope.addOutput = function() { + $scope.addOutput = function () { $scope.process.outputs.push(entityFactory.newOutput()); }; - $scope.removeOutput = function(index) { - if(index >= 0) { + $scope.removeOutput = function (index) { + if (index >= 0) { $scope.process.outputs.splice(index, 1); } }; - unwrapClusters(feedsList); function unwrapClusters(feeds) { $scope.feedsList = []; var typeOfData = Object.prototype.toString.call(feeds.entity); - if(typeOfData === "[object Array]") { + if (typeOfData === "[object Array]") { $scope.feedsList = feeds.entity; - } else if(typeOfData === "[object Object]") { + } else if (typeOfData === "[object Object]") { $scope.feedsList = [feeds.entity]; } else { //console.log("type of data not recognized"); } } + $scope.validateStartEndDate = function () { + delete $scope.invalidEndDate; + if (this.input.start && this.input.end) { + var startDate = new Date(this.input.start), + endDate = new Date(this.input.end); + if (endDate.toString !== 'Invalid Date' && startDate.toString !== 'Invalid Date') { + if (startDate > endDate) { + $scope.invalidEndDate = "ng-dirty ng-invalid"; + } + } + } + }; + $scope.init(); }]); -})(); +}()); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/process/process-properties-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/process/process-properties-controller.js b/falcon-ui/app/js/controllers/process/process-properties-controller.js index d4e747c..5b95fcd 100644 --- a/falcon-ui/app/js/controllers/process/process-properties-controller.js +++ b/falcon-ui/app/js/controllers/process/process-properties-controller.js @@ -27,8 +27,10 @@ */ var feedModule = angular.module('app.controllers.process'); - feedModule.controller('ProcessPropertiesCtrl', [ '$scope', function() { - + feedModule.controller('ProcessPropertiesCtrl', [ '$scope', '$timeout', function($scope, $timeout) { + $timeout(function () { + angular.element('#timeZoneSelect > select').trigger('focus'); + }, 500); }]); })(); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/process/process-root-ctrl.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/process/process-root-ctrl.js b/falcon-ui/app/js/controllers/process/process-root-ctrl.js index ba69705..7d461ba 100644 --- a/falcon-ui/app/js/controllers/process/process-root-ctrl.js +++ b/falcon-ui/app/js/controllers/process/process-root-ctrl.js @@ -25,12 +25,13 @@ * @requires EntityModel the entity model to copy the feed entity from * @requires Falcon the falcon entity service */ - var feedModule = angular.module('app.controllers.process'); + var processModule = angular.module('app.controllers.process'); - feedModule.controller('ProcessRootCtrl', [ + processModule.controller('ProcessRootCtrl', [ '$scope', '$state', '$interval', '$controller', 'EntityFactory', - 'EntitySerializer', 'X2jsService', 'ValidationService', - function ($scope, $state, $interval, $controller, entityFactory, serializer, X2jsService, validationService) { + 'EntitySerializer', 'X2jsService', 'ValidationService', 'SpinnersFlag', '$rootScope', + function ($scope, $state, $interval, $controller, entityFactory, + serializer, X2jsService, validationService, SpinnersFlag, $rootScope) { $scope.entityType = 'process'; @@ -90,27 +91,48 @@ }; var xmlPreviewWorker = $interval(xmlPreviewCallback, 1000); - + $scope.skipUndo = false; $scope.$on('$destroy', function() { + + var defaultProcess = entityFactory.newEntity('process'), + + nameIsEqual = ($scope.process.name == null || $scope.process.name === ""), // falsey as it needs also to catch undefined + ACLIsEqual = angular.equals($scope.process.ACL, defaultProcess.ACL), + workflowIsEqual = angular.equals($scope.process.workflow, defaultProcess.workflow); + $interval.cancel(xmlPreviewWorker); + + if (!$scope.skipUndo && (!nameIsEqual || !ACLIsEqual || !workflowIsEqual)) { + $scope.$parent.models.processModel = angular.copy(X2jsService.xml_str2json($scope.xml)); + $scope.$parent.cancel('process', $rootScope.previousState); + } }); //---------------------------------// $scope.goNext = function (formInvalid, stateName) { + SpinnersFlag.show = true; if (!validationService.nameAvailable || formInvalid) { validationService.displayValidations.show = true; validationService.displayValidations.nameShow = true; + SpinnersFlag.show = false; return; } validationService.displayValidations.show = false; validationService.displayValidations.nameShow = false; $state.go(stateName); }; + $scope.goBack = function (stateName) { + SpinnersFlag.backShow = true; validationService.displayValidations.show = false; validationService.displayValidations.nameShow = false; $state.go(stateName); }; + + $scope.goTest = function (formInvalid) { + console.log(formInvalid); + }; + } ]); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/process/process-summary-ctrl.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/process/process-summary-ctrl.js b/falcon-ui/app/js/controllers/process/process-summary-ctrl.js index d81bb62..494c249 100644 --- a/falcon-ui/app/js/controllers/process/process-summary-ctrl.js +++ b/falcon-ui/app/js/controllers/process/process-summary-ctrl.js @@ -27,8 +27,12 @@ */ var feedModule = angular.module('app.controllers.process'); - feedModule.controller('ProcessSummaryCtrl', [ '$scope', '$state', '$timeout', '$filter', 'Falcon', - function($scope, $state, $timeout, $filter, Falcon) { + feedModule.controller('ProcessSummaryCtrl', [ '$scope', '$state', '$timeout', '$filter', 'Falcon', 'SpinnersFlag', + function($scope, $state, $timeout, $filter, Falcon, SpinnersFlag) { + + $timeout(function () { + angular.element('.nextBtn').trigger('focus'); + }, 500); $scope.init = function() { if($scope.transform) { @@ -47,28 +51,36 @@ $scope.saveEntity = function() { var type = $scope.entityType; - if(!$scope.$parent.cloningMode) { + SpinnersFlag.show = true; + + if(!$scope.$parent.cloningMode) { Falcon.logRequest(); - Falcon.postUpdateEntity($scope.xml, $scope.entityType, $scope[type].name) + Falcon.postUpdateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + $scope.xml, $scope.entityType, $scope[type].name) .success(function (response) { - Falcon.logResponse('success', response, false); - $state.go('main'); + $scope.$parent.skipUndo = true; + Falcon.logResponse('success', response, false); + $state.go('main'); }) - .error(function (err) { - Falcon.logResponse('error', err, false); + .error(function (err) { + SpinnersFlag.show = false; + Falcon.logResponse('error', err, false); + angular.element('body, html').animate({scrollTop: 0}, 300); }); - } + } else { Falcon.logRequest(); - Falcon.postSubmitEntity($scope.xml, $scope.entityType) + Falcon.postSubmitEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + $scope.xml, $scope.entityType) .success(function (response) { - Falcon.logResponse('success', response, false); - $state.go('main'); - + $scope.$parent.skipUndo = true; + Falcon.logResponse('success', response, false); + $state.go('main'); + }) - .error(function (err) { - Falcon.logResponse('error', err, false); + .error(function (err) { + Falcon.logResponse('error', err, false); + SpinnersFlag.show = false; + angular.element('body, html').animate({scrollTop: 0}, 300); }); } http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/root-controller.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/controllers/root-controller.js b/falcon-ui/app/js/controllers/root-controller.js index 9a71d30..709f6b2 100644 --- a/falcon-ui/app/js/controllers/root-controller.js +++ b/falcon-ui/app/js/controllers/root-controller.js @@ -21,69 +21,118 @@ var app = angular.module('app.controllers.rootCtrl', ['app.services']); app.controller('RootCtrl', [ - "$scope", "$timeout", "Falcon", "FileApi", "EntityModel", "$state", "X2jsService", "ValidationService", - function ($scope, $timeout, Falcon, FileApi, EntityModel, $state, X2jsService, validationService) { + "$scope", "$timeout", "Falcon", "FileApi", "EntityModel", + "$state", "X2jsService", "ValidationService", "SpinnersFlag", "EntityFalcon", + function ($scope, $timeout, Falcon, FileApi, + EntityModel, $state, X2jsService, validationService, SpinnersFlag, EntityFalcon) { + + var resultsPerPage = 10; $scope.server = Falcon; $scope.validations = validationService; + $scope.buttonSpinners = SpinnersFlag; $scope.models = {}; + $scope.pages = []; + $scope.nextPages = false; + $scope.handleFile = function (evt) { Falcon.logRequest(); FileApi.loadFile(evt).then(function () { - Falcon.postSubmitEntity(FileApi.fileRaw, EntityModel.type).success(function (response) { - Falcon.logResponse('success', response, false); - $scope.refreshList(EntityModel.type); - }).error(function (err) { - Falcon.logResponse('error', err, false); - }); + if (EntityModel.type === 'Type not recognized') { + Falcon.logResponse('error', {status: 'ERROR', message:'Invalid xml. File not uploaded'}, false); + } else { + Falcon.postSubmitEntity(FileApi.fileRaw, EntityModel.type).success(function (response) { + Falcon.logResponse('success', response, false); + $scope.refreshList($scope.tags); + }).error(function (err) { + Falcon.logResponse('error', err, false); + }); + } + }); }; - $scope.lists = {}; - $scope.lists.feedList = []; - $scope.lists.clusterList = []; - $scope.lists.processList = []; + $scope.goPage = function(page){ + $scope.loading = true; + var offset = (page-1) * resultsPerPage; + EntityFalcon.searchEntities($scope.entityName, $scope.entityTags, $scope.entityType, offset).then(function() { + if (EntityFalcon.data !== null) { + $scope.actualPage = page; + $scope.searchList = EntityFalcon.data.entity; + var totalPages = Math.ceil(EntityFalcon.data.totalResults/resultsPerPage); + $scope.pages = [] + for(var i=0; i<totalPages; i++){ + $scope.pages[i] = {}; + $scope.pages[i].index = (i+1); + $scope.pages[i].label = ""+(i+1); + if(page === (i+1)){ + $scope.pages[i].enabled = false; + }else{ + $scope.pages[i].enabled = true; + } + } + if($scope.searchList.length === 0){ + Falcon.warningMessage("No results matched the search criteria."); + } + $timeout(function() { + angular.element('#tagsInput').focus(); + }, 0, false); + Falcon.responses.listLoaded = true; + $scope.loading = false; + } + }); + }; - $scope.refreshList = function (type) { - type = type.toLowerCase(); - Falcon.responses.listLoaded[type] = false; - if (Falcon.responses.multiRequest[type] > 0) { return; } + $scope.refreshList = function (tags) { - Falcon.logRequest(); + $scope.nameFounded = false; + $scope.typeFounded = false; + $scope.entityName = ""; + $scope.entityType = ""; + var tagsSt = ""; - Falcon.getEntities(type) - .success(function (data) { - - Falcon.logResponse('success', data, false, true); - Falcon.responses.listLoaded[type] = true; - $scope.lists[type + 'List'] = []; - - if (data === null) { - $scope.lists[type + 'List'] = []; - }else{ - var typeOfData = Object.prototype.toString.call(data.entity); - if (typeOfData === "[object Array]") { - $scope.lists[type + 'List'] = data.entity; - } else if (typeOfData === "[object Object]") { - $scope.lists[type + 'List'][0] = data.entity; - } else { - console.log("type of data not recognized"); - } + $scope.searchList = []; + + if(tags === undefined || tags.length === 0){ + $timeout(function() { + angular.element('#tagsInput').focus(); + }, 0, false); + return; + } + + for(var i=0; i<tags.length; i++){ + var tag = tags[i].text; + if(tag.indexOf("Name:") !== -1){ + $scope.nameFounded = true; + tag = tag.substring(5); + $scope.entityName = tag; + }else if(tag.indexOf("Type:") !== -1){ + $scope.typeFounded = true; + tag = tag.substring(5); + $scope.entityType = tag; + }else{ + tag = tag.substring(4); + tagsSt += tag; + if(i < tags.length-1){ + tagsSt += ","; } - }) - .error(function (err) { - Falcon.logResponse('error', err); - }); - }; + } + + } + + $scope.entityTags = tagsSt; + + $scope.goPage(1); - $scope.refreshLists = function () { - $scope.refreshList('cluster'); - $scope.refreshList('feed'); - $scope.refreshList('process'); }; - $scope.closeAlert = function (index) { - Falcon.removeMessage(index); + + $scope.cancel = function (type, state) { + var cancelInfo = { + state: state || $state.current.name, + message: type + ' edition canceled ' + }; + Falcon.logResponse('cancel', cancelInfo, type, false); }; }]); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/directives/chart.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/directives/chart.js b/falcon-ui/app/js/directives/chart.js new file mode 100644 index 0000000..f9d6983 --- /dev/null +++ b/falcon-ui/app/js/directives/chart.js @@ -0,0 +1,531 @@ +/** + * 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. + */ +(function () { + "use strict"; + + var d3Module = angular.module('chart-module', ['app.services.falcon']); + + // <d3-bar-chart class="chart" input="my.data" w="700" h="400" t="30" dx="[0,50]" dy="[24,0]" details="details"></d3-bar-chart> + d3Module.directive('chart', function() { + return { + scope: { + input: "=", + t: "@", + mode: "=", + details:"=" + }, + restrict: "EA", + link: function (scope, element) { + + + scope.$watch(function () { + return scope.input; + }, function () { + prepareData(); + }); + + angular.element(window).on('resize', prepareData); + + function prepareData () { + + if (scope.input.length === 0) { + return; + } + + scope.w = angular.element('.chartCol').width(); + scope.h = 400; + + + if (scope.mode === 'daily') { scope.xDomain = 14; } else { scope.xDomain = 24; } + + scope.yDomain = d3.max(scope.input, function (d) { + if (d.numFailedInstances >= d.numSuccessfullInstances) { + return d.numFailedInstances; + }else { + return d.numSuccessfullInstances; + } + }); + scope.yMaxDataSizeDomain = d3.max(scope.input, function (d) { + return d.dataSizeCopied; + }) + 100; + scope.yMaxDataSizeDomain = scope.yMaxDataSizeDomain * 1.2; + scope.yDomain = scope.yDomain * 1.2; + + d3.selectAll('svg').remove(); + + drawChart(); + + } + + function drawChart() { + + var x = d3.scale.linear().domain([0,scope.xDomain]).range( [0, (scope.w - (scope.t * 2) ) ]), + y = d3.scale.linear().domain([0, scope.yDomain]).range( [0, (scope.h - (scope.t * 2) ) ]), + yDataSizeScale = d3.scale.linear().domain([0, scope.yMaxDataSizeDomain]).range( [0, (scope.h - (scope.t * 2) ) ]), + + xAxis = d3.svg.axis() + .scale(x) + .orient("bottom") + .ticks(scope.xDomain), + + gridNumberRows = 11, + + canvas = d3.select(element[0]) + .append("svg") + .attr("width", scope.w) + .attr("height", scope.h), + + col, + tip, + + linePrepareTransition = d3.svg.line() + .x(function(d, i) { + return x(i); + }) + .y(function() { + return (y(scope.yDomain)); + }) + .interpolate('cardinal'), + + successLineFunc = d3.svg.line() + .x(function(d, i) { + return x(i); + }) + .y(function(d) { + return (y(scope.yDomain - d.numSuccessfullInstances)); + }) + .interpolate('cardinal'), + + failedLineFunc = d3.svg.line() + .x(function(d, i) { + return x(i); + }) + .y(function(d) { + return (y(scope.yDomain - d.numFailedInstances)); + }) + .interpolate('cardinal'), + + successAreaFunc = d3.svg.area() + .x(function(d, i) { + return x(i); + }) + .y0(y(scope.yDomain)) + .y1(function(d) { + return (y(scope.yDomain - d.numSuccessfullInstances)); + }) + .interpolate('cardinal'), + + failedAreaFunc = d3.svg.area() + .x(function(d, i) { + return x(i); + }) + .y0(y(scope.yDomain)) + .y1(function(d) { + return (y(scope.yDomain - d.numFailedInstances)); + }) + .interpolate('cardinal'); + + //---------------X AXIS ----------------------// + canvas.append("g") + .attr("class", "x axis") + .attr("transform", "translate(" + scope.t + "," + (( scope.h - scope.t ) + 0.5) + ")") + .call(xAxis); + + if (scope.mode === 'daily') { + + canvas.selectAll('g.dateAxis') + .data(scope.input).enter() + .append("g").attr('class', 'dateAxis') + .append("text") + .attr({ + "text-anchor": "middle", + x: function(d, i) { return x(i);}, + y: function() { return (y(scope.yDomain)); }, + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + (scope.t*1.5) + ")" + }).html(function(d) { + var format = d3.time.format.utc("%d %b"); + return format(new Date(d.startTime)); + }); + } + + //---------------GRID-------------------------// + + d3.range(0, (gridNumberRows + 1)).forEach(function (i) { + + canvas.append('svg:line') + .attr({ + stroke: "#d3d3d3", + 'stroke-width': 1, + x1: 0, + x2: x(scope.xDomain), + y1: y((scope.yDomain/gridNumberRows) * i), + y2: y((scope.yDomain/gridNumberRows) * i), + transform: "translate(" + scope.t + "," + scope.t + ")" + }); + + }); + + //----------BARS DATASIZE COPIED---------------// + + canvas.selectAll('rect.dataSize') + .data(scope.input).enter() + .append("svg:rect").attr('class', 'dataSize') + .attr({ + x: function(d, i) { return x(i); }, + y: function() { return yDataSizeScale(scope.yMaxDataSizeDomain); }, + width: function() { return x(1); }, + height: function() { return 0; }, + stroke: "none", + fill: "rgba(8,8,8,0.3)", + transform: "translate(" + scope.t + "," + scope.t + ")" + }) + .transition().duration(2000) + .attr({ + height: function(d) { return yDataSizeScale(d.dataSizeCopied); }, + y: function(d) { return yDataSizeScale(scope.yMaxDataSizeDomain - d.dataSizeCopied); } + }); + + //-------------LINES------------// + + canvas.append('svg:path') + .attr({ + d: linePrepareTransition(scope.input), + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")", + stroke: "green", + "stroke-width": 2, + "stroke-linecap": "round", + fill: "rgba(0,0,0,0)" + }) + .transition().duration(1000) + .attr({ + d: successLineFunc(scope.input) + }); + + canvas.append('svg:path') + .attr({ + d: linePrepareTransition(scope.input), + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")", + stroke: "red", + "stroke-width": 2, + fill: 'none' + }) + .transition().duration(1000).delay(500) + .attr({ + d: failedLineFunc(scope.input) + }); + + //-------------AREAS------------// + + canvas.append('svg:path') + .attr({ + d: linePrepareTransition(scope.input), + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")" + }) + .transition().duration(1000) + .attr({ + d: successAreaFunc(scope.input), + stroke: "none", + fill: "rgba(0,255,0,0.1)" + }); + + canvas.append('svg:path') + .attr({ + d: linePrepareTransition(scope.input), + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")" + }) + .transition().duration(1000).delay(500) + .attr({ + d: failedAreaFunc(scope.input), + stroke: "none", + fill: "rgba(255,0,0,0.1)" + }); + + //------------COL----------------------------// + + col = canvas.selectAll('g.col') + .data(scope.input).enter() + .append("g").attr('class', 'column'); + + col.append('svg:line') + .attr({ + stroke: "#d3d3d3", + 'stroke-width': 1, + x1: function(d, i) { return x(i); }, + x2: function(d, i) { return x(i); }, + y1: 0, + y2: y(scope.yDomain), + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")" + }); + + col.append('svg:line') + .attr({ + stroke: "#748484", + 'stroke-width': 3, + x1: function(d, i) { return x(i); }, + x2: function(d, i) { return x(i + 1); }, + y1: function (d) { return yDataSizeScale((scope.yMaxDataSizeDomain - d.dataSizeCopied)) + 1.5; }, + y2: function (d) { return yDataSizeScale((scope.yMaxDataSizeDomain - d.dataSizeCopied)) + 1.5; }, + transform: "translate(" + scope.t + "," + scope.t + ")" + }); + + col.append("circle") + .attr({ + r: 5, + fill: "green", + cx: function(d, i) { return x(i);}, + cy: function(d) { return (y(scope.yDomain - d.numSuccessfullInstances)); }, + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")" + }); + + col.append("circle") + .attr({ + r: 5, + fill: "red", + cx: function(d, i) { return x(i);}, + cy: function(d) { return (y(scope.yDomain - d.numFailedInstances)); }, + transform: "translate(" + (x(0.5) + parseInt(scope.t, 10)) + "," + scope.t + ")" + }); + + tip = col.append("g").attr('transform', "translate(" + scope.t + ", -" + scope.t/2 + ")"); + + tip.append("svg:rect") + .attr({ + stroke: "gray", + fill: "white", + transform: "translate(-6, -"+ scope.t + ")", + width: 50, + height: 50, + 'stroke-width': 1, + x: function(d, i) { return x(i);}, + y: function (d) { + + if (y(d.numSuccessfullInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numSuccessfullInstances) > y(d.numFailedInstances)) { + return (y(scope.yDomain) - y(d.numSuccessfullInstances)); + } else if (y(d.numFailedInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numFailedInstances) > y(d.numSuccessfullInstances)) { + return (y(scope.yDomain) - y(d.numFailedInstances)); + } else { + return (yDataSizeScale(scope.yMaxDataSizeDomain) - yDataSizeScale(d.dataSizeCopied)); + } + + } + }); + + tip.append("text") + .attr({ + x: function(d, i) { return x(i); }, + y: function (d) { + + if (y(d.numSuccessfullInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numSuccessfullInstances) > y(d.numFailedInstances)) { + return (y(scope.yDomain) - y(d.numSuccessfullInstances)); + } else if (y(d.numFailedInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numFailedInstances) > y(d.numSuccessfullInstances)) { + return (y(scope.yDomain) - y(d.numFailedInstances)); + } else { + return (yDataSizeScale(scope.yMaxDataSizeDomain) - yDataSizeScale(d.dataSizeCopied)); + } + + }, + transform: "translate(10, -" + (scope.t * 0.5) +")", + position: "relative" + }) + + .html(function(d) { + var tip = "<tspan x='' y='' fill='green'>" + d.numSuccessfullInstances + "</tspan>"; + return tip; + }); + + tip.append("text") + .attr({ + x: function(d, i) { return x(i); }, + y: function (d) { + + if (y(d.numSuccessfullInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numSuccessfullInstances) > y(d.numFailedInstances)) { + return (y(scope.yDomain) - y(d.numSuccessfullInstances)); + } else if (y(d.numFailedInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numFailedInstances) > y(d.numSuccessfullInstances)) { + return (y(scope.yDomain) - y(d.numFailedInstances)); + } else { + return (yDataSizeScale(scope.yMaxDataSizeDomain) - yDataSizeScale(d.dataSizeCopied)); + } + + }, + transform: "translate(10, -2)", + position: "relative" + }) + .html(function(d) { + var tip = "<tspan x='' y='' fill='red'>" + d.numFailedInstances + "</tspan>"; + + return tip; + }); + + tip.append("text") + .attr({ + x: function(d, i) { return x(i); }, + y: function (d) { + + if (y(d.numSuccessfullInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numSuccessfullInstances) > y(d.numFailedInstances)) { + return (y(scope.yDomain) - y(d.numSuccessfullInstances)); + } else if (y(d.numFailedInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numFailedInstances) > y(d.numSuccessfullInstances)) { + return (y(scope.yDomain) - y(d.numFailedInstances)); + } else { + return (yDataSizeScale(scope.yMaxDataSizeDomain) - yDataSizeScale(d.dataSizeCopied)); + } + + }, + transform: "translate(0, 13)", + position: "relative" + }) + .html(function(d) { + return "<tspan x='' y='' fill='gray'>" + d.dataSizeCopied + "</tspan>"; + }); + + tip.append("circle") + .attr({ + r: 5, + fill: "green", + cx: function(d, i) { return x(i);}, + cy: function (d) { + + if (y(d.numSuccessfullInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numSuccessfullInstances) > y(d.numFailedInstances)) { + return (y(scope.yDomain) - y(d.numSuccessfullInstances)); + } else if (y(d.numFailedInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numFailedInstances) > y(d.numSuccessfullInstances)) { + return (y(scope.yDomain) - y(d.numFailedInstances)); + } else { + return (yDataSizeScale(scope.yMaxDataSizeDomain) - yDataSizeScale(d.dataSizeCopied)); + } + + }, + transform: "translate(3,-20)" + }); + + tip.append("circle") + .attr({ + r: 5, + fill: "red", + cx: function(d, i) { return x(i);}, + cy: function (d) { + + if (y(d.numSuccessfullInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numSuccessfullInstances) > y(d.numFailedInstances)) { + return (y(scope.yDomain) - y(d.numSuccessfullInstances)); + } else if (y(d.numFailedInstances) > yDataSizeScale(d.dataSizeCopied) && y(d.numFailedInstances) > y(d.numSuccessfullInstances)) { + return (y(scope.yDomain) - y(d.numFailedInstances)); + } else { + return (yDataSizeScale(scope.yMaxDataSizeDomain) - yDataSizeScale(d.dataSizeCopied)); + } + + }, + transform: "translate(3,-6)" + }); + + //--------------CLICKABLE-----------// + + col.append("rect") + .attr({ + x: function(d, i) { return x(i); }, + y: 0, + width: function() { return x(1); }, + height: scope.h, + stroke: "none", + fill: "transparent", + transform: "translate(" + scope.t + ", 0)" + }) + .on("click", function(d){ scope.details(d); }); + + } + + prepareData(); + + } + }; + }); + + + d3Module.controller('chartCtrl', [ "$scope", "Falcon", function($scope, Falcon) { + + var formatFL = d3.time.format.utc("%A %d"), + formatSL = d3.time.format.utc("%b %Y"), + formatTL = d3.time.format.utc("%H:%M"); + + $scope.graphData = []; + + $scope.chartOptions = { + entity: "feed", + mode: "hourly", + day: "" + }; + + $scope.chartSidebarDate = {}; + + $scope.requestNewData = function () { + + var type = $scope.chartOptions.entity, + mode = $scope.chartOptions.mode, + fromDate = new Date($scope.chartOptions.day), + fromMonth = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'], + from = fromDate.getFullYear() + '-' + + (fromMonth[fromDate.getMonth()]) + '-' + + (function () { + var date = fromDate.getDate(); + if (date<10) { + return '0' + date; + } else { + return date; + } + }()), + to = from; //no to supported yet + + if (type && mode && $scope.chartOptions.day !== '' && $scope.chartOptions.day !== undefined) { + Falcon.getInstancesSummary(type, mode, from, to) + .success(function (data) { + $scope.graphData = data.summary; + }).error(function (error) { + Falcon.logResponse('error', error, false); + }); + } + $scope.chartSidebarDate = {}; + $scope.chartSidebarModel = undefined; + + }; + + $scope.dateFormat ='MM/dd/yyyy'; + $scope.openDatePicker = function($event) { + $event.preventDefault(); + $event.stopPropagation(); + $scope.opened = true; + }; + + $scope.details = function (obj) { + + var from = obj.startTime, + to = obj.endTime, + entityType = $scope.chartOptions.entity; + + $scope.chartSidebarDate.firstLeg = formatFL(new Date(from)); + $scope.chartSidebarDate.secondLeg = formatSL(new Date(from)); + $scope.chartSidebarDate.timeLeg = formatTL(new Date(from)); + + Falcon.getTopEntities(entityType, from, to).success(function (data) { + $scope.chartSidebarModel = data; + }).error(function (error) { + Falcon.logResponse('error', error, false); + }); + + }; + + }]); + + +}()); http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/directives/check-name.js ---------------------------------------------------------------------- diff --git a/falcon-ui/app/js/directives/check-name.js b/falcon-ui/app/js/directives/check-name.js index c6f79ab..bea0e22 100644 --- a/falcon-ui/app/js/directives/check-name.js +++ b/falcon-ui/app/js/directives/check-name.js @@ -18,9 +18,9 @@ (function () { 'use strict'; - var checkNameModule = angular.module('app.directives.check-name', ['app.services']); + var checkNameModule = angular.module('app.directives.check-name', ['app.services.falcon', 'app.services.validation']); - checkNameModule.directive('checkName', [ "ValidationService", "$timeout", function (validationService, $timeout) { + checkNameModule.directive('checkName', [ "ValidationService", "$timeout", "Falcon", "EntityFalcon", function (validationService, $timeout, Falcon, EntityFalcon) { return { replace: false, scope: { @@ -30,7 +30,8 @@ link: function (scope, element) { var options = scope.checkName, - entities = scope.$parent.lists[options.type + 'List'], + //entities = scope.$parent.lists[options.type + 'List'], + type = options.type, name = element[0].value; if (!options.check) { @@ -38,11 +39,25 @@ } scope.$watch(function () { - return element[0].value.length; + return element[0].value; }, function () { - if (element[0].value.length === 0) { - element.addClass('empty'); + if (!scope.$parent.editXmlDisabled) { + if (element[0].value.length === 0) { + element.addClass('empty'); + } + getNameAvailability(function() { + getMessage(); + if (element.hasClass('ng-valid') && validationService.nameAvailable) { + angular.element('.nameValidationMessage').addClass('hidden'); + } else { + element.parent().addClass("showValidationStyle"); + angular.element('.nameValidationMessage').removeClass('hidden'); + element.removeClass('empty'); + } + }); } + + }); function getLabels() { @@ -51,30 +66,45 @@ "</div><label class='custom-danger nameValidationMessage'></label>"); } - function getNameAvailability() { - var isAvailable = true; + function getNameAvailability(fn) { name = element[0].value; - - angular.forEach(entities, function (item) { - if (item.name === name) { - isAvailable = false; - } - }); - validationService.nameAvailable = isAvailable; if (name.length === 0) { angular.element('.nameInputDisplay').addClass('hidden'); - - } else if (!validationService.nameAvailable && name.length > 0 && element.hasClass('ng-valid')) { - angular.element('.nameInputDisplay').html('Name unavailable') - .removeClass('custom-success hidden').addClass('custom-danger'); - - } else if (validationService.nameAvailable && name.length > 0 && element.hasClass('ng-valid')) { - angular.element('.nameInputDisplay').html('Name available') - .removeClass('custom-danger hidden').addClass('custom-success'); - - } else if (element.hasClass('ng-invalid-pattern') && name.length > 0) { - angular.element('.nameInputDisplay').addClass('hidden'); + }else{ + Falcon.logRequest(); + Falcon.getEntityDefinition(type, name).success(function (data) { + Falcon.logResponse('success', data, false, true); + validationService.nameAvailable = false; + if (name.length === 0) { + angular.element('.nameInputDisplay').addClass('hidden'); + } else if (!validationService.nameAvailable && name.length > 0 && element.hasClass('ng-valid')) { + angular.element('.nameInputDisplay').html('Name unavailable') + .removeClass('custom-success hidden').addClass('custom-danger'); + } else if (validationService.nameAvailable && name.length > 0 && element.hasClass('ng-valid')) { + angular.element('.nameInputDisplay').html('Name available') + .removeClass('custom-danger hidden').addClass('custom-success'); + } else if (element.hasClass('ng-invalid-pattern') && name.length > 0) { + angular.element('.nameInputDisplay').addClass('hidden'); + } + if (fn) { fn(); } //>callback + }).error(function (err) { + Falcon.logResponse('error', err, false, true); + validationService.nameAvailable = true; + if (name.length === 0) { + angular.element('.nameInputDisplay').addClass('hidden'); + } else if (!validationService.nameAvailable && name.length > 0 && element.hasClass('ng-valid')) { + angular.element('.nameInputDisplay').html('Name unavailable') + .removeClass('custom-success hidden').addClass('custom-danger'); + } else if (validationService.nameAvailable && name.length > 0 && element.hasClass('ng-valid')) { + angular.element('.nameInputDisplay').html('Name available') + .removeClass('custom-danger hidden').addClass('custom-success'); + } else if (element.hasClass('ng-invalid-pattern') && name.length > 0) { + angular.element('.nameInputDisplay').addClass('hidden'); + } + if (fn) { fn(); } //>callback + }); } + } function getMessage() {
