Repository: ambari Updated Branches: refs/heads/branch-2.5 40e60bde8 -> f5b464999
AMBARI-19522. Hive View 2.0: Saving worksheet as saved query (pallavkul) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f5b46499 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f5b46499 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f5b46499 Branch: refs/heads/branch-2.5 Commit: f5b464999dad6674bb7b5b328d75b226dd27f317 Parents: 40e60bd Author: pallavkul <[email protected]> Authored: Mon Jan 16 14:21:43 2017 +0530 Committer: pallavkul <[email protected]> Committed: Mon Jan 16 14:23:33 2017 +0530 ---------------------------------------------------------------------- .../src/main/resources/ui/app/adapters/job.js | 6 ++ .../resources/ui/app/adapters/saved-query.js | 26 ++++++ .../resources/ui/app/components/query-editor.js | 2 + .../ui/app/components/query-result-table.js | 28 +++++- .../resources/ui/app/components/save-hdfs.js | 52 +++++++++++ .../main/resources/ui/app/models/saved-query.js | 29 ++++++ .../main/resources/ui/app/models/worksheet.js | 3 +- .../src/main/resources/ui/app/routes/queries.js | 4 - .../resources/ui/app/routes/queries/query.js | 93 +++++++++++++++++--- .../resources/ui/app/routes/savedqueries.js | 79 +++++++++++++++++ .../src/main/resources/ui/app/services/jobs.js | 26 ++++++ .../src/main/resources/ui/app/services/query.js | 12 +++ .../resources/ui/app/services/saved-queries.js | 52 +++++++++++ .../src/main/resources/ui/app/styles/app.scss | 2 +- .../templates/components/query-result-table.hbs | 29 ++++++ .../ui/app/templates/components/save-hdfs.hbs | 37 ++++++++ .../ui/app/templates/queries/query.hbs | 88 +++++++++++++----- .../resources/ui/app/templates/savedqueries.hbs | 52 +++++++++++ 18 files changed, 577 insertions(+), 43 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/adapters/job.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/adapters/job.js b/contrib/views/hive20/src/main/resources/ui/app/adapters/job.js index 8ccd7ad..e2f342e 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/adapters/job.js +++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/job.js @@ -27,5 +27,11 @@ export default ApplicationAdapter.extend({ getQuery(job) { let queryUrl = this.buildURL() + "/file" + encodeURI(job.get('queryFile')); console.log(queryUrl); + }, + + saveToHDFS(jobId, path){ + let resultUrl = this.urlForFindRecord(jobId, 'job').replace('/resources','') + "/results/csv/saveToHDFS?commence=true&file=" + path + ".csv"; + return this.ajax(resultUrl, 'GET'); } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/adapters/saved-query.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/adapters/saved-query.js b/contrib/views/hive20/src/main/resources/ui/app/adapters/saved-query.js new file mode 100644 index 0000000..5ee757b --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/saved-query.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 Ember from 'ember'; +import ApplicationAdapter from './application'; + +export default ApplicationAdapter.extend({ + buildURL(){ + return this._super(...arguments).replace('/resources','') + '/savedQueries/'; + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/components/query-editor.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/query-editor.js b/contrib/views/hive20/src/main/resources/ui/app/components/query-editor.js index b42c495..27d43d5 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/components/query-editor.js +++ b/contrib/views/hive20/src/main/resources/ui/app/components/query-editor.js @@ -21,6 +21,7 @@ import Ember from 'ember'; export default Ember.Component.extend({ tagName: "query-editor", + readOnly: false, _initializeEditor: function() { @@ -41,6 +42,7 @@ export default Ember.Component.extend({ lineNumbers: true, matchBrackets : true, autofocus: true, + readOnly: self.get('readOnly'), extraKeys: {'Ctrl-Space': 'autocomplete'} })); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/components/query-result-table.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/query-result-table.js b/contrib/views/hive20/src/main/resources/ui/app/components/query-result-table.js index 17df66d..429dfb3 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/components/query-result-table.js +++ b/contrib/views/hive20/src/main/resources/ui/app/components/query-result-table.js @@ -24,6 +24,8 @@ export default Ember.Component.extend({ classNames: ['query-result-table', 'clearfix'], + jobId: null, + queryResult: {'schema' :[], 'rows' :[]}, columns: Ember.computed('queryResult', function() { @@ -63,14 +65,17 @@ export default Ember.Component.extend({ return new Table(this.get('columns'), this.get('rows')); }), + showSaveHdfsModal:false, + + showDownloadCsvModal:false, + actions: { onScrolledToBottom() { - //this.send('goNextPage'); - console.log('hook for INFINITE scroll'); + //console.log('hook for INFINITE scroll'); }, onColumnClick(column) { - console.log('I am in onColumnClick'); + //console.log('I am in onColumnClick'); }, goNextPage(){ this.sendAction('goNextPage'); @@ -80,6 +85,23 @@ export default Ember.Component.extend({ }, expandQueryResultPanel(){ this.sendAction('expandQueryResultPanel'); + }, + + openSaveHdfsModal(){ + this.set('showSaveHdfsModal',true) + }, + + closeSaveHdfsModal(){ + this.set('showSaveHdfsModal',false) + }, + + saveToHDFS(jobId, pathName){ + console.log('saveToHDFS with jobId == ', jobId ); + console.log('saveToHDFS with pathName == ', pathName ); + + this.sendAction('saveToHDFS', jobId, pathName); + + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/components/save-hdfs.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/save-hdfs.js b/contrib/views/hive20/src/main/resources/ui/app/components/save-hdfs.js new file mode 100644 index 0000000..05b3b33 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/save-hdfs.js @@ -0,0 +1,52 @@ +/** + * 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.Component.extend({ + + label: null, + confirmText: 'Confirm', + rejectText: 'Reject', + + jobId: 0, + + savePathName: Ember.computed('jobId', function() { + return 'Worksheet_' + this.get('jobId'); + }), + + labelIcon: null, + confirmIcon: null, + rejectIcon: null, + + closable: true, + titleClass: 'primary', + confirmClass: 'primary', + rejectClass: 'default', + + actions: { + confirm() { + let pathName = $("input.path-name").val(); + this.sendAction('confirm', this.get('jobId'), pathName); + }, + + reject() { + this.sendAction('reject'); + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/models/saved-query.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/models/saved-query.js b/contrib/views/hive20/src/main/resources/ui/app/models/saved-query.js new file mode 100644 index 0000000..44536af --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/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/f5b46499/contrib/views/hive20/src/main/resources/ui/app/models/worksheet.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/models/worksheet.js b/contrib/views/hive20/src/main/resources/ui/app/models/worksheet.js index d254ed1..59395e6 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/models/worksheet.js +++ b/contrib/views/hive20/src/main/resources/ui/app/models/worksheet.js @@ -32,5 +32,6 @@ export default DS.Model.extend({ currentJobData: DS.attr({defaultValue: null}), hidePreviousButton: DS.attr('boolean', { defaultValue: true}), selectedTablesModels: DS.attr(), - selectedMultiDb: DS.attr() + selectedMultiDb: DS.attr(), + queryFile: DS.attr('string', {defaultValue: ""}) }); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/routes/queries.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/queries.js b/contrib/views/hive20/src/main/resources/ui/app/routes/queries.js index 2346345..d9f0360 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/routes/queries.js +++ b/contrib/views/hive20/src/main/resources/ui/app/routes/queries.js @@ -69,10 +69,6 @@ export default Ember.Route.extend({ this.set('controller.worksheets', this.store.peekAll('worksheet')); this.transitionTo('queries.query', localWs.title); - }, - - saveWorksheet(){ - // Here we will save the worksheet with some title. } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/routes/queries/query.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/queries/query.js b/contrib/views/hive20/src/main/resources/ui/app/routes/queries/query.js index 5eac78a..d4c82fa 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/routes/queries/query.js +++ b/contrib/views/hive20/src/main/resources/ui/app/routes/queries/query.js @@ -21,6 +21,8 @@ import Ember from 'ember'; export default Ember.Route.extend({ query: Ember.inject.service(), + jobs: Ember.inject.service(), + savedQueries: Ember.inject.service(), beforeModel(){ let existingWorksheets = this.store.peekAll('worksheet'); @@ -30,9 +32,7 @@ export default Ember.Route.extend({ }, afterModel(model) { - let dbmodel = this.store.findAll('database'); - if (dbmodel.get('length') > 0) { this.selectDatabase(dbmodel); } @@ -48,6 +48,10 @@ export default Ember.Route.extend({ this._super(...arguments); + controller.set('showWorksheetModal',false); + controller.set('worksheetModalSuccess',false); + controller.set('worksheetModalFail',false); + let self = this; let alldatabases = this.store.findAll('database'); @@ -61,7 +65,8 @@ export default Ember.Route.extend({ selectedTablesModels.pushObject( { 'dbname': selecteDBName , - 'tables': this.store.query('table', {databaseId: selecteDBName}) + 'tables': this.store.query('table', {databaseId: selecteDBName}), + 'isSelected': true } ) @@ -74,6 +79,7 @@ export default Ember.Route.extend({ controller.set('isQueryRunning', false); controller.set('currentQuery', model.get('query')); controller.set('queryResult', model.get('queryResult')); + controller.set('currentJobId', null); }, @@ -86,11 +92,12 @@ export default Ember.Route.extend({ let selectedTablesModels =[]; let selectedMultiDb = []; - selectedDBs.forEach(function(db){ + selectedDBs.forEach(function(db, index){ selectedTablesModels.pushObject( { 'dbname': db , - 'tables':self.store.query('table', {databaseId: db}) + 'tables':self.store.query('table', {databaseId: db}), + 'isSelected': (index === 0) ? true :false } ) selectedMultiDb.pushObject(db); @@ -103,23 +110,26 @@ export default Ember.Route.extend({ this.get('controller').set('selectedMultiDb', selectedMultiDb ); this.get('controller.model').set('selectedMultiDb', selectedMultiDb ); - }, showTables(db){ + let self = this; //should we do this by writing a seperate component. $('#' + db).toggle(); this.get('controller.model').set('selectedDb', db); }, executeQuery(isFirstCall){ + let self = this; + this.get('controller').set('currentJobId', null); let queryInput = this.get('controller').get('currentQuery'); this.get('controller.model').set('query', queryInput); let dbid = this.get('controller.model').get('selectedDb'); let worksheetTitle = this.get('controller.model').get('title'); + self.get('controller.model').set('jobData', []); self.get('controller').set('isQueryRunning', true); //Making the result set emply every time query runs. @@ -145,18 +155,21 @@ export default Ember.Route.extend({ "confFile":null, "globalSettings":""}; - this.get('query').createJob(payload).then(function(data) { // applying a timeout otherwise it goes for status code 409, although that condition is also handled in the code. setTimeout(function(){ self.get('controller.model').set('currentJobData', data); + self.get('controller.model').set('queryFile', data.job.queryFile); + + self.get('controller').set('currentJobId', data.job.id); + self.send('getJob', data); - }, 2000); + }, 2000); }, function(reason) { console.log(reason); }); - }, + getJob(data){ var self = this; @@ -187,7 +200,6 @@ export default Ember.Route.extend({ }, function(reason) { // on rejection console.log('reason' , reason); - if( reason.errors[0].status == 409 ){ setTimeout(function(){ self.send('getJob',data); @@ -197,7 +209,7 @@ export default Ember.Route.extend({ }, updateQuery(){ - console.log('I am in update query.') + console.log('I am in update query.'); }, goNextPage(){ @@ -285,8 +297,65 @@ export default Ember.Route.extend({ }else { Ember.$('.ember-light-table').css('height', '70vh'); } - } + }, + + openWorksheetModal(){ + this.get('controller').set('showWorksheetModal', true); + }, + saveWorksheetModal(){ + console.log('I am in saveWorksheetModal'); + let newTitle = $('#worksheet-title').val(); + + let currentQuery = this.get('controller').get('currentQuery'); + let selectedDb = this.get('controller.model').get('selectedDb'); + let owner = this.get('controller.model').get('owner'); + let queryFile = this.get('controller.model').get('queryFile'); + + let payload = {"title" : newTitle, + "dataBase": selectedDb, + "owner" : owner, + "shortQuery" : (currentQuery.length > 0) ? currentQuery : ";", + "queryFile" : queryFile }; + + this.get('savedQueries').saveQuery(payload) + .then((data) => { + console.log('Created saved query.', data); + this.get('controller.model').set('title', newTitle); + this.get('controller').set('worksheetModalSuccess', true); + + Ember.run.later(() => { + this.get('controller').set('showWorksheetModal', false); + }, 2 * 1000); + + }, (error) => { + console.log("Error encountered", error); + Ember.run.later(() => { + this.get('controller').set('worksheetModalFail', true); + }, 2 * 1000); + }); + }, + + closeWorksheetModal(){ + this.get('controller').set('showWorksheetModal', false); + }, + + saveToHDFS(jobId, path){ + + console.log('saveToHDFS query route with jobId == ', jobId); + console.log('saveToHDFS query route with path == ', path); + + this.get('query').saveToHDFS(jobId, path) + .then((data) => { + Ember.run.later(() => { + console.log('successfully saveToHDFS', data); + }, 2 * 1000); + + }, (error) => { + console.log("Error encountered", error); + }); + + } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/routes/savedqueries.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/savedqueries.js b/contrib/views/hive20/src/main/resources/ui/app/routes/savedqueries.js index 8719170..7b9cb09 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/routes/savedqueries.js +++ b/contrib/views/hive20/src/main/resources/ui/app/routes/savedqueries.js @@ -19,4 +19,83 @@ import Ember from 'ember'; export default Ember.Route.extend({ + + savedQueries: Ember.inject.service(), + + model() { + return this.get('savedQueries').getAllQueries(); + }, + + setupController(controller, model) { + this._super(...arguments); + controller.set('showDeleteSaveQueryModal', false); + controller.set('selectedSavedQueryId', null); + }, + + actions: { + historySavedQuery(id){ + console.log('historySavedQuery', id); + }, + + deleteSavedQuery(){ + let queryId = this.get('controller').get('selectedSavedQueryId'); + + console.log('deleteSavedQuery', queryId); + this.get('savedQueries').deleteSaveQuery(queryId) + .then((data) => { + console.log('Deleted saved query.', data); + this.get('controller').set('showDeleteSaveQueryModal', false ); + //$(window).reload(); + }, (error) => { + console.log("Error encountered", error); + }); + }, + + deleteSavedQuerypDeclined(){ + this.get('controller').set('selectedSavedQueryId', null); + this.get('controller').set('showDeleteSaveQueryModal', false ); + }, + + openDeleteSavedQueryModal(id){ + this.get('controller').set('showDeleteSaveQueryModal', true ); + this.get('controller').set('selectedSavedQueryId', id ); + }, + + openAsWorksheet(savedQuery){ + + let hasWorksheetModel = this.modelFor('queries'); + let worksheetId; + + if (Ember.isEmpty(hasWorksheetModel)){ + worksheetId = 1; + }else { + + let isWorksheetExist = (this.controllerFor('queries').get('model').filterBy('title', savedQuery.title).get('length') > 0); + if(isWorksheetExist) { + this.transitionTo('queries.query', savedQuery.title); + return; + } + + let worksheets = this.controllerFor('queries').get('model'); + worksheets.forEach((worksheet) => { + worksheet.set('selected', false); + }); + worksheetId = `worksheet${worksheets.get('length') + 1}`; + } + + let localWs = { + id: worksheetId, + title: savedQuery.title, + query: savedQuery.shortQuery, + selectedDb : savedQuery.dataBase, + owner: savedQuery.owner, + selected: true + }; + + this.store.createRecord('worksheet', localWs ); + + this.transitionTo('queries.query', localWs.title); + } + } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/services/jobs.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/services/jobs.js b/contrib/views/hive20/src/main/resources/ui/app/services/jobs.js index 4928e5c..723953c 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/services/jobs.js +++ b/contrib/views/hive20/src/main/resources/ui/app/services/jobs.js @@ -24,5 +24,31 @@ export default Ember.Service.extend({ return this.get('store').findRecord('job', jobId).then((job) => { return this.get('store').findRecord('file', job.get('queryFile')); }) + }, + + waitForJobToComplete(jobId, after) { + return new Ember.RSVP.Promise((resolve, reject) => { + Ember.run.later(() => { + this.get('store').findRecord('job', jobId, {reload: true}) + .then((job) => { + let status = job.get('status').toLowerCase(); + if (status === 'succeeded') { + this._fetchDummyResult(jobId); + resolve(); + } else if (status === 'error') { + reject() + } else { + resolve(this.waitForJobToComplete(jobId, after)); + } + }, (error) => { + reject(error); + }); + }, after); + }); + }, + + _fetchDummyResult(jobId) { + this.get('store').adapterFor('job').fetchResult(jobId); } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/services/query.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/services/query.js b/contrib/views/hive20/src/main/resources/ui/app/services/query.js index 5a2f62d..d95a2e5 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/services/query.js +++ b/contrib/views/hive20/src/main/resources/ui/app/services/query.js @@ -40,6 +40,18 @@ export default Ember.Service.extend({ reject(err); }); }); + }, + + saveToHDFS(jobId, path){ + let self = this; + return new Promise( (resolve, reject) => { + this.get('store').adapterFor('job').saveToHDFS(jobId, path).then(function(data) { + resolve(data); + }, function(err) { + reject(err); + }); + }); } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/services/saved-queries.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/services/saved-queries.js b/contrib/views/hive20/src/main/resources/ui/app/services/saved-queries.js new file mode 100644 index 0000000..29ef4b5 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/services/saved-queries.js @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Service.extend({ + + store: Ember.inject.service(), + + getAllQueries(){ + let url = this.get('store').adapterFor('saved-query').buildURL(); + return $.ajax(url, 'GET') + }, + + saveQuery(payload){ + return $.ajax({ + type: "POST", + url: this.get('store').adapterFor('saved-query').buildURL(), + data: JSON.stringify({savedQuery: payload}) , + contentType:"application/json; charset=utf-8", + dataType:"json", + headers: {'X-Requested-By': 'ambari'} + }) + }, + deleteSaveQuery(id){ + let deletURL = this.get('store').adapterFor('saved-query').buildURL() + id; + + return $.ajax({ + type: "DELETE", + url: deletURL, + contentType:"application/json; charset=utf-8", + dataType:"json", + headers: {'X-Requested-By': 'ambari'} + }) + } + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss b/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss index 6bf8e5a..8e0ab21 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss +++ b/contrib/views/hive20/src/main/resources/ui/app/styles/app.scss @@ -287,7 +287,7 @@ pre { border: 1px solid darken($database-search-background, 25%); margin-right: 0; .expand-button{ - position: absolute;right: 5px;top: 5px;z-index: 9999;cursor: pointer; + position: absolute;right: 5px;top: 5px;z-index: 99;cursor: pointer; } } http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/templates/components/query-result-table.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/components/query-result-table.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/components/query-result-table.hbs index 441352e..4bda978 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/templates/components/query-result-table.hbs +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/components/query-result-table.hbs @@ -18,6 +18,15 @@ {{#if columns.length}} <div class="clearfix" style="text-align: right; padding-right:5px"> + + <span class="dropdown"> + <button class="btn btn-default dropdown-toggle" title="Actions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">{{fa-icon "bars"}} </button> + <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenu"> + <li><a href="#" {{action "openSaveHdfsModal" }} class="text-uppercase">{{fa-icon "save"}} Save To HDFS</a></li> + <li><a href="#" {{action "openDownloadCsvModal" }} class="text-uppercase">{{fa-icon "download"}} Download As CSV</a></li> + </ul> + </span> + <button class="btn btn-default" title="Previous Page" {{action "goPrevPage" }} >{{fa-icon "arrow-left"}} </button> <button class="btn btn-default" title="Next Page" {{action "goNextPage" }}>{{fa-icon "arrow-right"}} </button> <button class="btn btn-default" title="Expand/Collspse" {{action "expandQueryResultPanel" }}>{{fa-icon "expand"}}</button> @@ -49,5 +58,25 @@ {{/light-table}} </div> +{{#if showSaveHdfsModal}} + {{save-hdfs + confirmText="OK" + rejectText="CLOSE" + label="Please enter save path and name." + jobId=jobId + labelIcon="save" + rejectIcon="times" + confirmIcon="check" + closable=false + confirmClass="success" + confirm="saveToHDFS" + reject="closeSaveHdfsModal" + }} +{{/if}} + +{{#if showDownloadCsvModal}} +Yahoo +{{/if}} + {{yield}} http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/templates/components/save-hdfs.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/components/save-hdfs.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/components/save-hdfs.hbs new file mode 100644 index 0000000..5b53102 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/components/save-hdfs.hbs @@ -0,0 +1,37 @@ +{{! +* 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. +}} + +{{#modal-dialog + close="reject" + translucentOverlay=true + clickOutsideToClose=true + container-class="modal-dialog"}} + <div class="modal-content"> + <div class="modal-header text-{{titleClass}}"> + <button type="button" class="close" {{action "reject"}}><span aria-hidden="true">×</span></button> + </div> + <div class="modal-body"> + <p class="lead">{{#if labelIcon}}{{fa-icon labelIcon size="lg"}}{{/if}} {{label}}</p> + {{input class="form-control path-name" type="text" value=savePathName}} + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-{{rejectClass}}" {{action "reject"}}>{{#if rejectIcon}}{{fa-icon rejectIcon}} {{/if}}{{rejectText}}</button> + <button type="button" class="btn btn-{{confirmClass}}" {{action "confirm"}}>{{#if confirmIcon}}{{fa-icon confirmIcon}} {{/if}}{{confirmText}}</button> + </div> + </div> +{{/modal-dialog}} http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query.hbs index 371f404..120a045 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query.hbs +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query.hbs @@ -29,6 +29,7 @@ </div> <div class="row query-editor-controls"> <button class="btn btn-success" {{action "executeQuery" }}>{{fa-icon "check"}} Execute</button> + <button class="btn btn-default" {{action "openWorksheetModal" }}>{{fa-icon "save"}} Save As</button> {{#if isQueryRunning}} <img src="http://www.bba-reman.com/images/fbloader.gif" height="22" width="32" /> {{/if}} @@ -36,18 +37,20 @@ </div> <div class="clearfix row query-editor-results" style="position: relative"> {{query-result-table - queryResult=queryResult - updateQuery='updateQuery' - previousPage=worksheet.previousPage - hidePreviousButton=hidePreviousButton - goNextPage='goNextPage' - goPrevPage='goPrevPage' - expandQueryResultPanel='expandQueryResultPanel'}} + queryResult=queryResult + jobId=currentJobId + updateQuery='updateQuery' + previousPage=worksheet.previousPage + hidePreviousButton=hidePreviousButton + goNextPage='goNextPage' + goPrevPage='goPrevPage' + expandQueryResultPanel='expandQueryResultPanel' + saveToHDFS='saveToHDFS' + }} </div> </div> </div> - <div class="col-md-3 database-panel"> <div class="database-container"> <div class="row"> @@ -59,27 +62,27 @@ <a role="button" data-toggle="collapse" data-parent="#accordion" href="javascript:void(0)" {{action 'showTables' tableModel.dbname }} aria-expanded="true" aria-controls={{tableModel.dbname}}> - {{ tableModel.dbname }} + {{ tableModel.dbname }} {{#if tableModel.isSelected}} {{fa-icon "check"}} {{/if}} </a> <small class="pull-right">Tables({{tableModel.tables.length}})</small> </h4> </div> <div id={{ tableModel.dbname }} class="db-tables collapse panel-collapse {{if singleDbModel 'in'}}" role="tabpanel" aria-labelledby="headingOne"> - <div class="panel-body"> - {{#if tableModel.tables.length }} - {{#list-filter header="tables" items=tableModel.tables - placeholder="Search Tables" - as |filteredItems|}} - {{#list-group class="table-list" items=filteredItems as |item|}} - {{list-item item=item itemClicked="tableSelected"}} - {{/list-group}} - {{/list-filter}} - {{else}} - <div class="empty">No Table found.</div> - {{/if}} - </div> + <div class="panel-body"> + {{#if tableModel.tables.length }} + {{#list-filter header="tables" items=tableModel.tables + placeholder="Search Tables" + as |filteredItems|}} + {{#list-group class="table-list" items=filteredItems as |item|}} + {{list-item item=item itemClicked="tableSelected"}} + {{/list-group}} + {{/list-filter}} + {{else}} + <div class="empty">No Table found.</div> + {{/if}} </div> + </div> </div> {{/each}} </div> @@ -87,4 +90,45 @@ </div> </div> +{{#if showWorksheetModal}} + + {{#modal-dialog translucentOverlay=true clickOutsideToClose=true container-class="modal-dialog modal-sm"}} + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title">Saving worksheet</h4> + </div> + <div class="modal-body"> + <div class="form-horizontal"> + <div class="form-group"> + <label for="title" class="col-sm-2 control-label">Title</label> + <div class="col-sm-10"> + {{input type="text" class="form-control" id="worksheet-title" placeholder="Title" value=worksheet.title }} + </div> + </div> + + {{#if worksheetModalSuccess }} + <div class="text-success">Successfully Saved.</div> + {{/if}} + {{#if worksheetModalFail }} + <div class="text-danger">Error</div> + {{/if}} + + + </div> + </div> + + <div class="modal-footer"> + <button type="button" class="btn btn-default" {{action "saveWorksheetModal"}}>{{fa-icon "check"}} Save</button> + <button type="button" class="btn btn-default" {{action "closeWorksheetModal"}}>{{fa-icon "close"}} Cancel</button> + </div> + </div> + {{/modal-dialog}} + + +{{/if}} + + + + + {{outlet}} http://git-wip-us.apache.org/repos/asf/ambari/blob/f5b46499/contrib/views/hive20/src/main/resources/ui/app/templates/savedqueries.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/savedqueries.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/savedqueries.hbs index b776fd2..0ab6cfd 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/templates/savedqueries.hbs +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/savedqueries.hbs @@ -16,4 +16,56 @@ * limitations under the License. }} +<div class="row jobs-table"> + <div class="col-md-12"> + <table class="table table-striped"> + <thead> + <tr> + <th width="30%">Preview</th> + <th width="20%">Title</th> + <th width="20%">Database</th> + <th width="20%">Owner</th> + <th width="10%">Action</th> + </tr> + </thead> + <tbody> + {{#each model.savedQueries as |savedQuery| }} + <tr> + <td>{{savedQuery.shortQuery}}</td> + <td>{{savedQuery.title}}</td> + <td>{{savedQuery.dataBase}}</td> + <td>{{savedQuery.owner}}</td> + <td> + <div class="dropdown"> + <a class="dropdown-toggle" id="dropdownMenu1121" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">{{fa-icon "cog"}}</a> + <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenu"> + <li><a href="#" {{action "historySavedQuery" savedQuery.id }} class="text-uppercase">{{fa-icon "history"}} History</a></li> + <li><a href="#" {{action "openDeleteSavedQueryModal" savedQuery.id}} class="text-uppercase">{{fa-icon "remove"}} Delete</a></li> + <li><a href="#" {{action "openAsWorksheet" savedQuery }} class="text-uppercase">{{fa-icon "folder-open-o"}} Open as worksheet</a></li> + </ul> + </div> + </td> + </tr> + {{/each}} + </tbody> + </table> + </div> +</div> + +{{#if showDeleteSaveQueryModal}} + {{confirm-dialog + title="Confirm" + label="Do You want to delete the saved query?" + titleIcon="minus" + labelIcon="save" + rejectIcon="times" + confirmIcon="check" + closable=false + confirmClass="success" + confirm="deleteSavedQuery" + reject="deleteSavedQuerypDeclined" + }} +{{/if}} + + {{outlet}}
