You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by pe...@apache.org on 2016/08/22 04:48:00 UTC

[07/16] falcon git commit: FALCON-2118 Proposal for new UI changes

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/datasource/datasource-advanced-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/datasource/datasource-advanced-controller.js b/falcon-ui/app/js/controllers/datasource/datasource-advanced-controller.js
new file mode 100644
index 0000000..a9f975b
--- /dev/null
+++ b/falcon-ui/app/js/controllers/datasource/datasource-advanced-controller.js
@@ -0,0 +1,34 @@
+/**
+ * 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.datasource.DatasourceGeneralInformationController
+   * @requires EntityModel the entity model to copy the datasource entity from
+   * @requires Falcon the falcon entity service
+   */
+  var datasourceModule = angular.module('app.controllers.datasource');
+
+  datasourceModule.controller('DatasourceAdvancedController', [ "$scope", function ($scope) {
+
+  }]);
+
+
+}());

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/datasource/datasource-general-information-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/datasource/datasource-general-information-controller.js b/falcon-ui/app/js/controllers/datasource/datasource-general-information-controller.js
new file mode 100644
index 0000000..1299b15
--- /dev/null
+++ b/falcon-ui/app/js/controllers/datasource/datasource-general-information-controller.js
@@ -0,0 +1,141 @@
+/**
+ * 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.datasource.DatasourceGeneralInformationController
+   * @requires EntityModel the entity model to copy the datasource entity from
+   * @requires Falcon the falcon entity service
+   */
+  var datasourceModule = angular.module('app.controllers.datasource');
+
+  datasourceModule.controller('DatasourceGeneralInformationController', [ "$scope", function ($scope) {
+    $scope.addTag = function () {
+      $scope.datasource.tags.push({key: null, value: null});
+    };
+
+    $scope.removeTag = function (index) {
+      if (index >= 0 && $scope.datasource.tags.length > 1) {
+        $scope.datasource.tags.splice(index, 1);
+      }
+    };
+
+    $scope.addParameter = function () {
+      $scope.datasource.parameters.push({name: null, value: null});
+    };
+
+    $scope.removeParameter = function (index) {
+      if (index >= 0 && $scope.datasource.parameters.length > 0) {
+        $scope.datasource.parameters.splice(index, 1);
+      }
+    };
+
+    $scope.addProperty = function () {
+      $scope.datasource.customProperties.push({name: null, value: null});
+    };
+
+    $scope.removeProperty = function (index) {
+      if (index >= 0 && $scope.datasource.customProperties.length > 0) {
+        $scope.datasource.customProperties.splice(index, 1);
+      }
+    };
+
+    $scope.addDriverJar = function () {
+      var lastOne = $scope.datasource.driver.jar.length - 1;
+      if($scope.datasource.driver.jar[lastOne].value) {
+        $scope.datasource.driver.jar.push({value:""});
+      }
+    };
+
+    $scope.removeDriverJar = function(index) {
+      if(index !== null && $scope.datasource.driver.jar[index]) {
+        $scope.datasource.driver.jar.splice(index, 1);
+      }
+    };
+
+    $scope.getDatabaseDefaultDetails = function() {
+      switch ($scope.datasource.type) {
+        case "postgres":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:postgresql://db_host:5433/test";
+          $scope.datasource.driver.clazz = "org.postgresql.Driver";
+          return;
+        case "mysql":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:mysql://db_host:3306";
+          $scope.datasource.driver.clazz = "com.mysql.jdbc.Driver";
+          return;
+        case "hsql":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:hsqldb:hsql://db_host:9001";
+          $scope.datasource.driver.clazz = "org.hsqldb.jdbcDriver";
+          return;
+        case "oracle":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:oracle:thin@db_host:1526:oracle_sid";
+          $scope.datasource.driver.clazz = "oracle.jdbc.driver.OracleDriver";
+          return;
+        case "teradata":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:teradata://db_host";
+          $scope.datasource.driver.clazz = "com.teradata.jdbc.TeraDriver";
+          return;
+        case "db2":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:db2://db_host:50000/SAMPLE";
+          $scope.datasource.driver.clazz = "com.ibm.db2.jcc.DB2Driver";
+          return;
+        case "netezza":
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:netezza://db_host:5480/test";
+          $scope.datasource.driver.clazz = "org.netezza.Driver";
+          return;
+        default:
+          $scope.datasource.interfaces.interfaces[0].endpoint = "jdbc:"
+          $scope.datasource.driver.clazz = "org.apache.sqoop.connector.jdbc.GenericJdbcConnector";
+          return;
+      }
+    }
+
+  //   $scope.datasource.interfaces.interfaces[0].endpoint = $scope.datasource.type;
+
+  //   $scope.$watchCollection(
+  //     "[datasource.type, datasource.host, datasource.port, datasource.databaseName]", function() {
+  //     var connectionString;
+  //     switch ($scope.datasource.type) {
+  //       case "sqlserver":
+  //         connectionString = "jdbc:jtds:sqlserver://";
+  //       case "mysql":
+  //         connectionString = "jdbc:mysql://";
+  //       case "postgresql":
+  //         connectionString = "jdbc:postgresql://";
+  //       case "oracle":
+  //         connectionString = "jdbc:oracle:thin:@//";
+  //       case "teradata":
+  //         connectionString = "jdbc:teradata://";
+  //       case "db2":
+  //         connectionString = "jdbc:db2://";
+  //       default:
+  //         connectionString = "jdbc://";
+  //     };
+  //     $scope.datasource.interfaces.interfaces[0].endpoint = connectionString
+  //         + $scope.datasource.host + ":"
+  //         + $scope.datasource.port + "/"
+  //         + $scope.datasource.databaseName;
+  //
+  //   });
+  //
+  }]);
+
+
+}());

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/datasource/datasource-module.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/datasource/datasource-module.js b/falcon-ui/app/js/controllers/datasource/datasource-module.js
new file mode 100644
index 0000000..c8b40f3
--- /dev/null
+++ b/falcon-ui/app/js/controllers/datasource/datasource-module.js
@@ -0,0 +1,33 @@
+/**
+ * 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.datasouurce.DatasourceController
+   * @requires EntityModel the entity model to copy the datasource entity from
+   * @requires Falcon the falcon entity service
+   */
+  angular.module('app.controllers.datasource',
+    [
+     'app.controllers.entity',
+     'app.services'
+    ]);
+
+})();

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/datasource/datasource-root-ctrl.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/datasource/datasource-root-ctrl.js b/falcon-ui/app/js/controllers/datasource/datasource-root-ctrl.js
new file mode 100644
index 0000000..2d38208
--- /dev/null
+++ b/falcon-ui/app/js/controllers/datasource/datasource-root-ctrl.js
@@ -0,0 +1,249 @@
+/**
+ * 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.datasource.DatasourceController
+   * @requires EntityModel the entity model to copy the datasource entity from
+   * @requires Falcon the falcon entity service
+   */
+  var datasourceModule = angular.module('app.controllers.datasource');
+
+  datasourceModule.controller('DatasourceController',
+    [ '$scope', '$state', '$timeout', "RouteHelper",
+      'Falcon', 'X2jsService',
+      'JsonTransformerFactory', 'EntityFactory',
+      'EntitySerializer', '$interval',
+      '$controller', "ValidationService",
+      "SpinnersFlag", "$rootScope", "DatasourceModel",
+      function($scope, $state, $timeout, RouteHelper, Falcon,
+               X2jsService, transformerFactory, entityFactory,
+               serializer, $interval, $controller,
+               validationService, SpinnersFlag, $rootScope, datasourceModel) {
+
+         $scope.entityType = 'datasource';
+         var stateMatrix = {
+                 general : {previous : '', next : 'summary'},
+                 summary : {previous : 'general', next : ''}
+         };
+         //extending root controller
+         $controller('EntityRootCtrl', {
+           $scope: $scope
+         });
+
+         $scope.skipUndo = false;
+         $scope.secureMode = $rootScope.secureMode;
+
+         $scope.$on('$destroy', function () {
+
+          //  if (!$scope.skipUndo && !angular.equals($scope.UIModel, EntityModel.defaultValues.datasourceModel)) {
+          //    if($scope.clone){
+          //      EntityModel.datasourceModel.UIModel.clone = true;
+          //    }
+          //    if($scope.editingMode){
+          //      EntityModel.datasourceModel.UIModel.edit = true;
+          //    }
+          //    $scope.$parent.cancel('datasource', $rootScope.previousState);
+          //  }
+         });
+
+         $scope.loadOrCreateEntity = function() {
+           var type = $scope.entityType;
+           if(!datasourceModel && $scope.$parent.models.datasourceModel){
+             datasourceModel = $scope.$parent.models.datasourceModel;
+           }
+           $scope.$parent.models.datasourceModel = null;
+           return datasourceModel ? serializer.preDeserialize(datasourceModel, type) : entityFactory.newEntity(type);
+         };
+
+         $scope.init = function() {
+           $scope.baseInit();
+           var type = $scope.entityType;
+           $scope[type] = $scope.loadOrCreateEntity();
+           if(datasourceModel && datasourceModel.clone === true){
+             $scope.cloningMode = true;
+             $scope.editingMode = false;
+             $scope[type].name = "";
+           }else if(datasourceModel && datasourceModel.edit === true){
+             $scope.editingMode = true;
+             $scope.cloningMode = false;
+           }else{
+             $scope.editingMode = false;
+             $scope.cloningMode = false;
+           }
+         }
+
+         $scope.init();
+
+         $scope.transform = function() {
+           var type = $scope.entityType;
+           var xml = serializer.serialize($scope[type], $scope.entityType);
+           $scope.prettyXml = X2jsService.prettifyXml(xml);
+           $scope.xml = xml;
+           return xml;
+         };
+
+         var xmlPreviewCallback = function() {
+           var type = $scope.entityType;
+           if($scope.editXmlDisabled) {
+             try {
+               $scope.transform();
+             } catch (exception) {
+               console.log('error when transforming xml');
+               console.log(exception);
+             }
+           } else {
+             try {
+               $scope[type] = serializer.deserialize($scope.prettyXml, type);
+               $scope.invalidXml = false;
+             } catch (exception) {
+               $scope.invalidXml = true;
+               console.log('user entered xml incorrect format');
+               console.log(exception);
+             }
+           }
+         };
+
+         $scope.$watch('datasource', xmlPreviewCallback, true);
+         $scope.$watch('prettyXml', xmlPreviewCallback, true);
+         $scope.$watch('datasource.interfaces', function() {
+           if ($scope.datasource.interfaces.interfaces[0]
+             && $scope.datasource.interfaces.interfaces[0].credential) {
+            $scope.datasource.interfaces.credential = $scope.datasource.interfaces.interfaces[0].credential;
+           }
+         }, true);
+
+         $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 ) : '';
+          };
+
+          $scope.isActive = function (route) {
+              return route === $state.current.name;
+          };
+
+          $scope.isCompleted = function (route) {
+              return $state.get(route).data && $state.get(route).data.completed;
+          };
+
+          $scope.goNext = function (formInvalid) {
+            $state.current.data = $state.current.data || {};
+            $state.current.data.completed = !formInvalid;
+
+            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(RouteHelper.getNextState($state.current.name, stateMatrix));
+            angular.element('body, html').animate({scrollTop: 0}, 500);
+          };
+
+          $scope.goBack = function () {
+            SpinnersFlag.backShow = true;
+            validationService.displayValidations.show = false;
+            validationService.displayValidations.nameShow = false;
+            $state.go(RouteHelper.getPreviousState($state.current.name, stateMatrix));
+            angular.element('body, html').animate({scrollTop: 0}, 500);
+          };
+
+          function cleanXml (xml) {
+            var obj = X2jsService.xml_str2json(xml);
+            //feed properties
+            // if (obj.datasource.properties.property.length === 1 && obj.feed.properties.property[0] === "") {
+            //   delete obj.datasource.properties;
+            // }
+
+            return X2jsService.json2xml_str(obj);
+          }
+
+          $scope.validate = function() {
+            var type = $scope.entityType;
+            var cleanedXml = cleanXml($scope.xml);
+            SpinnersFlag.validateShow = true;
+            Falcon.logRequest();
+
+            Falcon.postValidateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + cleanedXml, $scope.entityType, $scope[type].name)
+              .success(function (response) {
+                Falcon.logResponse('success', response, false);
+                SpinnersFlag.validateShow = false;
+                angular.element('body, html').animate({scrollTop: 0}, 300);
+              })
+              .error(function(err) {
+                Falcon.logResponse('error', err, false);
+                SpinnersFlag.validateShow = false;
+                angular.element('body, html').animate({scrollTop: 0}, 300);
+              });
+          }
+
+          $scope.saveEntity = function() {
+            var type = $scope.entityType;
+            var cleanedXml = cleanXml($scope.xml);
+            SpinnersFlag.show = true;
+
+            if($scope.editingMode) {
+              Falcon.logRequest();
+
+              Falcon.postUpdateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + cleanedXml, $scope.entityType, $scope[type].name)
+                .success(function (response) {
+                  $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('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + cleanedXml, $scope.entityType)
+                .success(function (response) {
+                  $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);
+                });
+            }
+
+            $scope.editingMode = false;
+            $scope.cloningMode = false;
+          };
+
+          if($state.current.name !== "forms.datasource.general"){
+            $state.go("forms.datasource.general");
+          }
+
+      }
+    ]);
+
+
+})();

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/datasource/datasource-summary-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/datasource/datasource-summary-controller.js b/falcon-ui/app/js/controllers/datasource/datasource-summary-controller.js
new file mode 100644
index 0000000..8440f13
--- /dev/null
+++ b/falcon-ui/app/js/controllers/datasource/datasource-summary-controller.js
@@ -0,0 +1,39 @@
+/**
+ * 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.datasource.DatasourceSummaryController
+   * @requires EntityModel the entity model to copy the datasource entity from
+   * @requires Falcon the falcon entity service
+   */
+  var datasourceModule = angular.module('app.controllers.datasource');
+
+  datasourceModule.controller('DatasourceSummaryController', [ "$scope", "$timeout",
+                                                function($scope, $timeout) {
+
+    if($scope.transform) {
+      $scope.transform();
+    }
+
+  }]);
+
+
+})();

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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
index 217bb9b..6670dbb 100644
--- a/falcon-ui/app/js/controllers/entity/entity-details.js
+++ b/falcon-ui/app/js/controllers/entity/entity-details.js
@@ -27,10 +27,12 @@
   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", "$timeout","$window", "$interval", "Falcon", "EntityModel","EntityScheduler", "$state",
+    "X2jsService", 'EntitySerializer', 'InstanceFalcon', 'entity', 'ExtensionSerializer', '$rootScope',
+    function ($scope, $timeout, $window, $interval, Falcon, EntityModel, EntityScheduler,
+      $state, X2jsService, serializer, InstanceFalcon, entity, extensionSerializer, $rootScope) {
 
-      $scope.entity = EntityModel;
+      $scope.entity = entity;
 
       var resultsPerPage = 10;
       var visiblePages = 3;
@@ -39,7 +41,15 @@
 
       $scope.pages = [];
       $scope.nextPages = false;
-      $scope.mirrorTag = "_falcon_mirroring_type";
+      $scope.mirrorTag = "_falcon_extension_name";
+
+      $scope.isSafeMode = function() {
+        return $rootScope.safeMode;
+      };
+
+      $scope.isSuperUser = function() {
+        return $rootScope.superUser;
+      };
 
       $scope.isMirror = function(tags){
         var flag = false;
@@ -49,22 +59,49 @@
         return flag;
       };
 
+      $scope.getMirrorType = function(tags) {
+        if (tags.search('_falcon_extension_name=HDFS-MIRRORING') !== -1) {
+          return "hdfs-mirror";
+        } else if (tags.search('_falcon_extension_name=HDFS-SNAPSHOT-MIRRORING') !== -1) {
+          return "snapshot";
+        } else if (tags.search('_falcon_extension_name=HIVE-MIRRORING') !== -1) {
+          return "hive-mirror";
+        }
+      };
+
       if($scope.entity.type === "feed"){
+        $scope.entityTypeLabel = "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{
+      } else if($scope.entity.type === "cluster"){
+        $scope.entityTypeLabel = "Cluster";
+        $scope.cluster = serializer.preDeserialize($scope.entity.model, "cluster");
+        $scope.cluster.name = $scope.entity.name;
+        $scope.cluster.type = $scope.entity.type;
+      }else if($scope.entity.type === "process"){
         var tags = $scope.entity.model.process.tags;
         if($scope.isMirror(tags)){
-          $scope.entityTypeLabel = "Mirror";
+          var mirrorType = $scope.getMirrorType(tags);
+          if (mirrorType === "snapshot") {
+            $scope.entityTypeLabel = "Snapshot";
+          } if (mirrorType === "hdfs-mirror") {
+            $scope.entityTypeLabel = "HDFS Mirror";
+          } else if (mirrorType === "hive-mirror") {
+            $scope.entityTypeLabel = "Hive Mirror";
+          }
+          $scope.extension = extensionSerializer.serializeExtensionModel(
+            $scope.entity.model, mirrorType, $rootScope.secureMode);
+        } else {
+          $scope.entityTypeLabel = "Process";
+          $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.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) {
@@ -141,7 +178,10 @@
         if(type === "FEED"){
           $scope.entityTypeLabel = "Feed";
           return "entypo download";
-        }else if(type === "PROCESS"){
+        } else if(type === "CLUSTER"){
+          $scope.entityTypeLabel = "Cluster";
+          return "entypo archive";
+        } else if(type === "PROCESS"){
           var tags = model.process.tags;
           if($scope.isMirror(tags)){
             $scope.entityTypeLabel = "Mirror";
@@ -156,6 +196,62 @@
         }
       };
 
+      $scope.deleteEntity = function () {
+        EntityScheduler.deleteEntity($scope.entity.type, $scope.entity.name).then(function(status){
+            if(status === "DELETED"){
+                $state.go("main");
+            }
+        });
+      };
+      $scope.cloneEntity = function () {
+        var type = $scope.entity.type.toLowerCase();
+        if(type === 'process' && $scope.isMirror($scope.entity.model.process.tags)){
+            type = $scope.getMirrorType($scope.entity.model.process.tags);
+            if (type === 'hdfs-mirror' || type === 'hive-mirror') {
+              type = 'dataset';
+            }
+        }
+        var state = 'forms.' + type;
+        $state.go(state, {'name' : $scope.entity.name, 'action' : 'clone'});
+      };
+
+      $scope.editEntity = function () {
+        var type = $scope.entity.type.toLowerCase();
+        if (type === 'cluster' && (!$rootScope.safeMode || !$rootScope.superUser)) {
+          return;
+        }
+        if(type === 'process' && $scope.isMirror($scope.entity.model.process.tags)){
+            type = $scope.getMirrorType($scope.entity.model.process.tags);
+            if (type === 'hdfs-mirror' || type === 'hive-mirror') {
+              type = 'dataset';
+            }
+        }
+        var state = 'forms.' + type;
+        $state.go(state, {'name' : $scope.entity.name, 'action' : 'edit'});
+      };
+
+      $scope.resumeEntity = function () {
+        EntityScheduler.resumeEntity($scope.entity.type, $scope.entity.name).then(function(status){
+            $scope.entity.status = status;
+        });
+      };
+
+      $scope.scheduleEntity = function () {
+        EntityScheduler.scheduleEntity($scope.entity.type, $scope.entity.name).then(function(status){
+            $scope.entity.status = status;
+        });
+      };
+
+      $scope.suspendEntity = function () {
+        EntityScheduler.suspendEntity($scope.entity.type, $scope.entity.name).then(function(status){
+            $scope.entity.status = status;
+        });
+      };
+
+      $scope.downloadEntity = function () {
+        EntityScheduler.downloadEntity($scope.entity.type, $scope.entity.name);
+      };
+
     }
   ]);
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/entity/entity-module.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/entity/entity-module.js b/falcon-ui/app/js/controllers/entity/entity-module.js
index cb36b45..aa5a4fd 100644
--- a/falcon-ui/app/js/controllers/entity/entity-module.js
+++ b/falcon-ui/app/js/controllers/entity/entity-module.js
@@ -21,8 +21,21 @@
   var entityModule = angular.module('app.controllers.entity',[ 'app.services' ]);
 
   entityModule.controller('EntityRootCtrl',
-    [ '$scope',
-      function($scope) {
+    [ '$scope', 'ValidationService',
+      function($scope, validationService) {
+
+        $scope.invalidXml = false;
+        $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;
+          }
+          field.$setValidity('required', $scope.isFrequencyValid);
+        };
 
         $scope.baseInit = function() {
           $scope.editXmlDisabled = true;
@@ -32,6 +45,11 @@
           $scope.editXmlDisabled = !$scope.editXmlDisabled;
         };
 
+        $scope.revertXml = function() {
+          $scope.transform();
+          $scope.invalidXml = false;
+        };
+
         $scope.capitalize = function(input) {
             return input.charAt(0).toUpperCase() + input.slice(1);
         };

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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
index 0775d61..5800aba 100644
--- a/falcon-ui/app/js/controllers/entity/instance-details.js
+++ b/falcon-ui/app/js/controllers/entity/instance-details.js
@@ -27,12 +27,13 @@
   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", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", 'DateHelper',
+    function ($scope, $interval, Falcon, EntityModel, $state, X2jsService, DateHelper) {
 
       $scope.instance = EntityModel.model;
       $scope.instance.type = EntityModel.type;
       $scope.instance.name = EntityModel.name;
+      $scope.dateFormat = DateHelper.getLocaleDateFormat() +'HH:mm';
 
       $scope.backToEntity = function () {
         var type = $scope.instance.type.toLowerCase();
@@ -45,7 +46,7 @@
             EntityModel.type = type;
             EntityModel.name = name;
             EntityModel.model = entityModel;
-            $state.go('entityDetails');
+            $state.go('entityDetails',{'name' : name, 'type' : type});
           })
           .error(function (err) {
             Falcon.logResponse('error', err, false, true);

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/feed/feed-advanced-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/feed/feed-advanced-controller.js b/falcon-ui/app/js/controllers/feed/feed-advanced-controller.js
new file mode 100644
index 0000000..4d80cc7
--- /dev/null
+++ b/falcon-ui/app/js/controllers/feed/feed-advanced-controller.js
@@ -0,0 +1,34 @@
+/**
+ * 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.FeedAdvancedController
+   * @requires clusters the list of clusters to display for selection of source
+   * @requires EntityModel the entity model to copy the feed entity from
+   * @requires Falcon the falcon entity service
+   */
+  var feedModule = angular.module('app.controllers.feed');
+
+  feedModule.controller('FeedAdvancedController', [ "$scope",function($scope) {
+
+  }]);
+
+})();

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 64c6892..6d829b9 100644
--- a/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js
+++ b/falcon-ui/app/js/controllers/feed/feed-clusters-controller.js
@@ -30,14 +30,38 @@
   feedModule.controller('FeedClustersController', [ "$scope", "clustersList", "EntityFactory", "$timeout",
                                             function($scope, clustersList, entityFactory, $timeout) {
 
-      function focusOnElement () {
-        $timeout(function () {
-          angular.element('#clusterNameSelect').trigger('focus');
-        }, 500);
+      unwrapClusters(clustersList);
+      $scope.sourceClusterName;
+      $scope.sourceClusterNotSelected = false;
+      $scope.sourceClusterExists = false;
+      $scope.targetClusterName;
+      $scope.targetClusterNotSelected = false;
+      $scope.targetClusterExists = false;
+
+      function preparePartitionString() {
+        $scope.feedPartitions = "";
+        $scope.feed.partitions.forEach(function(partition, index){
+          $scope.feedPartitions = $scope.feedPartitions.concat(partition.name);
+          if (index < $scope.feed.partitions.length - 1) {
+            $scope.feedPartitions = $scope.feedPartitions.concat(",");
+          }
+        });
       }
-      focusOnElement();
 
-      unwrapClusters(clustersList);
+      $scope.$watch("feed.partitions",function(){
+        preparePartitionString();
+        $scope.$broadcast("createClusterPartitions");
+      }, true);
+
+      $scope.createFeedClusterPartitions = function() {
+        if ($scope.feedPartitions != undefined) {
+          var currentPartitions = ($scope.feedPartitions.trim() === "") ? [] : $scope.feedPartitions.split(",");
+          $scope.feed.partitions = [];
+          currentPartitions.forEach(function(element) {
+            $scope.feed.partitions.push(entityFactory.newPartition(element));
+          });
+        }
+      };
 
       $scope.updateRetention = function() {
         if($scope.selectedCluster.retention.action === 'archive' && $scope.selectedCluster.type === 'source') {
@@ -64,15 +88,75 @@
         }
       };
 
-      $scope.addCluster = function() {
-        $scope.selectedCluster.selected = false;
-        var cluster = $scope.newCluster(true);
+      function openClusterInAccordion(object, flagValue) {
+        object.isAccordionOpened = flagValue;
+      }
+
+      $scope.feed.clusters.forEach(function(cluster) {
+        openClusterInAccordion(cluster, false);
+      });
+
+      function findClusterExists(clusterList, newClusterName, newClusterType) {
+        var clusterExists = false;
+        clusterList.forEach(function (cluster) {
+          if (cluster.name === newClusterName && cluster.type === newClusterType) {
+            clusterExists = true;
+            return;
+          }
+        });
+        return clusterExists;
+      }
+
+      $scope.clearSourceClusterFlags = function() {
+        $scope.sourceClusterNotSelected = false;
+        $scope.sourceClusterExists = false;
+      }
+
+      $scope.clearTargetClusterFlags = function() {
+        $scope.targetClusterNotSelected = false;
+        $scope.targetClusterExists = false;
+      }
+
+      $scope.addSourceCluster = function() {
+        $scope.clearSourceClusterFlags();
+        if ($scope.sourceClusterName == undefined) {
+          $scope.sourceClusterNotSelected = true;
+        } else if (!findClusterExists($scope.feed.clusters, $scope.sourceClusterName, 'source')) {
+          $scope.addCluster('source', $scope.sourceClusterName);
+        } else {
+          $scope.sourceClusterExists = true;
+        }
+      };
+
+      $scope.addTargetCluster = function() {
+        if ($scope.targetClusterName == undefined) {
+          $scope.targetClusterNotSelected = true;
+        } else if (!findClusterExists($scope.feed.clusters, $scope.targetClusterName, 'target')) {
+          $scope.addCluster('target', $scope.targetClusterName);
+        } else {
+          $scope.targetClusterExists = true;
+        }
+      };
+
+      $scope.addCluster = function(clusterType, clusterName) {
+        var cluster = $scope.newCluster(clusterType, true, clusterName);
+        if($scope.feed.storage.catalog.active){
+          cluster.storage.catalog.catalogTable.uri = $scope.feed.storage.catalog.catalogTable.uri
+        }
+        cluster.storage.fileSystem.locations.forEach(function (location) {
+          if (location.type === 'data') {
+            var dataLocation = $scope.feed.storage.fileSystem.locations.filter(function(obj) {
+              return obj.type == 'data';
+            })[0];
+            location.path = (dataLocation != undefined) ? dataLocation.path : '';
+          }
+        });
+        openClusterInAccordion(cluster, true);
         $scope.feed.clusters.push(cluster);
-        $scope.selectedCluster = cluster;
       };
 
-      $scope.newCluster = function(selected) {
-        return entityFactory.newCluster('target', selected);
+      $scope.newCluster = function(clusterType, selected, clusterName, partition) {
+        return entityFactory.newCluster(clusterType, selected, clusterName, partition);
       };
 
       $scope.handleCluster = function(cluster, index) {
@@ -89,12 +173,27 @@
         $scope.selectedCluster = cluster;
       };
 
-      $scope.removeCluster = function(index) {
-        if(index >= 0 && $scope.feed.clusters.length > 1 &&
-          $scope.feed.clusters[index].type !== 'source' &&
-          !$scope.archiveCluster.active) {
-          $scope.feed.clusters.splice(index, 1);
-          $scope.selectCluster($scope.sourceCluster);
+      function findClusterIndex(atIndex, ofType) {
+        var index = -1;
+        for (var i=0,len=$scope.feed.clusters.length;i<len;i++){
+          var cluster=$scope.feed.clusters[i];
+          if (cluster.type === ofType) {
+            index++;
+            if (index === atIndex) {
+              return i;
+            }
+          }
+        }
+        return -1;
+      };
+
+      $scope.removeCluster = function(clusterIndex, clusterType) {
+        if (clusterIndex >= 0 && $scope.feed.clusters.length > 0
+          && !$scope.archiveCluster.active) {
+          var clusterTypeIndex = findClusterIndex(clusterIndex, clusterType);
+          if (clusterTypeIndex > -1) {
+            $scope.feed.clusters.splice(clusterTypeIndex, 1);
+          }
         }
       };
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/feed/feed-general-information-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/feed/feed-general-information-controller.js b/falcon-ui/app/js/controllers/feed/feed-general-information-controller.js
index 40dbdbc..bb45bbd 100644
--- a/falcon-ui/app/js/controllers/feed/feed-general-information-controller.js
+++ b/falcon-ui/app/js/controllers/feed/feed-general-information-controller.js
@@ -28,8 +28,18 @@
   var feedModule = angular.module('app.controllers.feed');
 
 
-  feedModule.controller('FeedGeneralInformationController', [ "$scope", function ($scope) {
+  feedModule.controller('FeedGeneralInformationController', [ "$scope","clustersList",'EntityFactory',
+    function ($scope, clustersList, entityFactory) {
 
+    $scope.propPlaceholders = {
+      queueName: 'default',
+      jobPriority: '',
+      parallel: 3,
+      maxMaps: 8,
+      mapBandwidthKB: 1024
+    };
+
+    unwrapClusters(clustersList);
     $scope.nameValid = false;
 
     $scope.addTag = function () {
@@ -42,7 +52,120 @@
       }
     };
 
-  }]);
+    function unwrapClusters(clusters) {
+      if(clusters !== undefined && clusters !== null && clusters !== "null"){
+        $scope.clustersList = [];
+        var typeOfData = Object.prototype.toString.call(clusters.entity);
+        if(typeOfData === "[object Array]") {
+          $scope.clustersList = clusters.entity;
+        } else if(typeOfData === "[object Object]") {
+          $scope.clustersList = [clusters.entity];
+        } else {
+          //console.log("type of data not recognized");
+        }
+      }
+    }
+
+    function findClusterExists(clusterList, newClusterName, newClusterType) {
+      var clusterExists = false;
+      clusterList.forEach(function (cluster) {
+        if (cluster.name === newClusterName && cluster.type === newClusterType) {
+          clusterExists = true;
+          return;
+        }
+      });
+      return clusterExists;
+    }
+
+    $scope.onTypeChange = function(value){
+      $scope.feed.clusters = [];
+      if (value === 'hive' || value ==='hdfs') {
+        $scope.feed.sourceClusterLocationType = value;
+        $scope.feed.targetClusterLocationType = value;
+        $scope.feed.clusters.push(
+          entityFactory.newCluster('source', $scope.feed.sourceClusterLocationType, "", null));
+        $scope.feed.clusters.push(
+            entityFactory.newCluster('target', $scope.feed.targetClusterLocationType, "", null));
+      } else if (value === 'import') {
+        $scope.feed.targetClusterLocationType = "hdfs";
+        $scope.feed.clusters.push(
+            entityFactory.newCluster('source', $scope.feed.targetClusterLocationType, "", null))
+      } else if (value === 'export') {
+          $scope.feed.sourceClusterLocationType = "hdfs";
+        $scope.feed.clusters.push(
+          entityFactory.newCluster('source', $scope.feed.sourceClusterLocationType, "", null));
+      }
+    };
 
+    $scope.addClusterStorage = function(clusterDetails){
+      var cluster = entityFactory.newCluster(clusterDetails.type, clusterDetails.dataTransferType, "", null);
+      if($scope.feed.clusters.length > 1
+        && findClusterExists($scope.feed.clusters,cluster.name,cluster.type)){
+        if(cluster.type === 'source'){
+          $scope.sourceClusterExists = true;
+        }else{
+          $scope.targetClusterExists = true;
+        }
+        return;
+      }else{
+          $scope.sourceClusterExists = false;
+          $scope.targetClusterExists = false;
+      }
+      if(cluster.storage.fileSystem) {
+        cluster.storage.fileSystem.locations = [];
+        cluster.storage.fileSystem.locations.push({'type':'data','path':''});
+        cluster.storage.fileSystem.locations.push({'type':'stats','path':'/'});
+      }
+      $scope.feed.clusters.unshift(cluster);
+    };
 
+    $scope.toggleClusterStorage = function(type){
+      if(type === 'source'){
+        $scope.showSourceClusterStorage = !$scope.showSourceClusterStorage;
+      }else if(type === 'target'){
+        $scope.showTargetClusterStorage = !$scope.showTargetClusterStorage;
+      }
+    };
+
+    $scope.$watch("feed.import.source.includesCSV",function(){
+      if($scope.feed.dataTransferType === 'import' && $scope.feed.import.source.includesCSV){
+        $scope.feed.import.source.fields = { 'includes' : $scope.feed.import.source.includesCSV.split(",") };
+      }
+    }, true);
+    $scope.$watch("feed.import.source.excludesCSV",function(){
+      if($scope.feed.dataTransferType === 'import' && $scope.feed.import.source.excludesCSV){
+        $scope.feed.import.source.fields = { 'excludes' : $scope.feed.import.source.excludesCSV.split(",") };
+      }
+    }, true);
+    $scope.$watch("feed.export.target.includesCSV",function(){
+      if($scope.feed.dataTransferType === 'export' && $scope.feed.export.target.includesCSV){
+        $scope.feed.export.target.fields = { 'includes' : $scope.feed.export.target.includesCSV.split(",") };
+      }
+    }, true);
+    $scope.$watch("feed.export.target.excludesCSV",function(){
+      if($scope.feed.dataTransferType === 'export' && $scope.feed.export.target.excludesCSV){
+        $scope.feed.export.target.fields = { 'excludes' : $scope.feed.export.target.excludesCSV.split(",") };
+      }
+    }, true);
+
+    $scope.$watch("feed.sourceClusterLocationType", function(){
+      var sourceClusters = $scope.feed.clusters.filter(function(obj) {
+        return obj.type == 'source';
+      });
+      if(sourceClusters.length < 1){
+        var cluster = entityFactory.newCluster('source', $scope.feed.sourceClusterLocationType, "", null);
+        $scope.feed.clusters.push(cluster)
+      }
+    });
+
+    $scope.$watch("feed.targetClusterLocationType", function(){
+      var targetClusters = $scope.feed.clusters.filter(function(obj) {
+        return obj.type == 'target';
+      });
+      if(targetClusters.length < 1 && $scope.feed.dataTransferType !== 'import'){
+        var cluster = entityFactory.newCluster('target', $scope.feed.targetClusterLocationType, "", null);
+        $scope.feed.clusters.push(cluster)
+      }
+    });
+  }]);
 }());

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 055436d..7030be4 100644
--- a/falcon-ui/app/js/controllers/feed/feed-location-controller.js
+++ b/falcon-ui/app/js/controllers/feed/feed-location-controller.js
@@ -29,22 +29,9 @@
 
   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/76dc2e18/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 9282ea4..4be1360 100644
--- a/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js
+++ b/falcon-ui/app/js/controllers/feed/feed-root-ctrl.js
@@ -28,36 +28,63 @@
   var feedModule = angular.module('app.controllers.feed');
 
   feedModule.controller('FeedController',
-    [ '$scope', '$state', '$timeout',
+    [ '$scope', '$state', '$timeout', "RouteHelper", "DateHelper",
       'Falcon', 'X2jsService',
       'JsonTransformerFactory', 'EntityFactory',
       'EntitySerializer', '$interval',
       '$controller', "ValidationService",
-      "SpinnersFlag", "$rootScope",
-      function($scope, $state, $timeout, Falcon,
+      "SpinnersFlag", "$rootScope", "FeedModel", "datasourcesList",
+      function($scope, $state, $timeout, RouteHelper, DateHelper, Falcon,
                X2jsService, transformerFactory, entityFactory,
                serializer, $interval, $controller,
-               validationService, SpinnersFlag, $rootScope) {
+               validationService, SpinnersFlag, $rootScope, feedModel, datasourcesList) {
 
         $scope.entityType = 'feed';
-
+        var stateMatrix = {
+                general : {previous : '', next : 'summary'},
+                summary : {previous : 'general', next : ''}
+        };
         //extending root controller
         $controller('EntityRootCtrl', {
           $scope: $scope
         });
+        unwrapDatasources(datasourcesList);
 
         $scope.loadOrCreateEntity = function() {
           var type = $scope.entityType;
-          var model = $scope.models[type + 'Model'];
-          $scope.models[type + 'Model'] = null;
-          return model ? serializer.preDeserialize(model, type) : entityFactory.newEntity(type);
+          if(!feedModel && $scope.$parent.models.feedModel){
+            feedModel = $scope.$parent.models.feedModel;
+          }
+          $scope.$parent.models.feedModel = null;
+          if (feedModel) {
+            var feedEntity = serializer.preDeserialize(feedModel, type);
+            // if (feedEntity && feedEntity.clusters) {
+            //   feedEntity.clusters.forEach(function (feedCluster) {
+            //     feedCluster.storage = feedEntity.storage;
+            //   });
+            // }
+            return feedEntity;
+          } else {
+            return entityFactory.newEntity(type)
+          }
         };
 
         $scope.init = function() {
           $scope.baseInit();
           var type = $scope.entityType;
           $scope[type] = $scope.loadOrCreateEntity();
-          $scope.dateFormat ='MM/dd/yyyy';
+          if(feedModel && feedModel.clone === true){
+            $scope.cloningMode = true;
+            $scope.editingMode = false;
+            $scope[type].name = "";
+          }else if(feedModel && feedModel.edit === true){
+            $scope.editingMode = true;
+            $scope.cloningMode = false;
+          }else{
+            $scope.editingMode = false;
+            $scope.cloningMode = false;
+          }
+          $scope.dateFormat = DateHelper.getLocaleDateFormat();
         };
 
         $scope.openDatePicker = function($event, container) {
@@ -68,6 +95,19 @@
 
         $scope.init();
 
+        // $scope.$watch("feed.storage.fileSystem.locations",function(){
+        //   $scope.feed.clusters.forEach(function (feedCluster) {
+        //     feedCluster.storage.fileSystem.locations.forEach(function (location) {
+        //       if (location.type === 'data') {
+        //         var dataLocation = $scope.feed.storage.fileSystem.locations.filter(function(obj) {
+        //           return obj.type == 'data';
+        //         })[0];
+        //         location.path = (dataLocation != undefined) ? dataLocation.path : '';
+        //       }
+        //     });
+        //   });
+        // }, true);
+
         $scope.transform = function() {
           var type = $scope.entityType;
           var xml = serializer.serialize($scope[type], $scope.entityType);
@@ -76,23 +116,28 @@
           return xml;
         };
 
-        $scope.saveEntity = function() {
+        $scope.saveEntity = function(formInvalid) {
           var type = $scope.entityType;
           var cleanedXml = cleanXml($scope.xml);
-          SpinnersFlag.show = true;
+          SpinnersFlag.saveShow = true;
+          if (!validateFeedForm(formInvalid)) {
+            SpinnersFlag.saveShow = false;
+            return;
+          }
 
-          if(!$scope.$parent.cloningMode) {
+          if($scope.editingMode) {
             Falcon.logRequest();
 
             Falcon.postUpdateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + cleanedXml, $scope.entityType, $scope[type].name)
               .success(function (response) {
                 $scope.skipUndo = true;
                 Falcon.logResponse('success', response, false);
+                SpinnersFlag.saveShow = false;
                 $state.go('main');
               })
               .error(function(err) {
                 Falcon.logResponse('error', err, false);
-                SpinnersFlag.show = false;
+                SpinnersFlag.saveShow = false;
                 angular.element('body, html').animate({scrollTop: 0}, 300);
               });
           } else {
@@ -101,21 +146,23 @@
               .success(function (response) {
                 $scope.skipUndo = true;
                 Falcon.logResponse('success', response, false);
+                SpinnersFlag.saveShow = false;
                 $state.go('main');
               })
               .error(function(err) {
                 Falcon.logResponse('error', err, false);
-                SpinnersFlag.show = false;
+                SpinnersFlag.saveShow = false;
                 angular.element('body, html').animate({scrollTop: 0}, 300);
               });
           }
-
-          $scope.editingMode = false;
-          $scope.cloningMode = false;
         };
 
         $scope.isActive = function (route) {
-          return route === $state.$current.name;
+          return route === $state.current.name;
+        };
+
+        $scope.isCompleted = function (route) {
+          return $state.get(route).data && $state.get(route).data.completed;
         };
 
         $scope.parseDate = function(input) {
@@ -141,6 +188,7 @@
           if($scope.editXmlDisabled) {
             try {
               $scope.transform();
+              $scope.feed.storage = $scope.feed.clusters[0].storage;
             } catch (exception) {
               console.log('error when transforming xml');
               console.log(exception);
@@ -148,7 +196,10 @@
           } else {
             try {
               $scope[type] = serializer.deserialize($scope.prettyXml, type);
+              $scope.invalidXml = false;
+              joinIncludesExcludes();
             } catch (exception) {
+              $scope.invalidXml = true;
               console.log('user entered xml incorrect format');
               console.log(exception);
             }
@@ -156,7 +207,38 @@
 
         };
 
-        var xmlPreviewWorker = $interval(xmlPreviewCallback, 1000);
+        var joinIncludesExcludes = function(){
+          if($scope.feed.dataTransferType === 'import'){
+            $scope.dataSourceType = 'source';
+            if($scope.feed.import.source.includesCSV){
+              $scope.feed.import.source.columnsType = 'include';
+            } else if($scope.feed.import.source.excludesCSV){
+              $scope.feed.import.source.columnsType = 'exclude';
+            } else {
+              $scope.feed.import.source.columnsType = 'all';
+            }
+          }
+          if($scope.feed.dataTransferType === 'export'){
+            $scope.dataSourceType = 'target';
+            if($scope.feed.export.target.includesCSV){
+              $scope.feed.export.target.columnsType = 'include';
+            } else if($scope.export.import.target.excludesCSV){
+              $scope.feed.export.target.columnsType = 'exclude';
+            } else {
+              $scope.feed.export.target.columnsType = 'all';
+            }
+          }
+        };
+        $scope.$watch('feed', function(){
+          if($scope.editXmlDisabled) {
+            xmlPreviewCallback();
+          }
+        }, true);
+       $scope.$watch('prettyXml', function(){
+         if(!$scope.editXmlDisabled) {
+           xmlPreviewCallback();
+         }
+        }, true);
         $scope.skipUndo = false;
         $scope.$on('$destroy', function () {
 
@@ -168,38 +250,72 @@
               ACLIsEqual = angular.equals($scope.feed.ACL, defaultFeed.ACL),
               schemaIsEqual = angular.equals($scope.feed.schema, defaultFeed.schema);
 
-          $interval.cancel(xmlPreviewWorker);
-
           if (!$scope.skipUndo && (!nameIsEqual || !groupsIsEqual || !descriptionIsEqual || !ACLIsEqual || !schemaIsEqual)) {
             $scope.$parent.models.feedModel = angular.copy(X2jsService.xml_str2json($scope.xml));
+            if($scope.cloningMode){
+              $scope.$parent.models.feedModel.clone = true;
+            }
+            if($scope.editingMode){
+              $scope.$parent.models.feedModel.edit = true;
+            }
             $scope.$parent.cancel('feed', $rootScope.previousState);
           }
         });
-        $scope.goNext = function (formInvalid, stateName) {
-
-          SpinnersFlag.show = true;
+        function validateFeedForm(formInvalid) {
+          $state.current.data = $state.current.data || {};
+          $state.current.data.completed = !formInvalid;
 
           if (!validationService.nameAvailable || formInvalid) {
             validationService.displayValidations.show = true;
             validationService.displayValidations.nameShow = true;
-            SpinnersFlag.show = false;
-            return;
+            if ($scope.currentState == 'forms.feed.clusters') {
+              $scope.$broadcast('forms.feed.clusters:submit');
+            }
+            return false;
+          }
+
+          // Duplicate Cluster Check
+          if ($scope.feed.clusters) {
+            var clusterNames = $scope.feed.clusters.map(function(item){ return item.name });
+            var isDuplicateClusterExists = clusterNames.some(function(item, index){
+                return clusterNames.indexOf(item) != index
+            });
+            if(isDuplicateClusterExists) {
+              return false;
+            }
           }
           validationService.displayValidations.show = false;
           validationService.displayValidations.nameShow = false;
-
-          $state.go(stateName);
-
-
+          return true;
+        }
+        $scope.goNext = function (formInvalid) {
+          SpinnersFlag.show = true;
+          if (validateFeedForm(formInvalid)) {
+            SpinnersFlag.show = false;
+            $state.go(RouteHelper.getNextState($state.current.name, stateMatrix));
+          }
+          SpinnersFlag.show = false;
         };
-        $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));
         };
 
-
+        function unwrapDatasources(datasources) {
+		if(datasources !== undefined && datasources !== null && datasources !== "null"){
+			$scope.datasourceList = [];
+            var typeOfData = Object.prototype.toString.call(datasources.entity);
+            if(typeOfData === "[object Array]") {
+              $scope.datasourceList = datasources.entity;
+            } else if(typeOfData === "[object Object]") {
+              $scope.datasourceList = [datasources.entity];
+            } else {
+              //console.log("type of data not recognized");
+            }
+		}
+        }
 
         function cleanXml (xml) {
 
@@ -208,11 +324,13 @@
               feedLocationsArray = [];
 
           // cluster locations
-          obj.feed.clusters.cluster[0].locations.location.forEach(function (item) {
-            if (item._path) {
-              clusterLocationsArray.push(item);
-            }
-          });
+          if(obj.feed.clusters.cluster[0].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;
@@ -221,11 +339,13 @@
           }
 
           // feed locations
-          obj.feed.locations.location.forEach(function (item) {
-            if (item._path) {
-              feedLocationsArray.push(item);
-            }
-          });
+          if(obj.feed.locations){
+            obj.feed.locations.location.forEach(function (item) {
+              if (item._path) {
+                feedLocationsArray.push(item);
+              }
+            });
+          }
 
           if (feedLocationsArray.length === 0) {
             delete obj.feed.locations;
@@ -234,7 +354,8 @@
           }
 
           //feed properties
-          if (obj.feed.properties.property.length === 1 && obj.feed.properties.property[0] === "") {
+          if (obj.feed.properties && obj.feed.properties.property.length === 1
+              && obj.feed.properties.property[0] === "") {
             delete obj.feed.properties;
           }
 
@@ -242,6 +363,21 @@
 
         }
 
+         $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 ) : '';
+          };
+
+          $scope.emptyClusterName = function (cluster) {
+            return !(cluster.name === null || cluster.name.trim().length === 0);
+          };
+
+          if($state.current.name !== "forms.feed.general"){
+            $state.go("forms.feed.general");
+          }
       }]);
 
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 249b8da..1eb6c90 100644
--- a/falcon-ui/app/js/controllers/feed/feed-summary-controller.js
+++ b/falcon-ui/app/js/controllers/feed/feed-summary-controller.js
@@ -27,12 +27,8 @@
    */
   var feedModule = angular.module('app.controllers.feed');
 
-  feedModule.controller('FeedSummaryController', [ "$scope", "$filter", "$timeout",
-                                                function($scope, $filter, $timeout) {
-
-    $timeout(function () {
-      angular.element('.nextBtn').trigger('focus');
-    }, 500);
+  feedModule.controller('FeedSummaryController', [ "$scope", "$filter", "$timeout", "DateHelper",
+                                                function($scope, $filter, $timeout, DateHelper) {
 
     if($scope.transform) {
       $scope.transform();
@@ -47,6 +43,10 @@
       return input ? (output || input) : 'Not specified';
     };
 
+    $scope.getDateTimeString = function (date,time) {
+      return DateHelper.getDateTimeString(date,time);
+    };
+
   }]);
 
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 b2dcaea..a0a0a20 100644
--- a/falcon-ui/app/js/controllers/header-controller.js
+++ b/falcon-ui/app/js/controllers/header-controller.js
@@ -41,36 +41,67 @@
       };
 
       $scope.resetCluster = function () {
+        $scope.clearTags();
         validationService.displayValidations = {show: false, nameShow: false};
         angular.copy(EntityModel.defaultValues.cluster, EntityModel.clusterModel);
-        $state.go("forms.cluster.general");
+        $state.go("forms.cluster");
       };
 
       $scope.resetProcess = function () {
+        $scope.clearTags();
         validationService.displayValidations = {show: false, nameShow: false};
         $scope.cloningMode = true;
         $scope.models.processModel = null;
-        $state.go("forms.process.general");
+        $state.go("forms.process");
       };
 
       $scope.resetFeed = function () {
+        $scope.clearTags();
         validationService.displayValidations = {show: false, nameShow: false};
         $scope.cloningMode = true;
         $scope.models.feedModel = null;
-        $state.go("forms.feed.general");
+        $state.go("forms.feed");
       };
 
-      $scope.resetDataset = function () {
+      $scope.resetDataset = function (mirrorType) {
+        $scope.clearTags();
         validationService.displayValidations = {show: false, nameShow: false};
         EntityModel.datasetModel.toImportModel = undefined;
         angular.copy(EntityModel.defaultValues.MirrorUIModel, EntityModel.datasetModel.UIModel);
+        EntityModel.datasetModel.UIModel.type = mirrorType;
         $scope.cloningMode = true;
-        $scope.models.feedModel = null;
-        $state.go("forms.dataset.general");
+        if($rootScope.currentState === 'forms.dataset.general') {
+          $state.reload("forms.dataset");
+        } else if($rootScope.currentState === 'forms.dataset.summary') {
+          EntityModel.datasetModel.UIModel.ACL.owner = $cookieStore.get('userToken').user;
+          $state.go("forms.dataset.general");
+        } else {
+          $state.go("forms.dataset");
+        }
+      };
+
+      $scope.resetSnapshot = function () {
+        $scope.clearTags();
+        validationService.displayValidations = {show: false, nameShow: false};
+        $scope.cloningMode = true;
+        $scope.models.snapshotModel = null;
+        $state.go("forms.snapshot");
+      };
+
+      $scope.isMirror = function(mirrorType) {
+        return EntityModel.datasetModel.UIModel && EntityModel.datasetModel.UIModel.type === mirrorType;
+      };
+
+      $scope.resetDatasource = function () {
+        $scope.clearTags();
+        validationService.displayValidations = {show: false, nameShow: false};
+        $scope.cloningMode = true;
+        $scope.models.dataSource = null;
+        $state.go("forms.datasource");
       };
 
       $scope.userLogged = function () {
-        if($rootScope.isSecureMode()){
+        if($rootScope.isSecureMode() || $rootScope.ambariView()){
           return true;
         }else if($rootScope.userLogged()){
 		if(angular.isDefined($cookieStore.get('userToken')) && $cookieStore.get('userToken') !== null){
@@ -94,7 +125,7 @@
       };
 
       $scope.restore = function(state) {
-        $state.go(state);
+        $state.go(state, {name : null, action : null});
       };
 
       $scope.notify = function() {

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/falcon-ui/app/js/controllers/process/process-advanced-ctrl.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/process/process-advanced-ctrl.js b/falcon-ui/app/js/controllers/process/process-advanced-ctrl.js
new file mode 100644
index 0000000..a5c871b
--- /dev/null
+++ b/falcon-ui/app/js/controllers/process/process-advanced-ctrl.js
@@ -0,0 +1,34 @@
+/**
+ * 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.process.ProcessAdvancedCtrl
+   * @requires EntityModel the entity model to copy the process entity from
+   * @requires Falcon the falcon entity service
+   */
+  var processModule = angular.module('app.controllers.process');
+
+  processModule.controller('ProcessAdvancedCtrl', ['$scope', 'EntityFactory', '$timeout', 'DateHelper',
+                                              function($scope, entityFactory, $timeout, DateHelper) {
+
+  }]);
+
+})();

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 5605268..4f93dc8 100644
--- a/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js
+++ b/falcon-ui/app/js/controllers/process/process-clusters-ctrl.js
@@ -27,15 +27,15 @@
    */
   var feedModule = angular.module('app.controllers.process');
 
-  feedModule.controller('ProcessClustersCtrl', ['$scope', 'clustersList', 'EntityFactory', '$timeout',
-                                              function($scope, clustersList, entityFactory, $timeout) {
+  feedModule.controller('ProcessClustersCtrl', ['$scope', 'clustersList', 'EntityFactory', '$timeout', 'DateHelper',
+                                              function($scope, clustersList, entityFactory, $timeout, DateHelper) {
 
     $timeout(function () {
       angular.element('.firstSelectClusterStep').trigger('focus');
     }, 500);
 
     $scope.init = function() {
-      $scope.dateFormat = 'MM/dd/yyyy';
+      $scope.dateFormat = DateHelper.getLocaleDateFormat();
     };
 
     $scope.openDatePicker = function($event, container) {

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 bda465d..9ded878 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
@@ -27,18 +27,46 @@
    */
   var feedModule = angular.module('app.controllers.process');
 
-  feedModule.controller('ProcessGeneralInformationCtrl', [ '$scope', function($scope) {
-    var availableVerions = {
-      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']
-    };
+  feedModule.controller('ProcessGeneralInformationCtrl', [
+    '$scope', 'clustersList', 'feedsList', 'EntityFactory', 'Falcon', 'X2jsService','DateHelper',
+    function($scope, clustersList, feedsList, entityFactory, Falcon, X2jsService, DateHelper) {
+
     $scope.nameValid = false;
-    
+
+    $scope.$watch('process.workflow.spark.jar',function(){
+      if($scope.process.workflow.spark.jar && $scope.process.workflow.spark.jar.endsWith('.py')){
+        $scope.isPython = true;
+      }else{
+        $scope.isPython = false;
+      }
+    },true);
+
     $scope.init = function() {
-      $scope.versions = [];
+      unwrapClusters(clustersList);
+      unwrapFeeds(feedsList);
+      $scope.dateFormat = DateHelper.getLocaleDateFormat();
+    };
+
+    $scope.openDatePicker = function($event, container) {
+      $event.preventDefault();
+      $event.stopPropagation();
+      container.opened = true;
+    };
+
+    $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";
+          }
+        }
+      }
     };
 
+    // TAGS
     $scope.addTag = function() {
       $scope.process.tags.push({key: null, value: null});
     };
@@ -49,16 +77,101 @@
       }
     };
 
-    $scope.selectWorkflow = function() {
-      if($scope.process.workflow) {        
-        var engine = $scope.process.workflow.engine;
-        $scope.process.workflow.version = "";
-        $scope.versions = availableVerions[engine];
+    // inputs
+    $scope.addInput = function () {
+      $scope.process.inputs.push(entityFactory.newInput());
+    };
+
+    $scope.removeInput = function (index) {
+      if (index >= 0) {
+        $scope.process.inputs.splice(index, 1);
+      }
+    };
+
+    // OUTPUTS
+    $scope.addOutput = function () {
+      $scope.process.outputs.push(entityFactory.newOutput());
+    };
+
+    $scope.removeOutput = function (index) {
+      if (index >= 0) {
+        $scope.process.outputs.splice(index, 1);
       }
     };
 
     $scope.init();
-    $scope.selectWorkflow();
+
+    $scope.getSourceDefinition = function (clusterName) {
+      Falcon.getEntityDefinition("cluster", clusterName)
+        .success(function (data) {
+          $scope.sourceClusterModel = X2jsService.xml_str2json(data);
+          var sparkInterface = $scope.sourceClusterModel.cluster.interfaces.interface.filter(
+            function(clusterInterface) { return clusterInterface._type === 'spark'; }
+          )[0];
+          if (sparkInterface) {
+            var sparkEndpoint = sparkInterface._endpoint.trim();
+            if (sparkEndpoint.indexOf('yarn') != '-1') {
+              $scope.process.workflow.spark.master = 'yarn';
+              $scope.process.workflow.spark.mode = sparkEndpoint.substring(5);
+            } else if (sparkEndpoint === 'local') {
+              $scope.process.workflow.spark.master = 'local';
+            }
+          }
+        })
+        .error(function (err) {
+          Falcon.logResponse('error', err, false, true);
+        });
+    };
+
+    //-----------PROPERTIES----------------//
+    $scope.addProperty = function () {
+      var lastOne = $scope.process.properties.length - 1;
+      if($scope.process.properties[lastOne].name && $scope.process.properties[lastOne].value) {
+        $scope.process.properties.push(entityFactory.newProperty("", ""));
+      }
+    };
+
+    $scope.removeProperty = function(index) {
+      if(index !== null && $scope.process.properties[index]) {
+        $scope.process.properties.splice(index, 1);
+      }
+    };
+
+    $scope.policyChange = function(){
+      if($scope.process.retry.policy === 'final'){
+       $scope.process.retry.delay.quantity = '0';
+       $scope.process.retry.delay.unit = 'minutes';
+       $scope.process.retry.attempts = '0';
+      }else{
+        $scope.process.retry.delay.quantity = '30';
+        $scope.process.retry.delay.unit = 'minutes';
+        $scope.process.retry.attempts = '3';
+      }
+    }
+
+    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");
+      }
+    }
+
+    function unwrapFeeds(feeds) {
+      $scope.feedsList = [];
+      var typeOfData = Object.prototype.toString.call(feeds.entity);
+      if (typeOfData === "[object Array]") {
+        $scope.feedsList = feeds.entity;
+      } else if (typeOfData === "[object Object]") {
+        $scope.feedsList = [feeds.entity];
+      } else {
+        //console.log("type of data not recognized");
+      }
+    }
 
   }]);
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 7d461ba..f527383 100644
--- a/falcon-ui/app/js/controllers/process/process-root-ctrl.js
+++ b/falcon-ui/app/js/controllers/process/process-root-ctrl.js
@@ -28,13 +28,18 @@
   var processModule = angular.module('app.controllers.process');
 
   processModule.controller('ProcessRootCtrl', [
-    '$scope', '$state', '$interval', '$controller', 'EntityFactory',
-    'EntitySerializer', 'X2jsService', 'ValidationService', 'SpinnersFlag', '$rootScope',
-    function ($scope, $state, $interval, $controller, entityFactory,
-              serializer, X2jsService, validationService, SpinnersFlag, $rootScope) {
+    '$scope', '$state', '$interval', '$controller', 'EntityFactory', 'RouteHelper',
+    'EntitySerializer', 'X2jsService', 'ValidationService', 'SpinnersFlag', '$rootScope', 'ProcessModel', 'Falcon',
+    function ($scope, $state, $interval, $controller, entityFactory, RouteHelper,
+              serializer, X2jsService, validationService, SpinnersFlag, $rootScope, processModel, Falcon) {
 
       $scope.entityType = 'process';
 
+      var stateMatrix = {
+              general : {previous : '', next : 'summary'},
+              summary : {previous : 'general', next : ''}
+      };
+
         //extending root controller
       $controller('EntityRootCtrl', {
         $scope: $scope
@@ -44,20 +49,34 @@
         $scope.baseInit();
         var type = $scope.entityType;
         $scope[type] = $scope.loadOrCreateEntity();
+        if(processModel && processModel.clone === true){
+          $scope.cloningMode = true;
+          $scope.editingMode = false;
+          $scope[type].name = "";
+        }else if(processModel && processModel.edit === true){
+          $scope.editingMode = true;
+          $scope.cloningMode = false;
+        }else{
+          $scope.editingMode = false;
+          $scope.cloningMode = false;
+        }
       };
 
       $scope.isActive = function (route) {
-        return route === $state.$current.name;
+        return route === $state.current.name;
+      };
+
+      $scope.isCompleted = function (route) {
+        return $state.get(route).data && $state.get(route).data.completed;
       };
 
       $scope.loadOrCreateEntity = function() {
         var type = $scope.entityType;
-        var model = $scope.models[type + 'Model'];
-        $scope.models[type + 'Model'] = null;
-        if(model) {
-          return serializer.preDeserialize(model, type);
+        if(!processModel && $scope.$parent.models.processModel){
+          processModel = $scope.$parent.models.processModel;
         }
-        return entityFactory.newEntity(type);
+        $scope.$parent.models.processModel = null;
+        return processModel ? serializer.preDeserialize(processModel, type) : entityFactory.newEntity(type);
       };
 
       $scope.init();
@@ -82,7 +101,9 @@
         } else {
           try {
             $scope[type] = serializer.deserialize($scope.prettyXml, type);
+            $scope.invalidXml = false;
           } catch (exception) {
+            $scope.invalidXml = true;
             console.log('user entered xml incorrect format');
             console.log(exception);
           }
@@ -90,7 +111,17 @@
 
       };
 
-      var xmlPreviewWorker = $interval(xmlPreviewCallback, 1000);
+      $scope.$watch('process', function(){
+        if($scope.editXmlDisabled) {
+          xmlPreviewCallback();
+        }
+      }, true);
+     $scope.$watch('prettyXml', function(){
+       if(!$scope.editXmlDisabled) {
+         xmlPreviewCallback();
+       }
+      }, true);
+
       $scope.skipUndo = false;
       $scope.$on('$destroy', function() {
 
@@ -100,16 +131,22 @@
           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));
+          if($scope.cloningMode){
+            $scope.$parent.models.processModel.clone = true;
+          }
+          if($scope.editingMode){
+            $scope.$parent.models.processModel.edit = true;
+          }
           $scope.$parent.cancel('process', $rootScope.previousState);
         }
       });
 
       //---------------------------------//
-      $scope.goNext = function (formInvalid, stateName) {
+      $scope.goNext = function (formInvalid) {
+        $state.current.data = $state.current.data || {};
+        $state.current.data.completed = !formInvalid;
         SpinnersFlag.show = true;
         if (!validationService.nameAvailable || formInvalid) {
           validationService.displayValidations.show = true;
@@ -119,20 +156,69 @@
         }
         validationService.displayValidations.show = false;
         validationService.displayValidations.nameShow = false;
-        $state.go(stateName);
+        $state.go(RouteHelper.getNextState($state.current.name, stateMatrix));
       };
 
-      $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));
       };
 
       $scope.goTest = function (formInvalid) {
         console.log(formInvalid);
       };
 
+      $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 ) : '';
+      };
+
+      $scope.saveEntity = function() {
+        var type = $scope.entityType;
+        SpinnersFlag.saveShow = true;
+
+        if($scope.editingMode) {
+          Falcon.logRequest();
+          Falcon.postUpdateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'  + $scope.xml, $scope.entityType, $scope[type].name)
+            .success(function (response) {
+               $scope.skipUndo = true;
+               Falcon.logResponse('success', response, false);
+               SpinnersFlag.saveShow = false;
+               $state.go('main');
+
+            })
+            .error(function (err) {
+              Falcon.logResponse('error', err, false);
+              SpinnersFlag.saveShow = false;
+              angular.element('body, html').animate({scrollTop: 0}, 300);
+            });
+        }
+        else {
+          Falcon.logRequest();
+          Falcon.postSubmitEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + $scope.xml, $scope.entityType)
+            .success(function (response) {
+               $scope.skipUndo = true;
+               Falcon.logResponse('success', response, false);
+               SpinnersFlag.saveShow = false;
+               $state.go('main');
+
+            })
+            .error(function (err) {
+              Falcon.logResponse('error', err, false);
+              SpinnersFlag.saveShow = false;
+              angular.element('body, html').animate({scrollTop: 0}, 300);
+            });
+        }
+      };
+
+      if($state.current.name !== "forms.process.general"){
+        $state.go("forms.process.general");
+      }
     }
   ]);
 

http://git-wip-us.apache.org/repos/asf/falcon/blob/76dc2e18/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 494c249..b68b055 100644
--- a/falcon-ui/app/js/controllers/process/process-summary-ctrl.js
+++ b/falcon-ui/app/js/controllers/process/process-summary-ctrl.js
@@ -49,45 +49,6 @@
       return input ? (output || input) : 'Not specified';
     };
 
-    $scope.saveEntity = function() {
-      var type = $scope.entityType;
-      SpinnersFlag.show = true;
-
-      if(!$scope.$parent.cloningMode) {
-        Falcon.logRequest();
-        Falcon.postUpdateEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'  + $scope.xml, $scope.entityType, $scope[type].name)
-          .success(function (response) {
-             $scope.$parent.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.logRequest();
-        Falcon.postSubmitEntity('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + $scope.xml, $scope.entityType)
-          .success(function (response) {
-             $scope.$parent.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);
-          });
-      }
-
-      $scope.editingMode = false;
-      $scope.cloningMode = false;
-    };
-
     $scope.init();
 
   }]);