浏览代码

AMBARI-6560 Config History: implement "Configs" tab and Config Version History Table under Dashboard (with mock data). (atkach)

atkach 10 年之前
父节点
当前提交
10c0362a6e

+ 213 - 0
ambari-web/app/assets/data/configurations/service_versions.json

@@ -0,0 +1,213 @@
+{
+  "items": [
+    {
+      "serviceconfigversion": "1",
+      "servicename": "HDFS",
+      "createtime": "43800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "1",
+      "servicename": "YARN",
+      "createtime": "43300000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "2",
+      "servicename": "HDFS",
+      "createtime": "43500000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "2",
+      "servicename": "YARN",
+      "createtime": "13800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "3",
+      "servicename": "HDFS",
+      "createtime": "23800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "3",
+      "servicename": "YARN",
+      "createtime": "47800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "4",
+      "servicename": "HDFS",
+      "createtime": "43900000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "4",
+      "servicename": "YARN",
+      "createtime": "33800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "5",
+      "servicename": "HDFS",
+      "createtime": "41800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "5",
+      "servicename": "YARN",
+      "createtime": "46800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    },
+    {
+      "serviceconfigversion": "6",
+      "servicename": "YARN",
+      "createtime": "44800000000",
+      "appliedtime": "58600000000",
+      "author": "admin",
+      "notes": "Notes should be here",
+      "configurations": [
+        {
+          "type": "core-site",
+          "tag": "1",
+          "version": "1",
+          "Config": {
+            "cluster_name": "c1"
+          },
+          "properties": {}
+        }
+      ]
+    }
+  ]
+}

+ 1 - 0
ambari-web/app/controllers.js

@@ -26,6 +26,7 @@ require('controllers/installer');
 require('controllers/global/background_operations_controller');
 require('controllers/main');
 require('controllers/main/dashboard');
+require('controllers/main/dashboard/config_history_controller');
 require('controllers/main/admin');
 require('controllers/main/admin/highAvailability_controller');
 require('controllers/main/admin/highAvailability/nameNode/wizard_controller');

+ 73 - 0
ambari-web/app/controllers/main/dashboard/config_history_controller.js

@@ -0,0 +1,73 @@
+/**
+ * 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.
+ */
+
+App.MainConfigHistoryController = Em.ArrayController.extend({
+  name: 'mainConfigHistoryController',
+
+  dataSource: App.ServiceConfigVersion.find(),
+  content: function () {
+    return this.get('dataSource').toArray();
+  }.property('dataSource.@each.isLoaded'),
+  isLoaded: false,
+  isPolling: false,
+
+  /**
+   * initial data load
+   */
+  load: function () {
+    var self = this;
+
+    this.set('isLoaded', false);
+    this.loadHistoryToModel().done(function () {
+      self.set('isLoaded', true);
+      self.doPolling();
+    });
+  },
+
+  /**
+   * get data from server and push it to model
+   * @return {*}
+   */
+  loadHistoryToModel: function () {
+    var dfd = $.Deferred();
+
+    var url = '/data/configurations/service_versions.json';
+
+    App.HttpClient.get(url, App.serviceConfigVersionsMapper, {
+      complete: function () {
+        dfd.resolve();
+      }
+    });
+    return dfd.promise();
+  },
+
+  /**
+   * request latest data from server and update content
+   */
+  doPolling: function () {
+    var self = this;
+
+    setTimeout(function () {
+      if (self.get('isPolling')) {
+        self.loadHistoryToModel().done(function () {
+          self.doPolling();
+        })
+      }
+    }, App.componentsUpdateInterval);
+  }
+});

+ 6 - 0
ambari-web/app/controllers/main/service/item.js

@@ -44,6 +44,12 @@ App.MainServiceItemController = Em.Controller.extend({
     }
   },
 
+  /**
+   * flag to control router switch between service summary and configs
+   * @type {boolean}
+   */
+  routeToConfigs: false,
+
   isClientsOnlyService: function() {
     return App.get('services.clientOnly').contains(this.get('content.serviceName'));
   }.property('content.serviceName'),

+ 2 - 1
ambari-web/app/mappers.js

@@ -31,4 +31,5 @@ require('mappers/target_cluster_mapper');
 require('mappers/dataset_mapper');
 require('mappers/component_config_mapper');
 require('mappers/components_state_mapper');
-require('mappers/jobs/hive_jobs_mapper');
+require('mappers/jobs/hive_jobs_mapper');
+require('mappers/service_config_version_mapper');

+ 44 - 0
ambari-web/app/mappers/service_config_version_mapper.js

@@ -0,0 +1,44 @@
+/**
+ * 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.serviceConfigVersionsMapper = App.QuickDataMapper.create({
+  model: App.ServiceConfigVersion,
+  config: {
+    service_name: 'servicename',
+    version: "serviceconfigversion",
+    create_time: 'createtime',
+    applied_time: 'appliedtime',
+    author: 'author',
+    notes: 'notes'
+  },
+  map: function (json) {
+    var result = [];
+
+    if (json && json.items) {
+      json.items.forEach(function (item) {
+        var parsedItem = this.parseIt(item, this.get('config'));
+        parsedItem.id = parsedItem.service_name + '_' + parsedItem.version;
+        result.push(parsedItem);
+      }, this);
+
+      App.store.loadMany(this.get('model'), result);
+    }
+  }
+});

+ 10 - 0
ambari-web/app/messages.js

@@ -210,6 +210,8 @@ Em.I18n.translations = {
   'common.free': 'free',
   'common.type.string': 'string',
   'common.type.number': 'number',
+  'common.author': 'Author',
+  'common.notes': 'Notes',
 
   'passiveState.turnOn':'Turn On Maintenance Mode',
   'passiveState.turnOff':'Turn Off Maintenance Mode',
@@ -1917,6 +1919,14 @@ Em.I18n.translations = {
   'dashboard.services.configs.popup.stopService.body' : 'Service needs to be stopped for reconfiguration',
   'dashboard.services.configs.popup.restartService.header' : 'Restart service',
   'dashboard.services.configs.popup.restartService.body' : 'Service needs to be restarted for reconfiguration',
+
+  'dashboard.configHistory.title': 'Configs',
+  'dashboard.configHistory.table.version.title' : 'Service: version',
+  'dashboard.configHistory.table.modified.title' : 'Modified',
+  'dashboard.configHistory.table.empty' : 'No history to display',
+  'dashboard.configHistory.table.filteredHostsInfo': '{0} of {1} versions showing',
+  'dashboard.configHistory.table.current': '(Current)',
+
   'timeRange.presets.1hour':'1h',
   'timeRange.presets.12hour':'12h',
   'timeRange.presets.1day':'1d',

+ 1 - 0
ambari-web/app/models.js

@@ -57,3 +57,4 @@ require('models/config_group');
 require('models/jobs/tez_dag');
 require('models/jobs/job');
 require('models/jobs/hive_job');
+require('models/service_config_version');

+ 40 - 0
ambari-web/app/models/service_config_version.js

@@ -0,0 +1,40 @@
+/**
+ * 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 dateUtil = require('utils/date');
+
+
+App.ServiceConfigVersion = DS.Model.extend({
+  serviceName: DS.attr('string'),
+  version: DS.attr('number'),
+  createTime: DS.attr('number'),
+  appliedTime: DS.attr('number'),
+  author: DS.attr('string'),
+  notes: DS.attr('string'),
+  serviceVersion: function(){
+    return this.get('serviceName') + ': '+ this.get('version');
+  }.property('serviceName', 'version'),
+  modifiedDate: function() {
+    return dateUtil.dateFormat(this.get('createTime'));
+  }.property('createTime'),
+  isCurrent: true
+});
+
+App.ServiceConfigVersion.FIXTURES = [];

+ 14 - 3
ambari-web/app/routes/main.js

@@ -118,7 +118,6 @@ module.exports = Em.Route.extend({
         });
       }
     }),
-    //on click nav tabs events, go to widgets view or heatmap view
     goToDashboardView: function (router, event) {
       router.transitionTo(event.context);
     },
@@ -161,7 +160,19 @@ module.exports = Em.Route.extend({
         event.view.set('active', "active");
         router.transitionTo(event.context);
       }
-    })
+    }),
+    configHistory: Em.Route.extend({
+      route: '/config_history',
+      connectOutlets: function (router, context) {
+        router.set('mainDashboardController.selectedCategory', 'configHistory');
+        router.get('mainDashboardController').connectOutlet('mainConfigHistory');
+      }
+    }),
+    goToServiceConfigs: function (router, event) {
+      router.get('mainServiceItemController').set('routeToConfigs', true);
+      App.router.transitionTo('main.services.service.configs', App.Service.find(event.context));
+      router.get('mainServiceItemController').set('routeToConfigs', false);
+    }
   }),
 
   apps: Em.Route.extend({
@@ -656,7 +667,7 @@ module.exports = Em.Route.extend({
             if (!service || !service.get('isLoaded')) {
               service = App.Service.find().objectAt(0); // getting the first service to display
             }
-            if (service.get('routeToConfigs')) {
+            if (router.get('mainServiceItemController').get('routeToConfigs')) {
               router.transitionTo('service.configs', service);
             }
             else {

文件差异内容过多而无法显示
+ 2 - 51
ambari-web/app/styles/application.less


+ 1 - 1
ambari-web/app/templates/main/dashboard.hbs

@@ -30,7 +30,7 @@
         {{/each}}
       </ul>
 
-      <!--show widgets or heapmaps in the content-->
+      <!--show widgets, heatmaps or configs in the content-->
       {{outlet}}
     </div>
 </div>

+ 83 - 0
ambari-web/app/templates/main/dashboard/config_history.hbs

@@ -0,0 +1,83 @@
+{{!
+* 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="config_history">
+    <table class="table table-bordered table-striped" >
+        <thead>
+        {{#view view.sortView classNames="label-row"}}
+            {{view view.parentView.versionSort}}
+            {{view view.parentView.modifiedSort}}
+            {{view view.parentView.authorSort}}
+            {{view view.parentView.notesSort}}
+        {{/view}}
+
+        <tr class="filter-row">
+            <th class="first">{{view view.versionFilterView}}</th>
+            <th>{{view view.modifiedFilterView}}</th>
+            <th>{{view view.authorFilterView}}</th>
+            <th>{{view view.notesFilterView}}</th>
+        </tr>
+        </thead>
+        <tbody>
+        {{#if view.pageContent}}
+          {{#each item in view.pageContent}}
+              <tr>
+                  <td class="first"><a {{action goToServiceConfigs item.serviceName}}>
+                    {{item.serviceVersion}}{{#if item.isCurrent}}&nbsp;{{t dashboard.configHistory.table.current}}{{/if}}
+                  </a></td>
+                  <td>{{item.modifiedDate}}</td>
+                  <td>{{item.author}}</td>
+                  <td>{{item.notes}}</td>
+              </tr>
+          {{/each}}
+        {{else}}
+            <tr>
+                <td class="first" colspan="4">
+                  {{t dashboard.configHistory.table.empty}}
+                </td>
+            </tr>
+        {{/if}}
+        </tbody>
+    </table>
+
+    <div class="page-bar">
+        <div class="filtered-info span4">
+            <label>{{view.filteredContentInfo}} - <a {{action clearFilters target="view"}}
+                    href="#">{{t tableView.filters.clearAllFilters}}</a></label>
+        </div>
+        <div class="selected-hosts-info span4">
+          {{#if view.showSelectedFilter}}
+              <div>
+                  <a {{action filterSelected target="view"}} href="#">
+                    {{view.selectedHosts.length}}
+                    {{pluralize view.selectedHostsCount singular="t:hosts.filters.selectedHostInfo" plural="t:hosts.filters.selectedHostsInfo"}}
+                  </a>
+              </div>
+              - <a {{action clearSelection target="view"}} href="#">{{t hosts.filters.clearSelection}}</a>
+          {{/if}}
+        </div>
+        <div class="items-on-page">
+            <label>{{t common.show}}: {{view view.rowsPerPageSelectView 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>

+ 3 - 3
ambari-web/app/templates/main/host.hbs

@@ -55,7 +55,7 @@
     </div>
   </div>
 
-  <table class="datatable table table-bordered table-striped" id="hosts-table">
+  <table class="table table-bordered table-striped" id="hosts-table">
     <thead>
       {{#view view.sortView classNames="label-row" contentBinding="view.filteredContent"}}
         <th class="first"> </th>
@@ -70,7 +70,7 @@
         {{view view.parentView.loadAvgSort}}
         <th class="sort-view-6">{{t common.components}}</th>
       {{/view}}
-      <tr id="filter-row">
+      <tr class="filter-row">
         <th class="first"><div class="ember-view view-wrapper">{{view Ember.Checkbox checkedBinding="view.selectAllHosts"}}</div></th>
         <th> </th>
         <th>{{view view.nameFilterView}}</th>
@@ -147,7 +147,7 @@
   </div>
 
   <div class="page-bar">
-    <div class="filtered-hosts-info span4">
+    <div class="filtered-info span4">
       <label>{{view.filteredContentInfo}} - <a {{action clearFilters target="view"}} href="#">{{t tableView.filters.clearAllFilters}}</a></label>
     </div>
     <div class="selected-hosts-info span4">

+ 1 - 0
ambari-web/app/views.js

@@ -148,6 +148,7 @@ require('views/main/dashboard/widgets/node_managers_live');
 require('views/main/dashboard/widgets/yarn_memory');
 require('views/main/dashboard/widgets/supervisor_live');
 require('views/main/dashboard/widgets/flume_agent_live');
+require('views/main/dashboard/config_history_view');
 
 
 require('views/main/service');

+ 7 - 1
ambari-web/app/views/common/filter_view.js

@@ -271,7 +271,7 @@ module.exports = {
       attributeBindings: ['disabled','multiple'],
       disabled: false
     });
-    config.emptyValue = Em.I18n.t('any');
+    config.emptyValue = config.emptyValue || 'Any';
 
     return wrapperView.extend(config);
   },
@@ -480,6 +480,12 @@ module.exports = {
           return origin === compareValue;
         };
         break;
+      case 'select':
+        return function (origin, compareValue){
+          //TODO add filter by select value
+          return true;
+        };
+        break;
       case 'string':
       default:
         return function(origin, compareValue){

+ 20 - 1
ambari-web/app/views/common/table_view.js

@@ -18,7 +18,6 @@
 
 var App = require('app');
 var filters = require('views/common/filter_view');
-var sort = require('views/common/sort_view');
 
 App.TableView = Em.View.extend(App.UserPref, {
 
@@ -411,6 +410,26 @@ App.TableView = Em.View.extend(App.UserPref, {
     }
   }.observes('content.length'),
 
+  /**
+   * sort content by active sort column
+   */
+  sortContent: function() {
+    var activeSort = App.db.getSortingStatuses(this.get('controller.name')).find(function (sort) {
+      return (sort.status === 'sorting_asc' || sort.status === 'sorting_desc');
+    });
+    var sortIndexes = {
+      'sorting_asc': 1,
+      'sorting_desc': -1
+    };
+
+    this.get('content').sort(function (a, b) {
+      if (a.get(activeSort.name) > b.get(activeSort.name)) return sortIndexes[activeSort.status];
+      if (a.get(activeSort.name) < b.get(activeSort.name)) return -(sortIndexes[activeSort.status]);
+      return 0;
+    });
+    this.filter();
+  },
+
   /**
    * Does any filter is used on the page
    * @type {Boolean}

+ 9 - 5
ambari-web/app/views/main/dashboard.js

@@ -24,8 +24,8 @@ App.MainDashboardView = Em.View.extend({
   templateName: require('templates/main/dashboard'),
 
   selectedBinding: 'controller.selectedCategory',
-  categories: function() {
-    var items = [{
+  categories: [
+    {
       name: 'widgets',
       url: 'dashboard.index',
       label: Em.I18n.t('dashboard.widgets.title')
@@ -34,9 +34,13 @@ App.MainDashboardView = Em.View.extend({
       name: 'charts',
       url: 'dashboard.charts.index',
       label: Em.I18n.t('dashboard.heatmaps.title')
-    }];
-    return items;
-  }.property(''),
+    },
+    {
+      name: 'configHistory',
+      url: 'dashboard.configHistory',
+      label: Em.I18n.t('dashboard.configHistory.title')
+    }
+  ],
   NavItemView: Ember.View.extend({
     tagName: 'li',
     classNameBindings: 'isActive:active'.w(),

+ 133 - 0
ambari-web/app/views/main/dashboard/config_history_view.js

@@ -0,0 +1,133 @@
+/**
+ * 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.MainConfigHistoryView = App.TableView.extend({
+  templateName: require('templates/main/dashboard/config_history'),
+
+  controllerBinding: 'App.router.mainConfigHistoryController',
+
+  content: function () {
+    return this.get('controller.content');
+  }.property('controller.content'),
+
+  /**
+   * return filtered number of all content number information displayed on the page footer bar
+   * @returns {String}
+   */
+  filteredContentInfo: function () {
+    return this.t('hosts.filters.filteredHostsInfo').format(this.get('filteredCount'), this.get('content.length'));
+  }.property('filteredCount', 'totalCount'),
+
+
+  didInsertElement: function () {
+    this.set('controller.isPolling', true);
+    this.get('controller').load();
+  },
+
+  /**
+   * stop polling after leaving config history page
+   */
+  willDestroyElement: function () {
+    this.set('controller.isPolling', false);
+  },
+
+  sortView: sort.serverWrapperView,
+  versionSort: sort.fieldView.extend({
+    column: 1,
+    name: 'serviceVersion',
+    displayName: Em.I18n.t('dashboard.configHistory.table.version.title'),
+    classNames: ['first']
+  }),
+  modifiedSort: sort.fieldView.extend({
+    column: 2,
+    name: 'createTime',
+    displayName: Em.I18n.t('dashboard.configHistory.table.modified.title')
+  }),
+  authorSort: sort.fieldView.extend({
+    column: 3,
+    name: 'author',
+    displayName: Em.I18n.t('common.author')
+  }),
+  notesSort: sort.fieldView.extend({
+    column: 4,
+    name: 'notes',
+    displayName: Em.I18n.t('common.notes')
+  }),
+
+  versionFilterView: filters.createSelectView({
+    column: 1,
+    fieldType: 'filter-input-width',
+    content: ['All'],
+    valueBinding: "controller.filterObject.version",
+    onChangeValue: function () {
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'select');
+    },
+    emptyValue: Em.I18n.t('common.all')
+  }),
+
+  modifiedFilterView: filters.createSelectView({
+    column: 2,
+    fieldType: 'filter-input-width',
+    content: ['Any'],
+    valueBinding: "controller.filterObject.modified",
+    onChangeValue: function () {
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'select');
+    }
+  }),
+
+  authorFilterView: filters.createTextView({
+    column: 3,
+    fieldType: 'filter-input-width',
+    onChangeValue: function () {
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
+    }
+  }),
+
+  notesFilterView: filters.createTextView({
+    column: 4,
+    fieldType: 'filter-input-width',
+    onChangeValue: function () {
+      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
+    }
+  }),
+
+  /**
+   * sort content
+   */
+  refresh: function () {
+    this.sortContent();
+  },
+
+  /**
+   * associations between host property and column index
+   * @type {Array}
+   */
+  colPropAssoc: function () {
+    var associations = [];
+    associations[1] = 'serviceVersion';
+    associations[2] = 'createTime';
+    associations[3] = 'author';
+    associations[4] = 'notes';
+    return associations;
+  }.property()
+
+});

+ 4 - 4
ambari-web/app/views/main/service/menu.js

@@ -86,9 +86,9 @@ App.MainServiceMenuView = Em.CollectionView.extend({
     }.property('App.router.currentState.name', 'parentView.activeServiceId', 'isConfigurable'),
 
     goToConfigs: function () {
-      this.set('content.routeToConfigs', true);
+      App.router.set('mainServiceItemController.routeToConfigs', true);
       App.router.transitionTo('services.service.configs', this.get('content'));
-      this.set('content.routeToConfigs', false);
+      App.router.set('mainServiceItemController.routeToConfigs', false);
     },
 
     refreshRestartRequiredMessage: function() {
@@ -184,9 +184,9 @@ App.TopNavServiceMenuView = Em.CollectionView.extend({
     }.property('App.router.currentState.name', 'parentView.activeServiceId','isConfigurable'),
 
     goToConfigs: function () {
-      this.set('content.routeToConfigs', true);
+      App.router.set('mainServiceItemController.routeToConfigs', true);
       App.router.transitionTo('services.service.configs', this.get('content'));
-      this.set('content.routeToConfigs', false);
+      App.router.set('mainServiceItemController.routeToConfigs', false);
     },
 
     refreshRestartRequiredMessage: function() {

部分文件因为文件数量过多而无法显示