You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jl...@apache.org on 2016/06/27 23:36:36 UTC

[10/34] ambari git commit: AMBARI-17355 & AMBARI-17354: POC: FE & BE changes for first class support for Yarn hosted services

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/queries.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/queries.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/queries.js
new file mode 100644
index 0000000..cbf6b42
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/queries.js
@@ -0,0 +1,125 @@
+/**
+ * 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 FilterableMixin from 'hive/mixins/filterable';
+import constants from 'hive/utils/constants';
+
+export default Ember.ArrayController.extend(FilterableMixin, {
+  needs: [ constants.namingConventions.routes.history,
+           constants.namingConventions.openQueries ],
+
+  history: Ember.computed.alias('controllers.' + constants.namingConventions.routes.history),
+  openQueries: Ember.computed.alias('controllers.' + constants.namingConventions.openQueries),
+
+  sortAscending: true,
+  sortProperties: [],
+
+  init: function () {
+    this._super();
+
+    this.set('columns', Ember.ArrayProxy.create({ content: Ember.A([
+       Ember.Object.create({
+        caption: "columns.shortQuery",
+        property: 'shortQuery',
+        link: constants.namingConventions.subroutes.savedQuery
+      }),
+      Ember.Object.create({
+        caption: "columns.title",
+        property: 'title',
+        link: constants.namingConventions.subroutes.savedQuery
+      }),
+      Ember.Object.create({
+        caption: "columns.database",
+        property: 'dataBase',
+        link: constants.namingConventions.subroutes.savedQuery
+      }),
+      Ember.Object.create({
+        caption: "columns.owner",
+        property: 'owner',
+        link: constants.namingConventions.subroutes.savedQuery
+      })
+    ])}));
+  },
+
+  //row buttons
+  links: [
+    "buttons.history",
+    "buttons.delete"
+  ],
+
+  model: function () {
+    return this.filter(this.get('queries'));
+  }.property('queries', 'filters.@each'),
+
+  actions: {
+    executeAction: function (action, savedQuery) {
+      var self = this;
+
+      switch (action) {
+        case "buttons.history":
+          this.get('history').filterBy('queryId', savedQuery.get('id'), true);
+          this.transitionToRoute(constants.namingConventions.routes.history);
+          break;
+        case "buttons.delete":
+          var defer = Ember.RSVP.defer();
+          this.send('openModal',
+                    'modal-delete',
+                     {
+                        heading: "modals.delete.heading",
+                        text: "modals.delete.message",
+                        defer: defer
+                     });
+
+          defer.promise.then(function () {
+            savedQuery.destroyRecord();
+            self.get('openQueries').updatedDeletedQueryTab(savedQuery);
+          });
+
+          break;
+      }
+    },
+
+    sort: function (property) {
+      //if same column has been selected, toggle flag, else default it to true
+      if (this.get('sortProperties').objectAt(0) === property) {
+        this.set('sortAscending', !this.get('sortAscending'));
+      } else {
+        this.set('sortAscending', true);
+        this.set('sortProperties', [ property ]);
+      }
+    },
+
+    clearFilters: function () {
+      var columns = this.get('columns');
+
+      if (columns) {
+        columns.forEach(function (column) {
+          var filterValue = column.get('filterValue');
+
+          if (filterValue && typeof filterValue === 'string') {
+            column.set('filterValue');
+          }
+        });
+      }
+
+      //call clear filters from Filterable mixin
+      this.clearFilters();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/query-tabs.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
new file mode 100644
index 0000000..5f31c19
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/query-tabs.js
@@ -0,0 +1,176 @@
+/**
+ * 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({
+  jobProgressService: Ember.inject.service(constants.namingConventions.jobProgress),
+  openQueries   : Ember.inject.controller(constants.namingConventions.openQueries),
+  notifyService: Ember.inject.service(constants.namingConventions.notify),
+  index: Ember.inject.controller(),
+
+  tabClassNames : "fa queries-icon query-context-tab",
+
+  tabs: [
+    Ember.Object.create({
+      iconClass: 'text-icon',
+      id: 'query-icon',
+      text: 'SQL',
+      action: 'setDefaultActive',
+      name: constants.namingConventions.index,
+      tooltip: Ember.I18n.t('tooltips.query')
+    }),
+    Ember.Object.create({
+      iconClass: 'fa-gear',
+      id: 'settings-icon',
+      action: 'toggleOverlay',
+      template: 'settings',
+      outlet: 'overlay',
+      into: 'open-queries',
+      tooltip: Ember.I18n.t('tooltips.settings')
+    }),
+    Ember.Object.create({
+      iconClass: 'fa-area-chart',
+      id: 'visualization-icon',
+      action: 'toggleOverlay',
+      tooltip: Ember.I18n.t('tooltips.visualization'),
+      into: 'index',
+      outlet: 'overlay',
+      template: 'visualization-ui',
+      onTabOpen: 'onTabOpen'
+    }),
+    Ember.Object.create({
+      iconClass: 'fa-link',
+      id: 'visual-explain-icon',
+      action: 'toggleOverlay',
+      template: 'visual-explain',
+      outlet: 'overlay',
+      into: 'index',
+      onTabOpen: 'onTabOpen',
+      tooltip: Ember.I18n.t('tooltips.visualExplain')
+    }),
+    Ember.Object.create({
+      iconClass: 'text-icon',
+      id: 'tez-icon',
+      text: 'TEZ',
+      action: 'toggleOverlay',
+      template: 'tez-ui',
+      outlet: 'overlay',
+      into: 'index',
+      tooltip: Ember.I18n.t('tooltips.tez')
+    }),
+    Ember.Object.create({
+      iconClass: 'fa-envelope',
+      id: 'notifications-icon',
+      action: 'toggleOverlay',
+      template: 'messages',
+      outlet: 'overlay',
+      into: 'index',
+      badgeProperty: 'count',
+      onTabOpen: 'markMessagesAsSeen',
+      tooltip: Ember.I18n.t('tooltips.notifications')
+    })
+  ],
+
+  init: function() {
+    this.setupControllers();
+    this.setDefaultTab();
+    this.setupTabsBadges();
+  },
+
+  setupControllers: function() {
+    var tabs = this.get('tabs');
+    var self = this;
+
+    tabs.map(function (tab) {
+      var controller;
+
+      if (tab.get('template')) {
+        controller = self.container.lookup('controller:' + tab.get('template'));
+        tab.set('controller', controller);
+      }
+    });
+  },
+
+  setDefaultTab: function () {
+    var defaultTab = this.get('tabs.firstObject');
+
+    defaultTab.set('active', true);
+
+    this.set('default', defaultTab);
+    this.set('activeTab', defaultTab);
+  },
+
+  setupTabsBadges: function () {
+    var tabs = this.get('tabs').filterProperty('badgeProperty');
+
+    tabs.map(function (tab) {
+        Ember.oneWay(tab, 'badge', 'controller.' + tab.badgeProperty);
+    });
+  },
+
+  closeActiveOverlay: function () {
+    this.send('closeOverlay', this.get('activeTab'));
+  },
+
+  onTabOpen: function (tab) {
+    if (!tab.onTabOpen) {
+      return;
+    }
+
+    var controller = this.container.lookup('controller:' + tab.template);
+    controller.send(tab.onTabOpen, controller);
+  },
+
+  openOverlay: function (tab) {
+    this.closeActiveOverlay();
+    this.set('activeTab.active', false);
+    tab.set('active', true);
+    this.set('activeTab', tab);
+
+    this.onTabOpen(tab);
+    this.send('openOverlay', tab);
+  },
+
+  setDefaultActive: function () {
+    var activeTab = this.get('activeTab');
+    var defaultTab = this.get('default');
+
+    if (activeTab !== defaultTab) {
+      this.closeActiveOverlay();
+      defaultTab.set('active', true);
+      activeTab.set('active', false);
+      this.set('activeTab', defaultTab);
+    }
+  },
+
+  actions: {
+    toggleOverlay: function (tab) {
+      if (tab !== this.get('default') && tab.get('active')) {
+        this.setDefaultActive();
+      } else {
+        this.openOverlay(tab);
+      }
+    },
+
+    setDefaultActive: function () {
+      this.setDefaultActive();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/settings.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/settings.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/settings.js
new file mode 100644
index 0000000..77250b4
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/settings.js
@@ -0,0 +1,69 @@
+/**
+ * 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.Controller.extend({
+  openQueries: Ember.inject.controller(),
+  index: Ember.inject.controller(),
+
+  settingsService: Ember.inject.service('settings'),
+
+  predefinedSettings: Ember.computed.alias('settingsService.predefinedSettings'),
+  settings: Ember.computed.alias('settingsService.settings'),
+
+  init: function() {
+    this._super();
+
+    this.get('settingsService').loadDefaultSettings();
+  },
+
+  excluded: function() {
+    var settings = this.get('settings');
+
+    return this.get('predefinedSettings').filter(function(setting) {
+      return settings.findBy('key.name', setting.name);
+    });
+  }.property('settings.@each.key'),
+
+  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('settingsService').add();
+    },
+
+    remove: function (setting) {
+      this.get('settingsService').remove(setting);
+    },
+
+    addKey: function (name) {
+      this.get('settingsService').createKey(name);
+    },
+
+    removeAll: function () {
+      this.get('settingsService').removeAll();
+    },
+
+    saveDefaultSettings: function() {
+      this.get('settingsService').saveDefaultSettings();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/splash.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/splash.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/splash.js
new file mode 100644
index 0000000..5db93f7
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/splash.js
@@ -0,0 +1,126 @@
+/**
+ * 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({
+
+  databaseService: Ember.inject.service(constants.namingConventions.database),
+  isExpanded: false,
+  errors: "",
+  stackTrace: "",
+  startTests: function() {
+
+    var model = this.get('model');
+    var url = this.container.lookup('adapter:application').buildURL() + '/resources/hive/'
+    var self = this;
+
+    var processResponse = function(name, data) {
+
+      if( data != undefined ){
+        if(data.databases){
+          data = Ember.Object.create( {trace: null, message: "OK", status: "200"});
+        } else {
+          data = data;
+        }
+      } else {
+        data = Ember.Object.create( {trace: null, message: "Server Error", status: "500"});
+      }
+
+      model.set(name + 'Test', data.status == 200);
+
+      if (data.status != 200) {
+        var checkFailedMessage = "Service '" + name + "' check failed";
+        var errors = self.get("errors");
+        errors += checkFailedMessage;
+        errors += (data.message)?(': <i>' + data.message + '</i><br>'):'<br>';
+        self.set("errors", errors);
+      }
+
+      if (data.trace != null) {
+        var stackTrace = self.get("stackTrace");
+        stackTrace += checkFailedMessage + ':\n' + data.trace;
+        self.set("stackTrace", stackTrace);
+      }
+
+      model.set(name + 'TestDone', true);
+
+      var percent = model.get('percent');
+      model.set('percent', percent + 33.33);
+    };
+
+    var promises = ['hdfs', 'hiveserver', 'ats'].map(function(name) {
+
+      var finalurl = ((name == 'hiveserver') ? self.get('databaseService.baseUrl') : (url + name + 'Status')) || '' ;
+
+      return Ember.$.getJSON( finalurl )
+        .then(
+          function(data) {
+            processResponse(name, data);
+          },
+          function(reason) {
+            processResponse(name, reason.responseJSON);
+          }
+        );
+    });
+
+    return Ember.RSVP.all(promises);
+  },
+
+  progressBarStyle: function() {
+    return 'width: ' + this.get("model").get("percent") +  '%;';
+  }.property("model.percent"),
+
+  allTestsCompleted: function(){
+    return this.get('modelhdfsTestDone') && this.get('modelhiveserverTestDone') && this.get('modelatsTestDone');
+  }.property('modelhdfsTestDone', 'modelhiveserverTestDone', 'modelatsTestDone'),
+
+  modelhdfsTestDone: function() {
+    return this.get('model.hdfsTestDone');
+  }.property('model.hdfsTestDone' ),
+
+  modelhiveserverTestDone: function() {
+    return this.get('model.hiveserverTestDone');
+  }.property('model.hiveserverTestDone' ),
+
+  modelatsTestDone: function() {
+    return this.get('model.atsTestDone');
+  }.property('model.atsTestDone' ),
+
+  modelhdfsTest: function() {
+    return this.get('model.hdfsTest');
+  }.property('model.hdfsTest' ),
+
+  modelhiveserverTest: function() {
+    return this.get('model.hiveserverTest');
+  }.property('model.hiveserverTest' ),
+
+  modelatsTest: function() {
+    return this.get('model.atsTest');
+  }.property('model.atsTest' ),
+
+  actions: {
+    toggleStackTrace:function () {
+      var value = this.get('isExpanded');
+      this.set('isExpanded', !value);
+    }
+  }
+});
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/tez-ui.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/tez-ui.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/tez-ui.js
new file mode 100644
index 0000000..43835e0
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/tez-ui.js
@@ -0,0 +1,106 @@
+/**
+ * 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 ],
+
+  index: Ember.computed.alias('controllers.' + constants.namingConventions.index),
+
+  tezViewURL: null,
+  tezApiURL: '/api/v1/views/TEZ',
+  tezURLPrefix: '/views/TEZ',
+  tezDagPath: '?viewPath=/#/dag/',
+
+  isTezViewAvailable: Ember.computed.bool('tezViewURL'),
+
+  dagId: function () {
+    if (this.get('isTezViewAvailable')) {
+      return this.get('index.model.dagId');
+    }
+
+    return false;
+  }.property('index.model.dagId', 'isTezViewAvailable'),
+
+  dagURL: function () {
+    if (this.get('dagId')) {
+      return "%@%@%@".fmt(this.get('tezViewURL'), this.get('tezDagPath'), this.get('dagId'));
+    }
+
+    return false;
+  }.property('dagId'),
+
+  getTezView: function () {
+    if (this.get('isTezViewAvailable')) {
+      return;
+    }
+
+    var self = this;
+    Ember.$.getJSON(this.get('tezApiURL'))
+      .then(function (response) {
+        self.getTezViewInstance(response);
+      })
+      .fail(function (response) {
+        self.setTezViewError(response);
+      });
+  }.on('init'),
+
+  getTezViewInstance: function (data) {
+    var self = this;
+    var url = this.get('tezApiURL') + '/versions/' + data.versions[0].ViewVersionInfo.version;
+
+    Ember.$.getJSON(url)
+      .then(function (response) {
+        if (!response.instances.length) {
+          self.setTezViewError(response);
+          return;
+        }
+
+        self.set('isTezViewAvailable', true);
+
+        var instance = response.instances[0].ViewInstanceInfo;
+        self.setTezViewURL(instance);
+      });
+  },
+
+  setTezViewURL: function (instance) {
+    var url = "%@/%@/%@/".fmt(
+      this.get('tezURLPrefix'),
+      instance.version,
+      instance.instance_name
+    );
+
+    this.set('tezViewURL', url);
+  },
+
+  setTezViewError: function (data) {
+    // status: 404 => Tev View isn't deployed
+    if (data.status && data.status === 404) {
+      this.set('error', 'tez.errors.not.deployed');
+      return;
+    }
+
+    // no instance created
+    if (data.instances && !data.instances.length) {
+      this.set('error', 'tez.errors.no.instance');
+      return;
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/udfs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/udfs.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/udfs.js
new file mode 100644
index 0000000..3aec378
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/udfs.js
@@ -0,0 +1,143 @@
+/**
+ * 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 FilterableMixin from 'hive/mixins/filterable';
+import constants from 'hive/utils/constants';
+
+export default Ember.ArrayController.extend(FilterableMixin, {
+  fileResources: [],
+
+  sortAscending: true,
+  sortProperties: [],
+
+  columns: [
+    Ember.Object.create({
+      caption: 'placeholders.udfs.name',
+      property: 'name'
+    }),
+    Ember.Object.create({
+      caption: 'placeholders.udfs.className',
+      property: 'classname'
+    })
+  ],
+
+  model: function () {
+    return this.filter(this.get('udfs'));
+  }.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) {
+        this.set('sortAscending', !this.get('sortAscending'));
+      } else {
+        this.set('sortAscending', true);
+        this.set('sortProperties', [ property ]);
+      }
+    },
+
+    add: function () {
+      this.store.createRecord(constants.namingConventions.udf);
+    },
+
+    clearFilters: function () {
+      var columns = this.get('columns');
+
+      if (columns) {
+        columns.forEach(function (column) {
+          var filterValue = column.get('filterValue');
+
+          if (filterValue && typeof filterValue === 'string') {
+            column.set('filterValue');
+          }
+        });
+      }
+
+      //call clear filters from Filterable mixin
+      this.clearFilters();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
new file mode 100644
index 0000000..3f17760
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/upload-table.js
@@ -0,0 +1,740 @@
+/**
+ * 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 Uploader from 'hive/adapters/upload-table'
+import constants from 'hive/utils/constants';
+
+
+export default Ember.Controller.extend({
+  isLocalUpload : Ember.computed.equal("uploadSource","local"),
+  uploadSource : "local",
+  hdfsPath : "",
+  jobService: Ember.inject.service(constants.namingConventions.job),
+  notifyService: Ember.inject.service(constants.namingConventions.notify),
+  needs: ['databases'],
+  showErrors: false,
+  uploader: Uploader.create(),
+  baseUrl: "/resources/upload",
+  isFirstRowHeader: true, // is first row  header
+  header: null,  // header received from server
+  files: null, // files that need to be uploaded only file[0] is relevant
+  firstRow: [], // the actual first row of the table.
+  rows: null,  // preview rows received from server
+  databaseName: null,
+  selectedDatabase: null,
+  filePath: null,
+  tableName: null,
+  uploadProgressInfos : [],
+  onChangeUploadSource : function(){
+    this.clearFields();
+  }.observes("uploadSource"),
+  uploadProgressInfo : Ember.computed("uploadProgressInfos.[]",function(){
+    var info = "";
+    for( var i = 0 ; i < this.get('uploadProgressInfos').length ; i++)
+        info += this.get('uploadProgressInfos').objectAt(i);
+
+    return new Ember.Handlebars.SafeString(info);
+  }),
+  inputFileTypes :[
+    {id : "CSV", name : "CSV"},
+    {id : "JSON", name : "JSON"},
+    {id : "XML", name : "XML"}
+  ],
+  inputFileType : {id : "CSV", name : "CSV"},
+  inputFileTypeCSV : Ember.computed.equal('inputFileType.id',"CSV"),
+  fileTypes:[
+    "SEQUENCEFILE",
+    "TEXTFILE"    ,
+    "RCFILE"      ,
+    "ORC"         ,
+    "PARQUET"     ,
+    "AVRO"        ,
+    "INPUTFORMAT"
+  ],
+  selectedFileType: "ORC",
+  dataTypes: [
+    "TINYINT", //
+    "SMALLINT", //
+    "INT", //
+    "BIGINT", //
+    "BOOLEAN", //
+    "FLOAT", //
+    "DOUBLE", //
+    "STRING", //
+    "BINARY", // -- (Note: Available in Hive 0.8.0 and later)
+    "TIMESTAMP", // -- (Note: Available in Hive 0.8.0 and later)
+    "DECIMAL", // -- (Note: Available in Hive 0.11.0 and later)
+    "DATE", // -- (Note: Available in Hive 0.12.0 and later)
+    "VARCHAR", // -- (Note: Available in Hive 0.12.0 and later)
+    "CHAR" // -- (Note: Available in Hive 0.13.0 and later)
+  ],
+  isFirstRowHeaderDidChange: function () {
+    console.log("inside onFirstRowHeader : isFirstRowHeader : " + this.get('isFirstRowHeader'));
+    if (this.get('isFirstRowHeader') != null && typeof this.get('isFirstRowHeader') !== 'undefined') {
+      if (this.get('isFirstRowHeader') == false) {
+        if (this.get('rows')) {
+          this.get('rows').unshiftObject({row: this.get('firstRow')});
+        }
+      } else if( this.get('header') ) { // headers are available
+        // take first row of
+        this.get('header').forEach(function (item, index) {
+          console.log("item : ", item);
+          console.log("this.get('firstRow').objectAt(index)  : ", this.get('firstRow').objectAt(index));
+          Ember.set(item, 'name', this.get('firstRow')[index]);
+        }, this);
+
+        this.get('rows').removeAt(0);
+      }
+
+      this.printValues();
+    }
+  }.observes('isFirstRowHeader'),
+
+  popUploadProgressInfos : function(){
+    var msg = this.get('uploadProgressInfos').popObject();
+   // console.log("popedup message : " + msg);
+  },
+
+  pushUploadProgressInfos : function(info){
+    this.get('uploadProgressInfos').pushObject(info);
+   // console.log("pushed message : " + info);
+  },
+
+  clearUploadProgressModal : function(){
+  //  console.log("inside clearUploadProgressModal this.get('uploadProgressInfos') : " + this.get('uploadProgressInfos'));
+    var len = this.get('uploadProgressInfos').length;
+    for( var i = 0 ; i < len ; i++){
+      this.popUploadProgressInfos();
+    }
+  },
+
+  hideUploadModal : function(){
+    console.log("hiding the modal ....");
+    this.clearUploadProgressModal();
+    Ember.$("#uploadProgressModal").modal("hide");
+  },
+
+  showUploadModal : function(){
+    Ember.$("#uploadProgressModal").modal("show");
+  },
+
+  clearFields: function () {
+    this.set("hdfsPath");
+    this.set("header");
+    this.set("rows");
+    this.set("error");
+    this.set('isFirstRowHeader',true);
+    this.set('files');
+    this.set("firstRow");
+    this.set("selectedDatabase",null);
+    this.set("databaseName");
+    this.set("filePath");
+    this.set('tableName');
+    this.clearUploadProgressModal();
+    this.printValues();
+  },
+
+  printValues: function () {
+    console.log("printing all values : ");
+    console.log("header : ", this.get('header'));
+    console.log("rows : ", this.get('rows'));
+    console.log("error : ", this.get('error'));
+    console.log("isFirstRowHeader : ", this.get('isFirstRowHeader'));
+    console.log("files : ", this.get('files'));
+    console.log("firstRow : ", this.get('firstRow'));
+  },
+
+  generateTempTableName : function(){
+    var text = "";
+    var possible = "abcdefghijklmnopqrstuvwxyz";
+
+    for( var i=0; i < 30; i++ )
+      text += possible.charAt(Math.floor(Math.random() * possible.length));
+
+    return text;
+  },
+
+  waitForJobStatus: function (jobId, resolve, reject) {
+    console.log("finding status of job: ", jobId);
+    var self = this;
+    var fetchJobPromise = this.get('jobService').fetchJobStatus(jobId);
+      fetchJobPromise.then(function (data) {
+        console.log("waitForJobStatus : data : ", data);
+        var status = data.jobStatus;
+        if (status == "SUCCEEDED") {
+          console.log("resolving waitForJobStatus with : " , status);
+          resolve(status);
+        } else if (status == "CANCELED" || status == "CLOSED" || status == "ERROR") {
+          console.log("rejecting waitForJobStatus with : " + status);
+          reject(new Error(status));
+        } else {
+          console.log("retrying waitForJobStatus : ");
+          self.waitForJobStatus(jobId, resolve, reject);
+        }
+      }, function (error) {
+        console.log("rejecting waitForJobStatus with : " + error);
+        reject(error);
+    })
+  },
+
+  uploadForPreview: function (files) {
+    console.log("uploaderForPreview called.");
+    var self = this;
+    return this.get('uploader').uploadFiles('preview', files, {"isFirstRowHeader" : self.get("isFirstRowHeader"), "inputFileType" : self.get("inputFileType").id});
+  },
+
+  uploadForPreviewFromHDFS : function(){
+    console.log("uploadForPreviewFromHDFS called.");
+    return this.get('uploader').previewFromHDFS({"isFirstRowHeader" : this.get("isFirstRowHeader"),"inputFileType" : this.get("inputFileType").id , "hdfsPath" : this.get("hdfsPath") });
+  },
+
+  generatePreview : function(files){
+    var self = this;
+    var promise = null;
+    this.waitForGeneratingPreview();
+    if(this.get('isLocalUpload')){
+      promise = this.uploadForPreview(files);
+    }else{
+      promise = this.uploadForPreviewFromHDFS();
+    }
+
+    return promise.then(function (data) {
+        self.onGeneratePreviewSuccess(data);
+    }, function (error) {
+        self.onGeneratePreviewFailure(error);
+    });
+  },
+
+  waitForGeneratingPreview: function () {
+    console.log("waitForGeneratingPreview");
+    this.showUploadModal();
+    this.pushUploadProgressInfos("<li> Generating Preview .... </li>")
+  },
+
+  previewTable: function (data) {
+    console.log('inside previewTable');
+    this.set("header", data.header);
+    this.set("firstRow", data.rows[0].row);
+    console.log("firstRow : ", this.get('firstRow'));
+    this.set('isFirstRowHeader', data.isFirstRowHeader);
+    this.set('tableName',data.tableName);
+    if(data.isFirstRowHeader == true){
+        data.rows = data.rows.slice(1);
+    }
+    this.set("rows", data.rows);
+  },
+
+  onGeneratePreviewSuccess: function (data) {
+    console.log("onGeneratePreviewSuccess");
+    this.hideUploadModal();
+    this.previewTable(data);
+  },
+
+  onGeneratePreviewFailure: function (error) {
+    console.log("onGeneratePreviewFailure");
+    this.hideUploadModal();
+    this.setError(error);
+  },
+
+  createTable: function () {
+    console.log("table headers : ", this.get('header'));
+    var headers = this.get('header');
+
+    var selectedDatabase = this.get('selectedDatabase');
+    if (null == selectedDatabase || typeof selectedDatabase === 'undefined') {
+      throw new Error(Ember.I18n.t('hive.errors.emptyDatabase'));
+    }
+
+    this.set('databaseName', this.get('selectedDatabase').get('name'));
+    var databaseName = this.get('databaseName');
+    var tableName = this.get('tableName');
+    var isFirstRowHeader = this.get('isFirstRowHeader');
+    var filetype = this.get("selectedFileType");
+
+    if (null == databaseName || typeof databaseName === 'undefined' || databaseName == '') {
+      throw new Error(Ember.I18n.t('hive.errors.emptyDatabase'));
+    }
+    if (null == tableName || typeof tableName === 'undefined' || tableName == '') {
+      throw new Error(Ember.I18n.t('hive.errors.emptyTableName'));
+    }
+    if (null == isFirstRowHeader || typeof isFirstRowHeader === 'undefined') {
+      throw new Error(Ember.I18n.t('hive.errors.emptyIsFirstRow'));
+    }
+
+    this.validateColumns();
+
+    return this.get('uploader').createTable({
+      "isFirstRowHeader": isFirstRowHeader,
+      "header": headers,
+      "tableName": tableName,
+      "databaseName": databaseName,
+      "fileType":filetype
+    });
+  },
+
+  createActualTable : function(){
+    console.log("createActualTable");
+    this.pushUploadProgressInfos("<li> Starting to create Actual table.... </li>");
+    return this.createTable();
+  },
+
+  waitForCreateActualTable: function (jobId) {
+    console.log("waitForCreateActualTable");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Waiting for creation of Actual table.... </li>");
+    var self = this;
+    var p = new Ember.RSVP.Promise(function (resolve, reject) {
+      self.waitForJobStatus(jobId, resolve, reject);
+    });
+
+    return p;
+  },
+
+  onCreateActualTableSuccess : function(){
+    console.log("onCreateTableSuccess");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Successfully created Actual table. </li>");
+  },
+
+  onCreateActualTableFailure : function(error){
+    console.log("onCreateActualTableFailure");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Failed to create Actual table. </li>");
+    this.setError(error);
+  },
+
+  createTempTable : function(){
+    console.log("createTempTable");
+    this.pushUploadProgressInfos("<li> Starting to create Temporary table.... </li>");
+    var tempTableName = this.generateTempTableName();
+    this.set('tempTableName',tempTableName);
+    return this.get('uploader').createTable({
+      "isFirstRowHeader": this.get("isFirstRowHeader"),
+      "header": this.get("header"),
+      "tableName": tempTableName,
+      "databaseName": this.get('databaseName'),
+      "fileType":"TEXTFILE"
+    });
+  },
+
+  waitForCreateTempTable: function (jobId) {
+    console.log("waitForCreateTempTable");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Waiting for creation of Temporary table.... </li>");
+    var self = this;
+    var p = new Ember.RSVP.Promise(function (resolve, reject) {
+      self.waitForJobStatus(jobId, resolve, reject);
+    });
+
+    return p;
+  },
+
+  onCreateTempTableSuccess : function(){
+    console.log("onCreateTempTableSuccess");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Successfully created Temporary table. </li>");
+  },
+
+  deleteTable : function(databaseName, tableName){
+    console.log("deleting table " + databaseName + "." + tableName);
+
+    return this.get('uploader').deleteTable({
+      "database":  databaseName,
+      "table": tableName
+    });
+  },
+
+  deleteTableOnError : function(databaseName,tableName, tableLabel){
+      //delete table and wait for delete job
+    var self = this;
+    this.pushUploadProgressInfos("<li> Deleting " + tableLabel + " table...  </li>");
+
+    return this.deleteTable(databaseName,tableName).then(function(data){
+      return new Ember.RSVP.Promise(function(resolve,reject){
+        self.waitForJobStatus(data.jobId,resolve,reject);
+      });
+    }).then(function(){
+      self.popUploadProgressInfos();
+      self.pushUploadProgressInfos("<li> Successfully deleted " + tableLabel + " table. </li>");
+      return Ember.RSVP.Promise.resolve();
+    },function(err){
+      self.popUploadProgressInfos();
+      self.pushUploadProgressInfos("<li> Failed to delete " + tableLabel + " table. </li>");
+      self.setError(err);
+      return Ember.RSVP.Promise.reject();
+    });
+  },
+
+  rollBackActualTableCreation : function(){
+    return this.deleteTableOnError(this.get("databaseName"),this.get("tableName"),"Actual");
+  },
+
+
+  onCreateTempTableFailure : function(error){
+    console.log("onCreateTempTableFailure");
+    this.setError(error);
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Failed to create temporary table. </li>");
+    return this.rollBackActualTableCreation().then(function(data){
+      return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
+    },function(err){
+      return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
+    });
+  },
+
+  uploadFile : function(){
+    console.log("uploadFile");
+    this.pushUploadProgressInfos("<li> Starting to upload the file .... </li>");
+    if( this.get("isLocalUpload")){
+      return this.uploadTable();
+    }else{
+      return this.uploadTableFromHdfs();
+    }
+  },
+
+  waitForUploadingFile: function (data) {
+    console.log("waitForUploadingFile");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Waiting for uploading file .... </li>");
+    if( data.jobId ){
+      var self = this;
+          var p = new Ember.RSVP.Promise(function (resolve, reject) {
+            self.waitForJobStatus(data.jobId, resolve, reject);
+          });
+      return p;
+    }else{
+      return  Ember.RSVP.Promise.resolve(data);
+    }
+  },
+
+  onUploadingFileSuccess: function () {
+    console.log("onUploadingFileSuccess");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Successfully uploaded file. </li>");
+  },
+
+  rollBackTempTableCreation : function(){
+    var self = this;
+    return this.deleteTableOnError(this.get("databaseName"),this.get("tempTableName"),"Temporary").then(function(data){
+      return self.rollBackActualTableCreation();
+    },function(err){
+      return self.rollBackActualTableCreation();
+    })
+  },
+
+  onUploadingFileFailure: function (error) {
+    console.log("onUploadingFileFailure");
+    this.setError(error);
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Failed to upload file. </li>");
+    return this.rollBackTempTableCreation().then(function(data){
+      return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
+    },function(err){
+      return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
+    });
+  },
+
+  rollBackUploadFile : function(){
+    return this.rollBackTempTableCreation();
+  },
+
+  insertIntoTable : function(){
+    console.log("insertIntoTable");
+    this.pushUploadProgressInfos("<li> Starting to Insert rows from temporary table to actual table .... </li>");
+
+    return this.get('uploader').insertIntoTable({
+      "fromDatabase":  this.get("databaseName"),
+      "fromTable": this.get("tempTableName"),
+      "toDatabase": this.get("databaseName"),
+      "toTable": this.get("tableName")
+    });
+  },
+
+  waitForInsertIntoTable: function (jobId) {
+    console.log("waitForInsertIntoTable");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Waiting for Insertion of rows from temporary table to actual table .... </li>");
+    var self = this;
+    var p = new Ember.RSVP.Promise(function (resolve, reject) {
+      self.waitForJobStatus(jobId, resolve, reject);
+    });
+
+    return p;
+  },
+
+  onInsertIntoTableSuccess : function(){
+    console.log("onInsertIntoTableSuccess");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Successfully inserted rows from temporary table to actual table. </li>");
+  },
+
+  onInsertIntoTableFailure : function(error){
+    console.log("onInsertIntoTableFailure");
+    this.setError(error);
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Failed to insert rows from temporary table to actual table. </li>");
+    return this.rollBackUploadFile().then(function(data){
+      return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
+    },function(err){
+      return Ember.RSVP.Promise.reject(error); // always reject for the flow to stop
+    });
+  },
+
+  deleteTempTable : function(){
+    console.log("deleteTempTable");
+    this.pushUploadProgressInfos("<li> Starting to delete temporary table .... </li>");
+
+    return this.deleteTable(
+      this.get("databaseName"),
+      this.get("tempTableName")
+    );
+  },
+
+  waitForDeleteTempTable: function (jobId) {
+    console.log("waitForDeleteTempTable");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li> Waiting for deletion of temporary table .... </li>");
+    var self = this;
+    var p = new Ember.RSVP.Promise(function (resolve, reject) {
+      self.waitForJobStatus(jobId, resolve, reject);
+    });
+
+    return p;
+  },
+
+  onDeleteTempTableSuccess : function(){
+    console.log("onDeleteTempTableSuccess");
+    this.popUploadProgressInfos();
+    this.pushUploadProgressInfos("<li>Successfully inserted row. </li>");
+    this.onUploadSuccessfull();
+  },
+
+  onDeleteTempTableFailure : function(error){
+    console.log("onDeleteTempTableFailure");
+    this.setError(error);
+    this.setError("You will have to manually delete the table " + this.get("databaseName") + "." + this.get("tempTableName"));
+  },
+
+  createTableAndUploadFile : function(){
+    var self = this;
+    self.setError();
+    self.showUploadModal();
+    self.createActualTable()
+      .then(function(data){
+        console.log("1. received data : ", data);
+        return self.waitForCreateActualTable(data.jobId);
+      },function(error){
+        self.onCreateActualTableFailure(error);
+        console.log("Error occurred: ", error);
+        throw error;
+      })
+      .then(function(data){
+        console.log("2. received data : ", data);
+        self.onCreateActualTableSuccess(data);
+        return self.createTempTable(data);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          self.onCreateActualTableFailure(new Error("Server job for creation of actual table failed."));
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("3. received data : ", data);
+        return self.waitForCreateTempTable(data.jobId);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          return self.onCreateTempTableFailure(error);
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("4. received data : ", data);
+        self.onCreateTempTableSuccess(data);
+        return self.uploadFile(data);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          return self.onCreateTempTableFailure(new Error("Server job for creation of temporary table failed."));
+        }
+        throw error;
+      }).then(function(data){
+        console.log("4.5 received data : ", data);
+        return self.waitForUploadingFile(data);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          return self.onUploadingFileFailure(error);
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("5. received data : ", data);
+        self.onUploadingFileSuccess(data);
+        return self.insertIntoTable(data);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          return self.onUploadingFileFailure(new Error("Server job for upload of file failed."));
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("6. received data : ", data);
+        return self.waitForInsertIntoTable(data.jobId);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          return self.onInsertIntoTableFailure(error);
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("7. received data : ", data);
+        self.onInsertIntoTableSuccess(data);
+        return self.deleteTempTable(data);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          return self.onInsertIntoTableFailure(new Error("Server job for insert from temporary to actual table failed."));
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("8. received data : ", data);
+        return self.waitForDeleteTempTable(data.jobId);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          self.onDeleteTempTableFailure(error);
+        }
+        throw error;
+      })
+      .then(function(data){
+        console.log("9. received data : ", data);
+        self.onDeleteTempTableSuccess(data);
+      },function(error){
+        if(!self.get('error')){
+          console.log("Error occurred: ", error);
+          self.onDeleteTempTableFailure(new Error("Server job for deleting temporary table failed."));
+        }
+        throw error;
+      }).catch(function(error){
+        console.log("inside catch : ", error);
+      }).finally(function(){
+        console.log("finally hide the modal always");
+        self.hideUploadModal();
+      });
+  },
+
+  validateColumns: function () {
+    // throw exception if invalid.
+  },
+  setError: function (error) {
+    if(error){
+      console.log("upload table error : ", error);
+      this.set('error', JSON.stringify(error));
+      this.get('notifyService').error(error);
+    }else{
+      this.set("error");
+    }
+  },
+
+  previewError: function (error) {
+    this.setError(error);
+  },
+
+  uploadTableFromHdfs : function(){
+    console.log("uploadTableFromHdfs called.");
+    if(!(this.get("inputFileTypeCSV") == true && this.get("isFirstRowHeader") == false) ){
+      this.pushUploadProgressInfos("<li>Uploading file .... </li>");
+    }
+    return  this.get('uploader').uploadFromHDFS({
+        "isFirstRowHeader": this.get("isFirstRowHeader"),
+        "databaseName" :  this.get('databaseName'),
+        "tableName" : this.get("tempTableName"),
+        "inputFileType" : this.get("inputFileType").id,
+        "hdfsPath" : this.get("hdfsPath")
+      });
+  },
+  uploadTable: function () {
+    this.printValues();
+    return this.get('uploader').uploadFiles('upload', this.get('files'), {
+      "isFirstRowHeader": this.get("isFirstRowHeader"),
+      "databaseName" :  this.get('databaseName'),
+      "tableName" : this.get("tempTableName"),
+      "inputFileType" : this.get("inputFileType").id
+    });
+  },
+
+  onUploadSuccessfull: function (data) {
+    console.log("onUploadSuccessfull : ", data);
+    this.get('notifyService').success("Uploaded Successfully", "Table " + this.get('tableName') + " created in database " + this.get("databaseName"));
+    this.clearFields();
+  },
+
+  onUploadError: function (error) {
+    console.log("onUploadError : ", error);
+    this.setError(error);
+  },
+  showOrHide: function () {
+    if (this.get('show') == false) {
+      this.set("displayOption", "display:none");
+      this.set("showMoreOrLess", "Show More");
+    } else {
+      this.set("displayOption", "display:table-row");
+      this.set("showMoreOrLess", "Show Less");
+    }
+  },
+  displayOption: "display:none",
+  actions: {
+    toggleErrors: function () {
+      this.toggleProperty('showErrors');
+    },
+    filesUploaded: function (files) {
+      console.log("upload-table.js : uploaded new files : ", files);
+
+      this.clearFields();
+
+      this.set('files', files);
+      var name = files[0].name;
+      var i = name.indexOf(".");
+      var tableName = name.substr(0, i);
+      this.set('tableName', tableName);
+      var self = this;
+      return this.generatePreview(files)
+    },
+    previewFromHdfs : function(){
+      return this.generatePreview();
+    },
+    uploadTable : function(){
+      try{
+        this.createTableAndUploadFile();
+      }catch(e){
+        console.log("exception occured : ", e);
+        this.setError(e);
+        this.hideUploadModal();
+      }
+    },
+    uploadFromHDFS : function(){
+      this.set("isLocalUpload",false);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visual-explain.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
new file mode 100644
index 0000000..272aa11
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visual-explain.js
@@ -0,0 +1,64 @@
+/**
+ * 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({
+  jobProgressService: Ember.inject.service(constants.namingConventions.jobProgress),
+  openQueries   : Ember.inject.controller(constants.namingConventions.openQueries),
+  notifyService: Ember.inject.service(constants.namingConventions.notify),
+
+  index: Ember.inject.controller(),
+  verticesProgress: Ember.computed.alias('jobProgressService.currentJob.stages'),
+
+  actions: {
+    onTabOpen: function () {
+      var self = this;
+
+      // Empty query
+      if(this.get('openQueries.currentQuery.fileContent').length == 0){
+        this.set('json', undefined);
+        this.set('noquery', 'hive.errors.no.query');
+        return;
+      } else {
+        this.set('noquery', undefined);
+      }
+      // Introducing a common function
+      var getVisualExplainJson = function(){
+        self.set('showSpinner', undefined);
+        self.set('rerender');
+        self.get('index')._executeQuery(constants.jobReferrer.visualExplain, true, true).then(function (json) {
+          //this condition should be changed once we change the way of retrieving this json
+          if (json['STAGE PLANS']['Stage-1']) {
+            self.set('json', json);
+          } else {
+            self.set('json', {})
+          }
+        }, function (error) {
+          self.set('json', undefined);
+          self.get('notifyService').error(error);
+        });
+        self.toggleProperty('shouldChangeGraph');
+      }
+
+      getVisualExplainJson();
+
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visualization-ui.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visualization-ui.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visualization-ui.js
new file mode 100644
index 0000000..c908afd
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/controllers/visualization-ui.js
@@ -0,0 +1,134 @@
+/**
+* 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({
+  selectedRowCount: constants.defaultVisualizationRowCount,
+  needs: [ constants.namingConventions.index,
+            constants.namingConventions.openQueries,
+            constants.namingConventions.jobResults
+          ],
+  index         : Ember.computed.alias('controllers.' + constants.namingConventions.index),
+  openQueries   : Ember.computed.alias('controllers.' + constants.namingConventions.openQueries),
+  results   : Ember.computed.alias('controllers.' + constants.namingConventions.jobResults),
+  notifyService: Ember.inject.service(constants.namingConventions.notify),
+
+  polestarUrl: '',
+  voyagerUrl: '',
+  polestarPath: 'polestar/#/',
+  voyagerPath: 'voyager/#/',
+
+  showDataExplorer: true,
+  showAdvVisulization: false,
+
+  visualizationTabs: function () {
+    return [
+      Ember.Object.create({
+        name: 'Data Visualization',
+        id: 'visualization',
+        url: this.get('polestarUrl')
+      }),
+      Ember.Object.create({
+        name: 'Data Explorer',
+        id: 'data_explorer',
+        url: this.get('voyagerUrl')
+      })
+    ]
+  }.property('polestarUrl', 'voyagerUrl'),
+
+  activeTab: function () {
+    console.log("I am in activeTab function.");
+    this.get('visualizationTabs')[0].active = this.get("showDataExplorer");
+    this.get('visualizationTabs')[1].active = this.get("showAdvVisulization");
+  }.observes('polestarUrl', 'voyagerUrl'),
+
+  alterIframe: function () {
+    Ember.$("#visualization_frame").height(Ember.$("#visualization").height());
+  },
+
+  actions: {
+    onTabOpen: function () {
+      var self = this;
+      var model = this.get('index.model');
+      if (model) {
+        var existingJob = this.get('results').get('cachedResults').findBy('id', model.get('id'));
+        var url = this.container.lookup('adapter:application').buildURL();
+        url += '/' + constants.namingConventions.jobs + '/' + model.get('id') + '/results?&first=true';
+        url += '&count='+self.get('selectedRowCount')+'&job_id='+model.get('id')
+        if (existingJob) {
+          if(existingJob.results[0].rows.length === 0){
+            this.set("error", "Query has insufficient results to visualize the data.");
+            return;
+          }
+          this.set("error", null);
+          var id = model.get('id');
+          this.set("polestarUrl", this.get('polestarPath') + "?url=" + url);
+          this.set("voyagerUrl", this.get('voyagerPath') + "?url=" + url);
+          Ember.run.scheduleOnce('afterRender', this, function(){
+            self.alterIframe();
+          });
+        } else {
+          this.set("error", "No visualization available. Please execute a query and wait for the results to visualize the data.");
+        }
+      }
+    },
+
+      changeRowCount: function () {
+        var self = this;
+        if(isNaN(self.get('selectedRowCount')) || !(self.get('selectedRowCount')%1 === 0) || (self.get('selectedRowCount') <= 0)){
+          self.get('notifyService').error("Please enter a posive integer number.");
+          return;
+        }
+        var model = this.get('index.model');
+        if (model) {
+          var existingJob = this.get('results').get('cachedResults').findBy('id', model.get('id'));
+          var url = this.container.lookup('adapter:application').buildURL();
+          url += '/' + constants.namingConventions.jobs + '/' + model.get('id') + '/results?&first=true';
+          url += '&count='+self.get('selectedRowCount')+'&job_id='+model.get('id');
+          if (existingJob) {
+            this.set("error", null);
+            var id = model.get('id');
+
+            $('.nav-tabs.visualization-tabs li.active').each(function( index ) {
+
+              if($(this)[index].innerText.indexOf("Data Explorer") > -1){
+                self.set("showDataExplorer",true);
+                self.set("showAdvVisulization",false);
+                self.set("voyagerUrl", self.get('voyagerPath') + "?url=" + url);
+                self.set("polestarUrl", self.get('polestarPath') + "?url=" + url);
+                document.getElementById("visualization_frame").src =  self.get("voyagerUrl");
+              }
+              if($(this)[index].innerText.indexOf("Advanced Visualization") > -1){
+                self.set("showAdvVisulization",true);
+                self.set("showDataExplorer",false);
+                self.set("voyagerUrl", self.get('voyagerPath') + "?url=" + url);
+                self.set("polestarUrl", self.get('polestarPath') + "?url=" + url);
+                document.getElementById("visualization_frame").src = self.get("polestarUrl");
+              }
+            })
+            document.getElementById("visualization_frame").contentWindow.location.reload();
+          } else {
+            this.set("error", "No visualization available. Please execute a query and wait for the results to visualize data.");
+          }
+        }
+
+      }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/.gitkeep b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/all-uppercase.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/all-uppercase.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/all-uppercase.js
new file mode 100644
index 0000000..92930a9
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/all-uppercase.js
@@ -0,0 +1,25 @@
+/**
+ * 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 function allUppercase (input) {
+  return input ? input.toUpperCase() : input;
+}
+
+export default Ember.Handlebars.makeBoundHelper(allUppercase);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/code-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/code-helper.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/code-helper.js
new file mode 100644
index 0000000..8bbd19e
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/code-helper.js
@@ -0,0 +1,28 @@
+/**
+ * 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 function code (text) {
+  text = Ember.Handlebars.Utils.escapeExpression(text);
+  text = text.replace(/(\r\n|\n|\r)/gm, '<br>');
+
+  return new Ember.Handlebars.SafeString('<code>' + text + '</code>');
+}
+
+export default Ember.Handlebars.makeBoundHelper(code);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/date-binding.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/date-binding.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/date-binding.js
new file mode 100644
index 0000000..61251f8
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/date-binding.js
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+
+/* globals moment */
+
+import Ember from 'ember';
+
+export function pathBinding (data, key) {
+  return moment(data.get(key)).fromNow();
+}
+
+export default Ember.Handlebars.makeBoundHelper(pathBinding);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/format-column-type.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/format-column-type.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/format-column-type.js
new file mode 100644
index 0000000..13528b7
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/format-column-type.js
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ used to format the precision and scale of type in database's table's columns
+**/
+
+import Ember from "ember";
+
+var columnTypeFormatter = function(column) {
+  var type = column.type;
+  var ext = type;
+  if( type === "VARCHAR" || type === "CHAR" || type == "DECIMAL"  ) {
+      ext += '(' + column.precision;
+    if (type == "DECIMAL") {
+        ext += "," + column.scale;
+    }
+    ext += ")";
+  }
+
+  return ext;
+};
+
+export default Ember.Handlebars.makeBoundHelper(columnTypeFormatter);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/log-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/log-helper.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/log-helper.js
new file mode 100644
index 0000000..c29d129
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/log-helper.js
@@ -0,0 +1,28 @@
+/**
+ * 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 function log (text) {
+  text = Ember.Handlebars.Utils.escapeExpression(text);
+  text = text.replace(/(\r\n|\n|\r)/gm, '<br>');
+
+  return new Ember.Handlebars.SafeString(text);
+}
+
+export default Ember.Handlebars.makeBoundHelper(log);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/path-binding.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/path-binding.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/path-binding.js
new file mode 100644
index 0000000..926aaaa
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/path-binding.js
@@ -0,0 +1,29 @@
+/**
+ * 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 function pathBinding (data, key) {
+  if (!data || !key) {
+    return;
+  }
+
+  return data.get ? data.get(key) : data[key];
+}
+
+export default Ember.Handlebars.makeBoundHelper(pathBinding);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/preformatted-string.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/preformatted-string.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/preformatted-string.js
new file mode 100644
index 0000000..4ab6a2e
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/preformatted-string.js
@@ -0,0 +1,28 @@
+/**
+* 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 function preformattedString (string) {
+  string = string.replace(/\\n/g, '&#10;'); // newline
+  string = string.replace(/\\t/g, '&#09;'); // tabs
+  string = string.replace(/^\s+|\s+$/g, ''); // trim
+
+  return new Ember.Handlebars.SafeString(string);
+}
+
+export default Ember.Handlebars.makeBoundHelper(preformattedString);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/tb-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/tb-helper.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/tb-helper.js
new file mode 100644
index 0000000..81af5ff
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/helpers/tb-helper.js
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+export function tb (key, data) {
+  var path = data.get ? data.get(key) : data[key];
+
+  if (!path && key) {
+    return Ember.I18n.t(key);
+  }
+
+  if (path) {
+    return Ember.I18n.t(path);
+  }
+}
+
+export default Ember.Handlebars.makeBoundHelper(tb);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/index.html
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/index.html b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/index.html
new file mode 100644
index 0000000..2cbf9f0
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/index.html
@@ -0,0 +1,42 @@
+<!--
+ * 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.
+-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <title>Hive</title>
+    <meta name="description" content="">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+    {{content-for 'head'}}
+
+    <link rel="stylesheet" href="assets/vendor.css">
+    <link rel="stylesheet" href="assets/hive.css">
+
+    {{content-for 'head-footer'}}
+  </head>
+  <body>
+    {{content-for 'body'}}
+
+    <script src="assets/vendor.js"></script>
+    <script src="assets/hive.js"></script>
+
+    {{content-for 'body-footer'}}
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
new file mode 100644
index 0000000..b3630c1
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/initializers/i18n.js
@@ -0,0 +1,269 @@
+/**
+ * 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';
+
+var TRANSLATIONS;
+
+export default {
+  name: 'i18n',
+  initialize: function () {
+    Ember.ENV.I18N_COMPILE_WITHOUT_HANDLEBARS = true;
+    Ember.FEATURES.I18N_TRANSLATE_HELPER_SPAN = false;
+    Ember.I18n.translations = TRANSLATIONS;
+    Ember.TextField.reopen(Ember.I18n.TranslateableAttributes);
+  }
+};
+
+TRANSLATIONS = {
+  tooltips: {
+    refresh: 'Refresh database',
+    loadSample: 'Load sample data',
+    query: 'Query',
+    settings: 'Settings',
+    visualExplain: 'Visual Explain',
+    tez: 'Tez',
+    visualization: 'Visualization',
+    notifications: 'Notifications',
+    expand: 'Expand query panel',
+    makeSettingGlobal: 'Make setting global',
+    overwriteGlobalValue: 'Overwrite global setting value'
+  },
+
+  alerts: {
+    errors: {
+      save: {
+        query: "Error when trying to execute the query",
+        results: "Error when trying to save the results."
+      },
+      get: {
+        tables: 'Error when trying to retrieve the tables for the selected database',
+        columns: 'Error when trying to retrieve the table columns.'
+      },
+      sessions: {
+        delete: 'Error invalidating sessions'
+      },
+      job: {
+        status: "An error occured while processing the job."
+      }
+    },
+    success: {
+      sessions: {
+        deleted: 'Session invalidated.'
+      },
+      settings: {
+        saved: 'Settings have been saved.'
+      },
+      query: {
+        execution: 'Query has been submitted.',
+        save: 'The query has been saved.',
+        update: 'The query has been updated.'
+      }
+    }
+  },
+
+  modals: {
+    delete: {
+      heading: 'Confirm deletion',
+      message: 'Are you sure you want to delete this item?',
+      emptyQueryMessage: "Your query is empty. Do you want to delete this item?"
+    },
+
+    save: {
+      heading: 'Saving item',
+      saveBeforeCloseHeading: "Save item before closing?",
+      message: 'Enter name:',
+      overwrite: 'Saving will overwrite previously saved query'
+    },
+
+    download: {
+      csv: 'Download results as CSV',
+      hdfs: 'Please enter save path and name'
+    },
+
+    changeTitle: {
+      heading: 'Rename worksheet'
+    },
+    authenticationLDAP: {
+       heading: 'Enter the LDAP password'
+    }
+  },
+
+  titles: {
+    database: 'Database Explorer',
+    explorer: 'Databases',
+    results: 'Search Results',
+    settings: 'Database Settings',
+    query: {
+      tab: 'Worksheet',
+      editor: 'Query Editor',
+      process: 'Query Process Results',
+      parameters: 'Parameters',
+      visualExplain: 'Visual Explain',
+      tez: 'TEZ',
+      status: 'Status: ',
+      messages: 'Messages',
+      visualization: 'Visualization'
+    },
+    download: 'Save results...',
+    tableSample: '{{tableName}} sample'
+  },
+
+  placeholders: {
+    search: {
+      tables: 'Search tables...',
+      columns: 'Search columns in result tables...',
+      results: 'Filter columns...'
+    },
+    select: {
+      database: 'Select Database...',
+      udfs: 'Insert udfs',
+      file: 'Select File Resource...',
+      noFileResource: '(no file)',
+      value: "Select value..."
+    },
+    fileResource: {
+      name: "resource name",
+      path: "resource path"
+    },
+    udfs: {
+      name: 'udf name',
+      className: 'udf class name',
+      path: "resource path",
+      database: 'Select Database...'
+    },
+    settings: {
+      key: 'mapred.reduce.tasks',
+      value: '1'
+    }
+  },
+
+  menus: {
+    query: 'Query',
+    savedQueries: 'Saved Queries',
+    history: 'History',
+    udfs: 'UDFs',
+    uploadTable: 'Upload Table',
+    logs: 'Logs',
+    results: 'Results',
+    explain: 'Explain'
+  },
+
+  columns: {
+    id: 'id',
+    shortQuery: 'preview',
+    fileResource: 'file resource',
+    title: 'title',
+    database: 'database',
+    owner: 'owner',
+    user: 'user',
+    date: 'date submitted',
+    duration: 'duration',
+    status: 'status',
+    expand: '',
+    actions: ''
+  },
+
+  buttons: {
+    addItem: 'Add new item...',
+    insert: 'Insert',
+    delete: 'Delete',
+    cancel: 'Cancel',
+    edit: 'Edit',
+    execute: 'Execute',
+    explain: 'Explain',
+    saveAs: 'Save as...',
+    save: 'Save',
+    newQuery: 'New Worksheet',
+    newUdf: 'New UDF',
+    history: 'History',
+    ok: 'OK',
+    stopJob: 'Stop execution',
+    stoppingJob: 'Stopping...',
+    close: 'Close',
+    clearFilters: 'Clear filters',
+    expand: 'Expand message',
+    collapse: 'Collapse message',
+    previousPage: 'previous',
+    uploadTable: 'Upload Table',
+    showPreview: 'Preview',
+    nextPage: 'next',
+    loadMore: 'Load more...',
+    saveHdfs: 'Save to HDFS',
+    saveCsv: 'Download as CSV',
+    runOnTez: 'Run on Tez',
+    killSession: 'Kill Session'
+  },
+
+  labels: {
+    noTablesMatch: 'No tables match',
+    table: 'Table ',
+    hoursShort: "{{hours}} hrs",
+    minsShort: "{{minutes}} mins",
+    secsShort: "{{seconds}} secs"
+  },
+
+  popover: {
+    visualExplain: {
+      statistics: "Statistics"
+    },
+    queryEditorHelp: {
+      title: "Did you know?",
+      content: {
+        line1: "Press CTRL + Space to autocomplete",
+        line2: "You can execute queries with multiple SQL statements delimited by a semicolon ';'",
+        line3: "You can highlight and run a fragment of a query"
+      }
+    },
+    add: 'Add'
+  },
+
+  tez: {
+    errors: {
+      'not.deployed': "Tez View isn't deployed.",
+      'no.instance': "No instance of Tez View found.",
+      'no.dag': "No DAG available"
+    }
+  },
+
+  hive: {
+    errors: {
+      'no.query': "No query to process.",
+      'emptyDatabase' : "Please select Database.",
+      'emptyTableName' : "Please enter tableName.",
+      'emptyIsFirstRow' : "Please select is First Row Header?"
+    }
+  },
+
+  emptyList: {
+    history: {
+      noItems: "No queries were run.",
+      noMatches: "No jobs match your filtering criteria",
+    },
+    savedQueries: {
+      noItems: "No queries were saved.",
+      noMatches: "No queries match your filtering criteria"
+    }
+  },
+
+  settings: {
+    parsed: "Query settings added"
+  },
+
+  generalError: 'Unexpected error'
+};

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/contrib/views/hive-next/src/main/resources/ui/hive-web/app/mixins/filterable.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/app/mixins/filterable.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/mixins/filterable.js
new file mode 100644
index 0000000..aa1f4cd
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/app/mixins/filterable.js
@@ -0,0 +1,106 @@
+/**
+ * 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 utils from 'hive/utils/functions';
+
+export default Ember.Mixin.create({
+  init: function () {
+    this._super();
+    this.clearFilters();
+  },
+
+  filter: function (items) {
+    var self = this;
+
+    if (items && this.get('filters.length')) {
+      items = items.filter(function (item) {
+        return self.get('filters').every(function (filter) {
+          var propValue = item.get(filter.property);
+
+          if (!!filter.value) {
+            if (filter.min !== undefined && filter.max !== undefined) {
+              if (utils.isInteger(propValue)) {
+                return +propValue >= +filter.min && +propValue <= +filter.max;
+              } else if (utils.isDate(propValue)) {
+                return propValue >= filter.min && propValue <= filter.max;
+              } else {
+                return false;
+              }
+            } else if (filter.exactMatch) {
+              return propValue == filter.value;
+            } else {
+              return propValue && propValue.toLowerCase().indexOf(filter.value.toLowerCase()) > -1;
+            }
+          }
+
+          return false;
+        });
+      });
+    }
+
+    return items;
+  },
+
+  updateFilters: function (property, filterValue, exactMatch) {
+    var addFilter = function () {
+      if (!filterValue) {
+        return;
+      }
+
+      this.get('filters').pushObject(Ember.Object.create({
+        property: property,
+        exactMatch: exactMatch,
+        min: filterValue.min,
+        max: filterValue.max,
+        value: filterValue
+      }));
+    };
+
+    var existentFilter = this.get('filters').find(function (filter) {
+      return filter.property === property;
+    });
+
+    if (existentFilter) {
+      if (filterValue) {
+        //remove and add again for triggering collection change thus avoiding to add observers on individual properties of a filter
+        this.get('filters').removeObject(existentFilter);
+        addFilter.apply(this);
+      } else {
+        //ensures removal of the filterValue when it's an empty string
+        this.set('filters', this.get('filters').without(existentFilter));
+      }
+    } else {
+       addFilter.apply(this);
+    }
+  },
+
+  clearFilters: function () {
+    var filters = this.get('filters');
+
+    if (!filters || filters.get('length')) {
+      this.set('filters', Ember.A());
+    }
+  },
+
+  actions: {
+    filter: function (property, filterValue) {
+      this.updateFilters(property, filterValue);
+    }
+  }
+});