ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rle...@apache.org
Subject [2/2] ambari git commit: AMBARI-11958. Hive View Enahancements (Erik Bergenholtz via rlevas)
Date Wed, 17 Jun 2015 18:38:20 GMT
AMBARI-11958. Hive View Enahancements (Erik Bergenholtz via rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2580916a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2580916a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2580916a

Branch: refs/heads/branch-2.1
Commit: 2580916a6f3707d0f41c03bcd10015bbe3d21da6
Parents: c33e7d7
Author: Erik Bergenholtz <ebergenholtz@hortonworks.com>
Authored: Wed Jun 17 14:38:07 2015 -0400
Committer: Robert Levas <rlevas@hortonworks.com>
Committed: Wed Jun 17 14:38:13 2015 -0400

----------------------------------------------------------------------
 .../ui/hive-web/app/components/udf-tr-view.js   |  81 +++++
 .../ui/hive-web/app/controllers/index.js        | 113 +++---
 .../ui/hive-web/app/controllers/job-progress.js | 129 -------
 .../ui/hive-web/app/controllers/open-queries.js |  21 +-
 .../ui/hive-web/app/controllers/query-tabs.js   |  12 +-
 .../ui/hive-web/app/controllers/settings.js     | 360 ++-----------------
 .../ui/hive-web/app/controllers/udf.js          | 132 -------
 .../ui/hive-web/app/controllers/udfs.js         |  76 +++-
 .../hive-web/app/controllers/visual-explain.js  |  14 +-
 .../ui/hive-web/app/initializers/i18n.js        |   3 +-
 .../resources/ui/hive-web/app/models/job.js     |   1 +
 .../ui/hive-web/app/services/job-progress.js    | 102 ++++++
 .../ui/hive-web/app/services/session.js         |  48 +++
 .../ui/hive-web/app/services/settings.js        | 175 +++++++++
 .../resources/ui/hive-web/app/styles/app.scss   |  27 +-
 .../app/templates/components/udf-tr-view.hbs    |  77 ++++
 .../ui/hive-web/app/templates/index.hbs         |   8 +-
 .../hive-web/app/templates/settings-global.hbs  |  57 ---
 .../hive-web/app/templates/settings-query.hbs   |  72 ----
 .../ui/hive-web/app/templates/settings.hbs      |  49 ++-
 .../ui/hive-web/app/templates/udfs.hbs          |  89 +----
 .../ui/hive-web/app/utils/constants.js          |  14 +-
 .../ui/hive-web/app/views/visual-explain.js     |   2 +
 .../tests/unit/controllers/index-test.js        |  13 +-
 .../tests/unit/controllers/insert-udfs-test.js  |   2 +-
 .../tests/unit/controllers/settings-test.js     | 156 ++++----
 .../tests/unit/controllers/tez-ui-test.js       |   6 +-
 .../hive-web/tests/unit/controllers/udf-test.js |  92 -----
 .../tests/unit/services/settings-test.js        | 155 ++++++++
 .../ambari/view/utils/ambari/AmbariApi.java     |  15 +
 .../ambari/view/utils/ambari/Services.java      |  45 +++
 31 files changed, 1045 insertions(+), 1101 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/components/udf-tr-view.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/components/udf-tr-view.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/components/udf-tr-view.js
new file mode 100644
index 0000000..f019578
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/components/udf-tr-view.js
@@ -0,0 +1,81 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+import constants from 'hive/utils/constants';
+
+export default Ember.Component.extend({
+  tagName: 'tr',
+
+  didInsertElement: function () {
+    this._super();
+
+    if (this.get('udf.isNew')) {
+      this.set('udf.isEditing', true);
+    }
+  },
+
+  setfileBackup: function () {
+    if (!this.get('udf.isDirty')) {
+      this.set('fileBackup', this.get('udf.fileResource'));
+    }
+  }.observes('udf.isDirty').on('didInsertElement'),
+
+  actions: {
+    editUdf: function () {
+      this.set('udf.isEditing', true);
+    },
+
+    deleteUdf: function () {
+      this.sendAction('onDeleteUdf', this.get('udf'));
+    },
+
+    addFileResource: function () {
+      this.sendAction('onAddFileResource', this.get('udf'));
+    },
+
+    editFileResource: function (file) {
+      this.set('udf.fileResource', file);
+      this.set('udf.isEditingResource', true);
+    },
+
+    deleteFileResource: function (file) {
+      this.sendAction('onDeleteFileResource', file);
+    },
+
+    save: function () {
+      this.sendAction('onSaveUdf', this.get('udf'));
+    },
+
+    cancel: function () {
+      var self = this;
+
+      this.set('udf.isEditing', false);
+      this.set('udf.isEditingResource', false);
+
+      this.udf.get('fileResource').then(function (file) {
+        if (file) {
+          file.rollback();
+        }
+
+        self.udf.rollback();
+        self.udf.set('fileResource', self.get('fileBackup'));
+      });
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index.js
index ea2ed5d..b3cd127 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index.js
@@ -21,33 +21,47 @@ import utils from 'hive/utils/functions';
 
 export default Ember.Controller.extend({
   jobService: Ember.inject.service(constants.namingConventions.job),
+  jobProgressService: Ember.inject.service(constants.namingConventions.jobProgress),
   databaseService: Ember.inject.service(constants.namingConventions.database),
   notifyService: Ember.inject.service(constants.namingConventions.notify),
-
-  needs: [ constants.namingConventions.openQueries,
-           constants.namingConventions.udfs,
-           constants.namingConventions.jobLogs,
-           constants.namingConventions.jobResults,
-           constants.namingConventions.jobExplain,
-           constants.namingConventions.settings,
-           constants.namingConventions.visualExplain,
-           constants.namingConventions.tezUI,
-           constants.namingConventions.jobProgress,
-  ],
-
-  openQueries: Ember.computed.alias('controllers.' + constants.namingConventions.openQueries),
-  udfs: Ember.computed.alias('controllers.' + constants.namingConventions.udfs + '.udfs'),
-  logs: Ember.computed.alias('controllers.' + constants.namingConventions.jobLogs),
-  results: Ember.computed.alias('controllers.' + constants.namingConventions.jobResults),
-  explain: Ember.computed.alias('controllers.' + constants.namingConventions.jobExplain),
-  settings: Ember.computed.alias('controllers.' + constants.namingConventions.settings),
-  visualExplain: Ember.computed.alias('controllers.' + constants.namingConventions.visualExplain),
-  tezUI: Ember.computed.alias('controllers.' + constants.namingConventions.tezUI),
-  jobProgress: Ember.computed.alias('controllers.' + constants.namingConventions.jobProgress),
+  session: Ember.inject.service(constants.namingConventions.session),
+  settingsService: Ember.inject.service(constants.namingConventions.settings),
+
+  openQueries   : Ember.inject.controller(constants.namingConventions.openQueries),
+  udfs          : Ember.inject.controller(constants.namingConventions.udfs),
+  logs          : Ember.inject.controller(constants.namingConventions.jobLogs),
+  results       : Ember.inject.controller(constants.namingConventions.jobResults),
+  explain       : Ember.inject.controller(constants.namingConventions.jobExplain),
+  settings      : Ember.inject.controller(constants.namingConventions.settings),
+  visualExplain : Ember.inject.controller(constants.namingConventions.visualExplain),
+  tezUI         : Ember.inject.controller(constants.namingConventions.tezUI),
 
   selectedDatabase: Ember.computed.alias('databaseService.selectedDatabase'),
-
   isDatabaseExplorerVisible: true,
+  canKillSession: Ember.computed.and('model.sessionTag', 'model.sessionActive'),
+
+  queryProcessTabs: [
+    Ember.Object.create({
+      name: Ember.I18n.t('menus.logs'),
+      path: constants.namingConventions.subroutes.jobLogs
+    }),
+    Ember.Object.create({
+      name: Ember.I18n.t('menus.results'),
+      path: constants.namingConventions.subroutes.jobResults
+    }),
+    Ember.Object.create({
+      name: Ember.I18n.t('menus.explain'),
+      path: constants.namingConventions.subroutes.jobExplain
+    })
+  ],
+
+  queryPanelActions: [
+    Ember.Object.create({
+      icon: 'fa-expand',
+      action: 'toggleDatabaseExplorerVisibility',
+      tooltip: Ember.I18n.t('tooltips.expand')
+    })
+  ],
 
   init: function () {
     this._super();
@@ -163,7 +177,7 @@ export default Ember.Controller.extend({
 
     finalQuery = query;
     finalQuery = this.bindQueryParams(finalQuery);
-    finalQuery = this.prependQuerySettings(finalQuery);
+    finalQuery = this.prependGlobalSettings(finalQuery, job);
 
     job.set('forcedContent', finalQuery);
 
@@ -171,7 +185,7 @@ export default Ember.Controller.extend({
       return this.getVisualExplainJson(job, originalModel);
     }
 
-    return this.saveQuery(job, originalModel);
+    return this.createJob(job, originalModel);
   },
 
   getVisualExplainJson: function (job, originalModel) {
@@ -191,7 +205,7 @@ export default Ember.Controller.extend({
     return defer.promise;
   },
 
-  saveQuery: function (job, originalModel) {
+  createJob: function (job, originalModel) {
     var defer = Ember.RSVP.defer(),
         self = this,
         openQueries = this.get('openQueries');
@@ -205,6 +219,7 @@ export default Ember.Controller.extend({
     job.save().then(function () {
       //convert tab for current model since the execution will create a new job, and navigate to the new job route.
       openQueries.convertTabToJob(originalModel, job).then(function () {
+        self.get('jobProgressService').setupProgress(job);
         self.set('jobSaveSucceeded', true);
 
         //reset flag on the original model
@@ -214,8 +229,6 @@ export default Ember.Controller.extend({
       }, function (err) {
         handleError(err);
       });
-
-      self.get('settings').updateSettingsId(originalModel.get('id'), job.get('id'));
     }, function (err) {
       handleError(err);
     });
@@ -223,28 +236,17 @@ export default Ember.Controller.extend({
     return defer.promise;
   },
 
-  prependQuerySettings: function (query) {
-    var validSettings = this.get('settings').getCurrentValidSettings();
-    var regex = new RegExp(utils.regexes.setSetting);
-    var existingSettings = query.match(regex);
+  prependGlobalSettings: function (query, job) {
+    var jobGlobalSettings = job.get('globalSettings');
+    var currentGlobalSettings = this.get('settingsService').getSettings();
 
-    //clear previously added settings
-    if (existingSettings) {
-      existingSettings.forEach(function (setting) {
-        query = query.replace(setting, '');
-      });
+    // remove old globals
+    if (jobGlobalSettings) {
+      query.replace(jobGlobalSettings, '');
     }
 
-    query = query.trim();
-
-    //update with the current settings
-    if (validSettings.get('length')) {
-      query = '\n' + query;
-
-      validSettings.forEach(function (setting) {
-        query = setting + '\n' + query;
-      });
-    }
+    job.set('globalSettings', currentGlobalSettings);
+    query = currentGlobalSettings + query;
 
     return query;
   },
@@ -457,6 +459,10 @@ export default Ember.Controller.extend({
     return Ember.I18n.t('titles.query.process') + ' (' + Ember.I18n.t('titles.query.status') + this.get('content.status') + ')';
   }.property('content.status'),
 
+  updateSessionStatus: function() {
+    this.get('session').updateSessionStatus(this.get('model'));
+  }.observes('model', 'model.status'),
+
   actions: {
     stopCurrentJob: function () {
       this.get('jobService').stopJob(this.get('model'));
@@ -628,6 +634,21 @@ export default Ember.Controller.extend({
 
     toggleDatabaseExplorerVisibility: function () {
       this.toggleProperty('isDatabaseExplorerVisible');
+    },
+
+    killSession: function() {
+      var self = this;
+      var model = this.get('model');
+
+      this.get('session').killSession(model)
+        .catch(function (response) {
+          if ([200, 404].contains(response.status)) {
+            model.set('sessionActive', false);
+            self.notify.success(Ember.I18n.t('alerts.success.sessions.deleted'));
+          } else {
+            self.notify.error(response);
+          }
+        });
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job-progress.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job-progress.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job-progress.js
deleted file mode 100644
index 3181f90..0000000
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job-progress.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import Ember from 'ember';
-import constants from 'hive/utils/constants';
-
-export default Ember.Controller.extend({
-  needs: [ constants.namingConventions.index ],
-
-  jobs: [],
-
-  index: Ember.computed.alias('controllers.' + constants.namingConventions.index),
-
-  modelChanged: function () {
-    var model = this.get('index.model');
-    var job;
-
-    if (!this.isJob(model)) {
-      return;
-    }
-
-    job = this.jobs.findBy('model', model);
-
-    if (!job) {
-      job = this.jobs.pushObject(Ember.Object.create({
-        model: model,
-        stages: [],
-        totalProgress: 0,
-        retrievingProgress: false,
-      }));
-    }
-
-    this.set('currentJob', job);
-  }.observes('index.model'),
-
-  updateProgress: function () {
-    var job = this.get('currentJob');
-
-    if (!job.get('model.dagId')) {
-      return;
-    }
-
-    if (this.get('totalProgress') < 100 && !job.get('retrievingProgress')) {
-      this.reloadProgress(job);
-    }
-  }.observes('currentJob.model.dagId'),
-
-  totalProgress: function () {
-    if (!this.isJob(this.get('index.model'))) {
-      return;
-    }
-
-    return this.get('currentJob.totalProgress');
-  }.property('index.model', 'currentJob.totalProgress'),
-
-  stages: function () {
-    if (!this.isJob(this.get('index.model'))) {
-      return;
-    }
-
-    return this.get('currentJob.stages');
-  }.property('index.model', 'currentJob.stages.@each.value'),
-
-  reloadProgress: function (job) {
-    var self = this;
-    var url = '%@/%@/%@/progress'.fmt(this.container.lookup('adapter:application').buildURL(),
-                                         constants.namingConventions.jobs,
-                                         job.get('model.id'));
-
-    job.set('retrievingProgress', true);
-
-    Ember.$.getJSON(url).then(function (data) {
-      var total = 0;
-      var length = Object.keys(data.vertexProgresses).length;
-
-      if (!job.get('stages.length')) {
-        data.vertexProgresses.forEach(function (vertexProgress) {
-          var progress = vertexProgress.progress * 100;
-
-          job.get('stages').pushObject(Ember.Object.create({
-            name: vertexProgress.name,
-            value: progress
-          }));
-
-          total += progress;
-        });
-      } else {
-        data.vertexProgresses.forEach(function (vertexProgress) {
-          var progress = vertexProgress.progress * 100;
-
-          job.get('stages').findBy('name', vertexProgress.name).set('value', progress);
-
-          total += progress;
-        });
-      }
-
-      total /= length;
-
-      job.set('totalProgress', total);
-
-      if (job.get('model.isRunning') && total < 100) {
-        Ember.run.later(function () {
-          self.reloadProgress(job);
-        }, 1000);
-      } else {
-        job.set('retrievingProgress');
-      }
-    });
-  },
-
-  isJob: function (model) {
-    return model.get('constructor.typeKey') === constants.namingConventions.job;
-  }
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/open-queries.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/open-queries.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/open-queries.js
index 484df16..5ab46f6 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/open-queries.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/open-queries.js
@@ -26,14 +26,12 @@ export default Ember.ArrayController.extend({
 
   needs: [ constants.namingConventions.jobResults,
            constants.namingConventions.jobExplain,
-           constants.namingConventions.index,
-           constants.namingConventions.settings
+           constants.namingConventions.index
          ],
 
   jobResults: Ember.computed.alias('controllers.' + constants.namingConventions.jobResults),
   jobExplain: Ember.computed.alias('controllers.' + constants.namingConventions.jobExplain),
   index: Ember.computed.alias('controllers.' + constants.namingConventions.index),
-  settings: Ember.computed.alias('controllers.' + constants.namingConventions.settings),
 
   selectedTables: Ember.computed.alias('databaseService.selectedTables'),
   selectedDatabase: Ember.computed.alias('databaseService.selectedDatabase'),
@@ -155,8 +153,7 @@ export default Ember.ArrayController.extend({
         self = this,
         wasNew,
         defer = Ember.RSVP.defer(),
-        jobModel = model,
-        originalId = model.get('id');
+        jobModel = model;
 
     if (!query) {
       query = this.getQueryForModel(model);
@@ -203,11 +200,9 @@ export default Ember.ArrayController.extend({
 
       //update query tab path with saved model id if its a new record
       if (wasNew) {
-        self.get('settings').updateSettingsId(originalId, updatedModel.get('id'));
         tab.set('id', updatedModel.get('id'));
 
         self.get('fileService').loadFile(updatedModel.get('queryFile')).then(function (file) {
-          file.set('blockSettingsParser', true);
           file.set('fileContent', content);
           file.save().then(function (updatedFile) {
             self.removeObject(query);
@@ -215,8 +210,6 @@ export default Ember.ArrayController.extend({
             self.set('currentQuery', updatedFile);
 
             defer.resolve(updatedModel.get('id'));
-            self.get('settings').parseQuerySettings(false);
-            query.set('blockSettingsParser', false);
           }, function (err) {
             defer.reject(err);
           });
@@ -224,14 +217,11 @@ export default Ember.ArrayController.extend({
           defer.reject(err);
         });
       } else {
-        query.set('blockSettingsParser', true);
         query.set('fileContent', content);
         query.save().then(function () {
           self.toggleProperty('tabUpdated');
           defer.resolve(updatedModel.get('id'));
 
-          self.get('settings').parseQuerySettings(false);
-          query.set('blockSettingsParser', false);
         }, function (err) {
           defer.reject(err);
         });
@@ -271,14 +261,11 @@ export default Ember.ArrayController.extend({
     return defer.promise;
   },
 
-  keepOriginalQuery: function (jobId) {
+  keepOriginalQuery: function () {
     var selected = this.get('highlightedText');
     var hasQueryParams = this.get('index.queryParams.length');
-    var hasSettings = this.get('settings').hasSettings(jobId);
 
-    return selected && selected[0] !== "" ||
-         hasQueryParams ||
-         hasSettings;
+    return selected && selected[0] !== "" || hasQueryParams;
   },
 
   isDirty: function (model) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/query-tabs.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
index 7b6c222..4f5176c 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
@@ -24,8 +24,9 @@ export default Ember.Controller.extend({
 
   tabs: [
     Ember.Object.create({
-      iconClass: 'fa-code',
+      iconClass: 'text-icon',
       id: 'query-icon',
+      text: 'SQL',
       action: 'setDefaultActive',
       name: constants.namingConventions.index,
       tooltip: Ember.I18n.t('tooltips.query')
@@ -144,15 +145,6 @@ export default Ember.Controller.extend({
     }
   },
 
-  flashSettings: function() {
-    var settingsTab = this.get('tabs').findBy('id', 'settings-icon');
-    settingsTab.set('flash', true);
-
-    Ember.run.later(function() {
-      settingsTab.set('flash', false);
-    }, 1000);
-  },
-
   actions: {
     toggleOverlay: function (tab) {
       if (tab !== this.get('default') && tab.get('active')) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/settings.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/settings.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/settings.js
index 787f42b..77250b4 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/settings.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/settings.js
@@ -17,367 +17,53 @@
  */
 
 import Ember from 'ember';
-import constants from 'hive/utils/constants';
-import utils from 'hive/utils/functions';
 
-export default Ember.ArrayController.extend({
-  notifyService: Ember.inject.service(constants.namingConventions.notify),
+export default Ember.Controller.extend({
+  openQueries: Ember.inject.controller(),
+  index: Ember.inject.controller(),
 
-  needs: [
-    constants.namingConventions.index,
-    constants.namingConventions.openQueries,
-    constants.namingConventions.queryTabs
-  ],
+  settingsService: Ember.inject.service('settings'),
 
-  index: Ember.computed.alias('controllers.' + constants.namingConventions.index),
-  openQueries: Ember.computed.alias('controllers.' + constants.namingConventions.openQueries),
-  queryTabs: Ember.computed.alias('controllers.' + constants.namingConventions.queryTabs),
+  predefinedSettings: Ember.computed.alias('settingsService.predefinedSettings'),
+  settings: Ember.computed.alias('settingsService.settings'),
 
-  sessionTag: Ember.computed.alias('index.model.sessionTag'),
-  sessionActive: Ember.computed.alias('index.model.sessionActive'),
+  init: function() {
+    this._super();
 
-  createDefaultsSettings: function(settings) {
-    var globalSettings = [];
-    var newSetting;
-
-    for (var key in settings) {
-      newSetting = this.createSetting(key, settings[key]);
-      globalSettings.push(newSetting);
-    }
-
-    this.get('globalSettings').setObjects(globalSettings);
-  },
-
-  loadDefaultSettings: function() {
-    var adapter       = this.container.lookup('adapter:application');
-    var url           = adapter.buildURL() + '/savedQueries/defaultSettings';
-    var self = this;
-
-    adapter.ajax(url)
-      .then(function(response) {
-        self.createDefaultsSettings(response.settings);
-      })
-      .catch(function(error) {
-        self.get('notifyService').error(error);
-      });
-  }.on('init'),
-
-  setSettingsTabs: function() {
-    this.set('settingsTabs', Ember.ArrayProxy.create({ content: [
-      Ember.Object.create({
-        name: 'Query Settings',
-        view: constants.namingConventions.settingsQuery,
-        visible: true
-      }),
-      Ember.Object.create({
-        name: 'Global Settings',
-        view: constants.namingConventions.settingsGlobal,
-        visible: true
-      })
-    ]}));
-
-    this.set('selectedTab', this.get('selectTab.firstObject'));
-  }.on('init'),
-
-  canInvalidateSession: Ember.computed.and('sessionTag', 'sessionActive'),
-
-  predefinedSettings: constants.hiveParameters,
-
-  selectedSettings: function () {
-    var predefined = this.get('predefinedSettings');
-    var current = this.get('currentSettings.settings');
-
-    return predefined.filter(function (setting) {
-      return current.findBy('key.name', setting.name);
-    });
-  }.property('currentSettings.settings.@each.key'),
-
-  currentSettings: function () {
-    var currentId = this.get('index.model.id');
-    var targetSettings = this.findBy('id', currentId);
-
-   if (!targetSettings) {
-      targetSettings = this.pushObject(Ember.Object.create({
-        id: currentId,
-        settings: []
-      }));
-    }
-
-    return targetSettings;
-  }.property('index.model.id'),
-
-  settingsSets: [
-    Ember.Object.create({ name: 'Set 1' }),
-    Ember.Object.create({ name: 'Set 2' }),
-    Ember.Object.create({ name: 'Set 3' })
-  ],
-
-  globalSettings: Ember.ArrayProxy.create({ content: []}),
-
-  updateSettingsId: function (oldId, newId) {
-    this.filterBy('id', oldId).setEach('id', newId);
+    this.get('settingsService').loadDefaultSettings();
   },
 
-  getCurrentValidSettings: function () {
-    var currentSettings = this.get('currentSettings');
-    var globalSettings = this.get('globalSettings');
-    var validSettings = [];
-    var settings = Ember.copy(currentSettings.get('settings'));
+  excluded: function() {
+    var settings = this.get('settings');
 
-    globalSettings.map(function(setting) {
-      if (!settings.findBy('key.name', setting.get('key.name'))) {
-        settings.pushObject(setting);
-      }
+    return this.get('predefinedSettings').filter(function(setting) {
+      return settings.findBy('key.name', setting.name);
     });
+  }.property('settings.@each.key'),
 
-    if (!currentSettings && !globalSettings) {
-      return '';
-    }
-
-    settings.map(function (setting) {
-      if (setting.get('valid')) {
-        validSettings.pushObject('set %@ = %@;'.fmt(setting.get('key.name'), setting.get('value')));
-      }
-    });
-
-    return validSettings;
-  },
-
-  hasSettings: function (id) {
-    var settings;
-    var settingId = id ? id : this.get('index.model.id');
-
-    settings = this.findBy('id', settingId);
-
-    return settings && settings.get('settings.length');
-  },
-
-  createSetting: function(name, value) {
-    var self = this;
-    var setting = Ember.Object.createWithMixins({
-      valid     : true,
-      value     : Ember.computed.alias('selection.value'),
-      selection : Ember.Object.create(),
-
-      isInGlobal: function() {
-        return self.get('globalSettings').mapProperty('key.name').contains(this.get('key.name'));
-      }.property('key.name')
-    });
-
-    if (name) {
-      setting.set('key', Ember.Object.create({ name: name }));
-    }
-
-    if (value) {
-      setting.set('selection.value', value);
-    }
-
-    return setting;
-  },
-
-  parseQuerySettings: function(notify) {
-    var self           = this;
-    var query          = this.get('openQueries.currentQuery');
-    var content        = query.get('fileContent');
-    var regex          = new RegExp(utils.regexes.setSetting);
-    var settings       = content.match(regex);
-    var targetSettings = this.get('currentSettings');
-
-    if (!query || !settings) {
-      return;
-    }
-
-    var parsedSettings = [];
-    settings.forEach(function (setting) {
-      var KeyValue = setting.split('=');
-      var name     = KeyValue[0].replace('set', '').trim();
-      var value    = KeyValue[1].replace(';', '').trim();
-
-      if (!self.get('predefinedSettings').findBy('name', name)) {
-        self.get('predefinedSettings').pushObject({
-          name: name
-        });
-      }
-
-      if (self.get('globalSettings').findBy('key.name', name)) {
-        return false;
-      }
-
-      parsedSettings.push(self.createSetting(name, value));
-    });
-
-    if (notify) {
-      this.get('notifyService').info(Ember.I18n.t('settings.parsed'));
-      this.get('queryTabs').flashSettings();
-    }
-
-    query.set('fileContent', content.replace(regex, '').trim());
-    targetSettings.set('settings', parsedSettings);
-  },
-
-  parseQuerySettingsObserver: function () {
-    var query;
-
-    Ember.run(this, function () {
-      query = this.get('openQueries.currentQuery');
-    });
-
-    if (query.get('blockSettingsParser')) {
-      return;
-    }
-
-    this.parseQuerySettings(true);
-  }.observes('openQueries.currentQuery', 'openQueries.currentQuery.fileContent', 'openQueries.tabUpdated'),
-
-  validate: function () {
-    var settings = this.get('currentSettings.settings') || [];
-    var predefinedSettings = this.get('predefinedSettings');
-
-    settings.forEach(function (setting) {
-      var predefined = predefinedSettings.findBy('name', setting.get('key.name'));
-
-      if (!predefined) {
-        return;
-      }
-
-      if (predefined.values && predefined.values.contains(setting.get('value'))) {
-        setting.set('valid', true);
-        return;
-      }
-
-      if (predefined.validate && predefined.validate.test(setting.get('value'))) {
-        setting.set('valid', true);
-        return;
-      }
-
-      if (!predefined.validate) {
-        setting.set('valid', true);
-        return;
-      }
-
-      setting.set('valid', false);
-    });
-  }.observes('currentSettings.[]', 'currentSettings.settings.[]', 'currentSettings.settings.@each.value', 'currentSettings.settings.@each.key'),
-
-  currentSettingsAreValid: function () {
-    var currentSettings = this.get('currentSettings.settings');
-    var invalid = currentSettings.filterProperty('valid', false);
-
-    return invalid.length ? false : true;
-  }.property('currentSettings.settings.@each.value', 'currentSettings.settings.@each.key'),
-
-  loadSessionStatus: function () {
-    var model         = this.get('index.model');
-    var sessionActive = this.get('sessionActive');
-    var sessionTag    = this.get('sessionTag');
-    var adapter       = this.container.lookup('adapter:application');
-    var url           = adapter.buildURL() + '/jobs/sessions/' + sessionTag;
-
-    if (sessionTag && sessionActive === undefined) {
-      adapter.ajax(url, 'GET')
-        .then(function (response) {
-          model.set('sessionActive', response.session.actual);
-        })
-        .catch(function () {
-          model.set('sessionActive', false);
-        });
-    }
-  }.observes('index.model', 'index.model.status'),
+  parseGlobalSettings: function () {
+    this.get('settingsService').parseGlobalSettings(this.get('openQueries.currentQuery'), this.get('index.model'));
+  }.observes('openQueries.currentQuery', 'openQueries.currentQuery.fileContent', 'openQueries.tabUpdated').on('init'),
 
   actions: {
     add: function () {
-      this.get('currentSettings.settings').pushObject(this.createSetting());
+      this.get('settingsService').add();
     },
 
     remove: function (setting) {
-      var currentQuery = this.get('openQueries.currentQuery');
-      var currentQueryContent = currentQuery.get('fileContent');
-      var keyValue = 'set %@ = %@;\n'.fmt(setting.get('key.name'), setting.get('value'));
-
-      this.get('currentSettings.settings').removeObject(setting);
-
-      if (currentQueryContent.indexOf(keyValue) > -1) {
-        currentQuery.set('fileContent', currentQueryContent.replace(keyValue, ''));
-      }
+      this.get('settingsService').remove(setting);
     },
 
-    addKey: function (param) {
-      var newKey = this.get('predefinedSettings').pushObject({
-        name: param
-      });
-
-      this.get('currentSettings.settings').findBy('key', null).set('key', newKey);
+    addKey: function (name) {
+      this.get('settingsService').createKey(name);
     },
 
     removeAll: function () {
-      var currentQuery = this.get('openQueries.currentQuery'),
-          currentQueryContent = currentQuery.get('fileContent'),
-          regex = new RegExp(utils.regexes.setSetting),
-          settings = currentQueryContent.match(regex);
-
-      currentQuery.set('fileContent', currentQueryContent.replace(settings, ''));
-      this.get('currentSettings').set('settings', []);
-    },
-
-    invalidateSession: function () {
-      var self       = this;
-      var sessionTag = this.get('sessionTag');
-      var adapter    = this.container.lookup('adapter:application');
-      var url        = adapter.buildURL() + '/jobs/sessions/' + sessionTag;
-      var model = this.get('index.model');
-
-      // @TODO: Split this into then/catch once the BE is fixed
-      adapter.ajax(url, 'DELETE').catch(function (response) {
-        if ([200, 404].contains(response.status)) {
-          model.set('sessionActive', false);
-          self.get('notifyService').success(Ember.I18n.t('alerts.success.sessions.deleted'));
-        } else {
-          self.get('notifyService').error(response);
-        }
-      });
-    },
-
-    makeSettingGlobal: function(setting) {
-      // @TODO: should remove from all query settings?
-      // @TODO: validate setting? maybe its not needed bc it was already validated?
-      this.get('globalSettings').pushObject(setting);
-      this.get('currentSettings.settings').removeObject(setting);
-    },
-
-    removeGlobal: function(setting) {
-      this.get('globalSettings').removeObject(setting);
-    },
-
-    overwriteGlobalValue: function(setting) {
-      var globalSetting = this.get('globalSettings').findBy('key.name', setting.get('key.name'));
-
-      if (globalSetting) {
-        globalSetting.set('value', setting.get('value'));
-        this.get('currentSettings.settings').removeObject(setting);
-      }
+      this.get('settingsService').removeAll();
     },
 
     saveDefaultSettings: function() {
-      var self     = this;
-      var data     = {};
-      var adapter  = this.container.lookup('adapter:application');
-      var url      = adapter.buildURL() + '/savedQueries/defaultSettings';
-      var settings = this.get('globalSettings');
-
-      settings.forEach(function(setting) {
-        data[ setting.get('key.name') ] = setting.get('value');
-      });
-
-      adapter.ajax(url, 'POST', {
-        data: {settings: data }
-      })
-        .then(function(response) {
-          if (response && response.settings) {
-            self.get('notifyService').success(Ember.I18n.t('alerts.success.settings.saved'));
-          } else {
-            self.get('notifyService').error(response);
-          }
-        });
+      this.get('settingsService').saveDefaultSettings();
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udf.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udf.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udf.js
deleted file mode 100644
index ced29ca..0000000
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udf.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import Ember from 'ember';
-import constants from 'hive/utils/constants';
-
-export default Ember.ObjectController.extend({
-  init: function () {
-    this._super();
-
-    if (this.get('model.isNew')) {
-      this.set('isEditing', true);
-    }
-
-    // we need this because model.rollback doesnt roll back secondary relations
-    this.set('fileBackup', this.get('model.fileResource'));
-  },
-
-  actions: {
-    executeAction: function (action) {
-      switch (action) {
-        case 'buttons.edit':
-          this.set('isEditing', true);
-          break;
-        case 'buttons.delete':
-          var defer = Ember.RSVP.defer(),
-              self = this;
-
-          this.send('openModal',
-                    'modal-delete',
-                     {
-                        heading: 'modals.delete.heading',
-                        text: 'modals.delete.message',
-                        defer: defer
-                     });
-
-          defer.promise.then(function () {
-            self.get('model').destroyRecord();
-          });
-          break;
-      }
-    },
-
-    save: function () {
-      var self = this,
-          saveUdf = function () {
-            self.get('model').save().then(function (updatedModel) {
-              self.set('isEditing', false);
-              self.set('isEditingResource', false);
-              self.set('fileBackup', updatedModel.get('fileResource'));
-            });
-          };
-
-      //replace with a validation system if needed.
-      if (!this.get('model.name') || !this.get('model.classname')) {
-        return;
-      }
-
-      this.get('model.fileResource').then(function (file) {
-        if (file) {
-          if (!file.get('name') || !file.get('path')) {
-            return;
-          }
-
-          file.save().then(function () {
-            saveUdf();
-          });
-        } else {
-          saveUdf();
-        }
-      });
-    },
-
-    cancel: function () {
-      var self = this;
-
-      this.set('isEditing', false);
-      this.set('isEditingResource', false);
-
-      this.model.get('fileResource').then(function (file) {
-        if (file) {
-          file.rollback();
-        }
-
-        self.model.rollback();
-        self.model.set('fileResource', self.get('fileBackup'));
-      });
-    },
-
-    addFileResource: function () {
-      var file = this.store.createRecord(constants.namingConventions.fileResource);
-      this.set('isEditingResource', true);
-      this.model.set('fileResource', file);
-    },
-
-    editFileResource: function (file) {
-      this.set('isEditingResource', true);
-      this.model.set('fileResource', file);
-    },
-
-    removeFileResource: function (file) {
-      var defer = Ember.RSVP.defer();
-
-      this.send('openModal',
-                'modal-delete',
-                 {
-                    heading: Ember.I18n.translations.modals.delete.heading,
-                    text: Ember.I18n.translations.modals.delete.message,
-                    defer: defer
-                 });
-
-      defer.promise.then(function () {
-        file.destroyRecord();
-      });
-    }
-  }
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udfs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udfs.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udfs.js
index 437c9d0..6804260 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udfs.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udfs.js
@@ -20,19 +20,12 @@ import Ember from 'ember';
 import FilterableMixin from 'hive/mixins/filterable';
 import constants from 'hive/utils/constants';
 
-export default Ember.ArrayController.extend(FilterableMixin, {
-  itemController: constants.namingConventions.udf,
+export default Ember.Controller.extend(FilterableMixin, {
   fileResources: [],
 
   sortAscending: true,
   sortProperties: [],
 
-  //row buttons
-  links: [
-      'buttons.edit',
-      'buttons.delete'
-  ],
-
   columns: [
     Ember.Object.create({
       caption: 'placeholders.udfs.name',
@@ -49,6 +42,73 @@ export default Ember.ArrayController.extend(FilterableMixin, {
   }.property('udfs', 'filters.@each'),
 
   actions: {
+    handleAddFileResource: function (udf) {
+      var file = this.store.createRecord(constants.namingConventions.fileResource);
+      udf.set('fileResource', file);
+      udf.set('isEditingResource', true);
+    },
+
+    handleDeleteFileResource: function (file) {
+      var defer = Ember.RSVP.defer();
+
+      this.send('openModal',
+                'modal-delete',
+                 {
+                    heading: 'modals.delete.heading',
+                    text: 'modals.delete.message',
+                    defer: defer
+                 });
+
+      defer.promise.then(function () {
+        file.destroyRecord();
+      });
+    },
+
+    handleSaveUdf: function (udf) {
+      var self = this,
+          saveUdf = function () {
+            udf.save().then(function () {
+              udf.set('isEditing', false);
+              udf.set('isEditingResource', false);
+            });
+          };
+
+      //replace with a validation system if needed.
+      if (!udf.get('name') || !udf.get('classname')) {
+        return;
+      }
+
+      udf.get('fileResource').then(function (file) {
+        if (file) {
+          if (!file.get('name') || !file.get('path')) {
+            return;
+          }
+
+          file.save().then(function () {
+            saveUdf();
+          });
+        } else {
+          saveUdf();
+        }
+      });
+    },
+
+    handleDeleteUdf: function (udf) {
+      var defer = Ember.RSVP.defer();
+
+      this.send('openModal',
+                'modal-delete',
+                 {
+                    heading: 'modals.delete.heading',
+                    text: 'modals.delete.message',
+                    defer: defer
+                 });
+
+      defer.promise.then(function () {
+        udf.destroyRecord();
+      });
+    },
+
     sort: function (property) {
       //if same column has been selected, toggle flag, else default it to true
       if (this.get('sortProperties').objectAt(0) === property) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/visual-explain.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
index 8401388..d6ae8c4 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
@@ -20,19 +20,13 @@ import Ember from 'ember';
 import constants from 'hive/utils/constants';
 
 export default Ember.Controller.extend({
+  jobProgressService: Ember.inject.service(constants.namingConventions.jobProgress),
   notifyService: Ember.inject.service(constants.namingConventions.notify),
 
-  needs: [ constants.namingConventions.index,
-           constants.namingConventions.openQueries,
-           constants.namingConventions.jobProgress ],
+  index: Ember.inject.controller(),
+  openQueries: Ember.inject.controller(),
 
-  index: Ember.computed.alias('controllers.' + constants.namingConventions.index),
-  jobProgress: Ember.computed.alias('controllers.' + constants.namingConventions.jobProgress),
-  openQueries: Ember.computed.alias('controllers.' + constants.namingConventions.openQueries),
-
-  updateProgress: function () {
-    this.set('verticesProgress', this.get('jobProgress.stages'));
-  }.observes('jobProgress.stages', 'jobProgress.stages.@each.value'),
+  verticesProgress: Ember.computed.alias('jobProgressService.currentJob.stages'),
 
   observeCurrentQuery: function () {
     this.set('shouldChangeGraph', true);

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/initializers/i18n.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/initializers/i18n.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/initializers/i18n.js
index ab73c63..af5e3a7 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/initializers/i18n.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/initializers/i18n.js
@@ -198,7 +198,8 @@ TRANSLATIONS = {
     loadMore: 'Load more...',
     saveHdfs: 'Save to HDFS',
     saveCsv: 'Download as CSV',
-    runOnTez: 'Run on Tez'
+    runOnTez: 'Run on Tez',
+    killSession: 'Kill Session'
   },
 
   labels: {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/job.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/job.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/job.js
index 45393db..9079b5a 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/job.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/job.js
@@ -38,6 +38,7 @@ export default DS.Model.extend({
   applicationId: DS.attr(),
   referrer: DS.attr('string'),
   confFile: DS.attr('string'),
+  globalSettings: DS.attr('string'),
 
   dateSubmittedTimestamp: function () {
     var date = this.get('dateSubmitted');

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/services/job-progress.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/services/job-progress.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/services/job-progress.js
new file mode 100644
index 0000000..1e0b96b
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/services/job-progress.js
@@ -0,0 +1,102 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+import constants from 'hive/utils/constants';
+
+export default Ember.Service.extend({
+  jobs: [],
+
+  setupProgress: function (currentModel) {
+    var job = this.jobs.findBy('model', currentModel);
+
+    if (!job) {
+      job = this.jobs.pushObject(Ember.Object.create({
+        model: currentModel,
+        stages: [],
+        totalProgress: 0,
+        retrievingProgress: false,
+      }));
+    }
+
+    this.set('currentJob', job);
+  },
+
+  updateProgress: function () {
+    var job = this.get('currentJob');
+
+    if (!job.get('model.dagId')) {
+      return;
+    }
+
+    if (job.get('totalProgress') < 100 && !job.get('retrievingProgress')) {
+      this.reloadProgress(job);
+    }
+  }.observes('currentJob.model.dagId'),
+
+  reloadProgress: function (job) {
+    var self = this;
+    var url = '%@/%@/%@/progress'.fmt(this.container.lookup('adapter:application').buildURL(),
+                                         constants.namingConventions.jobs,
+                                         job.get('model.id'));
+
+    job.set('retrievingProgress', true);
+
+    Ember.$.getJSON(url).then(function (data) {
+      var total = 0;
+      var length = Object.keys(data.vertexProgresses).length;
+
+      if (!job.get('stages.length')) {
+        data.vertexProgresses.forEach(function (vertexProgress) {
+          var progress = vertexProgress.progress * 100;
+
+          job.get('stages').pushObject(Ember.Object.create({
+            name: vertexProgress.name,
+            value: progress
+          }));
+
+          total += progress;
+        });
+      } else {
+        data.vertexProgresses.forEach(function (vertexProgress) {
+          var progress = vertexProgress.progress * 100;
+
+          job.get('stages').findBy('name', vertexProgress.name).set('value', progress);
+
+          total += progress;
+        });
+      }
+
+      total /= length;
+
+      job.set('totalProgress', total);
+
+      if (job.get('model.isRunning') && total < 100) {
+        Ember.run.later(function () {
+          self.reloadProgress(job);
+        }, 1000);
+      } else {
+        job.set('retrievingProgress');
+      }
+    });
+  },
+
+  isJob: function (model) {
+    return model.get('constructor.typeKey') === constants.namingConventions.job;
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/services/session.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/services/session.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/services/session.js
new file mode 100644
index 0000000..d7d448d
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/services/session.js
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+
+  updateSessionStatus: function (model) {
+    var sessionActive = model.get('sessionActive');
+    var sessionTag    = model.get('sessionTag');
+    var adapter       = this.container.lookup('adapter:application');
+    var url           = adapter.buildURL() + '/jobs/sessions/' + sessionTag;
+
+    if (sessionTag && sessionActive === undefined) {
+      adapter.ajax(url, 'GET')
+        .then(function (response) {
+          model.set('sessionActive', response.session.actual);
+        })
+        .catch(function () {
+          model.set('sessionActive', false);
+        });
+    }
+  },
+
+  killSession: function (model) {
+    var sessionTag = model.get('sessionTag');
+    var adapter    = this.container.lookup('adapter:application');
+    var url        = adapter.buildURL() + '/jobs/sessions/' + sessionTag;
+
+    return adapter.ajax(url, 'DELETE');
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/services/settings.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/services/settings.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/services/settings.js
new file mode 100644
index 0000000..b813bbf
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/services/settings.js
@@ -0,0 +1,175 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+import constants from 'hive/utils/constants';
+
+export default Ember.Service.extend({
+
+  notifyService: Ember.inject.service('notify'),
+
+  settings: Ember.ArrayProxy.create({ content: [] }),
+  predefinedSettings: constants.hiveParameters,
+
+  _createSetting: function(name, value) {
+    var setting = Ember.Object.createWithMixins({
+      valid     : true,
+      value     : Ember.computed.alias('selection.value'),
+      selection : Ember.Object.create()
+    });
+
+    if (name) {
+      setting.set('key', Ember.Object.create({ name: name }));
+    }
+
+    if (value) {
+      setting.set('selection.value', value);
+    }
+
+    return setting;
+  },
+
+  _createDefaultSettings: function(settings) {
+    if (!settings) {
+      return;
+    }
+
+    for (var key in settings) {
+      this.get('settings').pushObject(this._createSetting(key, settings[key]));
+    }
+  },
+
+  _validate: function () {
+    var settings = this.get('settings');
+    var predefinedSettings = this.get('predefinedSettings');
+
+    settings.forEach(function (setting) {
+      var predefined = predefinedSettings.findBy('name', setting.get('key.name'));
+
+      if (!predefined) {
+        return;
+      }
+
+      if (predefined.values && predefined.values.contains(setting.get('value'))) {
+        setting.set('valid', true);
+        return;
+      }
+
+      if (predefined.validate && predefined.validate.test(setting.get('value'))) {
+        setting.set('valid', true);
+        return;
+      }
+
+      if (!predefined.validate) {
+        setting.set('valid', true);
+        return;
+      }
+
+      setting.set('valid', false);
+    });
+  }.observes('settings.@each.value', 'settings.@each.key'),
+
+  add: function() {
+    this.get('settings').pushObject(this._createSetting());
+  },
+
+  createKey: function(name) {
+    var key = { name: name };
+    this.get('predefinedSettings').pushObject(key);
+
+    this.get('settings').findBy('key', null).set('key', key);
+  },
+
+  remove: function(setting) {
+    this.get('settings').removeObject(setting);
+  },
+
+  removeAll: function() {
+    this.get('settings').clear();
+  },
+
+  loadDefaultSettings: function() {
+    var adapter       = this.container.lookup('adapter:application');
+    var url           = adapter.buildURL() + '/savedQueries/defaultSettings';
+    var self = this;
+
+    adapter.ajax(url)
+      .then(function(response) {
+        self._createDefaultSettings(response.settings);
+      })
+      .catch(function(error) {
+        self.get('notifyService').error(error);
+      });
+  },
+
+  saveDefaultSettings: function() {
+    var self     = this;
+    var data     = {};
+    var adapter  = this.container.lookup('adapter:application');
+    var url      = adapter.buildURL() + '/savedQueries/defaultSettings';
+    var settings = this.get('settings');
+
+    settings.forEach(function(setting) {
+      data[ setting.get('key.name') ] = setting.get('value');
+    });
+
+    adapter.ajax(url, 'POST', {
+      data: {settings: data }
+    })
+    .then(function(response) {
+      if (response && response.settings) {
+        self.get('notifyService').success(Ember.I18n.t('alerts.success.settings.saved'));
+      } else {
+        self.get('notifyService').error(response);
+      }
+    });
+  },
+
+  getSettings: function() {
+    var settings = this.get('settings');
+    var asString = "";
+
+    if (!settings.get('length')) {
+      return asString;
+    }
+
+    settings.forEach(function(setting) {
+      asString += "set %@=%@;\n".fmt(setting.get('key.name'), setting.get('value'));
+    });
+
+    asString += constants.globalSettings.comment;
+
+    return asString;
+  },
+
+  parseGlobalSettings: function(query, model) {
+    if (!query || !model || !model.get('globalSettings')) {
+      return;
+    }
+
+    var globals = model.get('globalSettings');
+    var content = query.get('fileContent');
+
+    if (globals !== this.getSettings()) {
+      return;
+    }
+
+    query.set('fileContent', content.replace(globals, ''));
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/styles/app.scss
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/styles/app.scss b/contrib/views/hive/src/main/resources/ui/hive-web/app/styles/app.scss
index 7be5dcc..6507d6b 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/styles/app.scss
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/styles/app.scss
@@ -407,9 +407,6 @@ body {
   cursor: pointer;
 }
 
-.settings-container {
-}
-
 .settings-container .close-settings {
   float: right;
   font-size: 18px;
@@ -434,40 +431,20 @@ body {
   }
 }
 
-.setting .remove, .setting .makeGlobal {
+.setting .remove {
   line-height: 30px;
   font-size: 18px;
   cursor: pointer;
-  // position: absolute;
-  // right: -5px;
-  // top: -10px;
-}
-
-.setting .makeGlobal.overwriteGlobal {
-  color: #ff3322;
 }
 
 .setting .setting-input-value {
-  width: calc(100% - 50px);
+  width: calc(100% - 30px);
   display: inline-block;
 }
 .setting .global-setting-value {
   width: calc(100% - 25px);
 }
 
-.setting .makeGlobal {
-  top: 30px;
-}
-
-.settings-set {
-  margin: 10px 0;
-}
-.settings-set h3 {
-  display: inline-block;
-  margin: 0 10px 0 0;
-  vertical-align: top;
-  line-height: 35px;
-}
 .settings-set .settings-set-selector {
   display: inline-block;
   width: 300px;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/components/udf-tr-view.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/components/udf-tr-view.hbs b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/components/udf-tr-view.hbs
new file mode 100644
index 0000000..4b5cd61
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/components/udf-tr-view.hbs
@@ -0,0 +1,77 @@
+{{!
+* 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.
+}}
+
+<td>
+  {{#if udf.isEditing}}
+    {{#if udf.isEditingResource}}
+      {{extended-input type="text"
+                       class="pull-left form-control halfed input-sm"
+                       placeholderTranslation="placeholders.fileResource.name"
+                       value=udf.fileResource.name}}
+      {{extended-input type="text"
+                       class="pull-left form-control halfed input-sm"
+                       placeholderTranslation="placeholders.fileResource.path"
+                       value=udf.fileResource.path}}
+    {{else}}
+      {{select-widget items=fileResources
+                      selectedValue=udf.fileResource
+                      labelPath="name"
+                      defaultLabelTranslation="placeholders.select.file"
+                      itemAdded="addFileResource"
+                      itemEdited="editFileResource"
+                      itemRemoved="deleteFileResource"
+                      canAdd=true
+                      canEdit=true}}
+    {{/if}}
+  {{else}}
+    {{#if udf.fileResource}}
+      {{udf.fileResource.name}}  ({{udf.fileResource.path}})
+    {{/if}}
+  {{/if}}
+</td>
+{{#each column in columns}}
+  <td>
+    {{#if udf.isEditing}}
+      {{extended-input type="text"
+                       class="pull-left form-control input-sm"
+                       placeholderTranslation=column.caption
+                       dynamicContextBinding="udf"
+                       dynamicValueBinding="column.property"}}
+    {{else}}
+      {{path-binding udf column.property}}
+    {{/if}}
+  </td>
+{{/each}}
+<td>
+  {{#if udf.isEditing}}
+    <div class="pull-right">
+      <button type="button" class="btn btn-sm btn-warning" {{action "cancel"}}>{{t "buttons.cancel"}}</button>
+      <button type="button" class="btn btn-sm btn-success" {{action "save"}}>{{t "buttons.save"}}</button>
+    </div>
+  {{else}}
+    <div class="btn-group pull-right">
+      <span data-toggle="dropdown">
+        <a class="fa fa-gear"></a>
+      </span>
+      <ul class="dropdown-menu" role="menu">
+        <li {{action 'editUdf'}}><a>{{t 'buttons.edit'}}</a></li>
+        <li {{action 'deleteUdf'}}><a>{{t 'buttons.delete'}}</a></li>
+      </ul>
+    </div>
+  {{/if}}
+</td>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/index.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/index.hbs b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/index.hbs
index 2fdf0ce..81d6ecf 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/index.hbs
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/index.hbs
@@ -50,13 +50,17 @@
 
           {{render 'insert-udfs'}}
 
+          {{#if canKillSession}}
+            <button type="button" class="btn btn-sm btn-danger kill-session" {{action "killSession"}}>{{t "buttons.killSession"}}</button>
+          {{/if}}
+
           <button type="button" class="btn btn-sm btn-primary  pull-right" {{action "addQuery"}}>{{t "buttons.newQuery"}}</button>
         </div>
       {{/panel-widget}}
 
       {{#if displayJobTabs}}
-        {{#if jobProgress.stages.length}}
-          {{#progress-widget value=jobProgress.totalProgress}}
+        {{#if jobProgressService.currentJob.stages.length}}
+          {{#progress-widget value=jobProgressService.currentJob.totalProgress}}
           {{/progress-widget}}
         {{/if}}
       {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-global.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-global.hbs b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-global.hbs
deleted file mode 100644
index 0712ec2..0000000
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-global.hbs
+++ /dev/null
@@ -1,57 +0,0 @@
-{{!
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-}}
-
-<div class='settings-controls'>
-  <button class="btn btn-success btn-xs" {{action 'saveDefaultSettings'}}><i class="fa fa-plus"></i> Save Default Settings</button>
-</div>
-
-{{#each setting in globalSettings}}
-  <div class="setting col-md-12 col-sm-12">
-    <form>
-      <div class="form-group">
-        <div class="input-group">
-          <div class="input-group-addon">
-            {{typeahead-widget
-                options=predefinedSettings
-                excluded=selectedSettings
-                optionLabelPath="name"
-                optionValuePath="name"
-                selection=setting.key
-            }}
-          </div>
-          <div {{bind-attr class=":input-group-addon setting.valid::has-error"}}>
-
-            <div class="setting-input-value global-setting-value">
-              {{#if setting.key.values}}
-                {{select-widget items=setting.key.values
-                                labelPath="value"
-                                selectedValue=setting.selection
-                                defaultLabelTranslation="placeholders.select.value"
-                }}
-              {{else}}
-                {{input class="input-sm form-control" placeholderTranslation="placeholders.select.value" value=setting.selection.value}}
-              {{/if}}
-            </div>
-
-            <span class="fa fa-times-circle remove pull-right" {{action 'removeGlobal' setting}}></span>
-          </div>
-        </div>
-      </div>
-    </form>
-  </div>
-{{/each}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-query.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-query.hbs b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-query.hbs
deleted file mode 100644
index 3d28d9b..0000000
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings-query.hbs
+++ /dev/null
@@ -1,72 +0,0 @@
-{{!
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-}}
-
-<div class='settings-controls'>
-  <button class="btn btn-success btn-xs" {{action 'add'}}><i class="fa fa-plus"></i> Add</button>
-  {{#if currentSettings.settings}}
-    <button class="btn btn-danger btn-xs" {{action 'removeAll'}}><i class="fa fa-minus"></i> Remove All</button>
-  {{/if}}
-
-
-  {{#if canInvalidateSession}}
-    <button class="btn btn-danger btn-xs pull-right" {{action 'invalidateSession'}}><i class="fa fa-times"></i> Invalidate Session</button>
-  {{/if}}
-</div>
-
-{{#each setting in currentSettings.settings}}
-  <div class="setting col-md-12 col-sm-12">
-    <form>
-      <div class="form-group">
-        <div class="input-group">
-          <div class="input-group-addon">
-            {{typeahead-widget
-                options=predefinedSettings
-                excluded=selectedSettings
-                optionLabelPath="name"
-                optionValuePath="name"
-                selection=setting.key
-                create="addKey"
-            }}
-          </div>
-          <div {{bind-attr class=":input-group-addon setting.valid::has-error"}}>
-
-            <div class="setting-input-value">
-              {{#if setting.key.values}}
-                {{select-widget items=setting.key.values
-                                labelPath="value"
-                                selectedValue=setting.selection
-                                defaultLabelTranslation="placeholders.select.value"
-                }}
-              {{else}}
-                {{input class="input-sm form-control" placeholderTranslation="placeholders.select.value" value=setting.selection.value}}
-              {{/if}}
-            </div>
-
-            <span class="fa fa-times-circle remove pull-right" {{action 'remove' setting}}></span>
-
-            {{#if setting.isInGlobal}}
-              <span class="fa fa-globe makeGlobal overwriteGlobal pull-right" title="Overwrite Global Setting" {{action 'overwriteGlobalValue' setting}}></span>
-            {{else}}
-              <span class="fa fa-globe makeGlobal pull-right" title="Make Global" {{action 'makeSettingGlobal' setting}}></span>
-            {{/if}}
-          </div>
-        </div>
-      </div>
-    </form>
-  </div>
-{{/each}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings.hbs b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings.hbs
index 31b9cff..55b659a 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings.hbs
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/settings.hbs
@@ -17,7 +17,50 @@
 }}
 
 <div class="editor-overlay settings-container fadeIn">
-  {{#tabs-widget tabs=settingsTabs selectedTab=selectedTab}}
-    {{partial selectedTab.view}}
-  {{/tabs-widget}}
+  <div class='settings-controls'>
+    <button class="btn btn-success btn-xs" {{action 'add'}}><i class="fa fa-plus"></i> Add</button>
+
+    {{#if settings.length}}
+      <button class="btn btn-danger btn-xs" {{action 'removeAll'}}><i class="fa fa-minus"></i> Remove All</button>
+    {{/if}}
+
+    <button class="btn btn-success btn-xs pull-right" {{action 'saveDefaultSettings'}}><i class="fa fa-plus"></i> Save Default Settings</button>
+  </div>
+
+  {{#each setting in settings}}
+    <div class="setting col-md-12 col-sm-12">
+      <form>
+        <div class="form-group">
+          <div class="input-group">
+            <div class="input-group-addon">
+              {{typeahead-widget
+                  options=predefinedSettings
+                  excluded=excluded
+                  optionLabelPath="name"
+                  optionValuePath="name"
+                  selection=setting.key
+                  create="addKey"
+              }}
+            </div>
+            <div {{bind-attr class=":input-group-addon setting.valid::has-error"}}>
+
+              <div class="setting-input-value">
+                {{#if setting.key.values}}
+                  {{select-widget items=setting.key.values
+                                  labelPath="value"
+                                  selectedValue=setting.selection
+                                  defaultLabelTranslation="placeholders.select.value"
+                  }}
+                {{else}}
+                  {{input class="input-sm form-control" placeholderTranslation="placeholders.select.value" value=setting.selection.value}}
+                {{/if}}
+              </div>
+
+              <span class="fa fa-times-circle remove pull-right" {{action 'remove' setting}}></span>
+            </div>
+          </div>
+        </div>
+      </form>
+    </div>
+  {{/each}}
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/udfs.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/udfs.hbs b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/udfs.hbs
index 9d057db..4cd1a97 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/udfs.hbs
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/templates/udfs.hbs
@@ -22,17 +22,13 @@
       <th>{{t "columns.fileResource"}}</th>
       {{#each column in columns}}
         <th>
-          {{#if column.caption}}
-            {{column-filter-widget class="pull-left"
-                                   column=column
-                                   filterValue=column.filterValue
-                                   sortAscending=controller.sortAscending
-                                   sortProperties=controller.sortProperties
-                                   columnSorted="sort"
-                                   columnFiltered="filter"}}
-          {{else}}
-            {{column.caption}}
-          {{/if}}
+          {{column-filter-widget class="pull-left"
+                                 column=column
+                                 filterValue=column.filterValue
+                                 sortAscending=controller.sortAscending
+                                 sortProperties=controller.sortProperties
+                                 columnSorted="sort"
+                                 columnFiltered="filter"}}
         </th>
       {{/each}}
       <th>
@@ -44,69 +40,14 @@
     </tr>
   </thead>
   <tbody>
-    {{#each udf in this}}
-      <tr>
-        <td>
-          {{#if udf.isEditing}}
-            {{#if udf.isEditingResource}}
-              {{extended-input type="text"
-                               class="pull-left form-control halfed input-sm"
-                               placeholderTranslation="placeholders.fileResource.name"
-                               value=udf.fileResource.name}}
-              {{extended-input type="text"
-                               class="pull-left form-control halfed input-sm"
-                               placeholderTranslation="placeholders.fileResource.path"
-                               value=udf.fileResource.path}}
-            {{else}}
-              {{select-widget items=fileResources
-                              selectedValue=udf.fileResource
-                              labelPath="name"
-                              defaultLabelTranslation="placeholders.select.file"
-                              itemAdded="addFileResource"
-                              itemEdited="editFileResource"
-                              itemRemoved="removeFileResource"
-                              canAdd=true
-                              canEdit=true}}
-            {{/if}}
-          {{else}}
-            {{#if udf.fileResource}}
-              {{udf.fileResource.name}}  ({{udf.fileResource.path}})
-            {{/if}}
-          {{/if}}
-        </td>
-        {{#each column in columns}}
-          <td>
-            {{#if udf.isEditing}}
-              {{extended-input type="text"
-                               class="pull-left form-control input-sm"
-                               placeholderTranslation=column.caption
-                               dynamicContextBinding="udf"
-                               dynamicValueBinding="column.property"}}
-            {{else}}
-              {{path-binding udf column.property}}
-            {{/if}}
-          </td>
-        {{/each}}
-        <td>
-          {{#if udf.isEditing}}
-            <div class="pull-right">
-              <button type="button" class="btn btn-sm btn-warning" {{action "cancel"}}>{{t "buttons.cancel"}}</button>
-              <button type="button" class="btn btn-sm btn-success" {{action "save"}}>{{t "buttons.save"}}</button>
-            </div>
-          {{else}}
-            <div class="btn-group pull-right">
-              <span data-toggle="dropdown">
-                <a class="fa fa-gear"></a>
-              </span>
-              <ul class="dropdown-menu" role="menu">
-                {{#each link in links}}
-                  <li {{action 'executeAction' link}}><a>{{tb-helper link}}</a></li>
-                {{/each}}
-              </ul>
-            </div>
-          {{/if}}
-        </td>
-      </tr>
+    {{#each udf in model}}
+      {{udf-tr-view udf=udf
+                    fileResources=fileResources
+                    columns=columns
+                    onAddFileResource="handleAddFileResource"
+                    onDeleteFileResource="handleDeleteFileResource"
+                    onSaveUdf="handleSaveUdf"
+                    onDeleteUdf='handleDeleteUdf'}}
     {{/each}}
   </tbody>
 </table>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/utils/constants.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/utils/constants.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/utils/constants.js
index 0539463..e4e445a 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/utils/constants.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/utils/constants.js
@@ -78,10 +78,9 @@ export default Ember.Object.create({
     databaseTree: 'databases-tree',
     databaseSearch: 'databases-search-results',
     settings: 'settings',
-    settingsQuery: 'settings-query',
-    settingsGlobal: 'settings-global',
     jobProgress: 'job-progress',
-    queryTabs: 'query-tabs'
+    queryTabs: 'query-tabs',
+    session: 'session'
   },
 
   hiveParameters: [
@@ -190,16 +189,13 @@ export default Ember.Object.create({
 
   //this can be replaced by a string.format implementation
   adapter: {
-    version: '0.4.0',
+    version: '1.0.0',
     instance: 'Hive',
     apiPrefix: '/api/v1/views/HIVE/versions/',
     instancePrefix: '/instances/',
     resourcePrefix: 'resources/'
   },
 
-  settings: {
-    executionEngine: 'hive.execution.engine'
-  },
   sampleDataQuery: 'SELECT * FROM %@ LIMIT 100;',
 
   notify: {
@@ -219,5 +215,9 @@ export default Ember.Object.create({
       typeClass : 'alert-info',
       typeIcon  : 'fa-info'
     }
+  },
+
+  globalSettings: {
+    comment: "--Global Settings--\n\n"
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/app/views/visual-explain.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/views/visual-explain.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/views/visual-explain.js
index d2a800c..8d85e20 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/app/views/visual-explain.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/views/visual-explain.js
@@ -440,6 +440,8 @@ export default Ember.View.extend({
       return array;
     };
 
+    this.set('edges', []);
+
     // Create a new directed graph
     var g = this.get('graph');
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js b/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
index 3ac9d8a..d66c899 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
@@ -23,31 +23,24 @@ moduleFor('controller:index', 'IndexController', {
   needs: [
           'controller:open-queries',
           'controller:udfs',
-          // 'controller:insert-udfs',
           'controller:index/history-query/logs',
           'controller:index/history-query/results',
           'controller:index/history-query/explain',
           'controller:settings',
-          'controller:job-progress',
           'controller:visual-explain',
           'controller:tez-ui',
           'service:job',
           'service:file',
           'service:database',
           'service:notify',
+          'service:job-progress',
+          'service:session',
+          'service:settings',
           'adapter:application',
           'adapter:database'
         ]
 });
 
-test('when initialized, controller sets the queryProcessTabs.', function () {
-  expect(1);
-
-  var controller = this.subject();
-
-  ok(controller.get('queryProcessTabs', 'queryProcessTabs is initialized.'));
-});
-
 test('modelChanged calls update on the open-queries cotnroller.', function () {
   expect(1);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2580916a/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js b/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
index 6f20024..e770bdd 100644
--- a/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
@@ -20,7 +20,7 @@ import Ember from 'ember';
 import { moduleFor, test } from 'ember-qunit';
 
 moduleFor('controller:insert-udfs', 'InsertUdfsController', {
-  needs: ['controller:udf', 'controller:udfs' ]
+  needs: 'controller:udfs'
 });
 
 test('controller is initialized correctly', function () {


Mime
View raw message