You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2013/03/23 05:38:03 UTC
svn commit: r1460092 - in /incubator/ambari/trunk: ./ ambari-web/app/
ambari-web/app/controllers/main/ ambari-web/app/mappers/
ambari-web/app/models/ ambari-web/app/routes/ ambari-web/app/styles/
ambari-web/app/templates/main/ ambari-web/app/views/comm...
Author: yusaku
Date: Sat Mar 23 04:38:02 2013
New Revision: 1460092
URL: http://svn.apache.org/r1460092
Log:
AMBARI-1653. HDFS Mirroring: Display DataSets table. (yusaku)
Added:
incubator/ambari/trunk/ambari-web/app/controllers/main/mirroring_controller.js
incubator/ambari/trunk/ambari-web/app/templates/main/mirroring.hbs
incubator/ambari/trunk/ambari-web/app/views/main/mirroring_view.js
Modified:
incubator/ambari/trunk/CHANGES.txt
incubator/ambari/trunk/ambari-web/app/controllers.js
incubator/ambari/trunk/ambari-web/app/mappers/dataset_mapper.js
incubator/ambari/trunk/ambari-web/app/messages.js
incubator/ambari/trunk/ambari-web/app/models/dataset.js
incubator/ambari/trunk/ambari-web/app/models/host.js
incubator/ambari/trunk/ambari-web/app/routes/main.js
incubator/ambari/trunk/ambari-web/app/styles/application.less
incubator/ambari/trunk/ambari-web/app/views.js
incubator/ambari/trunk/ambari-web/app/views/common/filter_view.js
incubator/ambari/trunk/ambari-web/app/views/common/sort_view.js
incubator/ambari/trunk/ambari-web/app/views/main/host.js
incubator/ambari/trunk/ambari-web/app/views/main/menu.js
Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Sat Mar 23 04:38:02 2013
@@ -12,6 +12,8 @@ Trunk (unreleased changes):
NEW FEATURES
+ AMBARI-1653. HDFS Mirroring: Display DataSets table. (yusaku)
+
AMBARI-1658. Implement API/Service Provider for HDFS mirroring. (tbeerbower)
AMBARI-1422. Allow client to specify a "context" value for asynchronous requests (jspeidel)
Modified: incubator/ambari/trunk/ambari-web/app/controllers.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/controllers.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/controllers.js (original)
+++ incubator/ambari/trunk/ambari-web/app/controllers.js Sat Mar 23 04:38:02 2013
@@ -75,6 +75,7 @@ require('controllers/main/charts/heatmap
require('controllers/main/charts/heatmap');
require('controllers/main/apps_controller');
require('controllers/main/apps/item_controller');
+require('controllers/main/mirroring_controller');
require('controllers/wizard/slave_component_groups_controller');
require('controllers/wizard/step1_controller');
require('controllers/wizard/step2_controller');
Added: incubator/ambari/trunk/ambari-web/app/controllers/main/mirroring_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/controllers/main/mirroring_controller.js?rev=1460092&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/controllers/main/mirroring_controller.js (added)
+++ incubator/ambari/trunk/ambari-web/app/controllers/main/mirroring_controller.js Sat Mar 23 04:38:02 2013
@@ -0,0 +1,24 @@
+/**
+ * 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');
+
+App.MainMirroringController = Em.ArrayController.extend({
+ name:'mainMirroringController',
+ content: App.DataSet.find()
+});
Modified: incubator/ambari/trunk/ambari-web/app/mappers/dataset_mapper.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/mappers/dataset_mapper.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/mappers/dataset_mapper.js (original)
+++ incubator/ambari/trunk/ambari-web/app/mappers/dataset_mapper.js Sat Mar 23 04:38:02 2013
@@ -46,16 +46,6 @@ App.dataSetMapper = App.QuickDataMapper.
//data: 'Instances.details'
},
- getDuration: function (startDate, endDate) {
-
- var milliseconds = endDate - startDate;
- var date = new Date(milliseconds);
- var h = Math.floor(milliseconds / 3600000);
- var m = Math.floor((milliseconds % 3600000) / 60000);
- var s = Math.floor(((milliseconds % 360000) % 60000) / 1000);
- return (h == 0 ? '' : h + 'hr ') + (m == 0 ? '' : m + 'mins ') + (s == 0 ? '' : s + 'secs ');
-
- },
map: function (json) {
if (!this.get('model')) {
return;
@@ -91,13 +81,13 @@ App.dataSetMapper = App.QuickDataMapper.
}
if (job.Instances.status === 'FAILED') {
if (last_failed_date == null || last_failed_date < end_date) {
- item.last_failed_date = end_date;
+ item.last_failed_date = end_date.getTime();
last_failed_date = end_date;
}
}
else if (job.Instances.status === 'SUCCESSFUL') {
if (last_succeeded_date == null || last_succeeded_date < end_date) {
- item.last_succeeded_date = end_date;
+ item.last_succeeded_date = end_date.getTime();
last_succeeded_date = end_date;
}
}
@@ -109,7 +99,7 @@ App.dataSetMapper = App.QuickDataMapper.
var last_end_date = new Date(item.last_job.Instances.end);
var last_start_date = new Date(item.last_job.Instances.start);
- item.last_duration = this.getDuration(last_start_date, last_end_date);
+ item.last_duration = last_end_date - last_start_date;
item.avg_data = '';
@@ -135,7 +125,7 @@ App.dataSetMapper = App.QuickDataMapper.
instance.Instances.end = new Date(instance.Instances.end); // neeed to be calulated end -start
- instance.duration = this.getDuration(instance.Instances.start, instance.Instances.end);
+ instance.duration = instance.Instances.end - instance.Instances.start;
instance.start_date_str = instance.Instances.start.toString();
instance.end_date_str = instance.Instances.end.toString();
Modified: incubator/ambari/trunk/ambari-web/app/messages.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/messages.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/messages.js (original)
+++ incubator/ambari/trunk/ambari-web/app/messages.js Sat Mar 23 04:38:02 2013
@@ -950,11 +950,19 @@ Em.I18n.translations = {
'apps.isRunning.popup.title':'Is running',
'apps.isRunning.popup.content':'Job is running now',
+ 'mirroring.table.noDatasets':'No datasets to display',
+ 'mirroring.table.datasetSource':'Dataset Source',
+ 'mirroring.table.lastSuccess':'Last Success',
+ 'mirroring.table.lastFail':'Last Fail',
+ 'mirroring.table.lastDuration':'Last Duration',
+ 'mirroring.table.avgData':'Avg Data',
+
'menu.item.dashboard':'Dashboard',
'menu.item.heatmaps':'Heatmaps',
'menu.item.services':'Services',
'menu.item.hosts':'Hosts',
'menu.item.jobs':'Jobs',
+ 'menu.item.mirroring':'Mirroring',
'menu.item.admin':'Admin',
'common.combobox.placeholder': 'Filter...',
Modified: incubator/ambari/trunk/ambari-web/app/models/dataset.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/models/dataset.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/models/dataset.js (original)
+++ incubator/ambari/trunk/ambari-web/app/models/dataset.js Sat Mar 23 04:38:02 2013
@@ -27,9 +27,9 @@ App.DataSet = DS.Model.extend({
sourceDir: DS.attr('string'),
targetDir: DS.attr('string'),
schedule: DS.attr('string'),
- lastSucceededDate: DS.attr('string'),
- lastFailedDate: DS.attr('date'),
- lastDuration: DS.attr('string'),
+ lastSucceededDate: DS.attr('number'),
+ lastFailedDate: DS.attr('number'),
+ lastDuration: DS.attr('number'),
avgData: DS.attr('string'),
createdDate: DS.attr('string'),
datasetJobs: DS.hasMany('App.DataSetJob')
Modified: incubator/ambari/trunk/ambari-web/app/models/host.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/models/host.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/models/host.js (original)
+++ incubator/ambari/trunk/ambari-web/app/models/host.js Sat Mar 23 04:38:02 2013
@@ -107,7 +107,7 @@ App.Host = DS.Model.extend({
* formatted bytes to appropriate value
*/
memoryFormatted: function () {
- return misc.formatBandwidth(this.get('memory') * 1000);
+ return misc.formatBandwidth(this.get('memory') * 1024);
}.property('memory'),
/**
* Return true if host not heartbeating last 180 seconds
Modified: incubator/ambari/trunk/ambari-web/app/routes/main.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/routes/main.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/routes/main.js (original)
+++ incubator/ambari/trunk/ambari-web/app/routes/main.js Sat Mar 23 04:38:02 2013
@@ -100,6 +100,13 @@ module.exports = Em.Route.extend({
}
}),
+ mirroring: Em.Route.extend({
+ route: '/mirroring',
+ connectOutlets: function (router) {
+ router.get('mainController').connectOutlet('mainMirroring');
+ }
+ }),
+
hosts: Em.Route.extend({
route: '/hosts',
index: Ember.Route.extend({
Modified: incubator/ambari/trunk/ambari-web/app/styles/application.less
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/styles/application.less?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/styles/application.less (original)
+++ incubator/ambari/trunk/ambari-web/app/styles/application.less Sat Mar 23 04:38:02 2013
@@ -2279,6 +2279,178 @@ ul.filter {
}
/*End Heatmap*/
+
+/*Start Mirroring*/
+
+#mirroring {
+
+ .page-bar {
+ border: 1px solid silver;
+ text-align: right;
+ div {
+ display: inline-block;
+ margin: 0 10px;
+ }
+ .items-on-page {
+ label {
+ display: inline;
+ }
+ select {
+ margin-bottom: 4px;
+ margin-top: 4px;
+ width: 70px;
+ }
+ }
+ .paging_two_button {
+ a.paginate_disabled_next, a.paginate_disabled_previous {
+ color: gray;
+ &:hover {
+ color: gray;
+ text-decoration: none;
+ cursor: default;
+ }
+ }
+
+ a.paginate_next, a.paginate_previous {
+ &:hover {
+ text-decoration: none;
+ cursor: pointer;
+ }
+ }
+ a {
+ padding:0 5px;
+ }
+ }
+ }
+
+ .table { //margin-bottom: 0;
+ thead { //background: #EDF5FC;
+ }
+ th {
+ border-top: none;
+ }
+ th, td {
+ width: 82px;
+ border-left-width: 0;
+ }
+ th.first, td.first {
+ width: 10px !important;
+ border-left-width: 1px;
+ }
+ td.first label {
+ padding-top: 3px;
+ }
+ td.first span {
+ display: block;
+ float: right;
+ height: 13px;
+ margin: 5px 0 0 0;
+ width: 13px;
+ }
+ ul.filter-components {
+ padding: 5px 0;
+ li {
+ display: block;
+ padding: 3px 0 3px 5px;
+ line-height: 20px;
+
+ label.checkbox {
+ padding-left: 3px;
+ }
+
+ input[type="checkbox"] {
+ margin: 4px 4px 2px 2px;
+ }
+ }
+ &>li {
+ &>ul {
+ height: 250px;
+ margin-left: 0;
+ overflow-y: scroll;
+ }
+ }
+ }
+ .sorting_asc {
+ background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAZAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgICAwMDAwMDAwMDAwEBAQEBAQECAQECAgIBAgIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD/8AAEQgAEwATAwERAAIRAQMRAf/EAHgAAAMBAQAAAAAAAAAAAAAAAAAFCAYKAQACAQUAAAAAAAAAAAAAAAAABQMCBAYHCBAAAQUAAQMEAwAAAAAAAAAAAwECBAUGABESByExIghBMxQRAAIBAwMDAwUAAAAAAAAAAAECAwAEBRESBiExUUHhB2GBIhMU/9oADAMBAAIRAxEAPwDvA8k+Qc54sxGj32qlNi0ucrjTj/JqGlmROyJXQ2u/bOsZTmBExPd70/HXmQcW41lOX5+145h0L391KEHhR3Z28Ii6sx9AKgubiO1gaeU6Io19h9TUg/S/7eP+wia3NbBIFbuqiyn3VTCjIMArHHTJarEDGGiNU8vOKVsc7/VxBuGR3yV683X86/Cq/GpssrhP2S8emiSKRm1JS5VfyLH0WfQug7KwZR0CilWHy39++ObQTgkgeV9ux+xq9uc6U8pLfZzP6mClZpKWrvq1DilJAt4Mewh/0hRyBOsaUMoVKLvXtVU6t6+nL/HZTJYi4/rxU81tdbSu+N2Rtp7jcpB0OnUa9aoeOOVdsgDL4I1pFS+NPHmcsQ2+fw+UpLWOwwwWNVQ1kCaIcgaiONkmLGEZrDDXtcnXo5PfjC+5VybKWrWWSyF5cWbEEpJNI6kqdQSrMRqD1B9KjS2t423xoqt5AArb8QVPRwoo4UUc
KK//2Q==) no-repeat right 50%;
+ }
+ .sorting_desc {
+ background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAZAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgICAwMDAwMDAwMDAwEBAQEBAQECAQECAgIBAgIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD/8AAEQgAEwATAwERAAIRAQMRAf/EAIEAAAIDAQAAAAAAAAAAAAAAAAAGBwgJCgEBAAIDAQAAAAAAAAAAAAAAAAMFBAYHCBAAAAUDAwMFAAAAAAAAAAAAAQIDBAUABgcSNTYRFQgTZFUWZhEAAAQEAggGAwAAAAAAAAAAAAECAxEhBAYSMjFBYRMzFDQFUZFSYmMHJFRk/9oADAMBAAIRAxEAPwDv4oAKACgCKc1tMmusb3Eph6cSgsgx7fucEZxGRks2llGIGVWgVm8q1dt0+6ogKaapSgdNbQPXTqAdwsN602bopk3vTnUW24rduwccbU2S5E8Sm1JM92czSZwNOKUYDFrCqTp1corDUFMpEcYap+Ipb4P5O8n81y9xXXlG50yY+thR3AEivqFvRDmduvSUrhuLtrFNXqCFvJm1LAQ5RMuchB6gBy13f7+tP6lsOipuz2jSGdy1ZJeNzmXnEtU+pWFTikmbxyTEjgglKKZpMU3ZanudYtTtSr8dMoYSKKvKMte0aUV5YGxgoASbD2iQ4Tyi6uB7Rvz/AHD9R8r7/wBWr64uta6/pKfq+JwUZP5/1/hwCFjIeTMrLo0np93q2xDtVCJh/9k=) no-repeat right 50%;
+ }
+ .sorting {
+ background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAZAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgICAwMDAwMDAwMDAwEBAQEBAQECAQECAgIBAgIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD/8AAEQgAEwATAwERAAIRAQMRAf/EAGgAAAIDAQAAAAAAAAAAAAAAAAUHAAYICgEBAQAAAAAAAAAAAAAAAAAAAAEQAAEEAQIFAgcAAAAAAAAAAAECAwQFABEGIRI0NQcTFDFBMmNUZRYRAQEBAQAAAAAAAAAAAAAAAAABEUH/2gAMAwEAAhEDEQA/AO93cd/XbXpLC9tHQ1Dr46nljUBby/gzGZB+p+Q6QhA+ZOApfDnllW/ha1tv6Ee7iyH5kRlvlbTIqHndWkNJ0HO7XFQbWeJUkpUeOpySrZh65UUnyFUW1ztaexRmIbaPyzoLE6vg2UWW9GC1e0XHnsSGEqfQohCwApK9OIGuAjfBP9VuG0m39vGqINVUe4r2xF21TVsuXZOI9N9lMmLBYkttQ21auBKhqtSUngCMkW5xqjKiYASh6SR2Tulr2HpOvf6j9p+V9/mwDeB//9k=) no-repeat right 50%;
+ }
+
+ div.view-wrapper {
+ .btn-group {
+ margin-bottom: 9px;
+ }
+ }
+
+ a.ui-icon-circle-close {
+ float: right;
+ opacity: 0.2;
+ padding: 1px;
+ position: relative;
+ right: -8px;
+ margin-top: 6px;
+ z-index: 10;
+ &:hover {
+ opacity: 0.7;
+ }
+ }
+ .notActive {
+ a.ui-icon-circle-close {
+ visibility: hidden;
+ }
+ }
+ }
+
+ .box-footer .footer-pagination {
+ float: right;
+ .nav {
+ margin-bottom: 0;
+ }
+ .dropdown {
+ margin-top: 3px;
+ }
+ .dropdown {
+ margin-top: 3px;
+ }
+ .dropdown select {
+ width: 60px;
+ }
+ .page-listing a {
+ line-height: 0;
+ border: none;
+ margin: 0;
+ margin-right: 10px;
+ cursor: pointer;
+ color: #0088CC;
+ padding: 8px 0;
+ float: left;
+ text-decoration: underline;
+ }
+ .page-listing a:hover {
+ text-decoration: none;
+ }
+ .page-listing {
+ width: 100px;
+ .table {
+ th.name {
+ width: 300px;
+ a.filter-label {
+ width: 57px;
+ display: block;
+ float: left;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*End Mirroring*/
+
.noDisplay {
display: none !important;
}
Added: incubator/ambari/trunk/ambari-web/app/templates/main/mirroring.hbs
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/templates/main/mirroring.hbs?rev=1460092&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/templates/main/mirroring.hbs (added)
+++ incubator/ambari/trunk/ambari-web/app/templates/main/mirroring.hbs Sat Mar 23 04:38:02 2013
@@ -0,0 +1,88 @@
+{{!
+* 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 id="mirroring">
+
+ <table class="datatable table table-bordered table-striped">
+ <thead>
+ <tr>
+ {{#view view.sortView contentBinding="view.filteredContent"}}
+ <th class="first"> </th>
+ {{view view.parentView.nameSort}}
+ {{view view.parentView.dataSetSourceSort}}
+ {{view view.parentView.lastSuccessSort}}
+ {{view view.parentView.lastFailSort}}
+ {{view view.parentView.lastDurationSort}}
+ {{view view.parentView.avgDataSort}}
+ {{/view}}
+ </tr>
+ <tr>
+ <th class="first"> </th>
+ <th>{{view view.nameFilterView}}</th>
+ <th>{{view view.datasetSourceFilterView}}</th>
+ <th>{{view view.lastSuccessFilterView}}</th>
+ <th>{{view view.lastFailFilterView}}</th>
+ <th>{{view view.lastDurationFilterView}}</th>
+ <th>{{view view.avgDataFilterView}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#if view.pageContent}}
+ {{#each dataset in view.pageContent}}
+ {{#view view.DatasetView contentBinding="dataset"}}
+
+ <td class="first">
+ </td>
+
+ <td class="name">
+ <a title="{{unbound dataset.name}}" href="#">{{unbound dataset.name}}</a>
+ </td>
+ <td>{{dataset.sourceDir}}</td>
+ <td>{{view.lastSucceededDateFormatted}}</td>
+ <td>{{view.lastFailedDateFormatted}}</td>
+
+ <td>
+ {{view.lastDurationFormatted}}
+ </td>
+
+ <td>{{dataset.avgData}}</td>
+ {{/view}}
+ {{/each}}
+ {{else}}
+ <tr>
+ <td class="first"></td>
+ <td colspan="6">
+ {{t mirroring.table.noDatasets}}
+ </td>
+ </tr>
+ {{/if}}
+ </tbody>
+ </table>
+
+ <div class="page-bar">
+ <div class="items-on-page">
+ <label>{{t common.show}}: {{view view.datasetsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+ </div>
+ <div class="info">{{view.paginationInfo}}</div>
+ <div class="paging_two_button">
+ {{view view.paginationLeft}}
+ {{view view.paginationRight}}
+ </div>
+ </div>
+</div>
+
Modified: incubator/ambari/trunk/ambari-web/app/views.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views.js Sat Mar 23 04:38:02 2013
@@ -119,6 +119,7 @@ require('views/main/apps_view');
require('views/main/apps/item_view');
require('views/main/apps/item/bar_view');
require('views/main/apps/item/dag_view');
+require('views/main/mirroring_view');
require('views/installer');
require('views/wizard/controls_view');
require('views/wizard/step1_view');
Modified: incubator/ambari/trunk/ambari-web/app/views/common/filter_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/common/filter_view.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/common/filter_view.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views/common/filter_view.js Sat Mar 23 04:38:02 2013
@@ -281,23 +281,7 @@ module.exports = {
}
rowValue = (jQuery(rowValue).text()) ? jQuery(rowValue).text() : rowValue;
- var convertedRowValue;
- if (rowValue === '<1KB') {
- convertedRowValue = 1;
- } else {
- var rowValueScale = rowValue.substr(rowValue.length - 2, 2);
- switch (rowValueScale) {
- case 'KB':
- convertedRowValue = parseFloat(rowValue)*1024;
- break;
- case 'MB':
- convertedRowValue = parseFloat(rowValue)*1048576;
- break;
- case 'GB':
- convertedRowValue = parseFloat(rowValue)*1073741824;
- break;
- }
- }
+ var convertedRowValue = rowValue*1024;
switch (compareChar) {
case '<':
@@ -314,6 +298,74 @@ module.exports = {
return match;
}
break;
+ case 'duration':
+ return function (rowValue, rangeExp) {
+ var compareChar = isNaN(rangeExp.charAt(0)) ? rangeExp.charAt(0) : false;
+ var compareScale = rangeExp.charAt(rangeExp.length - 1);
+ var compareValue = compareChar ? parseFloat(rangeExp.substr(1, rangeExp.length)) : parseFloat(rangeExp.substr(0, rangeExp.length));
+ var match = false;
+ if (rangeExp.length == 1 && compareChar !== false) {
+ // User types only '=' or '>' or '<', so don't filter column values
+ match = true;
+ return match;
+ }
+ switch (compareScale) {
+ case 's':
+ compareValue *= 1000;
+ break;
+ case 'm':
+ compareValue *= 60000;
+ break;
+ case 'h':
+ compareValue *= 3600000;
+ break;
+ default:
+ compareValue *= 1000;
+ }
+ rowValue = (jQuery(rowValue).text()) ? jQuery(rowValue).text() : rowValue;
+
+ switch (compareChar) {
+ case '<':
+ if (compareValue > rowValue) match = true;
+ break;
+ case '>':
+ if (compareValue < rowValue) match = true;
+ break;
+ case false:
+ case '=':
+ if (compareValue == rowValue) match = true;
+ break;
+ }
+ return match;
+ }
+ break;
+ case 'date':
+ return function (rowValue, rangeExp) {
+ var match = false;
+ var timePassed = new Date().getTime() - rowValue;
+ switch (rangeExp) {
+ case 'Past 1 Day':
+ match = timePassed <= 86400000;
+ break;
+ case 'Past 2 Days':
+ match = timePassed <= 172800000;
+ break;
+ case 'Past 7 Days':
+ match = timePassed <= 604800000;
+ break;
+ case 'Past 14 Days':
+ match = timePassed <= 1209600000;
+ break;
+ case 'Past 30 Days':
+ match = timePassed <= 2592000000;
+ break;
+ case 'Any':
+ match = true;
+ break;
+ }
+ return match;
+ }
+ break;
case 'number':
return function(rowValue, rangeExp){
var compareChar = rangeExp.charAt(0);
Modified: incubator/ambari/trunk/ambari-web/app/views/common/sort_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/common/sort_view.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/common/sort_view.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views/common/sort_view.js Sat Mar 23 04:38:02 2013
@@ -65,6 +65,17 @@ var wrapperView = Em.View.extend({
}
};
break;
+ case 'number':
+ func = function (a, b) {
+ var a = parseFloat(a.get(property.get('name')));
+ var b = parseFloat(b.get(property.get('name')));
+ if(order){
+ return b - a;
+ } else {
+ return a - b;
+ }
+ }
+ break;
default:
func = function(a,b){
if(order){
Modified: incubator/ambari/trunk/ambari-web/app/views/main/host.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/main/host.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/main/host.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views/main/host.js Sat Mar 23 04:38:02 2013
@@ -130,11 +130,13 @@ App.MainHostView = Em.View.extend({
}),
cpuSort: sort.fieldView.extend({
name:'cpu',
- displayName: Em.I18n.t('common.cpu')
+ displayName: Em.I18n.t('common.cpu'),
+ type: 'number'
}),
memorySort: sort.fieldView.extend({
name:'memory',
- displayName: Em.I18n.t('common.ram')
+ displayName: Em.I18n.t('common.ram'),
+ type: 'number'
}),
diskUsageSort: sort.fieldView.extend({
name:'diskUsage',
@@ -142,7 +144,8 @@ App.MainHostView = Em.View.extend({
}),
loadAvgSort: sort.fieldView.extend({
name:'loadAvg',
- displayName: Em.I18n.t('common.loadAvg')
+ displayName: Em.I18n.t('common.loadAvg'),
+ type: 'number'
}),
HostView:Em.View.extend({
content:null,
@@ -426,7 +429,7 @@ App.MainHostView = Em.View.extend({
associations[1] = 'publicHostName';
associations[2] = 'ip';
associations[3] = 'cpu';
- associations[4] = 'memoryFormatted';
+ associations[4] = 'memory';
associations[5] = 'loadAvg';
associations[6] = 'hostComponents';
associations[7] = 'criticalAlertsCount';
Modified: incubator/ambari/trunk/ambari-web/app/views/main/menu.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/main/menu.js?rev=1460092&r1=1460091&r2=1460092&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/main/menu.js (original)
+++ incubator/ambari/trunk/ambari-web/app/views/main/menu.js Sat Mar 23 04:38:02 2013
@@ -31,7 +31,8 @@ App.MainMenuView = Em.CollectionView.ext
{ label:Em.I18n.t('menu.item.heatmaps'), routing:'charts'},
{ label:Em.I18n.t('menu.item.services'), routing:'services'},
{ label:Em.I18n.t('menu.item.hosts'), routing:'hosts'},
- { label:Em.I18n.t('menu.item.jobs'), routing:'apps'}
+ { label:Em.I18n.t('menu.item.jobs'), routing:'apps'},
+ { label:Em.I18n.t('menu.item.mirroring'), routing:'mirroring'}
];
if(App.db.getUser().admin) result.push({ label:Em.I18n.t('menu.item.admin'), routing:'admin'});
Added: incubator/ambari/trunk/ambari-web/app/views/main/mirroring_view.js
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/views/main/mirroring_view.js?rev=1460092&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/views/main/mirroring_view.js (added)
+++ incubator/ambari/trunk/ambari-web/app/views/main/mirroring_view.js Sat Mar 23 04:38:02 2013
@@ -0,0 +1,288 @@
+/**
+ * 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 filters = require('views/common/filter_view');
+var sort = require('views/common/sort_view');
+
+App.MainMirroringView = Em.View.extend({
+ templateName: require('templates/main/mirroring'),
+ content: function () {
+ return this.get('controller.content');
+ }.property('controller.content'),
+
+ didInsertElement: function () {
+ this.filter();
+ },
+
+ /**
+ * return pagination information displayed on the mirroring page
+ */
+ paginationInfo: function () {
+ return this.t('apps.filters.paginationInfo').format(this.get('startIndex'), this.get('endIndex'), this.get('filteredContent.length'));
+ }.property('displayLength', 'filteredContent.length', 'startIndex', 'endIndex'),
+
+ paginationLeft: Ember.View.extend({
+ tagName: 'a',
+ template: Ember.Handlebars.compile('<i class="icon-arrow-left"></i>'),
+ classNameBindings: ['class'],
+ class: function () {
+ if (this.get("parentView.startIndex") > 1) {
+ return "paginate_previous";
+ }
+ return "paginate_disabled_previous";
+ }.property("parentView.startIndex", 'filteredContent.length'),
+
+ click: function () {
+ this.get('parentView').previousPage();
+ }
+ }),
+
+ paginationRight: Ember.View.extend({
+ tagName: 'a',
+ template: Ember.Handlebars.compile('<i class="icon-arrow-right"></i>'),
+ classNameBindings: ['class'],
+ class: function () {
+ if ((this.get("parentView.endIndex")) < this.get("parentView.filteredContent.length")) {
+ return "paginate_next";
+ }
+ return "paginate_disabled_next";
+ }.property("parentView.endIndex", 'filteredContent.length'),
+
+ click: function () {
+ this.get('parentView').nextPage();
+ }
+ }),
+
+ datasetsPerPageSelectView: Em.Select.extend({
+ content: ['10', '25', '50']
+ }),
+
+ // start index for displayed content on the mirroring page
+ startIndex: 1,
+
+ // calculate end index for displayed content on the mirroring page
+ endIndex: function () {
+ return Math.min(this.get('filteredContent.length'), this.get('startIndex') + parseInt(this.get('displayLength')) - 1);
+ }.property('startIndex', 'displayLength', 'filteredContent.length'),
+
+ /**
+ * onclick handler for previous page button on the mirroring page
+ */
+ previousPage: function () {
+ var result = this.get('startIndex') - parseInt(this.get('displayLength'));
+ if (result < 2) {
+ result = 1;
+ }
+ this.set('startIndex', result);
+ },
+
+ /**
+ * onclick handler for next page button on the mirroring page
+ */
+ nextPage: function () {
+ var result = this.get('startIndex') + parseInt(this.get('displayLength'));
+ if (result - 1 < this.get('filteredContent.length')) {
+ this.set('startIndex', result);
+ }
+ },
+
+ // the number of mirroring to show on every page of the mirroring page view
+ displayLength: null,
+
+ // calculates default value for startIndex property after applying filter or changing displayLength
+ updatePaging: function () {
+ this.set('startIndex', Math.min(1, this.get('filteredContent.length')));
+ }.observes('displayLength', 'filteredContent.length'),
+
+ sortView: sort.wrapperView,
+ nameSort: sort.fieldView.extend({
+ name: 'name',
+ displayName: Em.I18n.t('common.name')
+ }),
+ dataSetSourceSort: sort.fieldView.extend({
+ name: 'sourceDir',
+ displayName: Em.I18n.t('mirroring.table.datasetSource')
+ }),
+ lastSuccessSort: sort.fieldView.extend({
+ name: 'lastSucceededDate',
+ displayName: Em.I18n.t('mirroring.table.lastSuccess'),
+ type: 'number'
+ }),
+ lastFailSort: sort.fieldView.extend({
+ name: 'lastFailedDate',
+ displayName: Em.I18n.t('mirroring.table.lastFail'),
+ type: 'number'
+ }),
+ lastDurationSort: sort.fieldView.extend({
+ name: 'lastDuration',
+ displayName: Em.I18n.t('mirroring.table.lastDuration'),
+ type: 'number'
+ }),
+ avgDataSort: sort.fieldView.extend({
+ name: 'avgData',
+ displayName: Em.I18n.t('mirroring.table.avgData'),
+ type: 'number'
+ }),
+
+ /**
+ * Filter view for name column
+ * Based on <code>filters</code> library
+ */
+ nameFilterView: filters.createTextView({
+ fieldType: 'input-small',
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(1, this.get('value'), 'string');
+ }
+ }),
+
+ datasetSourceFilterView: filters.createTextView({
+ fieldType: 'input-small',
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(2, this.get('value'), 'string');
+ }
+ }),
+
+ lastSuccessFilterView: filters.createSelectView({
+ fieldType: 'input-medium',
+ content: ['Any', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(3, this.get('value'), 'date');
+ }
+ }),
+
+ lastFailFilterView: filters.createSelectView({
+ fieldType: 'input-medium',
+ content: ['Any', 'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days'],
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(4, this.get('value'), 'date');
+ }
+ }),
+
+ lastDurationFilterView: filters.createTextView({
+ fieldType: 'input-small',
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(5, this.get('value'), 'duration');
+ }
+ }),
+
+ avgDataFilterView: filters.createTextView({
+ fieldType: 'input-small',
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(6, this.get('value'), 'ambari-bandwidth');
+ }
+ }),
+
+ DatasetView: Em.View.extend({
+ content: null,
+ tagName: 'tr',
+
+ lastDurationFormatted: function () {
+ var milliseconds = this.get('content.lastDuration');
+ var h = Math.floor(milliseconds / 3600000);
+ var m = Math.floor((milliseconds % 3600000) / 60000);
+ var s = Math.floor(((milliseconds % 360000) % 60000) / 1000);
+ return (h == 0 ? '' : h + 'hr ') + (m == 0 ? '' : m + 'mins ') + (s == 0 ? '' : s + 'secs ');
+ }.property('content.lastDuration'),
+
+ lastSucceededDateFormatted: function () {
+ if (this.get('content.lastSucceededDate')) {
+ return $.timeago(this.get('content.lastSucceededDate'));
+ }
+ }.property('content.lastSucceededDate'),
+
+ lastFailedDateFormatted: function () {
+ if (this.get('content.lastFailedDate')) {
+ return $.timeago(this.get('content.lastFailedDate'));
+ }
+ }.property('content.lastFailedDate')
+ }),
+
+ /**
+ * Apply each filter to dataset
+ *
+ * @param iColumn number of column by which filter
+ * @param value
+ */
+ updateFilter: function (iColumn, value, type) {
+ var filterCondition = this.get('filterConditions').findProperty('iColumn', iColumn);
+ if (filterCondition) {
+ filterCondition.value = value;
+ } else {
+ filterCondition = {
+ iColumn: iColumn,
+ value: value,
+ type: type
+ }
+ this.get('filterConditions').push(filterCondition);
+ }
+ this.filter();
+ },
+
+ /**
+ * associations between dataset property and column index
+ */
+ colPropAssoc: function () {
+ var associations = [];
+ associations[1] = 'name';
+ associations[2] = 'sourceDir';
+ associations[3] = 'lastSucceededDate';
+ associations[4] = 'lastFailedDate';
+ associations[5] = 'lastDuration';
+ associations[6] = 'avgData';
+ return associations;
+ }.property(),
+
+ /**
+ * contain filter conditions for each column
+ */
+ filterConditions: [],
+
+ filteredContent: [],
+
+ // contain content to show on the current page of mirroring page view
+ pageContent: function () {
+ return this.get('filteredContent').slice(this.get('startIndex') - 1, this.get('endIndex'));
+ }.property('filteredContent.length', 'startIndex', 'endIndex'),
+
+ /**
+ * filter table by filterConditions
+ */
+ filter: function () {
+ var content = this.get('content');
+ var filterConditions = this.get('filterConditions').filterProperty('value');
+ var result;
+ var assoc = this.get('colPropAssoc');
+ if (filterConditions.length) {
+ result = content.filter(function (dataset) {
+ var match = true;
+ filterConditions.forEach(function (condition) {
+ var filterFunc = filters.getFilterByType(condition.type, false);
+ if (match) {
+ match = filterFunc(dataset.get(assoc[condition.iColumn]), condition.value);
+ }
+ });
+ return match;
+ });
+ this.set('filteredContent', result);
+ } else {
+ this.set('filteredContent', content.toArray());
+ }
+ }.observes('content')
+
+});