You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/07/31 14:13:07 UTC
[1/2] git commit: AMBARI-6693. Jobs View: Integrate UI with API.
(onechiporenko)
Repository: ambari
Updated Branches:
refs/heads/trunk c635f886b -> bf10914af
AMBARI-6693. Jobs View: Integrate UI with API. (onechiporenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/34c3355d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/34c3355d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/34c3355d
Branch: refs/heads/trunk
Commit: 34c3355de97f332323ec36d184dea42151618ce3
Parents: 0f4f7d7
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Thu Jul 31 15:10:26 2014 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Thu Jul 31 15:10:26 2014 +0300
----------------------------------------------------------------------
.../src/main/resources/ui/app/scripts/app.js | 2 +-
.../app/scripts/controllers/job_controller.js | 44 ++++--
.../app/scripts/controllers/jobs_controller.js | 99 ++++++------
.../resources/ui/app/scripts/helpers/number.js | 1 +
.../scripts/mappers/jobs/hive_jobs_mapper.js | 20 ++-
.../ui/app/scripts/routes/application_route.js | 8 +
.../views/job/hive_job_details_tez_dag_view.js | 155 ++++++++++++++-----
.../scripts/views/job/hive_job_details_view.js | 115 ++++++++++++--
.../resources/ui/app/scripts/views/jobs_view.js | 59 ++++++-
.../src/main/resources/ui/app/styles/main.less | 8 +-
.../resources/ui/app/templates/application.hbs | 2 +-
.../main/resources/ui/app/templates/job/job.hbs | 2 +-
.../main/resources/ui/app/templates/jobs.hbs | 1 +
13 files changed, 381 insertions(+), 135 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/app.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/app.js
index 1067704..3ab2c30 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/app.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/app.js
@@ -45,7 +45,7 @@ App.initializer({
* Prefix for API-requests
* @type {string}
*/
- urlPrefix: '/api/v1',
+ urlPrefix: '/api/v1/',
/**
* Current cluster name
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/job_controller.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/job_controller.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/job_controller.js
index bce4526..6047695 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/job_controller.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/job_controller.js
@@ -16,22 +16,41 @@
* limitations under the License.
*/
-App.JobController = Ember.ObjectController.extend({
+App.JobController = Ember.ObjectController.extend(App.RunPeriodically, {
name: 'jobController',
+ /**
+ * Is Job details info loaded
+ * @type {bool}
+ */
loaded: false,
+ /**
+ * Timeout for <code>loadJobDetails</code> periodic call
+ * @type {number}
+ */
loadTimeout: null,
- job: null,
-
+ /**
+ * Column which is currently sorted
+ * @type {string}
+ */
sortingColumn: null,
+ /**
+ * Modal-popup buttons
+ * @type {Em.Object[]}
+ */
showPopupButtons: [
Ember.Object.create({title: Em.I18n.t('ok'), dismiss: 'modal'})
],
+ /**
+ * Show popup with message about job-details loading error
+ * @param {string} title
+ * @method showPopup
+ */
showPopup: function (title) {
Bootstrap.ModalManager.open(
'errorPopup',
@@ -42,6 +61,11 @@ App.JobController = Ember.ObjectController.extend({
);
},
+ /**
+ * Init method called in <code>router.setupController</code>
+ * Load job's details info (like Tez Dag etc)
+ * @method loadJobDetails
+ */
loadJobDetails: function () {
var self = this,
timeout = this.get('loadTimeout'),
@@ -85,20 +109,6 @@ App.JobController = Ember.ObjectController.extend({
self.loadJobDetails();
}, 300);
}
- },
-
- /**
- * open jobs page
- * @method routeToJobs
- */
- routeToJobs: function () {
- this.transitionToRoute('jobs');
- },
-
- actions: {
- actionRouteToJobs: function () {
- this.routeToJobs();
- }
}
});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/jobs_controller.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/jobs_controller.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/jobs_controller.js
index f0fd64a..b5cdfc7 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/jobs_controller.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/controllers/jobs_controller.js
@@ -66,6 +66,18 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
],
actions: {
+
+ updateJobsByClick: function () {
+ this.set('navIDs.backIDs', []);
+ this.set('navIDs.nextID', '');
+ this.set('filterObject.nextFromId', '');
+ this.set('filterObject.backFromId', '');
+ this.set('filterObject.fromTs', '');
+ this.set('hasNewJobs', false);
+ this.set('resetPagination', true);
+ this.loadJobs();
+ },
+
submitCustomDate: function () {
if(this.get('filterObject').submitCustomDate())
Bootstrap.ModalManager.close('customDate');
@@ -74,11 +86,19 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
dismissCustomDate: function() {
this.set('filterObject.startTime', 'Any');
}
+
},
contentAndSortObserver: function () {
Ember.run.once(this, 'contentAndSortUpdater');
- }.observes('content.length', 'content.@each.id', 'content.@each.startTime', 'content.@each.endTime', 'sortProperties', 'sortAscending'),
+ }.observes(
+ 'content.length',
+ 'content.@each.id',
+ 'content.@each.startTime',
+ 'content.@each.endTime',
+ 'sortProperties',
+ 'sortAscending'
+ ),
contentAndSortUpdater: function () {
this.set('sortingDone', false);
@@ -236,7 +256,7 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
// Check that endDate is after startDate
var startDate = this.createCustomStartDate(),
endDate = this.createCustomEndDate();
- if (startDate && endDate && (startDate > endDate)) {
+ if (startDate && endDate && (startDate.getTime() > endDate.getTime())) {
errors.set('isEndDateError', true);
errorMessages.set('endDate', Em.I18n.t('jobs.customDateFilter.error.date.order'));
}
@@ -280,6 +300,7 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
return link;
}
+
}),
sortingColumnObserver: function () {
@@ -289,25 +310,6 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
}
}.observes('sortingColumn.name', 'sortingColumn.status'),
- updateJobsByClick: function () {
- this.set('navIDs.backIDs', []);
- this.set('navIDs.nextID', '');
- this.get('filterObject').set('nextFromId', '');
- this.get('filterObject').set('backFromId', '');
- this.get('filterObject').set('fromTs', '');
- this.set('hasNewJobs', false);
- this.set('resetPagination', true);
- this.loadJobs();
- },
-
- updateJobs: function (controllerName, funcName) {
- clearInterval(this.get('jobsUpdate'));
- var interval = setInterval(function () {
- App.router.get(controllerName)[funcName]();
- }, this.get('jobsUpdateInterval'));
- this.set('jobsUpdate', interval);
- },
-
setTotalOfJobs: function () {
if (this.get('totalOfJobs') < this.get('content.length')) {
this.set('totalOfJobs', this.get('content.length'));
@@ -315,8 +317,8 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
}.observes('content.length'),
startTimeObserver: function () {
- var time = "";
- var curTime = new Date().getTime();
+ var time = "",
+ curTime = new Date().getTime();
switch (this.get('filterObject.startTime')) {
case 'Past 1 hour':
time = curTime - 3600000;
@@ -347,7 +349,7 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
this.set("filterObject.windowStart", time);
this.set("filterObject.windowEnd", "");
}
- }.observes('filterObject.startTime'),
+ },
showCustomDatePopup: function () {
Bootstrap.ModalManager.open(
@@ -366,14 +368,16 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
var lastReceivedID = data.entities[0].entity;
if (this.get('lastJobID') == '') {
this.set('lastJobID', lastReceivedID);
- if (this.get('loaded') && App.HiveJob.find().get('length') < 1) {
+ if (this.get('loaded') && App.HiveJob.store.all('hiveJob').get('length') < 1) {
this.set('hasNewJobs', true);
}
}
- else if (this.get('lastJobID') !== lastReceivedID) {
- this.set('lastJobID', lastReceivedID);
- if (!App.HiveJob.find().findProperty('id', lastReceivedID)) {
- this.set('hasNewJobs', true);
+ else {
+ if (this.get('lastJobID') !== lastReceivedID) {
+ this.set('lastJobID', lastReceivedID);
+ if (!App.HiveJob.store.getById('hiveJob', lastReceivedID)) {
+ this.set('hasNewJobs', true);
+ }
}
}
},
@@ -402,11 +406,6 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
}
},
- init: function () {
- this.set('interval', 6000);
- this.loop('loadJobs');
- },
-
loadJobs: function () {
var yarnService = App.HiveJob.store.getById('service', 'YARN'),
atsComponent = App.HiveJob.store.getById('component', 'APP_TIMELINE_SERVER'),
@@ -415,16 +414,16 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
if (!Em.isNone(yarnService) && atsInValidState) {
this.set('loading', true);
var historyServerHostName = atsComponent.get('hostName');
- /*App.ajax.send({
- name: 'jobs.lastID',
- sender: self,
- data: {
- historyServerHostName: '',//historyServerHostName,
- ahsWebPort: ''//yarnService.get('ahsWebPort')
- },
- success: 'lastIDSuccessCallback',
- error : 'lastIDErrorCallback'
- });*/
+ App.ajax.send({
+ name: 'jobs_lastID',
+ sender: this,
+ data: {
+ historyServerHostName: historyServerHostName,
+ ahsWebPort: yarnService.get('ahsWebPort')
+ },
+ success: 'lastIDSuccessCallback',
+ error : 'lastIDErrorCallback'
+ });
App.ajax.send({
name: 'load_jobs',
sender: this,
@@ -489,11 +488,11 @@ App.JobsController = Ember.ArrayController.extend(App.RunPeriodically, {
refreshLoadedJobs: function () {
this.loadJobs();
}.observes(
- 'filterObject.id',
- 'filterObject.jobsLimit',
- 'filterObject.user',
- 'filterObject.windowStart',
- 'filterObject.windowEnd'
- )
+ 'filterObject.id',
+ 'filterObject.jobsLimit',
+ 'filterObject.user',
+ 'filterObject.windowStart',
+ 'filterObject.windowEnd'
+ )
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/helpers/number.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/helpers/number.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/helpers/number.js
index 4adf792..a8e9f6b 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/helpers/number.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/helpers/number.js
@@ -30,6 +30,7 @@ App.Helpers.number = {
* @return {String} Returns converted value with abbreviation.
*/
bytesToSize: function (bytes, precision, parseType, multiplyBy) {
+ if (isNaN(bytes)) bytes = 0;
if (Em.isNone(bytes)) {
return 'n/a';
} else {
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/mappers/jobs/hive_jobs_mapper.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/mappers/jobs/hive_jobs_mapper.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/mappers/jobs/hive_jobs_mapper.js
index e87d8e9..1cdb76d 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/mappers/jobs/hive_jobs_mapper.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/mappers/jobs/hive_jobs_mapper.js
@@ -53,7 +53,6 @@ App.hiveJobsMapper = App.QuickDataMapper.create({
map: function (json) {
var model = this.get('model'),
- jobsToDelete = App.HiveJob.store.all('hiveJob').get('content').mapProperty('id'),
map = this.get('json_map'),
hiveJobs = [];
@@ -64,8 +63,9 @@ App.hiveJobsMapper = App.QuickDataMapper.create({
json.entities = [json];
}
}
-
+ var currentEntityMap = {};
json.entities.forEach(function (entity) {
+ currentEntityMap[entity.entity] = entity.entity;
var hiveJob = Ember.JsonMapper.map(entity, map);
if (entity.events != null) {
@@ -87,12 +87,20 @@ App.hiveJobsMapper = App.QuickDataMapper.create({
if (!Em.isNone(tezDag)) {
hiveJob.tezDag = tezDag.id;
}
- jobsToDelete = jobsToDelete.without(hiveJob.id);
});
- jobsToDelete.forEach(function (id) {
- var r = App.HiveJob.store.getById('hiveJob', id);
- if(r) r.destroyRecord();
+ var jobsController = App.__container__.lookup('controller:Jobs');
+ if(hiveJobs.length > jobsController.get('filterObject.jobsLimit')) {
+ var lastJob = hiveJobs.pop();
+ if(jobsController.get('navIDs.nextID') != lastJob.id) {
+ jobsController.set('navIDs.nextID', lastJob.id);
+ }
+ currentEntityMap[lastJob.id] = null;
+ }
+ App.HiveJob.store.all('hiveJob').forEach(function (r) {
+ if(r && !currentEntityMap[r.get('id')]) {
+ r.destroyRecord();
+ }
});
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/routes/application_route.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/routes/application_route.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/routes/application_route.js
index 7532197..a34d085 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/routes/application_route.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/routes/application_route.js
@@ -32,6 +32,13 @@ App.JobsRoute = Ember.Route.extend({
model: function () {
return this.get('store').find('hiveJob');
+ },
+
+ setupController: function(controller, model) {
+ this._super(controller, model);
+ controller.set('interval', 6000);
+ controller.loop('loadJobs', true);
+ Em.addObserver(controller, 'filterObject.startTime', controller, 'startTimeObserver');
}
});
@@ -41,6 +48,7 @@ App.JobRoute = Ember.Route.extend({
setupController: function(controller, model) {
this._super(controller, model);
controller.set('loaded', false);
+ controller.loop('loadJobDetails', true);
},
model: function (params) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_tez_dag_view.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_tez_dag_view.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_tez_dag_view.js
index 1224d1e..7938fc5 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_tez_dag_view.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_tez_dag_view.js
@@ -16,19 +16,39 @@
*/
App.MainHiveJobDetailsTezDagView = Em.View.extend({
+
templateName: 'job/hive_job_details_tez_dag',
+
+ /**
+ * Selected Vertex
+ * @type {App.TezDagVertex}
+ */
selectedVertex: null,
+
+ /**
+ * @type {string}
+ */
summaryMetricType: null,
- svgVerticesLayer: null, // The contents of the <svg> element.
+
+ /**
+ * The contents of the <svg> element
+ */
+ svgVerticesLayer: null,
+
svgTezRoot: null,
+
svgWidth: -1,
+
svgHeight: -1,
// zoomScaleFom: -1, // Bound from parent view
// zoomScaleTo: -1, // Bound from parent view
// zoomScale: -1, // Bound from parent view
+
zoomTranslate: [0, 0],
+
zoomBehavior: null,
+
svgCreated: false,
/**
@@ -88,6 +108,10 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
$('.svg-tooltip').tooltip('destroy');
},
+ /**
+ * Basic init for graph
+ * @method createSvg
+ */
createSvg: function () {
var self = this;
var dagVisualModel = this.get('dagVisualModel');
@@ -124,6 +148,10 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
this.set('svgCreated', true);
},
+ /**
+ * Change graph's zoom
+ * @method zoomScaleObserver
+ */
zoomScaleObserver: function () {
var tezRoot = this.get("svgTezRoot"),
newScale = this.get('zoomScale'),
@@ -163,8 +191,8 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
}.observes('zoomScale', 'zoomScaleFrom', 'zoomScaleTo', 'zoomTranslate'),
/**
- * We have to make the height of the DAG section match the height of the
- * Summary section.
+ * We have to make the height of the DAG section match the height of the Summary section.
+ * @method adjustGraphHeight
*/
adjustGraphHeight: function () {
var rhsDiv = document.getElementById('tez-vertices-rhs'),
@@ -180,20 +208,24 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
}
},
+ /**
+ * Update graph when <code>selectedVertex</code> changed
+ * @method vertexSelectionUpdated
+ */
vertexSelectionUpdated: function () {
- var vertexId = this.get('selectedVertex.id');
- var zoomTranslate = [];
- var zoomBehavior = this.get('zoomBehavior');
- var selectedNode = this.get('dagVisualModel').nodes.findProperty('id', vertexId);
- var dagVisualModel = this.get('dagVisualModel');
+ var vertexId = this.get('selectedVertex.id'),
+ zoomTranslate = [],
+ zoomBehavior = this.get('zoomBehavior'),
+ selectedNode = this.get('dagVisualModel').nodes.findProperty('id', vertexId),
+ dagVisualModel = this.get('dagVisualModel');
if (dagVisualModel && dagVisualModel.nodes && dagVisualModel.nodes.length > 0) {
dagVisualModel.nodes.forEach(function (node) {
node.selected = node.id == vertexId;
})
}
if (!this.get('selectedVertex.notTableClick')) {
- var cX = selectedNode.x + (selectedNode.width) / 2;
- var cY = selectedNode.y + (selectedNode.height) / 2;
+ var cX = selectedNode.x + (selectedNode.width) / 2,
+ cY = selectedNode.y + (selectedNode.height) / 2;
zoomTranslate[0] = (225 / zoomBehavior.scale() - cX);
zoomTranslate[1] = (250 / zoomBehavior.scale() - cY);
this.set('zoomTranslate', [0, 0]);
@@ -203,21 +235,26 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
this.refreshGraphUI();
}.observes('selectedVertex'),
+ /**
+ * Update graph when new summary metric is selected
+ * @method summaryMetricTypeUpdated
+ */
summaryMetricTypeUpdated: function () {
- var summaryMetricType = this.get('summaryMetricType');
- var dagVisualModel = this.get('dagVisualModel');
- var min = dagVisualModel.minMetrics[summaryMetricType];
- var max = dagVisualModel.maxMetrics[summaryMetricType];
+ var summaryMetricType = this.get('summaryMetricType'),
+ dagVisualModel = this.get('dagVisualModel'),
+ min = dagVisualModel.minMetrics[summaryMetricType],
+ max = dagVisualModel.maxMetrics[summaryMetricType];
dagVisualModel.nodes.forEach(function (node) {
- var value = node.metrics[summaryMetricType];
- var percent = -1;
+ var value = node.metrics[summaryMetricType],
+ percent = -1;
if (App.Helpers.number.validateInteger(value) == null && value >= 0) {
if (App.Helpers.number.validateInteger(min) == null && App.Helpers.number.validateInteger(max) == null) {
if (max > min && value >= 0) {
percent = Math.round((value - min) * 100 / (max - min));
}
}
- } else {
+ }
+ else {
value = '';
}
switch (summaryMetricType) {
@@ -236,7 +273,8 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
}.observes('summaryMetricType'),
/**
- * Observes metrics of all vertices.
+ * Observes metrics of all vertices
+ * @method vertexMetricsUpdated
*/
vertexMetricsUpdated: function () {
var dagVisualModel = this.get('dagVisualModel');
@@ -285,11 +323,25 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
});
}
Ember.run.once(this, 'summaryMetricTypeUpdated');
- }.observes('content.tezDag.vertices.@each.fileReadBytes', 'content.tezDag.vertices.@each.fileWriteBytes',
- 'content.tezDag.vertices.@each.hdfsReadBytes', 'content.tezDag.vertices.@each.hdfsWriteBytes',
- 'content.tezDag.vertices.@each.recordReadCount', 'content.tezDag.vertices.@each.recordWriteCount',
- 'content.tezDag.vertices.@each.state', 'content.tezDag.vertices.@each.spilledRecords'),
+ }.observes(
+ 'content.tezDag.vertices.@each.fileReadBytes',
+ 'content.tezDag.vertices.@each.fileWriteBytes',
+ 'content.tezDag.vertices.@each.hdfsReadBytes',
+ 'content.tezDag.vertices.@each.hdfsWriteBytes',
+ 'content.tezDag.vertices.@each.recordReadCount',
+ 'content.tezDag.vertices.@each.recordWriteCount',
+ 'content.tezDag.vertices.@each.state',
+ 'content.tezDag.vertices.@each.spilledRecords'
+ ),
+ /**
+ * Create object with data for graph popups
+ * @param {string} vertexName
+ * @param {string} op
+ * @param {number} opIndex
+ * @returns {{name: string, value: string}[]}
+ * @method createOperationPlanObj
+ */
createOperationPlanObj: function (vertexName, op, opIndex) {
var operatorPlanObj = [],
text = this.get('content.tezDag.vertices').findBy('name', vertexName).get('operationPlan');
@@ -316,6 +368,7 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
*
* Terminology: 'vertices' and 'edges' are Tez terms. 'nodes' and 'links' are
* visual (d3) terms.
+ * @method drawTezDag
*/
drawTezDag: function () {
var self = this,
@@ -768,35 +821,46 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
/**
* Refreshes UI of the Tez graph with latest values
+ * @method refreshGraphUI
*/
refreshGraphUI: function () {
var svgLayer = this.get('svgVerticesLayer');
if (svgLayer != null) {
- var self = this;
- var metricNodes = svgLayer.selectAll(".metric");
- var metricNodeTexts = svgLayer.selectAll(".metric-text");
- var metricNodeTitles = svgLayer.selectAll(".metric-title");
- var nodeBackgrounds = svgLayer.selectAll(".background");
- var vertexIconTexts = svgLayer.selectAll(".vertex-icon-text");
- var vertexIconRects = svgLayer.selectAll(".vertex-icon-rect");
+ var self = this,
+ metricNodes = svgLayer.selectAll(".metric"),
+ metricNodeTexts = svgLayer.selectAll(".metric-text"),
+ metricNodeTitles = svgLayer.selectAll(".metric-title"),
+ nodeBackgrounds = svgLayer.selectAll(".background"),
+ vertexIconTexts = svgLayer.selectAll(".vertex-icon-text"),
+ vertexIconRects = svgLayer.selectAll(".vertex-icon-rect");
metricNodes.attr("class", function (node) {
- var classes = "metric ";
- var percent = node.metricPercent;
+ var classes = "metric ",
+ percent = node.metricPercent;
if (App.Helpers.number.validateInteger(percent) == null && percent >= 0) {
if (percent <= 20) {
classes += "heat-0-20 ";
- } else if (percent <= 40) {
- classes += "heat-20-40 ";
- } else if (percent <= 60) {
- classes += "heat-40-60 ";
- } else if (percent <= 80) {
- classes += "heat-60-80 ";
- } else if (percent <= 100) {
- classes += "heat-80-100 ";
- } else {
- classes += "heat-none";
}
- } else {
+ else
+ if (percent <= 40) {
+ classes += "heat-20-40 ";
+ }
+ else
+ if (percent <= 60) {
+ classes += "heat-40-60 ";
+ }
+ else
+ if (percent <= 80) {
+ classes += "heat-60-80 ";
+ }
+ else
+ if (percent <= 100) {
+ classes += "heat-80-100 ";
+ }
+ else {
+ classes += "heat-none";
+ }
+ }
+ else {
classes += "heat-none";
}
return classes;
@@ -846,6 +910,12 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
}
},
+ /**
+ * Get icon for vertex according to node state
+ * @param {object} node
+ * @returns {string}
+ * @method getVertexIcon
+ */
getVertexIcon: function (node) {
var icon = "";
switch (node.state) {
@@ -888,6 +958,7 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
* drawHeight: 40 // Height of actual drawing (that will be scaled)
* }
* </code>
+ * @method getNodeCalculatedDimensions
*/
getNodeCalculatedDimensions: function (node, minVertexDuration, maxVertexDuration) {
var size = {
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_view.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_view.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_view.js
index 122f236..807dd78 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_view.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/views/job/hive_job_details_view.js
@@ -29,12 +29,16 @@ App.JobView = Em.View.extend({
zoomScale: 1,
+ /**
+ * Is query visible
+ * @type {bool}
+ */
showQuery: false,
- willInsertElement: function () {
- this.get('controller').loadJobDetails();
- },
-
+ /**
+ * Current graph zoom
+ * @type {number}
+ */
zoomStep: function () {
var zoomStep = 0.01;
var zoomFrom = this.get('zoomScaleFrom');
@@ -45,10 +49,19 @@ App.JobView = Em.View.extend({
return zoomStep;
}.property('zoomScaleFrom', 'zoomScaleTo'),
+ /**
+ * Is graph in maximum zoom
+ * @type {bool}
+ */
isGraphMaximized: false,
actions: {
+ /**
+ * Summary metric change handler
+ * @param {string} summaryType
+ * @method doSelectSummaryMetricType
+ */
doSelectSummaryMetricType: function (summaryType) {
switch (summaryType) {
case Em.I18n.t('jobs.hive.tez.metric.input'):
@@ -75,6 +88,10 @@ App.JobView = Em.View.extend({
this.set('summaryMetricType', summaryType);
},
+ /**
+ * "Show more/less" click handler
+ * @method toggleShowQuery
+ */
toggleShowQuery: function () {
this.toggleProperty('showQuery');
var queryBlock = $('.query-info');
@@ -86,10 +103,20 @@ App.JobView = Em.View.extend({
}
},
+ /**
+ * Click handler for vertex-name in the table of vertexes
+ * @param {App.TezDagVertex} event
+ * @param {bool} notTableClick
+ * @method actionDoSelectVertex
+ */
actionDoSelectVertex: function (event, notTableClick) {
this.doSelectVertex(event, notTableClick);
},
+ /**
+ * Zoom-In click-handler
+ * @method doGraphZoomIn
+ */
doGraphZoomIn: function () {
var zoomTo = this.get('zoomScaleTo'),
zoomScale = this.get('zoomScale'),
@@ -101,6 +128,10 @@ App.JobView = Em.View.extend({
}
},
+ /**
+ * Zoom-out click-handler
+ * @method doGraphZoomOut
+ */
doGraphZoomOut: function () {
var zoomFrom = this.get('zoomScaleFrom'),
zoomScale = this.get('zoomScale'),
@@ -112,22 +143,42 @@ App.JobView = Em.View.extend({
}
},
+ /**
+ * Maximize graph
+ * @method doGraphMaximize
+ */
doGraphMaximize: function () {
this.set('isGraphMaximized', true);
},
+ /**
+ * Minimize graph
+ * @method doGraphMinimize
+ */
doGraphMinimize: function () {
this.set('isGraphMaximized', false);
}
},
+ /**
+ * "Show more/less"-message
+ * @type {string}
+ */
toggleShowQueryText: function () {
return this.get('showQuery') ? Em.I18n.t('jobs.hive.less') : Em.I18n.t('jobs.hive.more');
}.property('showQuery'),
+ /**
+ * Current metric type in the metrics-type listbox
+ * @type {string}
+ */
summaryMetricType: 'input',
+ /**
+ * List of available values for <code>summaryMetricType</code>
+ * @type {string[]}
+ */
summaryMetricTypesDisplay: [
Em.I18n.t('jobs.hive.tez.metric.input'),
Em.I18n.t('jobs.hive.tez.metric.output'),
@@ -137,10 +188,18 @@ App.JobView = Em.View.extend({
Em.I18n.t('jobs.hive.tez.metric.spilledRecords')
],
+ /**
+ * Display-value for <code>summaryMetricType</code>
+ * @type {string}
+ */
summaryMetricTypeDisplay: function () {
return Em.I18n.t('jobs.hive.tez.metric.' + this.get('summaryMetricType'));
}.property('summaryMetricType'),
+ /**
+ * List of sorted vertexes for current job
+ * @type {App.TezDagVertex[]}
+ */
sortedVertices: function () {
var sortColumn = this.get('controller.sortingColumn');
if (sortColumn && sortColumn.get('status')) {
@@ -156,12 +215,20 @@ App.JobView = Em.View.extend({
return vertices;
}.property('content.tezDag.vertices', 'controller.sortingColumn'),
+ /**
+ * When all data loaded in the controller, set <code>content</code>-value
+ * @method initialDataLoaded
+ */
initialDataLoaded: function () {
if (this.get('controller.loaded')) {
this.set('content', this.get('controller.content'));
}
}.observes('controller.loaded'),
+ /**
+ * Set proper value to <code>isSelected</code> for each vertex
+ * @method jobObserver
+ */
jobObserver: function () {
var content = this.get('content'),
selectedVertex = this.get('selectedVertex');
@@ -174,6 +241,12 @@ App.JobView = Em.View.extend({
}
}.observes('selectedVertex', 'content.tezDag.vertices.@each.id'),
+ /**
+ * Set <code>selectedVertex</code>
+ * @param {App.TezDagVertex} newVertex
+ * @param {bool} notTableClick
+ * @method doSelectVertex
+ */
doSelectVertex: function (newVertex, notTableClick) {
var currentVertex = this.get('selectedVertex');
if (currentVertex != null) {
@@ -185,8 +258,6 @@ App.JobView = Em.View.extend({
},
/**
- * Provides display information for vertex I/O.
- *
* {
* 'file': {
* 'read': {
@@ -219,12 +290,30 @@ App.JobView = Em.View.extend({
*/
selectedVertexIODisplay: {},
+ /**
+ * Handler to call <code>selectedVertexIODisplayObs</code> once
+ * @method selectedVertexIODisplayObsOnce
+ */
selectedVertexIODisplayObsOnce: function() {
Em.run.once(this, 'selectedVertexIODisplayObs');
- }.observes('selectedVertex.fileReadOps', 'selectedVertex.fileWriteOps', 'selectedVertex.hdfsReadOps', 'selectedVertex.hdfdWriteOps',
- 'selectedVertex.fileReadBytes', 'selectedVertex.fileWriteBytes', 'selectedVertex.hdfsReadBytes', 'selectedVertex.hdfdWriteBytes',
- 'selectedVertex.recordReadCount', 'selectedVertex.recordWriteCount', 'selectedVertex.status'),
+ }.observes(
+ 'selectedVertex.fileReadOps',
+ 'selectedVertex.fileWriteOps',
+ 'selectedVertex.hdfsReadOps',
+ 'selectedVertex.hdfdWriteOps',
+ 'selectedVertex.fileReadBytes',
+ 'selectedVertex.fileWriteBytes',
+ 'selectedVertex.hdfsReadBytes',
+ 'selectedVertex.hdfdWriteBytes',
+ 'selectedVertex.recordReadCount',
+ 'selectedVertex.recordWriteCount',
+ 'selectedVertex.status'
+ ),
+ /**
+ * Provides display information for vertex I/O.
+ * @method selectedVertexIODisplayObs
+ */
selectedVertexIODisplayObs: function () {
var v = this.get('selectedVertex'),
naString = Em.I18n.t('common.na'),
@@ -265,10 +354,18 @@ App.JobView = Em.View.extend({
this.set('selectedVertexIODisplay', r);
},
+ /**
+ * Can graph be zoomed-in
+ * @type {bool}
+ */
canGraphZoomIn: function () {
return this.get('zoomScale') < this.get('zoomScaleTo');
}.property('zoomScale', 'zoomScaleTo'),
+ /**
+ * Can graph be zoomed-out
+ * @type {bool}
+ */
canGraphZoomOut: function () {
return this.get('zoomScale') > this.get('zoomScaleFrom');
}.property('zoomScale', 'zoomScaleFrom')
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/scripts/views/jobs_view.js
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/scripts/views/jobs_view.js b/contrib/views/jobs/src/main/resources/ui/app/scripts/views/jobs_view.js
index 279298b..5fd9b01 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/scripts/views/jobs_view.js
+++ b/contrib/views/jobs/src/main/resources/ui/app/scripts/views/jobs_view.js
@@ -30,8 +30,9 @@ App.JobsView = App.TableView.extend({
filterCondition:[],
- /*
- If no jobs to display set noDataToShow to true, else set emptyData to false.
+ /**
+ * If no jobs to display set noDataToShow to true, else set emptyData to false.
+ * @method noDataToShowObserver
*/
noDataToShowObserver: function () {
this.set("noDataToShow", this.get("controller.content.length") === 0);
@@ -54,6 +55,10 @@ App.JobsView = App.TableView.extend({
}
},
+ /**
+ * Handler for id-filter applying
+ * @method onApplyIdFilter
+ */
onApplyIdFilter: function() {
var isIdFilterApplied = this.get('controller.filterObject.isIdFilterApplied');
this.get('childViews').forEach(function(childView) {
@@ -71,6 +76,10 @@ App.JobsView = App.TableView.extend({
});
}.observes('controller.filterObject.isIdFilterApplied'),
+ /**
+ * Save filter when filtering is complete
+ * @method saveFilter
+ */
saveFilter: function () {
if(this.get('tableFilteringComplete')){
this.updateFilter(1, this.get('controller.filterObject.id'), 'string');
@@ -140,11 +149,16 @@ App.JobsView = App.TableView.extend({
/**
* return filtered number of all content number information displayed on the page footer bar
* @returns {String}
+ * @method filteredJobs
*/
filteredJobs: function () {
return Em.I18n.t('jobs.filtered.jobs').fmt(this.get('controller.content.length'));
}.property('controller.content.length', 'controller.totalOfJobs'),
+ /**
+ * Manage tooltips for jobs
+ * @method pageContentObserver
+ */
pageContentObserver: function () {
if (!this.get('controller.loading')) {
var tooltip = $('.tooltip');
@@ -204,21 +218,41 @@ App.JobsView = App.TableView.extend({
}
}),
+ /**
+ * View for job's name
+ * @type {Em.View}
+ */
jobNameView: Em.View.extend({
+ /**
+ * Classname for link
+ * @type {string}
+ */
isLink: 'is-not-link',
+ /**
+ * Update link-status (enabled/disabled) after sorting is complete
+ */
isLinkObserver: function () {
this.refreshLinks();
}.observes('controller.sortingDone'),
+ /**
+ * Update <code>isLink</code> according to <code>job.hasTezDag<code>
+ * @method refreshLinks
+ */
refreshLinks: function () {
this.set('isLink', this.get('job.hasTezDag') ? "" : "is-not-link");
},
templateName: 'jobs/jobs_name',
- click: function(event) {
+ /**
+ * Click-handler.
+ * Go to Jobs details page if current job has Tez Dag
+ * @returns {null|boolean}
+ */
+ click: function() {
if (this.get('job.hasTezDag')) {
this.get('controller').transitionToRoute('job', this.get('job'));
}
@@ -231,7 +265,8 @@ App.JobsView = App.TableView.extend({
}),
/**
- * associations between content (jobs list) property and column index
+ * Associations between content (jobs list) property and column index
+ * @type {string[]}
*/
colPropAssoc: function () {
var associations = [];
@@ -254,6 +289,9 @@ App.JobsView = App.TableView.extend({
return Em.I18n.t('jobs.table.job.fail');
}.property(),
+ /**
+ * @type {Em.View}
+ */
jobsPaginationLeft: Ember.View.extend({
tagName: 'a',
templateName: 'table/navigation/pagination_left',
@@ -272,6 +310,9 @@ App.JobsView = App.TableView.extend({
}
}),
+ /**
+ * @type {Em.View}
+ */
jobsPaginationRight: Ember.View.extend({
tagName: 'a',
templateName: 'table/navigation/pagination_right',
@@ -290,10 +331,18 @@ App.JobsView = App.TableView.extend({
}
}),
+ /**
+ * Enable/disable "next"-arrow
+ * @type {bool}
+ */
hasNextJobs: function() {
- return (this.get("controller.navIDs.nextID.length") > 0);
+ return (this.get("controller.navIDs.nextID.length") > 1);
}.property('controller.navIDs.nextID'),
+ /**
+ * Enable/disable "back"-arrow
+ * @type {bool}
+ */
hasBackLinks: function() {
return (this.get("controller.navIDs.backIDs").length > 1);
}.property('controller.navIDs.backIDs.[].length')
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/styles/main.less
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/styles/main.less b/contrib/views/jobs/src/main/resources/ui/app/styles/main.less
index ce87bff..e648fe0 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/styles/main.less
+++ b/contrib/views/jobs/src/main/resources/ui/app/styles/main.less
@@ -16,8 +16,7 @@
* limitations under the License.
*/
-@import '../../app/bower_components/jquery-ui/themes/base/core.css';
-@import '../../app/bower_components/jquery-ui/themes/base/datepicker.css';
+@import '../../app/bower_components/jquery-ui/themes/base/all.css';
@import '../../app/bower_components/bootstrap/less/bootstrap';
@import '../../app/bower_components/font-awesome/less/font-awesome';
@@ -29,6 +28,10 @@ a {
cursor: pointer;
}
+.jobs-container {
+ margin-top: 20px;
+}
+
.icon-remove-sign {
color: #FF4B4B;
@@ -156,7 +159,6 @@ a {
.apply-btn {
font-size: 12px;
padding: 0px 8px;
- margin-left: 6px;
margin-top: -8px;
line-height: 22px;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/templates/application.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/templates/application.hbs b/contrib/views/jobs/src/main/resources/ui/app/templates/application.hbs
index 1a0b52e..f71f976 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/templates/application.hbs
+++ b/contrib/views/jobs/src/main/resources/ui/app/templates/application.hbs
@@ -16,6 +16,6 @@
* limitations under the License.
}}
-<div class="container">
+<div class="container jobs-container">
{{outlet}}
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/templates/job/job.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/templates/job/job.hbs b/contrib/views/jobs/src/main/resources/ui/app/templates/job/job.hbs
index aab95d7..46a6a35 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/templates/job/job.hbs
+++ b/contrib/views/jobs/src/main/resources/ui/app/templates/job/job.hbs
@@ -21,7 +21,7 @@
{{#if controller.loaded}}
<!-- Top Bar -->
<div class="top-bar">
- <a {{action "actionRouteToJobs" target="controller"}} href="#">{{t menu.item.jobs}}</a> > {{view.content.name}}
+ {{#link-to "jobs"}}{{t menu.item.jobs}}{{/link-to}} > {{view.content.name}}
<a {{action "toggleShowQuery" target="view"}} href="#" id="toggle-query">{{view.toggleShowQueryText}}</a>
<div class="pull-right">{{t apps.item.dag.type}}: <span class="label label-info">{{view.content.jobType}}</span></div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/34c3355d/contrib/views/jobs/src/main/resources/ui/app/templates/jobs.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/ui/app/templates/jobs.hbs b/contrib/views/jobs/src/main/resources/ui/app/templates/jobs.hbs
index 212c5d4..31aea32 100644
--- a/contrib/views/jobs/src/main/resources/ui/app/templates/jobs.hbs
+++ b/contrib/views/jobs/src/main/resources/ui/app/templates/jobs.hbs
@@ -19,6 +19,7 @@
<div id="jobs">
<div class="jobs_head">
+ <div>{{t menu.item.jobs}}</div>
{{#if controller.hasNewJobs}}
<div class="new-jobs-link">
<a href="javascript:void(null);" {{action updateJobsByClick target="controller"}}>{{t jobs.new_jobs.info}}</a>
[2/2] git commit: Merge remote-tracking branch 'origin/trunk' into
origin-trunk
Posted by on...@apache.org.
Merge remote-tracking branch 'origin/trunk' into origin-trunk
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/bf10914a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/bf10914a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/bf10914a
Branch: refs/heads/trunk
Commit: bf10914afe888277d16e4a43ea97d98d74c2b256
Parents: 34c3355 c635f88
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Thu Jul 31 15:12:58 2014 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Thu Jul 31 15:12:58 2014 +0300
----------------------------------------------------------------------
ambari-web/app/models/stack_service.js | 41 +++++++++++++++++------------
1 file changed, 24 insertions(+), 17 deletions(-)
----------------------------------------------------------------------