You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2014/02/13 00:12:33 UTC
git commit: AMBARI-4642. Jobs: implement server side filtering/limit
on Apps table (alexantonenko)
Updated Branches:
refs/heads/trunk f64fed6a1 -> 99a26c9a5
AMBARI-4642. Jobs: implement server side filtering/limit on Apps table (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/99a26c9a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/99a26c9a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/99a26c9a
Branch: refs/heads/trunk
Commit: 99a26c9a50cf019eefddb13d7aec03c6145eb65b
Parents: f64fed6
Author: Alex Antonenko <hi...@gmail.com>
Authored: Thu Feb 13 01:07:12 2014 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Thu Feb 13 01:07:12 2014 +0200
----------------------------------------------------------------------
.../app/controllers/main/jobs_controller.js | 220 ++++++++++++++++++-
ambari-web/app/messages.js | 7 +
ambari-web/app/styles/apps.less | 5 +
.../templates/main/jobs/custom_dates_popup.hbs | 39 ++++
ambari-web/app/views.js | 1 +
.../views/main/jobs/select_custom_date_view.js | 37 ++++
ambari-web/app/views/main/jobs_view.js | 22 +-
7 files changed, 303 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/controllers/main/jobs_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/jobs_controller.js b/ambari-web/app/controllers/main/jobs_controller.js
index 00980c7..c97b06b 100644
--- a/ambari-web/app/controllers/main/jobs_controller.js
+++ b/ambari-web/app/controllers/main/jobs_controller.js
@@ -26,10 +26,190 @@ App.MainJobsController = Em.ArrayController.extend({
loaded : false,
loading : false,
- /**
- * The number of jobs to be shown by last submitted time.
- */
- jobsLimit : -1,
+ loadJobsTimeout: null,
+
+ totalOfJobs: 0,
+ setTotalOfJobs: function () {
+ if(this.get('totalOfJobs') < this.get('content.length')){
+ this.set('totalOfJobs', this.get('content.length'));
+ }
+ }.observes('content.length'),
+
+ filterObject: Ember.Object.create({
+ id: "",
+ jobsLimit: -1,
+ user: "",
+ windowStart: "",
+ windowEnd: "",
+
+ /**
+ * Direct binding to startTime filter field
+ */
+ startTime: "",
+ onStartTimeChange:function(){
+ var time = "";
+ var curTime = new Date().getTime();
+ switch (this.get('startTime')) {
+ case 'Past 1 hour':
+ time = curTime - 3600000;
+ break;
+ case 'Past 1 Day':
+ time = curTime - 86400000;
+ break;
+ case 'Past 2 Days':
+ time = curTime - 172800000;
+ break;
+ case 'Past 7 Days':
+ time = curTime - 604800000;
+ break;
+ case 'Past 14 Days':
+ time = curTime - 1209600000;
+ break;
+ case 'Past 30 Days':
+ time = curTime - 2592000000;
+ break;
+ case 'Custom':
+ this.showCustomDatePopup();
+ break;
+ case 'Any':
+ time = "";
+ break;
+ }
+ if(this.get('startTime') != "Custom"){
+ this.set("windowStart", time);
+ this.set("windowEnd", "");
+ }
+ }.observes("startTime"),
+
+ // Fields values from Select Custom Dates form
+ customDateFormFields: Ember.Object.create({
+ startDate: null,
+ hoursForStart: null,
+ minutesForStart: null,
+ middayPeriodForStart: null,
+ endDate: null,
+ hoursForEnd: null,
+ minutesForEnd: null,
+ middayPeriodForEnd: null
+ }),
+
+ errors: Ember.Object.create({
+ isStartDateError: false,
+ isEndDateError: false
+ }),
+
+ errorMessages: Ember.Object.create({
+ startDate: '',
+ endDate: ''
+ }),
+
+ showCustomDatePopup: function () {
+ var self = this;
+ var windowEnd = "";
+ var windowStart = "";
+ App.ModalPopup.show({
+ header: Em.I18n.t('jobs.table.custom.date.header'),
+ onPrimary: function () {
+ self.validate();
+ if(self.get('errors.isStartDateError') || self.get('errors.isEndDateError')){
+ return false;
+ }
+
+ var windowStart = self.createCustomStartDate();
+ var windowEnd = self.createCustomEndDate();
+
+ self.set("windowEnd", windowStart.getTime());
+ self.set("windowStart", windowEnd.getTime());
+ this.hide();
+ },
+ onSecondary: function () {
+ self.set('startTime','Any');
+ this.hide();
+ },
+ bodyClass: App.JobsCustomDatesSelectView.extend({
+ controller: self
+ })
+ });
+ },
+
+ createCustomStartDate : function () {
+ var startDate = this.get('customDateFormFields.startDate');
+ var hoursForStart = this.get('customDateFormFields.hoursForStart');
+ var minutesForStart = this.get('customDateFormFields.minutesForStart');
+ var middayPeriodForStart = this.get('customDateFormFields.middayPeriodForStart');
+ if (startDate && hoursForStart && minutesForStart && middayPeriodForStart) {
+ return new Date(startDate + ' ' + hoursForStart + ':' + minutesForStart + ' ' + middayPeriodForStart);
+ }
+ return null;
+ },
+
+ createCustomEndDate : function () {
+ var endDate = this.get('customDateFormFields.endDate');
+ var hoursForEnd = this.get('customDateFormFields.hoursForEnd');
+ var minutesForEnd = this.get('customDateFormFields.minutesForEnd');
+ var middayPeriodForEnd = this.get('customDateFormFields.middayPeriodForEnd');
+ if (endDate && hoursForEnd && minutesForEnd && middayPeriodForEnd) {
+ return new Date(endDate + ' ' + hoursForEnd + ':' + minutesForEnd + ' ' + middayPeriodForEnd);
+ }
+ return null;
+ },
+
+ clearErrors: function () {
+ var errorMessages = this.get('errorMessages');
+ Em.keys(errorMessages).forEach(function (key) {
+ errorMessages.set(key, '');
+ }, this);
+ var errors = this.get('errors');
+ Em.keys(errors).forEach(function (key) {
+ errors.set(key, false);
+ }, this);
+ },
+
+ // Validation for every field in customDateFormFields
+ validate: function () {
+ var formFields = this.get('customDateFormFields');
+ var errors = this.get('errors');
+ var errorMessages = this.get('errorMessages');
+ this.clearErrors();
+ // Check if feild is empty
+ Em.keys(errorMessages).forEach(function (key) {
+ if (!formFields.get(key)) {
+ errors.set('is' + key.capitalize() + 'Error', true);
+ errorMessages.set(key, Em.I18n.t('jobs.customDateFilter.error.required'));
+ }
+ }, this);
+ // Check that endDate is after startDate
+ var startDate = this.createCustomStartDate();
+ var endDate = this.createCustomEndDate();
+ if (startDate && endDate && (startDate > endDate)) {
+ errors.set('isEndDateError', true);
+ errorMessages.set('endDate', Em.I18n.t('jobs.customDateFilter.error.date.order'));
+ }
+ },
+
+ /**
+ * Create link for server request
+ * @return {String}
+ */
+ createJobsFiltersLink: function() {
+ var link = "?fields=events,primaryfilters";
+
+ if(this.get("id") !== "") {
+ link = "/" + this.get("id") + link;
+ }
+ if(this.get("jobsLimit") != -1){
+ link += "&limit=" + this.get("jobsLimit");
+ }
+ if(this.get("user") !== ""){
+ link += "&primaryFilter=user:" + this.get("user");
+ }
+ if(this.get("startTime") !== ""){
+ link += this.get("windowStart") !== "" ? ("&windowStart=" + this.get("windowStart")) : "";
+ link += this.get("windowEnd") !== "" ? ("&windowEnd=" + this.get("windowEnd")) : "";
+ }
+ return link;
+ }
+ }),
/**
* List of users.
@@ -57,26 +237,42 @@ App.MainJobsController = Em.ArrayController.extend({
loadJobs : function() {
var self = this;
- var jobsLimit = this.get('jobsLimit');
var yarnService = App.YARNService.find().objectAt(0);
if (yarnService != null) {
this.set('loading', true);
- var historyServerHostName = yarnService.get('resourceManagerNode.hostName')
+ var historyServerHostName = yarnService.get('resourceManagerNode.hostName');
+ var filtersLink = this.get('filterObject').createJobsFiltersLink();
var hiveQueriesUrl = App.testMode ? "/data/jobs/hive-queries.json" : "/proxy?url=http://" + historyServerHostName
- + ":8188/ws/v1/apptimeline/HIVE_QUERY_ID?fields=events,primaryfilters";
- if (jobsLimit > 0) {
- hiveQueriesUrl += ("?limit=" + jobsLimit);
- }
+ + ":8188/ws/v1/apptimeline/HIVE_QUERY_ID" + filtersLink;
App.HttpClient.get(hiveQueriesUrl, App.hiveJobsMapper, {
complete : function(jqXHR, textStatus) {
self.set('loading', false);
self.set('loaded', true);
}
+ }, function (jqXHR, textStatus) {
+ App.hiveJobsMapper.map({entities : []});
});
}
},
+
+
refreshLoadedJobs : function() {
- this.loadJobs();
- }.observes('jobsLimit', 'App.router.clusterController.isLoaded')
+ var timeout = this.get('loadJobsTimeout');
+ var self = this;
+
+ clearTimeout(timeout);
+ timeout = setTimeout(function(){
+ self.loadJobs();
+ }, 300);
+
+ this.set('loadJobsTimeout', timeout);
+ }.observes(
+ 'filterObject.id',
+ 'filterObject.jobsLimit',
+ 'filterObject.user',
+ 'filterObject.windowStart',
+ 'filterObject.windowEnd',
+ 'App.router.clusterController.isLoaded'
+ )
})
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 0a967c5..2d82507 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1845,6 +1845,13 @@ Em.I18n.translations = {
'menu.item.jobs':'Jobs',
'menu.item.admin':'Admin',
+ 'jobs.table.custom.date.am':'AM',
+ 'jobs.table.custom.date.pm':'PM',
+ 'jobs.table.custom.date.header':'Select Custom Dates',
+ 'jobs.customDateFilter.error.required':'This field is required',
+ 'jobs.customDateFilter.error.date.order':'End Date must be after Start Date',
+ 'jobs.customDateFilter.startTime':'Start Time',
+ 'jobs.customDateFilter.endTime':'End Time',
'jobs.hive.tez.tasks':'Tez Tasks',
'jobs.hive.tez.hdfs':'HDFS',
'jobs.hive.tez.localFiles':'Local Files',
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/styles/apps.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/apps.less b/ambari-web/app/styles/apps.less
index 15c5c9c..8d3ea6e 100644
--- a/ambari-web/app/styles/apps.less
+++ b/ambari-web/app/styles/apps.less
@@ -747,6 +747,11 @@
}
}
+.jobs-custom-dates{
+ .help-inline{
+ color:#b94a48;
+ }
+}
@media all and (max-width: 1024px) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/templates/main/jobs/custom_dates_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/jobs/custom_dates_popup.hbs b/ambari-web/app/templates/main/jobs/custom_dates_popup.hbs
new file mode 100644
index 0000000..1b1d920
--- /dev/null
+++ b/ambari-web/app/templates/main/jobs/custom_dates_popup.hbs
@@ -0,0 +1,39 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="jobs-custom-dates">
+ <div>
+ <label>{{t jobs.customDateFilter.startTime}}</label>
+ {{view Ember.TextField valueBinding="customDateFormFields.startDate" class="input-small datepicker"}}
+ {{view Ember.Select contentBinding="view.hourOptions" selectionBinding="customDateFormFields.hoursForStart" class="input-mini"}}
+ {{view Ember.Select contentBinding="view.minuteOptions" selectionBinding="customDateFormFields.minutesForStart" class="input-mini"}}
+ {{view Ember.Select contentBinding="view.middayPeriodOptions" selectionBinding="customDateFormFields.middayPeriodForStart" class="input-mini"}}
+ <span class="help-inline">{{errorMessages.startDate}}</span>
+ </div>
+ <div>
+
+ </div>
+ <div>
+ <label>{{t jobs.customDateFilter.endTime}}</label>
+ {{view Ember.TextField valueBinding="customDateFormFields.endDate" class="input-small datepicker"}}
+ {{view Ember.Select contentBinding="view.hourOptions" selectionBinding="customDateFormFields.hoursForEnd" class="input-mini"}}
+ {{view Ember.Select contentBinding="view.minuteOptions" selectionBinding="customDateFormFields.minutesForEnd" class="input-mini"}}
+ {{view Ember.Select contentBinding="view.middayPeriodOptions" selectionBinding="customDateFormFields.middayPeriodForEnd" class="input-mini"}}
+ <span class="help-inline">{{errorMessages.endDate}}</span>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 13330ed..88cf9b1 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -215,6 +215,7 @@ require('views/main/charts/heatmap/heatmap_host');
require('views/main/charts/heatmap/heatmap_host_detail');
require('views/main/apps_view');
require('views/main/jobs_view');
+require('views/main/jobs/select_custom_date_view');
require('views/main/jobs/hive_job_details_view');
require('views/main/jobs/hive_job_details_tez_dag_view');
require('views/main/apps/item_view');
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/views/main/jobs/select_custom_date_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/jobs/select_custom_date_view.js b/ambari-web/app/views/main/jobs/select_custom_date_view.js
new file mode 100644
index 0000000..d0c03ef
--- /dev/null
+++ b/ambari-web/app/views/main/jobs/select_custom_date_view.js
@@ -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.
+ */
+
+var App = require('app');
+var date = require('utils/date');
+
+App.JobsCustomDatesSelectView = Em.View.extend({
+ name: 'jobsCustomDatesSelectView',
+ templateName: require('templates/main/jobs/custom_dates_popup'),
+
+ middayPeriodOptions: [Em.I18n.t('jobs.table.custom.date.am'), Em.I18n.t('jobs.table.custom.date.pm')],
+
+ hourOptions: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+
+ minuteOptions: ['00', '05', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55'],
+
+ didInsertElement: function () {
+ $('.datepicker').datepicker({
+ format: 'mm/dd/yyyy'
+ });
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/99a26c9a/ambari-web/app/views/main/jobs_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/jobs_view.js b/ambari-web/app/views/main/jobs_view.js
index 0cc3a7b..aeccab0 100644
--- a/ambari-web/app/views/main/jobs_view.js
+++ b/ambari-web/app/views/main/jobs_view.js
@@ -69,6 +69,7 @@ App.MainJobsView = App.TableView.extend({
*/
rowsPerPageSelectView: Em.Select.extend({
content: ['10', '25', '50', '100', "250", "500"],
+ valueBinding: "controller.filterObject.jobsLimit",
change: function () {
this.get('parentView').saveDisplayLength();
}
@@ -79,23 +80,16 @@ App.MainJobsView = App.TableView.extend({
* @returns {String}
*/
filteredJobs: function () {
- return Em.I18n.t('jobs.filtered.jobs').format(this.get('filteredContent.length'), this.get('content').get('length'));
+ return Em.I18n.t('jobs.filtered.jobs').format(this.get('content').get('length'), this.get('controller.totalOfJobs'));
}.property('content.length', 'filteredContent.length'),
/**
* Filter-field for Jobs ID.
* Based on <code>filters</code> library
*/
- /*jobsIdFilterView: filters.createTextView({
- valueBinding: "controller.filterObject.id"
- }),*/
-
jobsIdFilterView: filters.createTextView({
column: 0,
- fieldType: 'width70',
- onChangeValue: function(){
- this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
- }
+ valueBinding: "controller.filterObject.id"
}),
/**
@@ -145,9 +139,7 @@ App.MainJobsView = App.TableView.extend({
}.observes('users.length')
}),
- onChangeValue: function(){
- this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'multiple');
- }
+ valueBinding: 'controller.filterObject.user'
}),
/**
@@ -157,10 +149,8 @@ App.MainJobsView = App.TableView.extend({
startTimeFilterView: filters.createSelectView({
fieldType: 'input-medium',
column: 2,
- content: ['Any', 'Past 1 hour', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
- onChangeValue: function () {
- this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'date');
- }
+ content: ['Any', 'Past 1 hour', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days', 'Custom'],
+ valueBinding: "controller.filterObject.startTime"
}),
/**