You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by so...@apache.org on 2015/10/13 02:04:03 UTC

[10/22] falcon git commit: FALCON-1315 Update falcon ui for HiveDR, secure clusters and bug fixes. Contributed by Armando Reyna/Venkat Ranganathan.

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/html/process/processFormTpl.html
----------------------------------------------------------------------
diff --git a/falcon-ui/app/html/process/processFormTpl.html b/falcon-ui/app/html/process/processFormTpl.html
index 7bf423e..00d2c66 100644
--- a/falcon-ui/app/html/process/processFormTpl.html
+++ b/falcon-ui/app/html/process/processFormTpl.html
@@ -17,79 +17,90 @@
  * limitations under the License.
  */
 -->
-<div class="col-sm-24 entityForm">
-  <div class="col-sm-22 col-sm-offset-2">
+<div class="col-xs-22 col-xs-offset-1 entityForm" id="processFormTmpl">
+  <div class="col-xs-24">
     <div class="row">
-      <h3 id="formTitle" class="col-sm-24">
-        New Process
+
+      <h3 id="formTitle" class="col-xs-24">
+        <span class="entypo cycle icon-lg"></span> New Process
       </h3>
-      <div class="col-sm-15 detailsBox">
 
-        <div class="processProgressBox" ng-class="{
-          general:isActive('forms.process.general'),
-          properties:isActive('forms.process.properties'),
-          clusters:isActive('forms.process.clusters'),
-          inputsAndOutputs: isActive('forms.process.io'),
-          summary:isActive('forms.process.summary')
-          }">
-          <div class="progressBar col-md-24">
-            <div>
-              <span>
-                <div class="fir">1<span class="entypo check"></span></div>
-                <h6>General</h6>
-              </span>
-              <span>
-                <div class="sec">2<span class="entypo check"></span></div>
-                <h6>Properties</h6>
-              </span>
-              <span>
-                <div class="thi">3<span class="entypo check"></span></div>
-                <h6>Clusters</h6>
-              </span>
-              <span>
-                <div class="fou">4<span class="entypo check"></span></div>
-                <h6>Inputs & Outputs</h6>
-              </span>
-              <span>
-                <div class="fif">5<span class="entypo check"></span></div>
-                <h6>Summary</h6>
-              </span>
+      <div ng-class="{'col-xs-12' : propsOpen, 'col-xs-20' : !propsOpen}">
+        <div class="detailsBox">
+          <div class="processProgressBox" ng-class="{
+            general:isActive('forms.process.general'),
+            properties:isActive('forms.process.properties'),
+            clusters:isActive('forms.process.clusters'),
+            inputsAndOutputs: isActive('forms.process.io'),
+            summary:isActive('forms.process.summary')
+            }">
+            <div class="progressBar col-xs-24">
+              <div>
+                <span>
+                  <div class="fir">1<span class="entypo check"></span></div>
+                  <h6>General</h6>
+                </span>
+                <span>
+                  <div class="sec">2<span class="entypo check"></span></div>
+                  <h6>Properties</h6>
+                </span>
+                <span>
+                  <div class="thi">3<span class="entypo check"></span></div>
+                  <h6>Clusters</h6>
+                </span>
+                <span>
+                  <div class="fou">4<span class="entypo check"></span></div>
+                  <h6>Inputs & Outputs</h6>
+                </span>
+                <span>
+                  <div class="fif">5<span class="entypo check"></span></div>
+                  <h6>Summary</h6>
+                </span>
+              </div>
             </div>
           </div>
-        </div>
-       
-        <div class="row">
-          <div class="col-sm-offset-1 col-sm-22">
-            <fieldset id="fieldWrapper" ng-disabled="!editXmlDisabled">
-              <div ui-view class="formViewContainer"></div>
-            </fieldset>
+
+          <div class="row">
+            <div class="col-xs-offset-1 col-xs-22">
+              <fieldset id="fieldWrapper" ng-disabled="!editXmlDisabled">
+                <div ui-view class="formViewContainer"></div>
+              </fieldset>
+            </div>
           </div>
         </div>
-        
       </div>
 
-      <div class="col-sm-8 detailsBox col-sm-offset-1">
-        <div class="row">
+      <div ng-class="{'col-xs-12' : propsOpen, 'col-xs-4' : !propsOpen}">
+        <div class="detailsBox">
+          <div class="row">
 
-          <h5 class="col-xs-13 col-xs-offset-1 noSpecial">XML Preview</h5>  
-          <div class="col-xs-9">
-            <div id="editXmlButton" class="btn btn-default btn-xs pull-right" ng-click="toggleEditXml()" ng-class="{'btn-warning':!editXmlDisabled}">
-              Edit XML
+            <div class="col-xs-13 col-xs-offset-1 noSpecial">
+              <h5><i class="pointer glyphicon" ng-click="propsOpen = !propsOpen" ng-class="propsOpen ? 'glyphicon-minus-sign':'glyphicon-plus-sign'"></i> XML Preview</h5>
+            </div>
+
+            <div ng-if="propsOpen" class="col-xs-9">
+              <button type="button"
+                      id="editXmlButton"
+                      class="btn btn-default btn-xs pull-right"
+                      ng-click="toggleEditXml()"
+                      ng-class="{'btn-warning':!editXmlDisabled}">
+                <div ng-if="editXmlDisabled">Edit XML</div>
+                <div ng-if="!editXmlDisabled">Finish</div>
+              </button>
             </div>
-          </div>
 
-          <div class="col-sm-24">
-            <div class="row">
-              <div class="col-sm-22 col-sm-offset-1">
-                <textarea ng-model="prettyXml" rows="35" class="form-control" ng-disabled="editXmlDisabled">
-                </textarea>
+            <div ng-show="propsOpen" class="col-xs-24">
+              <div class="row">
+                <div class="col-xs-22 col-xs-offset-1" >
+                  <textarea ng-model="prettyXml" class="form-control prettyXml" elastic ng-disabled="editXmlDisabled"></textarea>
+                </div>
               </div>
             </div>
+
           </div>
-          
         </div>
       </div>
-      
+
     </div>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/html/process/processSummary.html
----------------------------------------------------------------------
diff --git a/falcon-ui/app/html/process/processSummary.html b/falcon-ui/app/html/process/processSummary.html
new file mode 100644
index 0000000..e9eb4a4
--- /dev/null
+++ b/falcon-ui/app/html/process/processSummary.html
@@ -0,0 +1,184 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<div class="summaryBox" id="processFormSummary">
+  <div class="row">
+    <h5 class="col-sm-24">{{entityTypeLabel}}</h5>
+
+    <label class="col-sm-24">Name</label>
+    <label class="col-sm-24 light">{{process.name}}</label>
+
+    <label class="col-sm-24">Tags</label>
+
+    <div class="col-sm-24">
+      <div ng-repeat="tag in process.tags | filter:{key: '!!'}">
+        {{tag.key}} = {{tag.value}}
+      </div>
+      <div ng-show="!hasTags()">No tags selected</div>
+    </div>
+
+    <h5 class="col-sm-24">Access Control List</h5>
+
+    <div class="row">
+      <div class="col-sm-8">
+        <label class="col-sm-24">Owner</label>
+        <label class="col-sm-24 light">{{process.ACL.owner}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Group</label>
+        <label class="col-sm-24 light">{{process.ACL.group}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Permissions</label>
+        <label class="col-sm-24 light">{{process.ACL.permission}}</label>
+      </div>
+    </div>
+
+    <h5 class="col-sm-24">Workflow</h5>
+
+    <div class="row">
+      <div class="col-sm-8">
+        <label class="col-sm-24">Name</label>
+        <label class="col-sm-24 light">{{process.workflow.name}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Engine</label>
+        <label class="col-sm-24 light">{{process.workflow.engine}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Version</label>
+        <label class="col-sm-24 light">{{process.workflow.version}}</label>
+      </div>
+    </div>
+    <label class="col-sm-24">Path</label>
+    <label class="col-sm-24 light">{{process.workflow.path}}</label>
+
+
+    <h5 class="col-sm-24">Timing</h5>
+    <label class="col-sm-24" ng-if="process.timezone">Timezone</label>
+    <label class="col-sm-24 light">{{process.timezone}}</label>
+
+    <div class="row">
+      <div class="col-sm-8">
+        <label class="col-sm-24">Frequency</label>
+        <label class="col-sm-24 light">Every {{process.frequency.quantity}} {{process.frequency.unit}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Max. parallel instances</label>
+        <label class="col-sm-24 light">{{process.parallel}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Order</label>
+        <label class="col-sm-24 light">{{process.order}}</label>
+      </div>
+    </div>
+
+    <h5 class="col-sm-24">Retry</h5>
+
+    <div class="row">
+      <div class="col-sm-8">
+        <label class="col-sm-24">Policy</label>
+        <label class="col-sm-24 light">{{process.retry.policy}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Attempts</label>
+        <label class="col-sm-24 light">{{process.retry.attempts}}</label>
+      </div>
+      <div class="col-sm-8">
+        <label class="col-sm-24">Delay</label>
+        <label class="col-sm-24 light">Up to {{process.retry.delay.quantity}} {{process.retry.delay.unit}}</label>
+      </div>
+    </div>
+
+
+  </div>
+</div>
+
+<div class="summaryBox">
+  <div class="row">
+    <h5 class="col-sm-24">Clusters</h5>
+
+    <div ng-repeat="cluster in process.clusters">
+      <div class="row col-sm-offset-1 col-sm-22 detailsBox">
+        <label class="col-sm-24">Name</label>
+        <label class="col-sm-24 light">{{cluster.name}}</label>
+
+        <h5 class="col-sm-24">Validity</h5>
+
+        <div class="row">
+          <div class="col-sm-12">
+            <label class="col-sm-24">Start</label>
+            <label class="col-sm-24 light">{{dateFormatter(entity.start)}} Z</label>
+          </div>
+          <div class="col-sm-12">
+            <label class="col-sm-24">End</label>
+            <label class="col-sm-24 light">{{dateFormatter(entity.end)}} Z</label>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<div class="summaryBox">
+  <div class="row">
+    <h5 class="col-sm-24">Inputs</h5>
+
+    <div ng-repeat="input in process.inputs">
+      <div class="row col-sm-offset-1 col-sm-22 detailsBox">
+        <label class="col-sm-24">Name</label>
+        <label class="col-sm-24 light">{{input.name}}</label>
+        <label class="col-sm-24">Feed</label>
+        <label class="col-sm-24 light">{{input.feed}}</label>
+
+        <h5 class="col-sm-24">Instance</h5>
+
+        <div class="row">
+          <div class="col-sm-12">
+            <label class="col-sm-24">Start</label>
+            <label class="col-sm-24 light">{{input.start}}</label>
+          </div>
+          <div class="col-sm-12">
+            <label class="col-sm-24">End</label>
+            <label class="col-sm-24 light">{{input.end}}</label>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<div class="summaryBox">
+  <div class="row">
+    <h5 class="col-sm-24">Outputs</h5>
+
+    <div ng-repeat="output in process.outputs">
+      <div class="row col-sm-offset-1 col-sm-22 detailsBox">
+        <label class="col-sm-24">Name</label>
+        <label class="col-sm-24 light">{{output.name}}</label>
+        <label class="col-sm-24">Feed</label>
+        <label class="col-sm-24 light">{{output.feed}}</label>
+
+        <h5 class="col-sm-24">Instance</h5>
+        <label class="col-sm-24">Instance</label>
+        <label class="col-sm-24 light">{{output.outputInstance}}</label>
+      </div>
+    </div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/index.html
----------------------------------------------------------------------
diff --git a/falcon-ui/app/index.html b/falcon-ui/app/index.html
index 2552194..13fbe35 100644
--- a/falcon-ui/app/index.html
+++ b/falcon-ui/app/index.html
@@ -27,19 +27,18 @@
     <link rel="icon" type="image/x-icon"
       href="data:image/png;base64,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"/>
   </head>
-  <body ng-cloak ng-controller="RootCtrl">  
-  
-  <section class="container-fluid">
-    <header class="row" nav-header></header>
-    <server-messages></server-messages>
-  </section>
-  
-  <section class="container-fluid">
-    <div class="row mainUIView" ui-view></div>
-  </section>
-  
-  <script src="js/vendor.min.js"></script>
-  <script src="js/main.min.js"></script>
-  
+  <body ng-cloak ng-controller="RootCtrl" id="body">
+
+    <section class="container-fluid">
+      <header class="row" nav-header id="mainHeader"></header>
+    </section>
+
+    <section class="container-fluid">
+      <div class="row mainUIView" ui-view id="mainUIView"></div>
+    </section>
+
+    <script src="js/vendor.min.js"></script>
+    <script src="js/main.min.js"></script>
+
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/app.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/app.js b/falcon-ui/app/js/app.js
index 1705cb4..5ae7eb6 100644
--- a/falcon-ui/app/js/app.js
+++ b/falcon-ui/app/js/app.js
@@ -19,15 +19,25 @@
   'use strict';
 
   var app = angular.module('app', [
-    'ui.bootstrap', 'ui.router', 'ngCookies', 'ngAnimate', 'ngMessages', 'checklist-model', 'app.controllers', 'app.directives', 'app.services'
+    'ui.bootstrap',
+    'ui.router',
+    'ngCookies',
+    'ngAnimate',
+    'ngMessages',
+    'checklist-model',
+    'app.controllers',
+    'app.directives',
+    'app.services',
+    'ngTagsInput',
+    'nsPopover', 'ngAnimate', 'ngMask', 'dateHelper'
   ]);
 
   app.config(["$stateProvider", "$urlRouterProvider", "$httpProvider", function ($stateProvider, $urlRouterProvider, $httpProvider) {
-  	
-  	$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
-  	
-  	$httpProvider.defaults.headers.common["X-Requested-By"] = 'X-Requested-By';
-  	
+
+    $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
+
+    $httpProvider.defaults.headers.common["X-Requested-By"] = 'X-Requested-By';
+
     $urlRouterProvider.otherwise("/");
 
     $stateProvider
@@ -36,9 +46,16 @@
         templateUrl: 'html/mainTpl.html',
         controller: 'DashboardCtrl'
       })
-      .state('entityDetails', {
-        controller: 'EntityDetailsCtrl',
-        templateUrl: 'html/entityDetailsTpl.html'
+      .state('authenticating', {
+        templateUrl: 'html/authenticating.html'
+      })
+      .state('login', {
+        controller: 'LoginFormCtrl',
+        templateUrl: 'html/login.html'
+      })
+      .state('entityDefinition', {
+        controller: 'EntityDefinitionCtrl',
+        templateUrl: 'html/entityDefinitionTpl.html'
       })
       .state('forms', {
         templateUrl: 'html/formsTpl.html'
@@ -73,9 +90,9 @@
         templateUrl: 'html/feed/feedFormClustersStepTpl.html',
         controller: 'FeedClustersController',
         resolve: {
-          clustersList: ['Falcon', function(Falcon) {
+          clustersList: ['Falcon', function (Falcon) {
             return Falcon.getEntities('cluster').then(
-              function(response) {
+              function (response) {
                 return response.data;
               });
           }]
@@ -101,9 +118,9 @@
         templateUrl: 'html/process/processFormClustersStepTpl.html',
         controller: 'ProcessClustersCtrl',
         resolve: {
-          clustersList: ['Falcon', function(Falcon) {
+          clustersList: ['Falcon', function (Falcon) {
             return Falcon.getEntities('cluster').then(
-              function(response) {
+              function (response) {
                 return response.data;
               });
           }]
@@ -113,9 +130,9 @@
         templateUrl: 'html/process/processFormInputsAndOutputsStepTpl.html',
         controller: 'ProcessInputsAndOutputsCtrl',
         resolve: {
-          feedsList: ['Falcon', function(Falcon) {
+          feedsList: ['Falcon', function (Falcon) {
             return Falcon.getEntities('feed').then(
-              function(response) {
+              function (response) {
                 return response.data;
               });
           }]
@@ -124,18 +141,201 @@
       .state('forms.process.summary', {
         templateUrl: 'html/process/processFormSummaryStepTpl.html',
         controller: 'ProcessSummaryCtrl'
-      });
-    
+      })
+      .state('entityDetails', {
+        views: {
+          '': {
+            controller: 'EntityDetailsCtrl',
+            templateUrl: 'html/entityDetailsTpl.html'
+          },
+          'feedSummary@entityDetails': {
+            templateUrl: 'html/feed/feedSummary.html'
+          },
+          'processSummary@entityDetails': {
+            templateUrl: 'html/process/processSummary.html'
+          }
+        }
+      })
+      .state('forms.dataset', {
+        controller: 'DatasetCtrl',
+        templateUrl: 'html/dataset/datasetFormTpl.html',
+        resolve: {
+          clustersList: ['Falcon', function (Falcon) {
+            return Falcon.getEntities('cluster').then(
+              function (response) {
+                return response.data.entity;
+              });
+          }]
+        }
+      })
+      .state('forms.dataset.general', {
+        templateUrl: 'html/dataset/datasetFormGeneralStepTpl.html'
+      })
+      .state('forms.dataset.summary', {
+        templateUrl: 'html/dataset/datasetFormSummaryStepTpl.html'
+      })
+      .state('instanceDetails', {
+        templateUrl: 'html/instanceDetails.html',
+        controller: 'InstanceDetailsCtrl'
+      })
+    ;
+
   }]);
 
-  app.run(['$rootScope', 
-           function ($rootScope) {	
-    
-    $rootScope.$on('$stateChangeError',
-      function(event, toState, toParams, fromState, fromParams, error){
-        console.log('Manual log of stateChangeError: ' + error);
+  app.run(['$rootScope', '$state', '$location', '$http', '$stateParams', '$cookieStore', 'SpinnersFlag', 'ServerAPI', '$timeout', '$interval',
+    function ($rootScope, $state, $location, $http, $stateParams, $cookieStore, SpinnersFlag, ServerAPI, $timeout, $interval) {
+
+      if(!$rootScope.secureModeDefined){
+        $rootScope.secureMode = false;
+        ServerAPI.clearUser().then(function() {
+          ServerAPI.getServerConfig().then(function() {
+            if (ServerAPI.data) {
+              ServerAPI.data.properties.forEach(function(property) {
+                if(property.key == 'authentication'){
+                  if(property.value == 'kerberos'){
+                    $rootScope.secureMode = true;
+                  }
+                }
+              });
+            }
+            $rootScope.secureModeDefined = true;
+          });
+        });
+      }
+
+      var location = $location.absUrl();
+      var index = location.indexOf("views/");
+      if (index !== -1) {
+        index = index + 6;
+        var path = location.substring(index);
+        var servicePaths = path.split("/");
+        $rootScope.serviceURI = '/api/v1/views/' + servicePaths[0] + '/versions/' + servicePaths[1] + '/instances/' + servicePaths[2] + '/resources/proxy';
+      }
+
+      $rootScope.ambariView = function () {
+        var location_call = $location.absUrl();
+        var index_call = location_call.indexOf("views/");
+        if (index_call !== -1) {
+          return true;
+        } else {
+          return false;
+        }
+      };
+
+      $rootScope.isSecureMode = function () {
+        if(!$rootScope.secureModeDefined){
+          return false;
+        }else if ($rootScope.secureMode) {
+          return true;
+        }else {
+          return false;
+        }
+      };
+
+      $rootScope.userLogged = function () {
+        if($rootScope.ambariView()){
+          return true;
+        } else {
+          if (angular.isDefined($cookieStore.get('userToken')) && $cookieStore.get('userToken') !== null) {
+            return true;
+          } else {
+            return false;
+          }
+        }
+      };
+
+      //$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
+      $rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from) {
+        SpinnersFlag.show = false;
+        SpinnersFlag.backShow = false;
+
+        $rootScope.previousState = from.name;
+        $rootScope.currentState = to.name;
       });
-		
-  }]);
+
+      $rootScope.$on('$stateChangeError',
+        //function(event, toState, toParams, fromState, fromParams, error){
+        function (event, toState, toParams, fromState, error) {
+          console.log('Manual log of stateChangeError: ' + error);
+        });
+
+      var checkRedirect = function(event, toState){
+        if (toState.name !== 'login') {
+          if ($rootScope.ambariView()) {
+
+            if (angular.isDefined($cookieStore.get('userToken')) && $cookieStore.get('userToken') !== null) {
+
+            } else {
+              event.preventDefault();
+              $http.get($rootScope.serviceURI).success(function (data) {
+                var userToken = {};
+                userToken.user = data;
+                $cookieStore.put('userToken', userToken);
+                $state.transitionTo('main');
+              });
+            }
+
+          }else if ($rootScope.secureMode) {
+
+            ServerAPI.getCurrentUser().then(function() {
+              var userToken = {};
+              userToken.user = ServerAPI.user;
+              $cookieStore.put('userToken', userToken);
+              $state.transitionTo('main');
+            });
+
+          }else if ($rootScope.userLogged()) {
+
+            var userToken = $cookieStore.get('userToken');
+            var timeOut = new Date().getTime();
+            timeOut = timeOut - userToken.timeOut;
+            if (timeOut > userToken.timeOutLimit) {
+              $cookieStore.put('userToken', null);
+              event.preventDefault();
+              $state.transitionTo('login');
+            } else {
+              userToken.timeOut = new Date().getTime();
+              $cookieStore.put('userToken', userToken);
+            }
+
+          } else {
+            event.preventDefault();
+            $state.transitionTo('login');
+          }
+        }
+      };
+
+      $rootScope.$on('$stateChangeStart',
+        function (event, toState) {
+          if ($rootScope.userLogged()) {
+            var userToken = $cookieStore.get('userToken');
+            var timeOut = new Date().getTime();
+            timeOut = timeOut - userToken.timeOut;
+            if (timeOut > userToken.timeOutLimit) {
+              $cookieStore.put('userToken', null);
+              event.preventDefault();
+              $state.transitionTo('login');
+            } else {
+              userToken.timeOut = new Date().getTime();
+              $cookieStore.put('userToken', userToken);
+            }
+          }else{
+            var interval;
+            if(!$rootScope.secureModeDefined){
+              if (toState.name !== 'authenticating') {
+                event.preventDefault();
+                $state.transitionTo('authenticating');
+              }
+              interval = $interval(function() {
+                if($rootScope.secureModeDefined){
+                  $interval.cancel(interval);
+                  checkRedirect(event, toState);
+                }
+              }, 1000);
+            }
+          }
+        });
+
+    }]);
 
 })();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/cluster/cluster-module.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/cluster/cluster-module.js b/falcon-ui/app/js/controllers/cluster/cluster-module.js
index d00a937..d0fdf86 100644
--- a/falcon-ui/app/js/controllers/cluster/cluster-module.js
+++ b/falcon-ui/app/js/controllers/cluster/cluster-module.js
@@ -26,9 +26,10 @@
    */
   var clusterModule = angular.module('app.controllers.cluster', [ 'app.services' ]);
 
-  clusterModule.controller('ClusterFormCtrl', [
-    "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", "ValidationService",
-    function ($scope, $interval, Falcon, EntityModel, $state, X2jsService, validationService) {
+  clusterModule.controller('ClusterFormCtrl', [ "$scope", "$interval", "Falcon", "EntityModel", "$state",
+                                                "X2jsService", "ValidationService", "SpinnersFlag", "$timeout", "$rootScope", "$cookieStore",
+                                              function ($scope, $interval, Falcon, EntityModel, $state,
+                                                        X2jsService, validationService, SpinnersFlag, $timeout, $rootScope, $cookieStore) {
 
       $scope.clusterEntity = EntityModel;
       $scope.xmlPreview = { edit: false };
@@ -62,9 +63,11 @@
         }
         //-------------ACL----------------//
         if (!$scope.clusterEntity.clusterModel.cluster.ACL) {
-          $scope.clusterEntity.clusterModel.cluster.ACL = {
+          angular.copy(EntityModel.defaultValues.cluster.cluster.ACL, $scope.clusterEntity.clusterModel.cluster.ACL);
+          $scope.clusterEntity.clusterModel.cluster.ACL._owner = $cookieStore.get('userToken').user;
+          /*$scope.clusterEntity.clusterModel.cluster.ACL = {
             _owner: "", _group: "", _permission: ""
-          };
+          };*/
         }
         //------------Location------------//
         modelLocationsArray.forEach(function(element) {
@@ -117,20 +120,27 @@
           $scope.removeLocation(lastLocationIndex);
         }
         //deletes ACL if empty
-        if ($scope.clusterEntity.clusterModel.cluster.ACL &&
+        /*if ($scope.clusterEntity.clusterModel.cluster.ACL &&
             $scope.clusterEntity.clusterModel.cluster.ACL._owner === "") {
           delete $scope.clusterEntity.clusterModel.cluster.ACL;
-        }
+        }*/
         //deletes tags if empty
-        if ($scope.clusterEntity.clusterModel.cluster.tags.length === 0) {
+        if (!$scope.clusterEntity.clusterModel.cluster.tags) {
           delete $scope.clusterEntity.clusterModel.cluster.tags;
         }
         //moves properties to be the last element if acl exists
         $scope.arrangeFieldsOrder();
       }
-      $scope.arrangeFieldsOrder = function () {
-        var BK = $scope.clusterEntity.clusterModel.cluster,
-          orderedObj = {};
+      $scope.arrangeFieldsOrder = function (xmlObj) {
+
+        var BK,
+            orderedObj = {};
+
+        if (xmlObj) {
+          BK = xmlObj.cluster;
+        } else {
+          BK = $scope.clusterEntity.clusterModel.cluster;
+        }
 
         orderedObj._xmlns = 'uri:falcon:cluster:0.1';
         orderedObj._name = BK._name;
@@ -161,10 +171,13 @@
       };
       $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]});
-        });
+        if ($scope.clusterEntity.clusterModel.cluster.tags) {
+          $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});
@@ -208,17 +221,23 @@
       };
       //--------------------------------------//
       $scope.goSummaryStep = function (formInvalid) {
+        SpinnersFlag.show = true;
         if (!$scope.validations.nameAvailable || formInvalid) {
           validationService.displayValidations.show = true;
           validationService.displayValidations.nameShow = true;
+          SpinnersFlag.show = false;
           return;
         }
         cleanModel();
         $scope.secondStep = true;
         $state.go("forms.cluster.summary");
+        $timeout(function () {
+          angular.element('.nextBtn').trigger('focus');
+        }, 500);
 
       };
       $scope.goGeneralStep = function () {
+        SpinnersFlag.backShow = true;
         $scope.secondStep = false;
         validationService.displayValidations.show = false;
         validationService.displayValidations.nameShow = false;
@@ -239,19 +258,23 @@
         }
       };
       $scope.saveCluster = function () {
+        SpinnersFlag.show = true;
         $scope.saveModelBuffer();
         Falcon.logRequest();
         Falcon.postSubmitEntity($scope.jsonString, "cluster").success(function (response) {
+           $scope.skipUndo = true;
            Falcon.logResponse('success', response, false);
            $state.go('main');
          }).error(function (err) {
+           SpinnersFlag.show = false;
            Falcon.logResponse('error', err, false);
+           angular.element('body, html').animate({scrollTop: 0}, 300);
          });
       };
-    
+
       //--------------------------------------//
       //----------XML preview-----------------//
-    
+
       $scope.xmlPreview.editXML = function () {
         $scope.xmlPreview.edit = !$scope.xmlPreview.edit;
       };
@@ -261,9 +284,15 @@
         $scope.xml = xmlStr;
       };
       $scope.transformBack = function() {
+
         try {
           var xmlObj = X2jsService.xml_str2json($scope.prettyXml);
-          $scope.clusterEntity.clusterModel = xmlObj;
+
+          if (!xmlObj.cluster.ACL || !xmlObj.cluster.ACL._owner || !xmlObj.cluster.ACL._group || !xmlObj.cluster.ACL._permission) {
+            xmlObj.cluster.ACL = angular.copy(EntityModel.defaultValues.cluster.cluster.ACL);
+          }
+
+          $scope.arrangeFieldsOrder(xmlObj);
 
           if($scope.clusterEntity.clusterModel.cluster.properties && $scope.clusterEntity.clusterModel.cluster.properties.property[0] === '') {
             $scope.clusterEntity.clusterModel.cluster.properties.property=[];
@@ -272,6 +301,7 @@
         catch(err) {
           console.log('xml malformed');
         }
+
       };
       $scope.saveModelBuffer = function () {
         $scope.jsonString = angular.toJson($scope.clusterEntity.clusterModel);
@@ -294,6 +324,24 @@
       }
       var refresher = $interval(xmlPreviewCallback, 1000);
 
+      $scope.skipUndo = false;
+      $scope.$on('$destroy', function () {
+        var model = angular.copy($scope.clusterEntity.clusterModel.cluster),
+            defaultModel = angular.toJson(EntityModel.defaultValues.cluster.cluster);
+
+        model.interfaces.interface.forEach(function (item, index) {
+          if (item._type === "registry" && item._endpoint === "" && item._version === "") {
+            model.interfaces.interface.splice(index, 1);
+          }
+        });
+
+        model = angular.toJson(model);
+
+        if (!$scope.skipUndo && !angular.equals(model, defaultModel)) {
+          $interval.cancel(refresher);
+          $scope.$parent.cancel('cluster', $rootScope.previousState);
+        }
+      });
 
       //------------init------------//
       normalizeModel();

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/controllers.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/controllers.js b/falcon-ui/app/js/controllers/controllers.js
index 9fa878e..4867851 100644
--- a/falcon-ui/app/js/controllers/controllers.js
+++ b/falcon-ui/app/js/controllers/controllers.js
@@ -17,8 +17,9 @@
  */
 (function () {
   'use strict';
-  
+
   angular.module('app.controllers', [
+                                      'app.controllers.login',
                                       'app.controllers.navHeader',
                                       'app.controllers.rootCtrl',
                                       'app.controllers.dashboardCtrl',
@@ -26,7 +27,9 @@
                                       'app.controllers.cluster',
                                       'app.controllers.feed',
                                       'app.controllers.process',
-                                      'app.controllers.entity'   
+                                      'app.controllers.entity',
+                                      'app.controllers.instance',
+                                      'app.controllers.dataset'
                                     ]);
 
 })();

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/dashboard-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/dashboard-controller.js b/falcon-ui/app/js/controllers/dashboard-controller.js
index bd60736..7a8d1b4 100644
--- a/falcon-ui/app/js/controllers/dashboard-controller.js
+++ b/falcon-ui/app/js/controllers/dashboard-controller.js
@@ -21,79 +21,103 @@
   var dashboardCtrlModule = angular.module('app.controllers.dashboardCtrl', ['app.services']);
 
   dashboardCtrlModule.controller('DashboardCtrl', [ "$scope", "Falcon", "EntityModel", "FileApi", "$state", "X2jsService",
-    function ($scope, Falcon, EntityModel, FileApi, $state, X2jsService) {
-      
-      $scope.$parent.refreshLists();
+      "$timeout", function ($scope, Falcon, EntityModel, FileApi, $state, X2jsService, $timeout) {
+
+      $scope.$parent.refreshList();
+
+      $timeout(function() {
+        angular.element('#nsPopover').trigger('click');
+      }, 1000);
+
+      $scope.focusSearch = function () {
+        $scope.$parent.refreshList($scope.tags);
+      };
 
       $scope.deleteEntity = function (type, name) {
         type = type.toLowerCase(); //new sandbox returns uppercase type
         Falcon.logRequest();
         Falcon.deleteEntity(type, name)
-          .success(function (data) {          
-            Falcon.logResponse('success', data, type);           
-            $scope.$parent.refreshList(type);              
+          .success(function (data) {
+            Falcon.logResponse('success', data, type);
+            $scope.$parent.refreshList($scope.tags);
           })
           .error(function (err) {
-            
+
             Falcon.logResponse('error', err, type);
           });
       };
       $scope.cloneEntity = function (type, name) {
         type = type.toLowerCase(); //new sandbox returns uppercase type
-        
+
         Falcon.logRequest();
         Falcon.getEntityDefinition(type, name)
           .success(function (data) {
             Falcon.logResponse('success', data, false, true);
             var modelName = type + "Model",
                 entityModel = X2jsService.xml_str2json(data);
-                
-            EntityModel[modelName] = entityModel;
-            EntityModel[modelName][type]._name = "";
-            $scope.models[modelName] = angular.copy(entityModel);
-            $scope.cloningMode = true; // dont know utility of this
-            $scope.$parent.cloningMode = true;
-            $state.go('forms.' + type + ".general");
+
+            if (entityModel.process && entityModel.process.tags && entityModel.process.tags.search('_falcon_mirroring_type') !== -1) {
+
+              entityModel.process.name = "";
+              EntityModel.datasetModel.toImportModel = entityModel;
+              $scope.$parent.cloningMode = true;
+              $state.go('forms.dataset.general');
+
+            } else {
+              EntityModel[modelName] = entityModel;
+              EntityModel[modelName][type]._name = "";
+              $scope.models[modelName] = angular.copy(entityModel);
+              $scope.cloningMode = true; // dont know utility of this
+              $scope.$parent.cloningMode = true;
+              $state.go('forms.' + type + ".general");
+            }
           })
           .error(function (err) {
             Falcon.logResponse('error', err, false, true);
           });
       };
-      $scope.editEntity = function (type, name) {        
+      $scope.editEntity = function (type, name) {
         type = type.toLowerCase(); //new sandbox returns uppercase type
-        
+
         Falcon.logRequest();
         Falcon.getEntityDefinition(type, name)
           .success(function (data) {
             Falcon.logResponse('success', data, false, true);
             var entityModel = X2jsService.xml_str2json(data);
             var modelName = type + "Model";
-            EntityModel[modelName] = entityModel;
-            $scope.models[modelName] = angular.copy(entityModel);
-            $scope.editingMode = true;// dont know utility of this
-            $scope.$parent.cloningMode = false;
-            $state.go('forms.' + type + ".general");
+
+            if (entityModel.process && entityModel.process.tags.search('_falcon_mirroring_type') !== -1) {
+
+              EntityModel.datasetModel.toImportModel = entityModel;
+              $scope.$parent.cloningMode = false;
+              $state.go('forms.dataset.general');
+
+            } else {
+              EntityModel[modelName] = entityModel;
+              $scope.models[modelName] = angular.copy(entityModel);
+              $scope.editingMode = true;// dont know utility of this
+              $scope.$parent.cloningMode = false;
+              $state.go('forms.' + type + ".general");
+            }
           })
           .error(function (err) {
             Falcon.logResponse('error', err, false, true);
           });
       };
       //-----------------------------------------//
-      $scope.entityDetails = function (name, type) {
+      $scope.entityDefinition = function (name, type) {
+
     	  type = type.toLowerCase(); //new sandbox returns uppercase type
-    	  
+
     	  Falcon.logRequest();
           Falcon.getEntityDefinition(type, name)
             .success(function (data) {
               Falcon.logResponse('success', data, false, true);
               var entityModel = X2jsService.xml_str2json(data);
-              var modelName = type + "Model";
-              EntityModel[modelName] = entityModel;
-              $scope.models[modelName] = angular.copy(entityModel);
-              $scope.editingMode = true;// dont know utility of this
-              $scope.$parent.cloningMode = false;
-              //$state.go('forms.' + type + ".general");
-              $state.go('entityDetails');
+              EntityModel.type = type;
+              EntityModel.name = name;
+              EntityModel.model = entityModel;
+              $state.go('entityDefinition');
             })
             .error(function (err) {
               Falcon.logResponse('error', err, false, true);
@@ -104,7 +128,7 @@
         Falcon.logRequest();
         Falcon.postResumeEntity(type, name).success(function (data) {
           Falcon.logResponse('success', data, type);
-          $scope.$parent.refreshList(type);      
+          $scope.$parent.refreshList($scope.tags);
         })
         .error(function (err) {
           Falcon.logResponse('error', err, type);
@@ -114,7 +138,7 @@
         Falcon.logRequest();
         Falcon.postScheduleEntity(type, name).success(function (data) {
           Falcon.logResponse('success', data, type);
-          $scope.$parent.refreshList(type);      
+          $scope.$parent.refreshList($scope.tags);
         })
         .error(function (err) {
           Falcon.logResponse('error', err, type);
@@ -125,19 +149,72 @@
         Falcon.logRequest();
         Falcon.postSuspendEntity(type, name)
           .success(function (message) {
-            Falcon.logResponse('success', message, type);           
-            $scope.$parent.refreshList(type);      
+            Falcon.logResponse('success', message, type);
+              $scope.$parent.refreshList($scope.tags);
           })
           .error(function (err) {
             Falcon.logResponse('error', err, type);
-            
+
           });
       };
+
+      $scope.loadTags = function(query) {
+        var tags = new Array();
+        if(!$scope.$parent.nameFounded){
+          tags.push({ text: 'Name:' + query });
+        }
+        if(!$scope.$parent.typeFounded){
+          var queryAux = query.toUpperCase();
+          if(queryAux === "F" || queryAux === "FE" || queryAux === "FEE" || queryAux === "FEED"){
+            tags.push({ text: 'Type:feed'});
+          }
+          if(queryAux === "P" || queryAux === "PR" || queryAux === "PRO" || queryAux === "PROC" || queryAux === "PROCE"
+              || queryAux === "PROCES" || queryAux === "PROCESS"){
+            tags.push({ text: 'Type:process'});
+          }
+          if(queryAux === "M" || queryAux === "MI" || queryAux === "MIR" || queryAux === "MIRR" || queryAux === "MIRRO"
+              || queryAux === "MIRROR"){
+            tags.push({ text: 'Type:mirror'});
+          }
+        }
+        if(query !== "*"){
+          tags.push({ text: 'Tag:' + query });
+        }
+        return tags;
+      };
+
       $scope.relationsEntity = function (type, name) {
         console.log("relations " + type + " - " + name);
       };
-      
-      
+
+      $scope.displayResults = function () {
+        $scope.$parent.refreshList($scope.tags);
+      };
+
+      $scope.entityDetails = function (name, type) {
+
+        type = type.toLowerCase(); //new sandbox returns uppercase type
+
+        Falcon.logRequest();
+        Falcon.getEntityDefinition(type, name)
+            .success(function (data) {
+              Falcon.logResponse('success', data, false, true);
+              var entityModel = X2jsService.xml_str2json(data);
+              EntityModel.type = type;
+              EntityModel.name = name;
+              EntityModel.model = entityModel;
+              $state.go('entityDetails');
+            })
+            .error(function (err) {
+              Falcon.logResponse('error', err, false, true);
+            });
+      };
+
+      $scope.clearTags = function(){
+        $scope.tags = [];
+        $scope.$parent.refreshList($scope.tags);
+      };
+
     }]);
 
 })();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/dataset/dataset-controller.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/dataset/dataset-controller.js b/falcon-ui/app/js/controllers/dataset/dataset-controller.js
new file mode 100644
index 0000000..a28cd77
--- /dev/null
+++ b/falcon-ui/app/js/controllers/dataset/dataset-controller.js
@@ -0,0 +1,642 @@
+/**
+ * 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 datasetModule = angular.module('app.controllers.dataset', [ 'app.services' ]);
+
+  datasetModule.controller('DatasetCtrl', [
+    "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService", "DateHelper",
+    "ValidationService", "SpinnersFlag", "$timeout", "$rootScope", "clustersList", "$cookieStore",
+    function ($scope, $interval, Falcon, EntityModel, $state, X2jsService, DateHelper,
+              validationService, SpinnersFlag, $timeout, $rootScope, clustersList, $cookieStore) {
+
+
+      $scope.skipUndo = false;
+      $scope.$on('$destroy', function () {
+
+        if (!$scope.skipUndo && !angular.equals($scope.UIModel, EntityModel.defaultValues.MirrorUIModel)) {
+          $scope.$parent.cancel('dataset', $rootScope.previousState);
+        }
+      });
+
+      $scope.isActive = function (route) {
+        return route === $state.current.name;
+      };
+
+      $scope.isCompleted = function (route) {
+        return $state.get(route).data && $state.get(route).data.completed;
+      };
+
+      $scope.clone = $scope.$parent.cloningMode;
+
+      if (!clustersList) {
+        $scope.clustersList = [];
+      } else if (clustersList.type) { // is an object
+        $scope.clustersList = [clustersList];
+      } else {
+        $scope.clustersList = clustersList;
+      }
+
+      $scope.switchModel = function (type) {
+        $scope.model = EntityModel.datasetModel[type].process;
+        $scope.UIModel.formType = type;
+        $scope.completeModel = EntityModel.datasetModel[type];
+        switchTag(type);
+        checkClusters();
+      };
+      $scope.model = EntityModel.datasetModel.HDFS.process;
+      $scope.UIModel = EntityModel.datasetModel.UIModel;
+      $scope.completeModel = EntityModel.datasetModel.HDFS;
+
+      $scope.UIModel.acl.owner = $cookieStore.get('userToken').user;
+
+      //-------------------------//
+      function checkClusters() {
+        if ($scope.UIModel.source.cluster && $scope.UIModel.formType === 'HIVE') {
+          $scope.getSourceDefinition();
+        }
+        if ($scope.UIModel.target.cluster && $scope.UIModel.formType === 'HIVE') {
+          $scope.getTargetDefinition();
+        }
+      }
+      $scope.checkFromSource = function () {
+        if ($scope.UIModel.source.location !== "HDFS") {
+          $scope.UIModel.target.location = "HDFS";
+          $scope.UIModel.runOn = 'target';
+        }
+      };
+      $scope.checkFromTarget = function () {
+        if ($scope.UIModel.target.location !== "HDFS") {
+          $scope.UIModel.source.location = "HDFS";
+          $scope.UIModel.runOn = 'source';
+        }
+      };
+      //----------------TAGS---------------------//
+      $scope.addTag = function () {
+        if ($scope.UIModel.tags.newTag.value === "_falcon_mirroring_type") {
+          return;
+        }
+        $scope.UIModel.tags.tagsArray.push($scope.UIModel.tags.newTag);
+        $scope.UIModel.tags.newTag = {value: "", key: ""};
+        $scope.convertTags();
+      };
+      $scope.removeTag = function (index) {
+        $scope.UIModel.tags.tagsArray.splice(index, 1);
+        $scope.convertTags();
+      };
+      function switchTag (type) {
+        $scope.UIModel.tags.tagsArray.forEach(function (item) {
+          if (item.key === "_falcon_mirroring_type") {
+            item.value = type;
+          }
+        });
+      }
+      $scope.convertTags = function () {
+        var result = [];
+        $scope.UIModel.tags.tagsArray.forEach(function (element) {
+          if (element.key && element.value) {
+            result.push(element.key + "=" + element.value);
+          }
+        });
+        result = result.join(",");
+        $scope.UIModel.tags.tagsString = result;
+      };
+      $scope.splitTags = function () {
+        $scope.UIModel.tags.tagsArray = [];
+        $scope.UIModel.tags.tagsString.split(",").forEach(function (fieldToSplit) {
+          var splittedString = fieldToSplit.split("=");
+          $scope.UIModel.tags.tagsArray.push({key: splittedString[0], value: splittedString[1]});
+        });
+      };
+      //----------- Alerts -----------//
+      $scope.addAlert = function () {
+        $scope.UIModel.alerts.alertsArray.push($scope.UIModel.alerts.alert.email);
+        $scope.UIModel.alerts.alert = {email: ""};
+      };
+      $scope.removeAlert = function (index) {
+        $scope.UIModel.alerts.alertsArray.splice(index, 1);
+      };
+      //----------------- DATE INPUTS -------------------//
+      $scope.dateFormat = 'MM/dd/yyyy';
+
+      $scope.openStartDatePicker = function ($event) {
+        $event.preventDefault();
+        $event.stopPropagation();
+        $scope.startOpened = true;
+      };
+      $scope.openEndDatePicker = function ($event) {
+        $event.preventDefault();
+        $event.stopPropagation();
+        $scope.endOpened = true;
+      };
+
+      $scope.constructDate = function () {
+
+        if ($scope.UIModel.validity.start && $scope.UIModel.validity.end && $scope.UIModel.validity.startTime && $scope.UIModel.validity.endTime) {
+          $scope.UIModel.validity.startISO = DateHelper.createISO($scope.UIModel.validity.start, $scope.UIModel.validity.startTime, $scope.UIModel.validity.tz);
+          $scope.UIModel.validity.endISO = DateHelper.createISO($scope.UIModel.validity.end, $scope.UIModel.validity.endTime, $scope.UIModel.validity.tz);
+        }
+
+      };
+      $scope.$watch(function () {
+        return $scope.UIModel.validity.tz;
+      }, function () {
+        return $scope.constructDate();
+      });
+
+      //-------------------------------------//
+
+      $scope.goNext = function (formInvalid, stateName) {
+        $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;
+          angular.element('body, html').animate({scrollTop: 0}, 500);
+          return;
+        }
+        validationService.displayValidations.show = false;
+        validationService.displayValidations.nameShow = false;
+        $scope.convertTags();
+        createXML();
+        $state.go(stateName);
+        angular.element('body, html').animate({scrollTop: 0}, 500);
+      };
+
+      $scope.goBack = function (stateName) {
+        SpinnersFlag.backShow = true;
+        validationService.displayValidations.show = false;
+        validationService.displayValidations.nameShow = false;
+        $state.go(stateName);
+        angular.element('body, html').animate({scrollTop: 0}, 500);
+      };
+
+      $scope.sourceClusterModel = {};
+      $scope.targetClusterModel = {};
+
+      $scope.getSourceDefinition = function () { // only fills general step info, rest of operations performed in createXml
+        Falcon.getEntityDefinition("cluster", $scope.UIModel.source.cluster)
+          .success(function (data) {
+            $scope.sourceClusterModel = X2jsService.xml_str2json(data);
+            if (!EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath && EntityModel.datasetModel.UIModel.formType === 'HIVE') {
+              EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath = findLocation($scope.sourceClusterModel.cluster.locations.location, 'staging');
+            }
+            if (!EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint && EntityModel.datasetModel.UIModel.formType === 'HIVE') {
+              EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint = replaceHive(findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'registry'));
+            }
+
+          })
+          .error(function (err) {
+            $scope.UIModel.source.cluster = "";
+            Falcon.logResponse('error', err, false, true);
+          });
+      };
+      $scope.getTargetDefinition = function () {
+        Falcon.getEntityDefinition("cluster", $scope.UIModel.target.cluster)
+          .success(function (data) {
+            $scope.targetClusterModel = X2jsService.xml_str2json(data);
+            if (!EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath && EntityModel.datasetModel.UIModel.formType === 'HIVE') {
+              EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath = findLocation($scope.targetClusterModel.cluster.locations.location, 'staging');
+            }
+            if (!EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint && EntityModel.datasetModel.UIModel.formType === 'HIVE') {
+              EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint = replaceHive(findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'registry'));
+            }
+          })
+          .error(function (err) {
+            $scope.UIModel.target.cluster = "";
+            Falcon.logResponse('error', err, false, true);
+          });
+      };
+
+      function findLocation (array, locationString) {
+        var loc = "";
+        array.forEach(function (item) {
+          if (item._name === locationString) {
+            loc = item._path;
+          }
+        });
+        return loc;
+      }
+      function findInterface(array, interfaceString) {
+        var inter = "";
+        array.forEach(function (item) {
+          if (item._type === interfaceString) {
+            inter = item._endpoint;
+          }
+        });
+        return inter;
+      }
+
+      function replaceHive(string) {
+        if (string) {
+          var splitted = string.split(':');
+          var uri = 'hive2' + ':' + splitted[1] + ':10000';
+          return uri;
+        }
+      }
+
+      function createXML() {
+        $scope.model._name = $scope.UIModel.name;
+        $scope.model.tags = $scope.UIModel.tags.tagsString;
+        $scope.model.retry._policy = $scope.UIModel.retry.policy;
+        $scope.model.retry._delay = $scope.UIModel.retry.delay.unit + '(' + $scope.UIModel.retry.delay.number + ')';
+        $scope.model.retry._attempts = $scope.UIModel.retry.attempts;
+        $scope.model.ACL._owner = $scope.UIModel.acl.owner;
+        $scope.model.ACL._group = $scope.UIModel.acl.group;
+        $scope.model.ACL._permission = $scope.UIModel.acl.permissions;
+        $scope.model.frequency = $scope.UIModel.frequency.unit + '(' + $scope.UIModel.frequency.number + ')';
+        $scope.model.clusters.cluster[0].validity._start = $scope.UIModel.validity.startISO;
+        $scope.model.clusters.cluster[0].validity._end = $scope.UIModel.validity.endISO;
+        $scope.model.timezone = $scope.UIModel.validity.tz;
+        if ($scope.UIModel.formType === 'HDFS') {
+
+          if ($scope.UIModel.runOn === "source") {
+            $scope.model.clusters.cluster[0]._name = $scope.UIModel.source.cluster;
+          } else {
+            $scope.model.clusters.cluster[0]._name = $scope.UIModel.target.cluster;
+          }
+
+          $scope.model.workflow._name = $scope.UIModel.name + '-WF';
+
+          $scope.model.properties.property.forEach(function (item) {
+            if (item._name === 'distcpMaxMaps') {
+              item._value = $scope.UIModel.allocation.hdfs.maxMaps;
+            }
+            if (item._name === 'distcpMapBandwidth') {
+              item._value = $scope.UIModel.allocation.hdfs.maxBandwidth;
+            }
+            if (item._name === 'drSourceDir') {
+              item._value = $scope.UIModel.source.path;
+            }
+            if (item._name === 'drTargetDir') {
+              item._value = $scope.UIModel.target.path;
+            }
+            if (item._name === 'drSourceClusterFS') {
+              if ($scope.UIModel.source.location === 'HDFS') {
+                item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'write');
+              } else {
+                item._value = $scope.UIModel.source.url;
+              }
+            }
+            if (item._name === 'drTargetClusterFS') {
+              if ($scope.UIModel.target.location === 'HDFS') {
+                item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'write');
+              } else {
+                item._value = $scope.UIModel.target.url;
+              }
+            }
+            if (item._name === 'drNotificationReceivers') {
+              item._value = (function () {
+                if ($scope.UIModel.alerts.alertsArray.length === 0) {
+                  return "NA";
+                } else {
+                  return $scope.UIModel.alerts.alertsArray.join();
+                }
+              }());
+            }
+            if (item._name === 'sourceCluster') {
+              if ($scope.UIModel.source.location === 'HDFS') { item._value = $scope.UIModel.source.cluster; }
+              else { item._value = ""; }
+            }
+            if (item._name === 'targetCluster') {
+              if ($scope.UIModel.target.location === 'HDFS') { item._value = $scope.UIModel.target.cluster; }
+              else { item._value = ""; }
+            }
+          });
+
+        } else if ($scope.UIModel.formType === 'HIVE') {
+
+          $scope.model.clusters.cluster[0]._name = $scope.UIModel.source.cluster;
+          $scope.model.properties.property.forEach(function (item) {
+            if (item._name === 'distcpMaxMaps') {
+              item._value = $scope.UIModel.allocation.hive.maxMapsDistcp;
+            }
+            if (item._name === 'distcpMapBandwidth') {
+              item._value = $scope.UIModel.allocation.hive.maxBandwidth;
+            }
+            if (item._name === 'sourceCluster') {
+              item._value = $scope.UIModel.source.cluster;
+            }
+            if (item._name === 'targetCluster') {
+              item._value = $scope.UIModel.target.cluster;
+            }
+            if (item._name === 'sourceHiveServer2Uri') {
+              item._value = $scope.UIModel.hiveOptions.source.hiveServerToEndpoint;
+            }
+            if (item._name === 'targetHiveServer2Uri') {
+              item._value = $scope.UIModel.hiveOptions.target.hiveServerToEndpoint;
+            }
+            if (item._name === 'sourceStagingPath') {
+              item._value = $scope.UIModel.hiveOptions.source.stagingPath;
+            }
+            if (item._name === 'targetStagingPath') {
+              item._value = $scope.UIModel.hiveOptions.target.stagingPath;
+            }
+            if (item._name === 'sourceNN') {
+              item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'write');
+            }
+            if (item._name === 'targetNN') {
+              item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'write');
+            }
+            if (item._name === 'sourceMetastoreUri') {
+              item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'registry');
+            }
+            if (item._name === 'targetMetastoreUri') {
+              item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'registry');
+            }
+            if (item._name === 'sourceTable') {
+              if ($scope.UIModel.source.hiveDatabaseType === "databases") {
+                item._value = "*";
+              } else {
+                item._value = $scope.UIModel.source.hiveTables;
+              }
+            }
+            if (item._name === 'sourceDatabase') {
+              if ($scope.UIModel.source.hiveDatabaseType === "databases") {
+                item._value = $scope.UIModel.source.hiveDatabases;
+              } else {
+                item._value = $scope.UIModel.source.hiveDatabase;
+              }
+            }
+            if (item._name === 'maxEvents') {
+              item._value = $scope.UIModel.allocation.hive.maxMapsEvents;
+            }
+            if (item._name === 'replicationMaxMaps') {
+              item._value = $scope.UIModel.allocation.hive.maxMapsMirror;
+            }
+            if (item._name === 'clusterForJobRun') {
+              if ($scope.UIModel.runOn === "source") {
+                item._value = $scope.UIModel.source.cluster;
+              } else {
+                item._value = $scope.UIModel.target.cluster;
+              }
+            }
+            if (item._name === 'clusterForJobRunWriteEP') {
+              if ($scope.UIModel.runOn === "source") {
+                item._value = findInterface($scope.sourceClusterModel.cluster.interfaces.interface, 'write');
+              } else {
+                item._value = findInterface($scope.targetClusterModel.cluster.interfaces.interface, 'write');
+              }
+            }
+            if (item._name === 'drJobName') {
+              item._value = $scope.UIModel.name;
+            }
+            if (item._name === 'drNotificationReceivers') {
+              item._value = (function () {
+                if ($scope.UIModel.alerts.alertsArray.length === 0) {
+                  return "NA";
+                } else {
+                  return $scope.UIModel.alerts.alertsArray.join();
+                }
+              }());
+            }
+
+          });
+
+        } else {
+          console.log('error in form type');
+        }
+
+        $scope.xmlString = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + X2jsService.json2xml_str($scope.completeModel);
+
+      }
+
+      $scope.save = function () {
+        SpinnersFlag.show = true;
+
+        if(!$scope.$parent.cloningMode) {
+          Falcon.postUpdateEntity($scope.xmlString, 'process', $scope.model._name)
+            .success(function (response) {
+              $scope.skipUndo = true;
+              Falcon.logResponse('success', response, false);
+              $state.go('main');
+
+            })
+            .error(function (err) {
+              SpinnersFlag.show = false;
+              Falcon.logResponse('error', err, false);
+              angular.element('body, html').animate({scrollTop: 0}, 300);
+            });
+        } else {
+          Falcon.postSubmitEntity($scope.xmlString, 'process')
+            .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);
+            });
+        }
+
+      };
+
+      function identifyLocationType (val) {
+        if (validationService.patterns.s3.test(val)) {
+          return "s3";
+        } else if (validationService.patterns.azure.test(val)) {
+          return "azure";
+        } else {
+          return "HDFS";
+        }
+      }
+
+      function importModel(model) {
+
+        var mirrorType;
+
+        if (model.process.tags.search('_falcon_mirroring_type=HDFS') !== -1) {
+          mirrorType = 'HDFS';
+        } else {
+          mirrorType = 'HIVE';
+        }
+        $scope.switchModel(mirrorType);
+        EntityModel.datasetModel.UIModel.formType = mirrorType;
+        EntityModel.datasetModel.UIModel.name = (function () { if (!$scope.clone) { return model.process._name; } else { return ""; } }());
+        EntityModel.datasetModel.UIModel.retry.policy = model.process.retry._policy;
+        EntityModel.datasetModel.UIModel.retry.attempts = model.process.retry._attempts;
+        EntityModel.datasetModel.UIModel.retry.delay.number = (function () {
+          return parseInt(model.process.retry._delay.split('(')[1]);
+        }());
+        EntityModel.datasetModel.UIModel.retry.delay.unit = (function () {
+          return model.process.retry._delay.split('(')[0];
+        }());
+        EntityModel.datasetModel.UIModel.frequency.number = (function () {
+          return parseInt(model.process.frequency.split('(')[1]);
+        }());
+        EntityModel.datasetModel.UIModel.frequency.unit = (function () {
+          return model.process.frequency.split('(')[0];
+        }());
+        EntityModel.datasetModel.UIModel.acl.owner = model.process.ACL._owner;
+        EntityModel.datasetModel.UIModel.acl.group = model.process.ACL._group;
+        EntityModel.datasetModel.UIModel.acl.permissions = model.process.ACL._permission;
+
+        EntityModel.datasetModel.UIModel.validity.startISO = model.process.clusters.cluster[0].validity._start;
+        EntityModel.datasetModel.UIModel.validity.endISO = model.process.clusters.cluster[0].validity._end;
+        EntityModel.datasetModel.UIModel.validity.tz = model.process.timezone;
+        EntityModel.datasetModel.UIModel.validity.start = DateHelper.importDate (model.process.clusters.cluster[0].validity._start, model.process.timezone);
+        EntityModel.datasetModel.UIModel.validity.startTime = DateHelper.importDate (model.process.clusters.cluster[0].validity._start, model.process.timezone);
+        EntityModel.datasetModel.UIModel.validity.end = DateHelper.importDate (model.process.clusters.cluster[0].validity._end, model.process.timezone);
+        EntityModel.datasetModel.UIModel.validity.endTime = DateHelper.importDate (model.process.clusters.cluster[0].validity._end, model.process.timezone);
+
+        EntityModel.datasetModel.UIModel.tags.tagsString = model.process.tags;
+        EntityModel.datasetModel.UIModel.tags.tagsArray = (function () {
+          var array = [];
+          model.process.tags.split(',').forEach(function (fieldToSplit) {
+            var splittedString = fieldToSplit.split("=");
+            array.push({key: splittedString[0], value: splittedString[1]});
+          });
+          return array;
+        }());
+
+        if (mirrorType === 'HDFS') {
+          model.process.properties.property.forEach(function (item) {
+            if (item._name === 'distcpMaxMaps') {
+              EntityModel.datasetModel.UIModel.allocation.hdfs.maxMaps = item._value;
+            }
+            if (item._name === 'distcpMapBandwidth') {
+              EntityModel.datasetModel.UIModel.allocation.hdfs.maxBandwidth = item._value;
+            }
+            if (item._name === 'drSourceDir') {
+              EntityModel.datasetModel.UIModel.source.path = item._value;
+            }
+            if (item._name === 'drTargetDir') {
+              EntityModel.datasetModel.UIModel.target.path = item._value;
+            }
+            if (item._name === 'drNotificationReceivers') {
+              EntityModel.datasetModel.UIModel.alerts.alertsArray = (function () {
+                if (item._value !== "NA") {
+                  return item._value.split(',');
+                } else {
+                  return [];
+                }
+              }());
+            }
+            if (item._name === 'targetCluster') {
+              EntityModel.datasetModel.UIModel.target.cluster = item._value;
+            }
+            if (item._name === 'sourceCluster') {
+              EntityModel.datasetModel.UIModel.source.cluster = item._value;
+            }
+            if (item._name === 'drSourceClusterFS') {
+              EntityModel.datasetModel.UIModel.source.url = item._value;
+            }
+            if (item._name === 'drTargetClusterFS') {
+              EntityModel.datasetModel.UIModel.target.url = item._value;
+            }
+          });
+
+          if (EntityModel.datasetModel.UIModel.source.cluster === model.process.clusters.cluster[0]._name) {
+            EntityModel.datasetModel.UIModel.runOn = "source";
+          }
+          if (EntityModel.datasetModel.UIModel.target.cluster === model.process.clusters.cluster[0]._name) {
+            EntityModel.datasetModel.UIModel.runOn = "target";
+          }
+
+          EntityModel.datasetModel.UIModel.source.location = identifyLocationType(EntityModel.datasetModel.UIModel.source.url);
+          EntityModel.datasetModel.UIModel.target.location = identifyLocationType(EntityModel.datasetModel.UIModel.target.url);
+
+        } else if (mirrorType === 'HIVE') {
+
+          model.process.properties.property.forEach(function (item) {
+            if (item._name === 'distcpMaxMaps') {
+              EntityModel.datasetModel.UIModel.allocation.hive.maxMapsDistcp = item._value;
+            }
+            if (item._name === 'distcpMapBandwidth') {
+              EntityModel.datasetModel.UIModel.allocation.hive.maxBandwidth = item._value;
+            }
+            if (item._name === 'sourceCluster') {
+              EntityModel.datasetModel.UIModel.source.cluster = item._value;
+            }
+            if (item._name === 'targetCluster') {
+              EntityModel.datasetModel.UIModel.target.cluster = item._value;
+            }
+            if (item._name === 'sourceStagingPath') {
+              EntityModel.datasetModel.UIModel.hiveOptions.source.stagingPath = item._value;
+            }
+            if (item._name === 'targetStagingPath') {
+              EntityModel.datasetModel.UIModel.hiveOptions.target.stagingPath = item._value;
+              if (item._value === "*") {
+                EntityModel.datasetModel.UIModel.source.hiveDatabaseType = "databases";
+              } else {
+                EntityModel.datasetModel.UIModel.source.hiveDatabaseType = "tables";
+              }
+            }
+            if (item._name === 'sourceHiveServer2Uri') {
+              EntityModel.datasetModel.UIModel.hiveOptions.source.hiveServerToEndpoint = item._value;
+            }
+            if (item._name === 'targetHiveServer2Uri') {
+              EntityModel.datasetModel.UIModel.hiveOptions.target.hiveServerToEndpoint = item._value;
+            }
+            if (item._name === 'sourceTable') {
+              EntityModel.datasetModel.UIModel.source.hiveTables = item._value;
+              if (EntityModel.datasetModel.UIModel.source.hiveDatabaseType === "databases") {
+                EntityModel.datasetModel.UIModel.source.hiveTables = "*";
+              }
+              else {
+                EntityModel.datasetModel.UIModel.source.hiveTables = item._value;
+              }
+            }
+            if (item._name === 'sourceDatabase') {
+              if (EntityModel.datasetModel.UIModel.source.hiveDatabaseType === "databases") {
+                EntityModel.datasetModel.UIModel.source.hiveDatabases = item._value;
+              } else {
+                EntityModel.datasetModel.UIModel.source.hiveDatabase = item._value;
+              }
+            }
+            if (item._name === 'maxEvents') {
+              EntityModel.datasetModel.UIModel.allocation.hive.maxMapsEvents = item._value;
+            }
+            if (item._name === 'replicationMaxMaps') {
+              EntityModel.datasetModel.UIModel.allocation.hive.maxMapsMirror = item._value;
+            }
+            if (item._name === 'clusterForJobRun') {
+              if (EntityModel.datasetModel.UIModel.source.cluster === item._value) {
+                EntityModel.datasetModel.UIModel.runOn = "source";
+              } else {
+                EntityModel.datasetModel.UIModel.runOn = "target";
+              }
+            }
+            if (item._name === 'drNotificationReceivers') {
+              EntityModel.datasetModel.UIModel.alerts.alertsArray = (function () {
+                if (item._value !== "NA") {
+                  return item._value.split(',');
+                } else {
+                  return [];
+                }
+              }());
+            }
+
+          });
+        }
+
+        if(EntityModel.datasetModel.UIModel.source.cluster) { $scope.getSourceDefinition(); }
+        if(EntityModel.datasetModel.UIModel.target.cluster) { $scope.getTargetDefinition(); }
+
+      }
+      if (EntityModel.datasetModel.toImportModel) {
+        importModel(EntityModel.datasetModel.toImportModel);
+      }
+    }]);
+}());

http://git-wip-us.apache.org/repos/asf/falcon/blob/86180d93/falcon-ui/app/js/controllers/entity/entity-definition.js
----------------------------------------------------------------------
diff --git a/falcon-ui/app/js/controllers/entity/entity-definition.js b/falcon-ui/app/js/controllers/entity/entity-definition.js
new file mode 100644
index 0000000..5afe400
--- /dev/null
+++ b/falcon-ui/app/js/controllers/entity/entity-definition.js
@@ -0,0 +1,50 @@
+/**
+ * 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('EntityDefinitionCtrl', [
+    "$scope", "$interval", "Falcon", "EntityModel", "$state", "X2jsService",
+    function ($scope, $interval, Falcon, EntityModel, $state, X2jsService) {
+
+      $scope.entity = EntityModel;
+      $scope.xmlPreview = { edit: false };
+
+      var xmlStr = X2jsService.json2xml_str(angular.copy($scope.entity.model));
+      $scope.prettyXml = X2jsService.prettifyXml(xmlStr);
+      $scope.xml = xmlStr;
+
+    }
+  ]);
+
+  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();});
+    };
+  });
+
+})();