ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alexantone...@apache.org
Subject [07/12] ambari git commit: AMBARI-9676. Initial Hive View Submission to Contrib (alexantonenko)
Date Tue, 24 Feb 2015 16:32:00 GMT
http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/explain.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/explain.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/explain.js
new file mode 100644
index 0000000..dc75280
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/explain.js
@@ -0,0 +1,119 @@
+/**
+ * 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';
+import utils from 'hive/utils/functions';
+
+export default Ember.ObjectController.extend({
+  cachedExplains: [],
+
+  clearCachedExplainSet: function (jobId) {
+    var existingJob = this.get('cachedExplains').findBy('id', jobId);
+
+    if (existingJob) {
+      this.set('cachedExplains', this.get('cachedExplains').without(existingJob));
+    }
+  },
+
+  initExplain: function () {
+    var cachedExplain;
+
+    cachedExplain = this.get('cachedExplains').findBy('id', this.get('content.id'));
+
+    if (cachedExplain) {
+      this.formatExplainResults(cachedExplain);
+    } else {
+      this.getExplain();
+    }
+  }.observes('content'),
+
+  getExplain: function () {
+    var self = this;
+    var url = this.container.lookup('adapter:application').buildURL();
+    url += '/' + constants.namingConventions.jobs + '/' + this.get('content.id') + '/results?first=true';
+
+    Ember.$.getJSON(url).then(function (data) {
+      var explainSet = self.get('cachedExplains').pushObject(Ember.Object.create({
+        id: self.get('content.id'),
+        explain: data
+      }));
+
+      self.set('content.explain', explainSet);
+
+      self.formatExplainResults(explainSet);
+    });
+  },
+
+  formatExplainResults: function (explainSet) {
+    var formatted = [],
+        orderedNodes = [],
+        currentNode,
+        currentNodeWhitespace,
+        previousNode,
+        formattedExplain = [],
+        getLeadingWhitespacesCount = function (str) {
+          return str.replace(utils.regexes.whitespaces, '$1').length;
+        };
+
+    explainSet = explainSet
+                 .get('explain.rows')
+                 .map(function (row) {
+                    return row[0];
+                  })
+                 .filter(Boolean)
+                 .map(function (str) {
+                    return {
+                      text: str,
+                      parentNode: null,
+                      contents: []
+                    }
+                  });
+
+    for (var i = 0; i < explainSet.length; i++) {
+      currentNode = explainSet[i];
+      previousNode = explainSet[i-1];
+
+      if (i > 0) {
+        currentNodeWhitespace = getLeadingWhitespacesCount(currentNode.text);
+
+        if (currentNodeWhitespace > getLeadingWhitespacesCount(previousNode.text)) {
+          currentNode.parentNode = previousNode;
+          previousNode.contents.pushObject(currentNode);
+        } else {
+          for (var j = i - 1; j >= 0; j--) {
+            if (currentNodeWhitespace === getLeadingWhitespacesCount(explainSet[j].text)) {
+              if (currentNodeWhitespace > 0) {
+                currentNode.parentNode = explainSet[j].parentNode;
+                currentNode.parentNode.contents.pushObject(currentNode);
+              } else {
+                formatted.pushObject(currentNode);
+              }
+
+              break;
+            }
+          }
+        }
+      } else {
+        formatted.pushObject(currentNode);
+      }
+    }
+
+    this.set('formattedExplain', formatted);
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/logs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/logs.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/logs.js
new file mode 100644
index 0000000..f633dd4
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/logs.js
@@ -0,0 +1,95 @@
+/**
+ * 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({
+  needs: [ constants.namingConventions.loadedFiles ],
+
+  files: Ember.computed.alias('controllers.' + constants.namingConventions.loadedFiles),
+
+  reloadJobLogs: function (job) {
+    var self = this,
+        defer = Ember.RSVP.defer(),
+        handleError = function (err) {
+          self.send('addAlert', constants.namingConventions.alerts.error, err.responseText);
+          defer.reject();
+        };
+
+    job.reload().then(function () {
+      self.get('files').reload(job.get('logFile')).then(function (file) {
+        var fileContent = file.get('fileContent');
+
+        if (fileContent) {
+          job.set('log', fileContent);
+        }
+
+        defer.resolve();
+      },function (err) {
+        handleError(err);
+      });
+    }, function (err) {
+      handleError(err);
+    });
+
+    return defer.promise;
+  },
+
+  listenForUpdates: function (job) {
+    Ember.run.later(this, function () {
+      var self = this;
+
+      this.reloadJobLogs(job).then(function () {
+        var stillRunning = self.isJobRunning(job);
+
+        //if the current model is the same with the one displayed, continue reloading job
+        if (stillRunning && job.get('id') === self.get('content.id')) {
+          self.listenForUpdates(job);
+        } else if (!stillRunning) {
+          job.set('isRunning', undefined);
+
+          if (job.get('id') === self.get('content.id')) {
+            self.transitionToRoute(constants.namingConventions.subroutes.jobResults);
+          }
+        }
+      });
+    }, 2000);
+  },
+
+  isJobRunning: function (job) {
+    var status = job.get('status');
+
+    return status !== constants.statuses.finished &&
+           status !== constants.statuses.canceled &&
+           status !== constants.statuses.closed &&
+           status !== constants.statuses.error;
+  },
+
+  getLogs: function () {
+    var self = this,
+        job = this.get('content');
+
+    if (this.isJobRunning(job)) {
+      job.set('isRunning', true);
+      this.reloadJobLogs(job).then(function () {
+        self.listenForUpdates(job);
+      });
+    }
+  }.observes('content')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/results.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/results.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/results.js
new file mode 100644
index 0000000..34e69bd
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/index/history-query/results.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.ObjectController.extend({
+  cachedResults: [],
+
+  keepAlive: function (job) {
+    Ember.run.later(this, function () {
+      var self = this;
+      var url = this.container.lookup('adapter:application').buildURL();
+      url += '/' + constants.namingConventions.jobs + '/' + job.get('id') + '/results/keepAlive';
+
+      var existingJob = self.cachedResults.findBy('id', job.get('id'));
+
+      if (existingJob) {
+        Ember.$.getJSON(url).fail(function (data) {
+          //backend issue, this will be split in done and fail callbacks once its fixed.
+          if (data.status === 404) {
+            existingJob.set('results', []);
+            self.send('getNextPage', true, job);
+          } else if (data.status === 200) {
+            self.keepAlive(job);
+          }
+        });
+      }
+    }, 1000 * 300);
+  },
+
+  clearCachedResultsSet: function (jobId) {
+    this.set('cachedResults', this.get('cachedResults').without(this.get('cachedResults').findBy('id', jobId)));
+  },
+
+  initResults: function () {
+    var existingJob;
+
+    if (this.get('content.status') !== constants.statuses.finished) {
+      return;
+    }
+
+    existingJob = this.cachedResults.findBy('id', this.get('content.id'));
+
+    if (existingJob) {
+      this.set('results', existingJob.results.findBy('offset', existingJob.get('offset')));
+    } else {
+      this.send('getNextPage', true);
+    }
+  }.observes('content.status'),
+
+  disableNext: function () {
+    return !this.get('results.hasNext');
+  }.property('results'),
+
+  disablePrevious: function () {
+    return this.cachedResults.findBy('id', this.get('content.id')).results.indexOf(this.get('results')) <= 0;
+  }.property('results'),
+
+  actions: {
+    getNextPage: function (firstPage, job) {
+      var self = this;
+      var id = job ? job.get('id') : this.get('content.id');
+      var existingJob = this.cachedResults.findBy('id', id);
+      var resultsIndex;
+      var url = this.container.lookup('adapter:application').buildURL();
+      url += '/' + constants.namingConventions.jobs + '/' + id + '/results';
+
+      if (firstPage) {
+        url += '?first=true';
+      }
+
+      if (existingJob) {
+        resultsIndex = existingJob.results.indexOf(this.get('results'));
+
+        if (~resultsIndex && resultsIndex < existingJob.get('results.length') - 1) {
+          this.set('results', existingJob.results.objectAt(resultsIndex + 1));
+          return;
+        }
+      }
+
+      Ember.$.getJSON(url).then(function (results) {
+        if (existingJob) {
+          existingJob.results.pushObject(results);
+          existingJob.set('offset', results.offset);
+        } else {
+          self.cachedResults.pushObject(Ember.Object.create({
+            id: id,
+            results: [ results ],
+            offset: results.offset
+          }));
+        }
+
+        //only set results if the method was called for the current model, not after a keepAlive request.
+        if (!job) {
+          self.set('results', results);
+        }
+
+        if (firstPage) {
+          self.keepAlive(job || self.get('content'));
+        }
+      }, function (err) {
+        self.set('error', err.responseText);
+      });
+    },
+
+    getPreviousPage: function () {
+      var existingJob,
+          resultsIndex;
+
+      existingJob = this.cachedResults.findBy('id', this.get('content.id'));
+      resultsIndex = existingJob.results.indexOf(this.get('results'));
+
+      if (resultsIndex > 0) {
+        this.set('results', existingJob.results.objectAt(resultsIndex - 1));
+      }
+    }
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/insert-udfs.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/insert-udfs.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/insert-udfs.js
new file mode 100644
index 0000000..fcfd113
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/insert-udfs.js
@@ -0,0 +1,58 @@
+/**
+ * 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.ArrayController.extend({
+  needs: [ constants.namingConventions.udfs, constants.namingConventions.fileResources ],
+
+  model: Ember.A(),
+
+  udfs: Ember.computed.alias('controllers.' + constants.namingConventions.udfs + '.udfs'),
+
+  updateUdfs: function () {
+    var self = this,
+        udfs = this.get('udfs'),
+        udfsWithoutFiles;
+
+    this.clear();
+
+    if (udfs && udfs.get('length')) {
+      udfs.getEach('fileResource.id').uniq().forEach(function (fileResourceId) {
+        if (fileResourceId) {
+          self.pushObject(Ember.Object.create({
+            file: udfs.findBy('fileResource.id', fileResourceId).get('fileResource'),
+            udfs: udfs.filterBy('fileResource.id', fileResourceId)
+          }));
+        }
+      });
+
+      udfsWithoutFiles = udfs.filter(function (udf) {
+        return !udf.get('isNew') && !udf.get('fileResource.id');
+      });
+
+      if (udfsWithoutFiles.get('length')) {
+       self.pushObject(Ember.Object.create({
+          name: "placeholders.select.noFileResource",
+          udfs: udfsWithoutFiles
+        }));
+      }
+    }
+  }.on('init').observes('udfs.@each.isNew')
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job.js
new file mode 100644
index 0000000..5bb1cd5
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/job.js
@@ -0,0 +1,49 @@
+/**
+ * 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({
+  needs: [ constants.namingConventions.history, constants.namingConventions.loadedFiles ],
+
+  files: Ember.computed.alias('controllers.' + constants.namingConventions.loadedFiles),
+
+  canStop: function () {
+    return this.get('status') === constants.statuses.running ||
+           this.get('status') === constants.statuses.initialized ||
+           this.get('status') === constants.statuses.pending;
+  }.property('status'),
+
+  actions: {
+    loadFile: function () {
+      var self = this;
+      if (!this.get('file')) {
+        this.get('files').loadFile(this.get('model.queryFile')).then(function (file) {
+          self.set('file', file);
+        });
+      }
+
+      this.set('expanded', !this.get('expanded'));
+    },
+
+    stop: function () {
+      this.send('interruptJob', this.get('model'));
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/loaded-files.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/loaded-files.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/loaded-files.js
new file mode 100644
index 0000000..3a11171
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/loaded-files.js
@@ -0,0 +1,65 @@
+/**
+ * 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.ArrayController.extend({
+  contains: function (obj) {
+    if (typeof obj === 'string') {
+      return this.findBy('id', obj);
+    }
+
+    return this._super(obj);
+  },
+
+  loadFile: function (path) {
+    var self = this;
+    var defer = Ember.RSVP.defer();
+    var file = this.contains(path);
+
+    if (file) {
+      defer.resolve(file);
+    } else {
+      this.store.find(constants.namingConventions.file, path).then(function (file) {
+        self.pushObject(file);
+        defer.resolve(file);
+      }, function (err) {
+        defer.reject(err);
+      });
+    }
+
+    return defer.promise;
+  },
+
+  reload: function (path) {
+    var defer = Ember.RSVP.defer();
+
+    this.store.find(constants.namingConventions.file, path).then(function (file) {
+      file.reload().then(function (reloadedFile) {
+        defer.resolve(reloadedFile);
+      }, function (err) {
+        defer.reject(err);
+      });
+    }, function (err) {
+      defer.reject(err);
+    });
+
+    return defer.promise;
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-delete.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-delete.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-delete.js
new file mode 100644
index 0000000..0fbcd6b
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-delete.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 default Ember.Controller.extend({
+  actions: {
+     delete: function () {
+      this.send('closeModal');
+      this.defer.resolve();
+    },
+
+    close: function () {
+      this.send('closeModal');
+      this.defer.reject();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-save.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-save.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-save.js
new file mode 100644
index 0000000..6dc1349
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/modal-save.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 default Ember.Controller.extend({
+  actions: {
+    save: function () {
+      this.send('closeModal');
+      this.defer.resolve(this.get('text'));
+    },
+
+    close: function () {
+      this.send('closeModal');
+      this.defer.reject();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/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
new file mode 100644
index 0000000..e97c0e6
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/open-queries.js
@@ -0,0 +1,320 @@
+/**
+ * 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.ArrayController.extend({
+  needs: [ constants.namingConventions.databases,
+           constants.namingConventions.loadedFiles,
+           constants.namingConventions.jobResults,
+           constants.namingConventions.jobExplain,
+           constants.namingConventions.columns,
+           constants.namingConventions.index,
+           constants.namingConventions.settings
+         ],
+
+  databases: Ember.computed.alias('controllers.' + constants.namingConventions.databases),
+
+  files: Ember.computed.alias('controllers.' + constants.namingConventions.loadedFiles),
+
+  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),
+
+  init: function () {
+    this._super();
+
+    this.set('queryTabs', Ember.ArrayProxy.create({ content: Ember.A([])}));
+  },
+
+  pushObject: function (queryFile, model) {
+    return this._super(queryFile || Ember.Object.create({
+      id: model.get('id'),
+      fileContent: ""
+    }));
+  },
+
+  getTabForModel: function (model) {
+    return this.get('queryTabs').find(function (tab) {
+      return tab.id === model.get('id') && tab.type === model.get('constructor.typeKey');
+    });
+  },
+
+  updateTabSubroute: function (model, path) {
+    var tab = this.get('queryTabs').find(function (tab) {
+      return tab.id === model.get('id') && tab.type === model.get('constructor.typeKey');
+    });
+
+    if (tab) {
+      tab.set('subroute', path);
+    }
+  },
+
+  getQueryForModel: function (model) {
+    return this.find(function (openQuery) {
+      if (model.get('isNew')) {
+        return openQuery.get('id') === model.get('id');
+      }
+
+      return openQuery.get('id') === model.get('queryFile');
+    });
+  },
+
+  update: function (model) {
+    var path,
+        type,
+        currentQuery,
+        defer = Ember.RSVP.defer(),
+        existentTab,
+        self = this,
+        updateSubroute = function () {
+          var isExplainedQuery,
+              subroute;
+
+          if (model.get('constructor.typeKey') === constants.namingConventions.job) {
+            isExplainedQuery = self.get('currentQuery.fileContent').indexOf(constants.namingConventions.explainPrefix) > -1;
+
+            if (isExplainedQuery) {
+              subroute = constants.namingConventions.subroutes.jobExplain;
+            } else {
+              subroute = constants.namingConventions.subroutes.jobLogs;
+            }
+
+            if (!existentTab.get('subroute')) {
+              self.updateTabSubroute(model, subroute);
+            }
+          }
+
+          defer.resolve(isExplainedQuery);
+        };
+
+    existentTab = this.getTabForModel(model);
+
+    if (!existentTab) {
+      type = model.get('constructor.typeKey');
+      path = type === constants.namingConventions.job ?
+             constants.namingConventions.subroutes.historyQuery :
+             constants.namingConventions.subroutes.savedQuery;
+
+      existentTab = this.get('queryTabs').pushObject(Ember.Object.create({
+        name: model.get('title'),
+        id: model.get('id'),
+        visible: true,
+        path: path,
+        type: type
+      }));
+
+      if (model.get('isNew')) {
+        this.set('currentQuery', this.pushObject(null, model));
+
+        defer.resolve();
+      } else {
+        this.get('files').loadFile(model.get('queryFile')).then(function (file) {
+          self.set('currentQuery', self.pushObject(file));
+
+          updateSubroute();
+        });
+
+        if (model.get('logFile') && !model.get('log')) {
+          this.get('files').loadFile(model.get('logFile')).then(function (file) {
+            model.set('log', file.get('fileContent'));
+          });
+        }
+      }
+    } else {
+      currentQuery = this.getQueryForModel(model);
+      this.set('currentQuery', currentQuery);
+
+      updateSubroute();
+    }
+
+    return defer.promise;
+  },
+
+  save: function (model, query) {
+    var tab = this.getTabForModel(model),
+        self = this,
+        wasNew,
+        defer = Ember.RSVP.defer(),
+        jobModel = model,
+        originalId = model.get('id');
+
+    if (!query) {
+      query = this.getQueryForModel(model);
+    }
+
+    if (model.get('isNew')) {
+      wasNew = true;
+      model.set('id', null);
+    }
+
+    //if current query it's a job, convert it to a savedQuery before saving
+    if (model.get('constructor.typeKey') === constants.namingConventions.job) {
+      model = this.store.createRecord(constants.namingConventions.savedQuery, {
+        dataBase: this.get('databases.selectedDatabase.name'),
+        title: model.get('title'),
+        queryFile: model.get('queryFile'),
+        owner: model.get('owner')
+      });
+    }
+
+    model.save().then(function (updatedModel) {
+      tab.set('name', updatedModel.get('title'));
+      jobModel.set('queryId', updatedModel.get('id'));
+
+      var content = self.get('index').prependQuerySettings(query.get('fileContent'));
+      //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('files').loadFile(updatedModel.get('queryFile')).then(function (file) {
+          file.set('fileContent', content);
+          file.save().then(function (updatedFile) {
+            self.removeObject(query);
+            self.pushObject(updatedFile);
+            self.set('currentQuery', updatedFile);
+
+            defer.resolve();
+          }, function (err) {
+            defer.reject(err);
+          });
+        }, function (err) {
+          defer.reject(err);
+        });
+      } else {
+        query.set('fileContent', content);
+        query.save().then(function () {
+          self.toggleProperty('tabUpdated');
+          defer.resolve();
+        }, function (err) {
+          defer.reject(err);
+        });
+      }
+    }, function (err) {
+      defer.reject(err);
+    });
+
+    return defer.promise;
+  },
+
+  convertTabToJob: function (model, job) {
+    var defer = Ember.RSVP.defer(),
+        oldQuery = this.getQueryForModel(model),
+        tab = this.getTabForModel(model),
+        jobId = job.get('id'),
+        self = this;
+
+    tab.set('id', job.get('id'));
+    tab.set('type', constants.namingConventions.job);
+    tab.set('path', constants.namingConventions.subroutes.historyQuery);
+
+    this.get('files').loadFile(job.get('queryFile')).then(function (file) {
+      //replace old model representing file to reflect model update to job
+      if (self.keepOriginalQuery(jobId)) {
+        file.set('fileContent', oldQuery.get('fileContent'));
+      }
+
+      self.removeObject(oldQuery);
+      self.pushObject(file);
+
+      defer.resolve();
+    }, function (err) {
+      defer.reject(err);
+    });
+
+    return defer.promise;
+  },
+
+  keepOriginalQuery: function (jobId) {
+    var selected = this.get('highlightedText');
+    var hasQueryParams = this.get('index.queryParams.length');
+    var hasSettings = this.get('settings').hasSettings(jobId);
+
+    if ( selected && selected[0] !== "" ||
+         hasQueryParams ||
+         hasSettings ) {
+      return true;
+    }
+
+    return false;
+  },
+
+  actions: {
+    removeQueryTab: function (tab) {
+      var self = this,
+          defer,
+          remainingTabs = this.get('queryTabs').without(tab),
+          lastTab = remainingTabs.get('lastObject'),
+          closeTab = function () {
+            self.set('queryTabs', remainingTabs);
+
+            //remove cached results set
+            if (tab.type === constants.namingConventions.job) {
+              self.get('jobResults').clearCachedResultsSet(tab.id);
+              self.get('jobExplain').clearCachedExplainSet(tab.id);
+            }
+
+            if (lastTab.type === constants.namingConventions.job) {
+              self.transitionToRoute(constants.namingConventions.subroutes.historyQuery, lastTab.id);
+            } else {
+              self.transitionToRoute(constants.namingConventions.subroutes.savedQuery, lastTab.id);
+            }
+          };
+
+      this.store.find(tab.type, tab.id).then(function (model) {
+        var query = self.getQueryForModel(model);
+
+        if ((model.get('isNew') && !query.get('fileContent')) ||
+            (!model.get('isNew') && !query.get('isDirty'))) {
+          closeTab();
+        } else {
+          defer = Ember.RSVP.defer();
+          self.send('openModal',
+                    'modal-save',
+                     {
+                        heading: "modals.save.saveBeforeCloseHeading",
+                        text: model.get('title'),
+                        defer: defer
+                     });
+
+          defer.promise.then(function (text) {
+            model.set('title', text);
+            self.save(model, query).then(function () {
+              closeTab();
+            });
+          }, function () {
+            model.rollback();
+            closeTab();
+          });
+        }
+      });
+    },
+
+    getColumnsForAutocomplete: function (tableName, callback) {
+      this.get('databases').getAllColumns(tableName).then(function () {
+        callback();
+      });
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/queries.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/queries.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/queries.js
new file mode 100644
index 0000000..85730a4
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/queries.js
@@ -0,0 +1,107 @@
+/**
+ * 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 ],
+
+  sortAscending: true,
+  sortProperties: [],
+
+  init: function () {
+    var oneYearAgo = new Date();
+    oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
+
+    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 () {
+    var queries = this.get('queries');
+    queries = queries ? queries.filterBy('isNew', false) : queries;
+
+    return this.filter(queries);
+  }.property('queries', 'filters.@each'),
+
+  actions: {
+    executeAction: function (action, savedQuery) {
+      switch (action) {
+        case "buttons.history":
+          this.get('controllers.' + constants.namingConventions.routes.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();
+          });
+
+          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 ]);
+      }
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/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
new file mode 100644
index 0000000..51101c5
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/settings.js
@@ -0,0 +1,150 @@
+/**
+ * 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.ArrayController.extend({
+  needs: [
+    constants.namingConventions.index,
+    constants.namingConventions.openQueries
+  ],
+
+  index: Ember.computed.alias('controllers.' + constants.namingConventions.index),
+  openQueries: Ember.computed.alias('controllers.' + constants.namingConventions.openQueries),
+
+  showSettingsOverlay: false,
+
+  querySettings: function () {
+    var currentId = this.get('index.model.id');
+    return this.findBy('id', currentId);
+  }.property('model.[]', 'index.model.id'),
+
+  updateSettingsId: function (oldId, newId) {
+    this.filterBy('id', oldId).setEach('id', newId);
+  },
+
+  getSettingsString: function (id) {
+    var currentId = id ? id : this.get('index.model.id');
+
+    var querySettings = this.findBy('id', currentId);
+
+    if (!querySettings) {
+      return "";
+    }
+
+    var settings = querySettings.get('settings').map(function (setting) {
+      return 'set %@ = %@;'.fmt(setting.key, setting.value);
+    });
+
+    if (querySettings.get('runOnTez')) {
+      settings.push('set %@ = tez;'.fmt(constants.settings.executionEngine));
+    }
+
+    return settings.join("\n");
+  },
+
+  hasSettings: function (id) {
+    id = id ? id : this.get('index.model.id');
+    var settings = this.findBy('id', id);
+
+    return settings && settings.get('settings.length');
+  },
+
+  parseQuerySettings: function () {
+    var id = this.get('index.model.id');
+    var query = this.get('openQueries.currentQuery');
+    var content = query.get('fileContent');
+    var runOnTez = false;
+
+
+    var regex = new RegExp(/^set\s+[\w-.]+(\s+|\s?)=(\s+|\s?)[\w-.]+(\s+|\s?);/gim);
+    var settings = content.match(regex);
+
+    if (!settings) {
+      return;
+    }
+
+    query.set('fileContent', content.replace(regex, '').trim());
+    settings = settings.map(function (setting) {
+      var KV = setting.split('=');
+
+      return {
+        key: KV[0].replace('set', '').trim(),
+        value: KV[1].replace(';', '').trim()
+      };
+    });
+
+    // remove runOnTez from settings
+    settings = settings.findBy('key', constants.settings.executionEngine).without(false);
+
+    this.setSettingForQuery(id, settings, !!runOnTez);
+  }.observes('openQueries.currentQuery', 'openQueries.tabUpdated'),
+
+  setSettingForQuery: function (id, settings, runOnTez) {
+    var querySettings = this.findBy('id', id);
+
+    if (!querySettings) {
+      this.pushObject(Ember.Object.create({
+        id: id,
+        settings: settings,
+        runOnTez: runOnTez
+      }));
+    } else {
+      querySettings.setProperties({
+        'settings': settings,
+        'runOnTez': runOnTez
+      });
+    }
+  },
+
+  createSettingsForQuery: function () {
+    var currentId = this.get('index.model.id');
+
+    if (!this.findBy('id', currentId)) {
+      this.pushObject(Ember.Object.create({
+        id: currentId,
+        settings: [],
+        runOnTez: false
+      }));
+    }
+  },
+
+  actions: {
+    toggleOverlay: function () {
+      // create a setting object if its not already there
+      this.createSettingsForQuery();
+      this.toggleProperty('showSettingsOverlay');
+    },
+
+    add: function () {
+      var currentId = this.get('index.model.id'),
+       querySettings = this.findBy('id', currentId);
+
+      querySettings.settings.pushObject(Ember.Object.create({
+        key: '',
+        value: ''
+      }));
+    },
+
+    remove: function (setting) {
+      var currentId = this.get('index.model.id');
+      this.findBy('id', currentId).settings.removeObject(setting);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/tables.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/tables.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/tables.js
new file mode 100644
index 0000000..1d773e7
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/tables.js
@@ -0,0 +1,93 @@
+/**
+ * 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({
+  pageCount: 10,
+
+  init: function () {
+    this._super();
+
+    var databaseAdapter = this.container.lookup('adapter:database');
+    var baseUrl = databaseAdapter.buildURL() + '/' +
+                  databaseAdapter.pathForType(constants.namingConventions.database) + '/';
+
+    this.set('baseUrl', baseUrl);
+  },
+
+  getTablesPage: function (database, searchTerm, firstSearchPage) {
+    var defer = Ember.RSVP.defer(),
+        url = this.get('baseUrl') +
+              database.get('name') +
+              '/table.page?count=';
+
+    url += this.get('pageCount');
+
+    if (searchTerm) {
+      url += '&searchId=searchTables' + '&like=' + searchTerm;
+
+      if (firstSearchPage) {
+        url += '&first=true';
+      }
+    } else if (!database.get('tables.length')) {
+      url += '&first=true';
+    }
+
+    Ember.$.getJSON(url).then(function (data) {
+      var tables;
+
+      tables = data.rows.map(function (row) {
+        return Ember.Object.create({
+          name: row[0]
+        });
+      });
+
+      defer.resolve({
+        tables: tables,
+        hasNext: data.hasNext
+      });
+    }, function (err) {
+      defer.reject(err);
+    });
+
+    return defer.promise;
+  },
+
+  getTables: function (databaseName) {
+    var defer = Ember.RSVP.defer(),
+        url = this.get('baseUrl') +
+              databaseName +
+              '/table';
+
+    Ember.$.getJSON(url).then(function (data) {
+      var tables = data.tables.map(function (table) {
+        return Ember.Object.create({
+          name: table
+        });
+      });
+
+      defer.resolve(tables);
+    }, function (err) {
+      defer.reject(err);
+    });
+
+    return defer.promise;
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/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
new file mode 100644
index 0000000..657743c
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udf.js
@@ -0,0 +1,138 @@
+/**
+ * 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({
+  needs: [ constants.namingConventions.udfs, constants.namingConventions.fileResources ],
+
+  columns: Ember.computed.alias('controllers.' + constants.namingConventions.udfs + '.columns'),
+  links: Ember.computed.alias('controllers.' + constants.namingConventions.udfs + '.links'),
+  fileResources: Ember.computed.alias('controllers.' + constants.namingConventions.fileResources),
+
+  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: Ember.I18n.translations.modals.delete.heading,
+                        text: Ember.I18n.translations.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/f5482d89/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
new file mode 100644
index 0000000..52faba1
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/controllers/udfs.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';
+import FilterableMixin from 'hive/mixins/filterable';
+import constants from 'hive/utils/constants';
+
+export default Ember.ArrayController.extend(FilterableMixin, {
+  itemController: constants.namingConventions.udf,
+
+  sortAscending: true,
+  sortProperties: [],
+
+  init: function () {
+    this._super();
+
+    this.set('columns', Ember.ArrayProxy.create({ content: Ember.A([
+      Ember.Object.create({
+        caption: 'placeholders.udfs.name',
+        property: 'name'
+      }),
+      Ember.Object.create({
+        caption: 'placeholders.udfs.className',
+        property: 'classname'
+      })
+    ])}));
+  },
+
+  //row buttons
+  links: [
+      'buttons.edit',
+      'buttons.delete'
+  ],
+
+  model: function () {
+    return this.filter(this.get('udfs'));
+  }.property('udfs', 'filters.@each'),
+
+  actions: {
+    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);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/.gitkeep b/contrib/views/hive/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/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/code-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/code-helper.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/code-helper.js
new file mode 100644
index 0000000..327636f
--- /dev/null
+++ b/contrib/views/hive/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/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/date-binding.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/date-binding.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/date-binding.js
new file mode 100644
index 0000000..4baeca8
--- /dev/null
+++ b/contrib/views/hive/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/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/log-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/log-helper.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/log-helper.js
new file mode 100644
index 0000000..c603c60
--- /dev/null
+++ b/contrib/views/hive/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/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/path-binding.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/path-binding.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/path-binding.js
new file mode 100644
index 0000000..e53772e
--- /dev/null
+++ b/contrib/views/hive/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/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/tb-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/tb-helper.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/helpers/tb-helper.js
new file mode 100644
index 0000000..fcce185
--- /dev/null
+++ b/contrib/views/hive/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/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/index.html
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/index.html b/contrib/views/hive/src/main/resources/ui/hive-web/app/index.html
new file mode 100644
index 0000000..4f609bd
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/index.html
@@ -0,0 +1,38 @@
+<!--
+ * 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">
+  </head>
+  <body>
+    {{content-for 'body'}}
+
+    <script src="assets/vendor.js"></script>
+    <script src="assets/hive.js"></script>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/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
new file mode 100644
index 0000000..0040307
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/initializers/i18n.js
@@ -0,0 +1,160 @@
+/**
+ * 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 = {
+  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.'
+      }
+    }
+  },
+  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:'
+    }
+  },
+  titles: {
+    database: 'Database Explorer',
+    explorer: 'Databases',
+    results: 'Search Results',
+    settings: 'Database Settings',
+    query: {
+      editor: 'Query Editor',
+      process: 'Query Process Results',
+      parameters: 'Parameters'
+    },
+    download: 'Save results...'
+  },
+  placeholders: {
+    search: {
+      tables: 'Search tables...',
+      columns: 'Search columns in result tables...'
+    },
+    select: {
+      database: 'Select Database...',
+      udfs: 'Insert udfs',
+      file: 'Select File Resource...',
+      noFileResource: '(no file)'
+    },
+    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',
+    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 Query',
+    newUdf: 'New UDF',
+    history: 'History',
+    ok: 'OK',
+    stopJob: 'Stop execution',
+    close: 'Close',
+    clearFilters: 'Clear filters',
+    expand: 'Expand message',
+    collapse: 'Collapse message',
+    previousPage: 'previous',
+    nextPage: 'next',
+    loadMore: 'Load more...',
+    saveHdfs: 'Save to HDFS',
+    saveCsv: 'Download as CSV',
+    runOnTez: 'Run on Tez'
+  },
+  labels: {
+    noTablesMatches: 'No tables matches for'
+  },
+  popover: {
+    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'
+  }
+};

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/filterable.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/filterable.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/filterable.js
new file mode 100644
index 0000000..55d4593
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/filterable.js
@@ -0,0 +1,104 @@
+/**
+ * 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 () {
+      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 () {
+    if (!this.get('filters') || this.get('filters.length')) {
+      this.set('filters', Ember.A());
+    }
+  },
+
+  actions: {
+    filter: function (property, filterValue) {
+      this.updateFilters(property, filterValue);
+    },
+
+    clearFilters: function () {
+      this.clearFilters();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/sortable.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/sortable.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/sortable.js
new file mode 100644
index 0000000..f766032
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/mixins/sortable.js
@@ -0,0 +1,31 @@
+/**
+ * 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.SortableMixin.reopen({
+  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 ]);
+    }
+  }
+});
\ No newline at end of file

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

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/models/database.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/database.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/database.js
new file mode 100644
index 0000000..11ee144
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/database.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 DS from 'ember-data';
+
+var Database = DS.Model.extend({
+  name: DS.attr()
+});
+
+export default Database;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file-resource.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file-resource.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file-resource.js
new file mode 100644
index 0000000..47f4911
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file-resource.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 DS from 'ember-data';
+
+export default DS.Model.extend({
+  name: DS.attr(),
+  path: DS.attr(),
+  owner: DS.attr()
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file.js
new file mode 100644
index 0000000..f8f1b9b
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/file.js
@@ -0,0 +1,26 @@
+/**
+ * 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 DS from 'ember-data';
+
+export default DS.Model.extend({
+  fileContent: DS.attr(),
+  hasNext: DS.attr(),
+  page: DS.attr,
+  pageCount: DS.attr()
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/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
new file mode 100644
index 0000000..95e5d57
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/job.js
@@ -0,0 +1,32 @@
+/**
+ * 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 DS from 'ember-data';
+
+export default DS.Model.extend({
+  title: DS.attr('string'),
+  queryId: DS.attr(),
+  queryFile: DS.attr('string'),
+  owner: DS.attr('string'),
+  dataBase: DS.attr('string'),
+  duration: DS.attr(),
+  status: DS.attr('string'),
+  dateSubmitted: DS.attr('date'),
+  forcedContent: DS.attr('string'),
+  logFile: DS.attr('string')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/models/saved-query.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/saved-query.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/saved-query.js
new file mode 100644
index 0000000..44536af
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/saved-query.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 DS from 'ember-data';
+
+var Model = DS.Model.extend({
+  dataBase: DS.attr('string'),
+  title: DS.attr('string'),
+  queryFile: DS.attr('string'),
+  owner: DS.attr('string'),
+  shortQuery: DS.attr('string')
+});
+
+export default Model;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/models/udf.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/models/udf.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/udf.js
new file mode 100644
index 0000000..c64221e
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/models/udf.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.
+ */
+
+import DS from 'ember-data';
+import constants from 'hive/utils/constants';
+
+export default DS.Model.extend({
+  name: DS.attr(),
+  classname: DS.attr(),
+  fileResource: DS.belongsTo(constants.namingConventions.fileResource, { async: true }),
+  owner: DS.attr()
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/f5482d89/contrib/views/hive/src/main/resources/ui/hive-web/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive/src/main/resources/ui/hive-web/app/router.js b/contrib/views/hive/src/main/resources/ui/hive-web/app/router.js
new file mode 100644
index 0000000..244bc58
--- /dev/null
+++ b/contrib/views/hive/src/main/resources/ui/hive-web/app/router.js
@@ -0,0 +1,47 @@
+ /**
+ * 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 config from './config/environment';
+import constants from 'hive/utils/constants';
+
+var Router = Ember.Router.extend({
+  location: config.locationType
+});
+
+Router.map(function() {
+  var savedQueryPath = constants.namingConventions.routes.queries + '/:' + constants.namingConventions.savedQuery + '_id';
+  var historyQueryPath = constants.namingConventions.routes.history + '/:' + constants.namingConventions.job + '_id';
+
+  this.route(constants.namingConventions.routes.queries);
+  this.route(constants.namingConventions.routes.history);
+  this.route(constants.namingConventions.routes.udfs);
+
+  this.resource(constants.namingConventions.routes.index, { path: '/' }, function () {
+    this.route(constants.namingConventions.routes.savedQuery, { path: savedQueryPath});
+    this.route(constants.namingConventions.routes.historyQuery, { path: historyQueryPath}, function () {
+      this.route(constants.namingConventions.routes.logs);
+      this.route(constants.namingConventions.routes.results);
+      this.route(constants.namingConventions.routes.explain);
+    });
+  });
+
+  this.route('loading');
+});
+
+export default Router;

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


Mime
View raw message