瀏覽代碼

AMBARI-770. Cluster Management pages for Ambari Web. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/branches/AMBARI-666@1390762 13f79535-47bb-0310-9956-ffa450edef68
Yusaku Sako 12 年之前
父節點
當前提交
1aea3a7a77
共有 91 個文件被更改,包括 3900 次插入288 次删除
  1. 2 0
      AMBARI-666-CHANGES.txt
  2. 二進制
      ambari-web/app/assets/img/arrow-right.png
  3. 二進制
      ambari-web/app/assets/img/health-status-dead.png
  4. 二進制
      ambari-web/app/assets/img/health-status-live.png
  5. 二進制
      ambari-web/app/assets/img/status-corrupt.jpg
  6. 二進制
      ambari-web/app/assets/img/status-ok.jpg
  7. 13 0
      ambari-web/app/controllers.js
  8. 21 0
      ambari-web/app/controllers/main/admin.js
  9. 52 0
      ambari-web/app/controllers/main/admin/advanced.js
  10. 34 0
      ambari-web/app/controllers/main/admin/authentication.js
  11. 21 0
      ambari-web/app/controllers/main/admin/item.js
  12. 27 0
      ambari-web/app/controllers/main/admin/user.js
  13. 22 0
      ambari-web/app/controllers/main/admin/user/edit.js
  14. 1 2
      ambari-web/app/controllers/main/alert.js
  15. 38 0
      ambari-web/app/controllers/main/dashboard.js
  16. 194 0
      ambari-web/app/controllers/main/host.js
  17. 75 0
      ambari-web/app/controllers/main/host/details.js
  18. 32 0
      ambari-web/app/controllers/main/service/info/audit.js
  19. 22 0
      ambari-web/app/controllers/main/service/info/configs.js
  20. 22 0
      ambari-web/app/controllers/main/service/info/metrics.js
  21. 21 0
      ambari-web/app/controllers/main/service/info/summary.js
  22. 40 1
      ambari-web/app/controllers/main/service/item.js
  23. 1 0
      ambari-web/app/initialize.js
  24. 76 1
      ambari-web/app/messages.js
  25. 7 1
      ambari-web/app/models.js
  26. 82 3
      ambari-web/app/models/alert.js
  27. 87 0
      ambari-web/app/models/authentication.js
  28. 111 35
      ambari-web/app/models/cluster.js
  29. 267 0
      ambari-web/app/models/form.js
  30. 81 0
      ambari-web/app/models/pagination.js
  31. 153 20
      ambari-web/app/models/service.js
  32. 65 0
      ambari-web/app/models/service_audit.js
  33. 20 0
      ambari-web/app/models/service_metrics.js
  34. 48 4
      ambari-web/app/models/user.js
  35. 220 21
      ambari-web/app/routes/main.js
  36. 112 2
      ambari-web/app/styles/app.css
  37. 74 0
      ambari-web/app/styles/application.less
  38. 20 0
      ambari-web/app/templates/common/form.hbs
  39. 24 0
      ambari-web/app/templates/common/form/checkbox.hbs
  40. 25 0
      ambari-web/app/templates/common/form/field.hbs
  41. 18 0
      ambari-web/app/templates/common/grid/header.hbs
  42. 6 3
      ambari-web/app/templates/installer/slave_hosts.hbs
  43. 4 2
      ambari-web/app/templates/main/admin.hbs
  44. 27 0
      ambari-web/app/templates/main/admin/advanced.hbs
  45. 19 0
      ambari-web/app/templates/main/admin/advanced/uninstall.hbs
  46. 37 0
      ambari-web/app/templates/main/admin/audit.hbs
  47. 49 0
      ambari-web/app/templates/main/admin/authentication.hbs
  48. 25 0
      ambari-web/app/templates/main/admin/security.hbs
  49. 42 0
      ambari-web/app/templates/main/admin/user.hbs
  50. 34 0
      ambari-web/app/templates/main/admin/user/edit.hbs
  51. 27 0
      ambari-web/app/templates/main/admin/user/row.hbs
  52. 79 104
      ambari-web/app/templates/main/dashboard.hbs
  53. 129 0
      ambari-web/app/templates/main/host.hbs
  54. 19 0
      ambari-web/app/templates/main/host/audit.hbs
  55. 40 0
      ambari-web/app/templates/main/host/details.hbs
  56. 19 0
      ambari-web/app/templates/main/host/metrics.hbs
  57. 41 0
      ambari-web/app/templates/main/host/summary.hbs
  58. 3 3
      ambari-web/app/templates/main/menu.hbs
  59. 51 0
      ambari-web/app/templates/main/service/info/audit.hbs
  60. 136 0
      ambari-web/app/templates/main/service/info/configs.hbs
  61. 20 0
      ambari-web/app/templates/main/service/info/metrics.hbs
  62. 66 0
      ambari-web/app/templates/main/service/info/summary.hbs
  63. 27 72
      ambari-web/app/templates/main/service/item.hbs
  64. 27 0
      ambari-web/app/utils/helper.js
  65. 19 1
      ambari-web/app/utils/validator.js
  66. 21 1
      ambari-web/app/views.js
  67. 45 0
      ambari-web/app/views/common/form/field.js
  68. 1 1
      ambari-web/app/views/main/admin.js
  69. 24 0
      ambari-web/app/views/main/admin/advanced.js
  70. 27 0
      ambari-web/app/views/main/admin/advanced/password.js
  71. 115 0
      ambari-web/app/views/main/admin/audit.js
  72. 41 0
      ambari-web/app/views/main/admin/authentication.js
  73. 58 0
      ambari-web/app/views/main/admin/menu.js
  74. 23 0
      ambari-web/app/views/main/admin/security.js
  75. 40 0
      ambari-web/app/views/main/admin/user.js
  76. 43 0
      ambari-web/app/views/main/admin/user/edit.js
  77. 24 0
      ambari-web/app/views/main/admin/user/row.js
  78. 1 4
      ambari-web/app/views/main/dashboard.js
  79. 42 0
      ambari-web/app/views/main/host.js
  80. 26 0
      ambari-web/app/views/main/host/audit.js
  81. 26 0
      ambari-web/app/views/main/host/details.js
  82. 49 0
      ambari-web/app/views/main/host/menu.js
  83. 26 0
      ambari-web/app/views/main/host/metrics.js
  84. 29 0
      ambari-web/app/views/main/host/summary.js
  85. 14 5
      ambari-web/app/views/main/menu.js
  86. 24 0
      ambari-web/app/views/main/service/info/audit.js
  87. 26 0
      ambari-web/app/views/main/service/info/configs.js
  88. 50 0
      ambari-web/app/views/main/service/info/menu.js
  89. 26 0
      ambari-web/app/views/main/service/info/metrics.js
  90. 23 0
      ambari-web/app/views/main/service/info/summary.js
  91. 2 2
      ambari-web/app/views/main/service/menu.js

+ 2 - 0
AMBARI-666-CHANGES.txt

@@ -12,6 +12,8 @@ AMBARI-666 branch (unreleased changes)
 
   NEW FEATURES
 
+  AMBARI-770. Cluster Management pages for Ambari Web. (yusaku)
+
   AMBARI-769. Implement step 9 (Install,start and test) of installer wizard.
   (Jaimin Jetly via yusaku)
 

二進制
ambari-web/app/assets/img/arrow-right.png


二進制
ambari-web/app/assets/img/health-status-dead.png


二進制
ambari-web/app/assets/img/health-status-live.png


二進制
ambari-web/app/assets/img/status-corrupt.jpg


二進制
ambari-web/app/assets/img/status-ok.jpg


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

@@ -31,6 +31,19 @@ require('controllers/installer/step6_controller');
 require('controllers/installer/step7_controller');
 require('controllers/installer/step9_controller');
 require('controllers/main');
+require('controllers/main/admin');
+require('controllers/main/admin/item');
+require('controllers/main/admin/user');
+require('controllers/main/admin/user/edit');
+require('controllers/main/admin/advanced');
+require('controllers/main/admin/authentication');
 require('controllers/main/service');
 require('controllers/main/service/item');
+require('controllers/main/service/info/summary');
+require('controllers/main/service/info/metrics');
+require('controllers/main/service/info/configs');
+require('controllers/main/service/info/audit');
 require('controllers/main/alert');
+require('controllers/main/host');
+require('controllers/main/host/details');
+require('controllers/main/dashboard');

+ 21 - 0
ambari-web/app/controllers/main/admin.js

@@ -0,0 +1,21 @@
+/**
+ * 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.MainAdminController = Em.Controller.extend({
+  name:'mainAdminController'
+})

+ 52 - 0
ambari-web/app/controllers/main/admin/advanced.js

@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.MainAdminAdvancedController = Em.Controller.extend({
+  name:'mainAdminAdvancedController',
+  uninstall: function(event){
+    var params = event.context;
+    App.ModalPopup.show({
+      uninstallParams: params,
+      header: Em.I18n.t('admin.advanced.popup.header'),
+      bodyClass: App.MainAdminAdvancedPasswordView.reopen({}), // layout: Em.Handlebars.compile()
+      onPrimary: function(){
+        var form = this.getForm();
+        if(form) {
+          if(form.isValid()) {
+            console.warn("TODO: request for cluster uninstall");
+          }
+        }
+        this.onClose();
+      },
+      onSecondary: function(){
+        this.onClose();
+      },
+
+      getForm: function(){
+        var form = false;
+        $.each(this.get('_childViews'), function(){
+          if(this.get('path') == "bodyClass") {
+            return form = this.get('_childViews')[0];
+          }
+        });
+
+        return form;
+      }
+    })
+  }
+})

+ 34 - 0
ambari-web/app/controllers/main/admin/authentication.js

@@ -0,0 +1,34 @@
+/**
+ * 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.MainAdminAuthenticationController = Em.Controller.extend({
+  name:'mainAdminAuthenticationController',
+  save:function (event) {
+    var form = event.context;
+    form.save();
+    App.ModalPopup.show({
+      header: Em.I18n.t('admin.authentication.form.testConfiguration'),
+      body:form.get('resultText'),
+      secondary:false,
+      onPrimary: function(){
+        this.hide();
+      }
+    });
+  },
+  content:App.Authentication.find(1)
+})

+ 21 - 0
ambari-web/app/controllers/main/admin/item.js

@@ -0,0 +1,21 @@
+/**
+ * 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.MainAdminItemController = Em.Controller.extend({
+  name:'mainAdminItemController'
+})

+ 27 - 0
ambari-web/app/controllers/main/admin/user.js

@@ -0,0 +1,27 @@
+/**
+ * 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.MainAdminUserController = Em.Controller.extend({
+  name:'mainAdminUserController',
+  deleteRecord:function (event) {
+    if (Em.I18n.t('question.sure')) {
+      event.context.deleteRecord();
+      App.store.commit();
+    }
+  }
+})

+ 22 - 0
ambari-web/app/controllers/main/admin/user/edit.js

@@ -0,0 +1,22 @@
+/**
+ * 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.MainAdminUserEditController = Em.Controller.extend({
+  name:'mainAdminUserEditController',
+  content:false
+})

+ 1 - 2
ambari-web/app/controllers/main/alert.js

@@ -17,6 +17,5 @@
  */
 
 App.MainAlertController = Em.ArrayController.extend({
-  name:'mainAlertController',
-  content: App.Alert.find()
+  name:'mainAlertController'
 })

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

@@ -0,0 +1,38 @@
+/**
+ * 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.MainDashboardController = Em.Controller.extend({
+  name:'mainDashboardController',
+  alerts: App.Alert.find(),
+  services:function(){
+    return App.router.get('mainServiceController.content');
+  }.property('App.router.mainServiceController.content'),
+  alertsFilteredBy: 'All',
+  alertsFilter: function(event) {
+    if (event.context) {
+      this.set('alerts', event.context.get('alerts'));
+      this.set('alertsFilteredBy', event.context.get('label'))
+    } else {
+      this.set('alerts', App.Alert.find());
+      this.set('alertsFilteredBy', 'All')
+    }
+  },
+  alertsCount: function() {
+    return this.alerts.get('content').length;
+  }.property()
+})

+ 194 - 0
ambari-web/app/controllers/main/host.js

@@ -0,0 +1,194 @@
+/**
+ * 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.MainHostController = Em.ArrayController.extend(App.Pagination, {
+  name:'mainHostController',
+  content: [],
+  fullContent: App.Host.find(),
+  clusters: App.Cluster.find(),
+  allComponents: App.Component.find(),
+  totalBinding: 'fullContent.length',
+  filters: {components:[]},
+  pageSize: 3,
+  pageSizeRange: [1,3,5,'all'],
+  rangeStart: 0,
+  allChecked: false,
+  selectedHostsIds: [],
+  sortingAsc: true,
+
+  isDisabled:true,
+
+  onAllChecked: function () {
+    var hosts = this.get('content');
+    hosts.setEach('isChecked', this.get('allChecked'));
+    this.set('isDisabled', !this.get('allChecked'));
+    var selectedHostsIds = this.get('allChecked') ? hosts.getEach('id'):[];
+    this.set('selectedHostsIds', selectedHostsIds);
+  }.observes('allChecked'),
+
+  onHostChecked: function (checked, hostId) {
+    var selected = this.get('selectedHostsIds');
+    if (checked) selected.push(hostId);
+    else {
+      var index = selected.indexOf(hostId);
+      if(index!=-1) selected.splice(index, 1);
+    }
+    this.set('isDisabled', selected.length == 0);
+  },
+
+  changeSelectedHosts: function() {
+    var visibleHosts = this.get('content');
+    var selectedHosts = visibleHosts.filterProperty('isChecked', true);
+    this.get('fullContent').forEach(function(item) {
+      var index = visibleHosts.getEach('id').indexOf(item.get('id'));
+      if(index == -1) item.set('isChecked', false);
+    });
+    this.set('isDisabled', selectedHosts.length == 0);
+    this.set('selectedHostsIds', selectedHosts.getEach('id'));
+  },
+
+  setFilters: function(checked, componentId) {
+    var filters = this.get('filters.components');
+    if (checked){
+      filters.push(componentId);
+    } else {
+      var index = filters.indexOf(componentId);
+      if(index!=-1) filters.splice(index, 1);
+    }
+    this.changeContent();
+  },
+
+  filterByComponentId: function(componentId) {
+    this.set('filters.components', [componentId]);
+    this.changeContent();
+  },
+
+  changeContent: function() {
+    var items = [];
+    var filters = this.get('filters.components');
+    if (filters.length){
+      this.get('fullContent').forEach(function(item) {
+        var inFilters = true;
+        $.each(filters, function (i, componentId) {
+          if (item.get('components').getEach('id').indexOf(componentId) == -1){
+            inFilters = false;
+          }
+        });
+        if (inFilters){
+          items.push(item);
+        }
+      });
+      this.set('total', items.length);
+    } else {
+      items = this.get('fullContent');
+      this.set('total', this.get('fullContent.length'));
+    }
+    var content = items.slice(this.get('rangeStart'), this.get('rangeStop'));
+    this.replace(0, this.get('length'), content);
+    this.changeSelectedHosts();
+  }.observes('rangeStart', 'rangeStop', 'filters.components', 'total'),
+
+  showNextPage: function() {
+    this.nextPage();
+  },
+  showPreviousPage: function() {
+    this.previousPage();
+  },
+  assignedToRackPopup: function(event) {
+    var self = this;
+    App.ModalPopup.show({
+      header: Em.I18n.t('hosts.assignedToRack.popup.header'),
+      body: Em.I18n.t('hosts.assignedToRack.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        self.assignedToRack(event.context);
+        this.hide();
+      },
+      onSecondary: function() {
+        this.hide();
+      }
+    });
+  },
+
+  assignedToRack: function(rack) {
+    var hosts = this.get('content');
+    var selectedHosts = hosts.filterProperty('isChecked', true);
+    selectedHosts.setEach('cluster', rack);
+  },
+
+  decommissionButtonPopup: function() {
+    var self = this;
+    App.ModalPopup.show({
+      header: Em.I18n.t('hosts.decommission.popup.header'),
+      body: Em.I18n.t('hosts.decommission.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        alert('do');
+        this.hide();
+      },
+      onSecondary: function() {
+        this.hide();
+      }
+    });
+  },
+  deleteButtonPopup: function() {
+    var self = this;
+    App.ModalPopup.show({
+      header: Em.I18n.t('hosts.delete.popup.header'),
+      body: Em.I18n.t('hosts.delete.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        self.removeHosts();
+        this.hide();
+      },
+      onSecondary: function() {
+        this.hide();
+      }
+    });
+  },
+  removeHosts: function () {
+    var hosts = this.get('content');
+    var selectedHosts = hosts.filterProperty('isChecked', true);
+    selectedHosts.forEach(function (_hostInfo) {
+      console.log('Removing:  ' + _hostInfo.hostName);
+    });
+//    App.db.removeHosts(selectedHosts);
+    this.get('fullContent').removeObjects(selectedHosts);
+  },
+  sortByName: function () {
+    var asc = this.get('sortingAsc');
+    var objects = this.get('fullContent').toArray().sort(function(a, b)
+    {
+      var nA = a.get('hostName').toLowerCase();
+      var nB = b.get('hostName').toLowerCase();
+      if(nA < nB)
+        return asc ? -1 : 1;
+      else if(nA > nB)
+        return asc ? 1 : -1;
+      return 0;
+    });
+    this.set('fullContent', objects);
+    this.set('sortingAsc', !this.get('sortingAsc'));
+    this.changeContent();
+  }
+
+});

+ 75 - 0
ambari-web/app/controllers/main/host/details.js

@@ -0,0 +1,75 @@
+/**
+ * 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.MainHostDetailsController = Em.Controller.extend({
+  name: 'mainHostDetailsController',
+  content: null,
+  startComponents: function(){
+    return this.get('content.workStatus');
+  }.property('content.workStatus'),
+  stopComponents: function(){
+    return !this.get('startComponents');
+  }.property('startComponents'),
+  changeWorkStatus: function(){
+    if (this.get('startComponents')) {
+      this.set('iconClass', 'play');
+    } else {
+      this.set('iconClass', 'stop');
+    }
+  }.observes('startComponents'),
+  iconClass: '',
+
+  startConfirmPopup: function (event) {
+    var self = this;
+    App.ModalPopup.show({
+      header: Em.I18n.t('hosts.host.start.popup.header'),
+      body: Em.I18n.t('hosts.host.start.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        console.log(self.get('content.components').getEach('workStatus'));
+        self.get('content.components').setEach('workStatus', self.get('content.workStatus'));
+
+        self.set('content.workStatus', !self.get('content.workStatus'));
+
+        this.hide();
+      },
+      onSecondary: function() {
+        this.hide();
+      }
+    });
+  },
+  stopConfirmPopup: function (event) {
+    var self = this;
+    App.ModalPopup.show({
+      header: Em.I18n.t('hosts.host.stop.popup.header'),
+      body: Em.I18n.t('hosts.host.stop.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        console.log(self.get('content.components').getEach('workStatus'));
+        self.get('content.components').setEach('workStatus', self.get('content.workStatus'));
+        self.set('content.workStatus', !self.get('content.workStatus'));
+        this.hide();
+      },
+      onSecondary: function() {
+        this.hide();
+      }
+    });
+  }
+})

+ 32 - 0
ambari-web/app/controllers/main/service/info/audit.js

@@ -0,0 +1,32 @@
+/**
+ * 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.MainServiceInfoAuditController = Em.Controller.extend({
+  name: 'mainServiceInfoAuditController',
+  users: App.User.find(),
+  performedBy: function() {
+    var auditItems = this.content.get('serviceAudit');
+    var itemUsers = auditItems.getEach('user');
+    var result = [];
+    this.users.forEach(function(item, index, self) {
+      if (res = itemUsers.findProperty ('id', item.get('id')))
+        result.push(res);
+    });
+    return result;
+  }.property('content')
+})

+ 22 - 0
ambari-web/app/controllers/main/service/info/configs.js

@@ -0,0 +1,22 @@
+/**
+ * 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.MainServiceInfoConfigsController = Em.Controller.extend({
+  name: 'mainServiceInfoConfigsController',
+  content: 'Configs'
+})

+ 22 - 0
ambari-web/app/controllers/main/service/info/metrics.js

@@ -0,0 +1,22 @@
+/**
+ * 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.MainServiceInfoMetricsController = Em.Controller.extend({
+  name: 'mainServiceInfoMetricsController',
+  content: 'Metrics'
+})

+ 21 - 0
ambari-web/app/controllers/main/service/info/summary.js

@@ -0,0 +1,21 @@
+/**
+ * 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.MainServiceInfoSummaryController = Em.Controller.extend({
+  name: 'mainServiceInfoSummaryController'
+})

+ 40 - 1
ambari-web/app/controllers/main/service/item.js

@@ -18,5 +18,44 @@
 
 App.MainServiceItemController = Em.Controller.extend({
   name: 'mainServiceItemController',
-  content: null
+//  content: App.Service.find(1),
+  showRebalancer: function() {
+    if(this.content.get('serviceName') == 'hdfs') {
+      return true;
+    } else {
+      return false;
+    }
+  }.property('content'),
+  startConfirmPopup: function (event) {
+    App.ModalPopup.show({
+      header: Em.I18n.t('services.service.start.popup.header'),
+      body: Em.I18n.t('services.service.start.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        alert('do');
+        this.hide();
+      },
+      onSecondary: function() {
+        alert('not do');
+        this.hide();
+      }
+    });
+  },
+  stopConfirmPopup: function (event) {
+    App.ModalPopup.show({
+      header: Em.I18n.t('services.service.stop.popup.header'),
+      body: Em.I18n.t('services.service.stop.popup.body'),
+      primary: 'Yes',
+      secondary: 'No',
+      onPrimary: function() {
+        alert('do');
+        this.hide();
+      },
+      onSecondary: function() {
+        alert('not do');
+        this.hide();
+      }
+    });
+  }
 })

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

@@ -21,6 +21,7 @@ window.App = require('app');
 
 require('messages');
 require('utils/db');
+require('utils/helper');
 require('models');
 require('controllers');
 require('views');

+ 76 - 1
ambari-web/app/messages.js

@@ -89,6 +89,7 @@ Em.I18n.translations = {
   'installer.step4.body': 'Choose which services you want to install on your cluster.<br>Note that some services have dependencies (e.g., HBase requires ZooKeeper.)',
 
   'installer.step5.header': 'Assign Masters',
+  'installer.step5.attention': 'more hosts without master service',
   'installer.step5.body': 'Assign master components to hosts you want to run them on.',
 
   'installer.step6.header': 'Assign Slaves',
@@ -108,6 +109,80 @@ Em.I18n.translations = {
   'installer.step9.host.status.success': 'success',
   'installer.step9.host.status.warning': 'tolerable failures encountered',
   'installer.step9.host.status.failed': 'failures encountered',
+  'installer.step10.header': 'Summary',
 
-  'installer.step10.header': 'Summary'
+  'form.create': 'Create',
+  'form.save': 'Save',
+  'form.cancel': 'Cancel',
+  'form.password':'Password',
+  'form.passwordRetype':'Retype Password',
+  'form.saveSuccess':'Successfully saved.',
+  'form.saveError':'Sorry, errors occured.',
+
+  'form.validator.invalidIp':'Please enter valid ip address',
+
+  'admin.advanced.title':'Advanced',
+  'admin.advanced.caution':'This section is for advanced user only.<br/>Proceed with caution.',
+  'admin.advanced.button.uninstallIncludingData':'Uninstall cluster including all data.',
+  'admin.advanced.button.uninstallKeepData':'Uninstall cluster but keep data.',
+
+  'admin.advanced.popup.header':'Uninstall Cluster',
+  /*'admin.advanced.popup.text':'Uninstall Cluster',*/
+
+  'admin.audit.grid.date':"Date/Time",
+  'admin.audit.grid.category':"Category",
+  'admin.audit.grid.operationName':"Operation",
+  'admin.audit.grid.performedBy':"Performed By",
+
+  'admin.authentication.form.method.database':'Use Ambari Database to authenticate users',
+  'admin.authentication.form.method.ldap':'Use LDAP/Active Directory to authenticate',
+  'admin.authentication.form.primaryServer':'Primary Server',
+  'admin.authentication.form.secondaryServer':'Secondary Server',
+  'admin.authentication.form.useSsl':'Use SSL',
+  'admin.authentication.form.bind.anonymously':"Bind Anonymously",
+  'admin.authentication.form.bind.useCrenedtials':"Use Credentials To Bind",
+  'admin.authentication.form.bindUserDN':'Bind User DN',
+  'admin.authentication.form.searchBaseDN':'Search Base DN',
+  'admin.authentication.form.usernameAttribute':'Username Attribute',
+
+  'admin.authentication.form.userDN':'User DN',
+  'admin.authentication.form.password':'Password',
+  'admin.authentication.form.configurationTest':'Configuration Test',
+  'admin.authentication.form.testConfiguration':'Test Configuration',
+
+  'admin.authentication.form.test.success':'The configuration passes the test',
+  'admin.authentication.form.test.fail':'The configuration fails the test',
+
+  'admin.security.title':'Kerberos Security has not been enabled on this cluster.',
+  'admin.security.button.enable':'Kerberos Security has not been enabled on this cluster.',
+
+  'admin.users.ldapAuthentionUsed':'LDAP Authentication is being used to authenticate users',
+  'admin.users.addButton': 'Add User',
+  'admin.users.delete': 'delete',
+  'admin.users.edit': 'edit',
+  'admin.users.privileges': 'Admin',
+  'admin.users.password': 'Password',
+  'admin.users.passwordRetype': 'Retype Password',
+  'admin.users.username': 'Username',
+
+  'question.sure': 'Are you sure?',
+
+  'services.service.start': 'Start',
+  'services.service.stop': 'Stop',
+  'services.service.start.popup.header': 'Confirmation',
+  'services.service.stop.popup.header': 'Confirmation',
+  'services.service.start.popup.body': 'Are you sure?',
+  'services.service.stop.popup.body': 'Are you sure?',
+
+  'hosts.host.start.popup.header': 'Confirmation',
+  'hosts.host.stop.popup.header': 'Confirmation',
+  'hosts.host.start.popup.body': 'Are you sure?',
+  'hosts.host.stop.popup.body': 'Are you sure?',
+  'hosts.assignedToRack.popup.body': 'Are you sure?',
+  'hosts.assignedToRack.popup.header': 'Confirmation',
+  'hosts.decommission.popup.body': 'Are you sure?',
+  'hosts.decommission.popup.header': 'Confirmation',
+  'hosts.delete.popup.body': 'Are you sure?',
+  'hosts.delete.popup.header': 'Confirmation'
 };
+

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

@@ -19,8 +19,14 @@
 
 // load all models here
 
+require('models/form'); // should be the 1st
+require('models/authentication');
 require('models/cluster');
 require('models/hosts');
 require('models/service');
 require('models/service_config');
-require('models/alert');
+require('models/service_audit');
+require('models/service_metrics');
+require('models/alert');
+require('models/user');
+require('models/pagination');

+ 82 - 3
ambari-web/app/models/alert.js

@@ -32,16 +32,95 @@ App.Alert.FIXTURES = [
     title: 'Corrupt/Missing Block',
     service_id: 1,
     date: 'August 29, 2012 17:00',
-    status: 'all bad',
+    status: 'corrupt',
     message: 'message'
   },
-
   {
     id: 2,
     title: 'Corrupt/Missing Block',
+    service_id: 1,
+    date: 'August 30, 2012 17:00',
+    status: 'ok',
+    message: 'message'
+  },
+  {
+    id: 3,
+    title: 'Corrupt/Missing Block',
+    service_id: 2,
+    date: 'August 29, 2012 17:00',
+    status: 'corrupt',
+    message: 'message'
+  },
+  {
+    id: 4,
+    title: 'Corrupt/Missing Block',
     service_id: 2,
+    date: 'August 30, 2012 17:00',
+    status: 'ok',
+    message: 'message'
+  },
+  {
+    id: 5,
+    title: 'Corrupt/Missing Block',
+    service_id: 3,
     date: 'August 29, 2012 17:00',
-    status: 'all bad',
+    status: 'corrupt',
+    message: 'message'
+  },
+  {
+    id: 6,
+    title: 'Corrupt/Missing Block',
+    service_id: 3,
+    date: 'August 30, 2012 17:00',
+    status: 'ok',
+    message: 'message'
+  },
+  {
+    id: 7,
+    title: 'Corrupt/Missing Block',
+    service_id: 4,
+    date: 'August 29, 2012 17:00',
+    status: 'corrupt',
+    message: 'message'
+  },
+  {
+    id: 8,
+    title: 'Corrupt/Missing Block',
+    service_id: 4,
+    date: 'August 30, 2012 17:00',
+    status: 'ok',
+    message: 'message'
+  },
+  {
+    id: 9,
+    title: 'Corrupt/Missing Block',
+    service_id: 5,
+    date: 'August 29, 2012 17:00',
+    status: 'corrupt',
+    message: 'message'
+  },
+  {
+    id: 10,
+    title: 'Corrupt/Missing Block',
+    service_id: 5,
+    date: 'August 30, 2012 17:00',
+    status: 'ok',
+    message: 'message'
+  },
+  {
+    id: 11,
+    title: 'Corrupt/Missing Block',
+    service_id: 6,
+    date: 'August 29, 2012 17:00',
+    status: 'corrupt',
+    message: 'message'
+  },
+  {
+    id: 12,
+    title: 'Corrupt/Missing Block',
+    service_id: 6,
+    date: 'August 30, 2012 17:00',
+    status: 'ok',
     message: 'message'
   }
 ];

+ 87 - 0
ambari-web/app/models/authentication.js

@@ -0,0 +1,87 @@
+/**
+ * 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.Authentication = DS.Model.extend({
+  method:DS.attr('boolean'), // use LDAP
+  primaryServer:DS.attr('string'),
+  secondaryServer:DS.attr('string'),
+  useSsl:DS.attr('boolean'),
+  bindMethod:DS.attr('boolean'), // use credentials
+  bindUser:DS.attr('string'),
+  password:DS.attr('string'),
+  retypePassword:DS.attr('string'),
+  searchBaseDn:DS.attr('string'),
+  usernameAttribute:DS.attr('string')
+});
+
+App.Authentication.FIXTURES = [
+  {
+    id:1,
+    method:false,
+    primary_server:"1.2.3.4:78",
+    secondary_server:"225.225.255.255:12",
+    use_ssl:false,
+    bind_method:false,
+    bind_user:"hadoop\Administrator",
+    password:"1234",
+    retype_password:"1234",
+    search_base_dn:"DC=hadoop,DC=abc,DC=com",
+    username_attribute:"sAMAccountName"
+  }
+]
+
+App.AuthenticationForm = App.Form.extend({
+  testResult:false,
+  isObjectNew:false,
+  fieldsOptions:[
+    { name:"method", displayName:"", isRequired:false, displayType:"select",
+      values:[
+        {value:0, label:Em.I18n.t("admin.authentication.form.method.database")},
+        {value:1, label:Em.I18n.t("admin.authentication.form.method.ldap")}
+      ]
+    },
+    { name:"primaryServer", displayName:Em.I18n.t("admin.authentication.form.primaryServer"), validator:'ipaddress'},
+    { name:"secondaryServer", displayName:Em.I18n.t("admin.authentication.form.secondaryServer"), validator:'ipaddress'},
+    { name:"useSsl", displayName:Em.I18n.t("admin.authentication.form.useSsl"), displayType:"checkbox", isRequired:false },
+    { name:"bindMethod", displayName:'', displayType:"select", isRequired:false,
+      values:[
+        {value:0, label:Em.I18n.t("admin.authentication.form.bind.anonymously")},
+        {value:1, label:Em.I18n.t("admin.authentication.form.bind.useCrenedtials")}
+      ]},
+    { name:"bindUser", displayName:Em.I18n.t('admin.authentication.form.bindUserDN')},
+    { name:"password", displayName:Em.I18n.t('form.password'), displayType:"password" },
+    { name:"passwordRetype", displayName:Em.I18n.t('form.passwordRetype'), displayType:"passwordRetype"},
+    { name:"searchBaseDn", displayName:Em.I18n.t('admin.authentication.form.searchBaseDN')},
+    { name:"usernameAttribute", displayName:Em.I18n.t('admin.authentication.form.usernameAttribute')},
+
+    { name:"userDN", displayName:Em.I18n.t('admin.authentication.form.userDN') },
+    { name:"userPassword", displayName:Em.I18n.t('admin.authentication.form.password'), displayType:'password'}
+  ],
+  fields:[],
+  testConfiguration:function () {
+    console.warn('Configuration test is randomized');
+    this.set('testResult', parseInt(Math.random() * 2));
+    return true;
+  },
+  testConfigurationMessage:function () {
+    return this.get('testResult') ? Em.I18n.t('admin.authentication.form.test.success') : Em.I18n.t('admin.authentication.form.test.fail');
+  }.property('testResult'),
+  testConfigurationClass:function () {
+    return this.get('testResult') ? "text-success" : "text-error";
+  }.property('testConfigurationMessage')
+});

+ 111 - 35
ambari-web/app/models/cluster.js

@@ -20,9 +20,14 @@
 var App = require('app');
 
 App.User = Em.Object.extend({
-  username: null
+  username: DS.attr("string")
 });
 
+App.User.FIXTURES = [
+  {},
+  {}
+];
+
 App.ClusterModel = Em.Object.extend({
     clusterName: null,
     hosts: [],
@@ -46,31 +51,102 @@ DS.Model.reopen({
 */
 
 App.Host = DS.Model.extend({
-    hostName: DS.attr('string'),
-    cluster: DS.belongsTo('App.Cluster')
+  hostName: DS.attr('string'),
+  cluster: DS.belongsTo('App.Cluster'),
+  components: DS.hasMany('App.Component'),
+  cpu: DS.attr('string'),
+  memory: DS.attr('string'),
+  diskUsage: DS.attr('string'),
+  loadAvg: DS.attr('string'),
+  os: DS.attr('string'),
+  ip: DS.attr('string'),
+  isChecked: false,
+  healthStatus: DS.attr('string'),
+  workStatus: DS.attr('boolean')
 });
 
 App.Host.FIXTURES = [
-    {
-        id: 1,
-        host_name: 'host1',
-        cluster_id: 1
-    },
-    {
-        id: 2,
-        host_name: 'host2',
-        cluster_id: 1
-    },
-    {
-        id: 3,
-        host_name: 'host3',
-        cluster_id: 2
-    },
-    {
-        id: 4,
-        host_name: 'host4',
-        cluster_id: 2
-    }
+  {
+    id: 1,
+    host_name: 'z_host1',
+    cluster_id: 1,
+    components:[1, 2, 3, 4],
+    cpu: '2x2.5GHz',
+    memory: '8GB',
+    disk_usage: '40',
+    load_avg: '0.2, 1.2, 2.4',
+    ip: '123.123.123.123',
+    health_status: 'LIVE',
+    work_status: true
+  },
+  {
+    id: 2,
+    host_name: 'host2',
+    cluster_id: 1,
+    components:[4, 5],
+    cpu: '2x2.5GHz',
+    memory: '8GB',
+    disk_usage: '20',
+    load_avg: '0.2, 1.2, 2.4',
+    ip: '255.255.255.255',
+    health_status: 'DEAD',
+    work_status: true
+  },
+  {
+    id: 3,
+    host_name: 'n_host3',
+    cluster_id: 2,
+    components:[4, 5, 7],
+    health_status: 'LIVE',
+    work_status: false
+  },
+  {
+    id: 4,
+    host_name: 'b_host4',
+    cluster_id: 2,
+    health_status: 'DEAD',
+    work_status: false
+  },
+  {
+    id: 5,
+    host_name: 'host5',
+    cluster_id: 1,
+    components:[4, 5],
+    cpu: '2x2.5GHz',
+    memory: '8GB',
+    disk_usage: '20',
+    load_avg: '0.2, 1.2, 2.4',
+    ip: '255.255.255.255',
+    health_status: 'DEAD',
+    work_status: true
+  },
+  {
+    id: 6,
+    host_name: 'a_host6',
+    cluster_id: 1,
+    components:[4, 5],
+    cpu: '2x2.5GHz',
+    memory: '8GB',
+    disk_usage: '20',
+    load_avg: '0.2, 1.2, 2.4',
+    ip: '255.255.255.255',
+    health_status: 'LIVE',
+    work_status: false
+
+  },
+  {
+    id: 7,
+    host_name: 'host7',
+    cluster_id: 1,
+    components:[4, 5],
+    cpu: '2x2.5GHz',
+    memory: '8GB',
+    disk_usage: '20',
+    load_avg: '0.2, 1.2, 2.4',
+    ip: '255.255.255.255',
+    health_status: 'LIVE',
+    work_status: true
+  }
 ];
 
 App.Cluster = DS.Model.extend({
@@ -80,18 +156,18 @@ App.Cluster = DS.Model.extend({
 });
 
 App.Cluster.FIXTURES = [
-    {
-        id: 1,
-        cluster_name: 'cluster1',
-        stack_name: 'HDP',
-        hosts: [1, 2]
-    },
+  {
+    id: 1,
+    cluster_name: 'cluster1',
+    stack_name: 'HDP',
+    hosts: [1, 2]
+  },
 
-    {
-        id: 2,
-        cluster_name: 'cluster2',
-        stack_name: 'BigTop',
-        hosts: [3]
-    }
+{
+    id: 2,
+    cluster_name: 'cluster2',
+    stack_name: 'BigTop',
+    hosts: [3]
+  }
 ];
 

+ 267 - 0
ambari-web/app/models/form.js

@@ -0,0 +1,267 @@
+/**
+ * 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 validator = require('utils/validator');
+
+// move this to models cause some errors
+App.Form = Em.View.extend({
+  /**
+   * generating fields from fieldsOptions
+   */
+  classNames:["form-horizontal"],
+  i18nprefix:'form.',
+  fields:[],
+  field:{},
+  messages:[],
+  object:false,
+  result:0, // save result var (-1 - error; 0 - init; 1 - success)
+  templateName:require('templates/common/form'),
+  tagName:'form',
+
+  init:function () {
+    this._super();
+    var thisForm = this;
+    if (!this.fields.length)
+      $.each(this.fieldsOptions,
+        function () {
+          var field = App.FormField.create(this);
+          field.set('form', thisForm);
+          thisForm.fields.push(field);
+          thisForm.set("field." + field.get('name'), field);
+        });
+  },
+  getField:function (name) {
+//    return this.fields[name];
+
+    var field = false;
+    $.each(this.fields, function () {
+      if (this.get('name') == name) {
+        return field = this;
+      }
+    });
+    return field;
+
+  },
+  isValid:function () {
+    var isValid = true;
+    $.each(this.fields, function () {
+      this.validate();
+      if (!this.get('isValid')) {
+        isValid = false;
+      }
+    })
+
+    return isValid;
+  },
+
+  isObjectNew:function () {
+    var object = this.get('object');
+    return !(object instanceof DS.Model && object.get('id'));
+  }.property("object"),
+
+  updateValues:function () {
+    var object = this.get('object');
+    if (object instanceof Em.Object) {
+      $.each(this.fields, function () {
+        this.set('value', object.get(this.get('name')));
+      });
+    } else {
+      this.clearValues();
+    }
+
+  }.observes("object"),
+
+  /**
+   *
+   */
+  getValues:function () {
+    var values = {};
+    $.each(this.fields, function () {
+      values[this.get('name')] = this.get('value');
+    });
+    return values;
+  },
+
+  clearValues:function () {
+    $.each(this.fields, function () {
+      this.set('value', '');
+    });
+  },
+
+  /**
+   * need to refactor for integration
+   * @return {Boolean}
+   */
+  save:function () {
+    var thisForm = this;
+    var object = this.get('object');
+    if (!this.get('isObjectNew')) {
+      $.each(this.getValues(), function (i, v) {
+        object.set(i, v);
+      });
+    } else {
+      if (this.get('className'))
+        App.store.createRecord(App.User, this.getValues())
+      else
+        console.log("Please define class name for your form " + this.constructor);
+    }
+
+    App.store.commit();
+    this.set('result', 1);
+
+    return true;
+  },
+
+  resultText:function () {
+    var text = "";
+    switch (this.get('result')) {
+      case -1:
+        text = this.t("form.saveError");
+        break;
+      case 1:
+        text = this.t("form.saveSuccess");
+        break;
+    }
+
+    return text;
+  }.property('result'),
+
+  saveButtonText:function () {
+    return Em.I18n.t(this.get('i18nprefix') + (this.get('isObjectNew') ? "create" : "save"));
+  }.property('isObjectNew')
+
+//  not recommended
+//  cancelButtonText:function () {
+//    return Em.I18n.t(this.get('i18nprefix') + 'cancel').property();
+//  }
+});
+
+App.FormField = Em.Object.extend({ // try to realize this as view
+  name:'',
+  displayName:'',
+//  defaultValue:'', NOT REALIZED YET
+  description:'',
+  disabled:false,
+  displayType:'string', // string, digits, number, directories, textarea, checkbox
+  disableRequiredOnPresent:false,
+  errorMessage:'',
+  form:false,
+  isRequired:true, // by default a config property is required
+  unit:'',
+  value:null,
+
+  isValid:function () {
+    return this.get('errorMessage') === '';
+  }.property('errorMessage'),
+
+  viewClass:function () {
+    var options = {};
+    var element = Em.TextField;
+    switch (this.get('displayType')) {
+      case 'checkbox':
+        element = Em.Checkbox;
+        options.checkedBinding = "value";
+        break;
+      case 'select':
+        element = Em.Select;
+        options.content = this.get('values');
+        options.valueBinding = "value";
+        options.optionValuePath="content.value";
+        options.optionLabelPath="content.label";
+        break;
+      case 'password':
+        options['type'] = 'password';
+        break;
+      case 'passwordRetype':
+        options['type'] = 'password';
+        break;
+      case 'textarea':
+        element = Em.TextArea;
+        break;
+    }
+
+    return element.extend(options);
+  }.property('displayType'),
+
+  validate:function () {
+    var digitsRegex = /^\d+$/;
+    var numberRegex = /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/;
+
+    var value = this.get('value');
+
+    var isError = false;
+
+    if (!(!this.get('form.isObjectNew') && this.get('disableRequiredOnExistent')) && this.get('isRequired')) {
+      if (typeof value === 'string' && value.trim().length === 0) {
+        this.set('errorMessage', 'This is required');
+        isError = true;
+      }
+    }
+
+    if (!isError) {
+
+      switch (this.get('validator')) {
+        case 'ipaddress':
+          if (!validator.isIpAddress(value)) {
+            isError = true;
+            this.set('errorMessage', Em.I18n.t("form.validator.invalidIp"));
+          };
+          break;
+        default:
+          break;
+      }
+
+
+      switch (this.get('displayType')) {
+        case 'digits':
+          if (!digitsRegex.test(value)) {
+            this.set('errorMessage', 'Must contain digits only');
+            isError = true;
+          }
+          break;
+        case 'number':
+          if (!numberRegex.test(value)) {
+            this.set('errorMessage', 'Must be a valid number');
+            isError = true;
+          }
+          break;
+        case 'directories':
+          break;
+        case 'custom':
+          break;
+        case 'password':
+          break;
+        case 'passwordRetype':
+          var form = this.get('form');
+          var passwordField = form.getField('password');
+          if (passwordField.get('isValid')
+            && (passwordField.get('value') != this.get('value'))
+            && passwordField.get('value') && this.get('value')
+            ) {
+            this.set('errorMessage', "Passwords are different");
+            isError = true;
+          }
+
+          break;
+      }
+    }
+    if (!isError) {
+      this.set('errorMessage', '');
+    }
+  }.observes('value')
+});

+ 81 - 0
ambari-web/app/models/pagination.js

@@ -0,0 +1,81 @@
+/**
+ * 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');
+
+/**
+ @extends Ember.Mixin
+
+ Implements common pagination management properties for controllers.
+ */
+App.Pagination = Em.Mixin.create({
+
+  total: 0,
+  rangeStart: 0,
+  pageSize: 0,
+//  didRequestRange: Em.K,
+
+  rangeStop: function() {
+    var rangeStop = this.get('rangeStart') + this.get('pageSize'),
+      total = this.get('total');
+    if (rangeStop < total) {
+      return rangeStop;
+    }
+    return total;
+  }.property('total', 'rangeStart', 'pageSize').cacheable(),
+
+  hasPrevious: function() {
+    return this.get('rangeStart') > 0;
+  }.property('rangeStart').cacheable(),
+
+  hasNext: function() {
+    return this.get('rangeStop') < this.get('total');
+  }.property('rangeStop', 'total').cacheable(),
+
+  nextPage: function() {
+    if (this.get('hasNext')) {
+      this.incrementProperty('rangeStart', this.get('pageSize'));
+    }
+  },
+
+  previousPage: function() {
+    if (this.get('hasPrevious')) {
+      this.decrementProperty('rangeStart', this.get('pageSize'));
+    }
+  },
+
+  currentPage: function () {
+    return this.get('rangeStop') / this.get('pageSize');
+  }.property('rangeStop', 'pageSize').cacheable(),
+
+  startPosition: function() {
+    return this.get('rangeStart')  + 1;
+  }.property('rangeStart').cacheable(),
+
+  totalPages: function() {
+    return Math.ceil(this.get('total') / this.get('pageSize'));
+  }.property('total', 'pageSize').cacheable(),
+
+//  changeContent: function() {
+////    this.didRequestRange(this.get('rangeStart'), this.get('rangeStop'));
+//  }.observes('total', 'rangeStart', 'rangeStop'),
+
+  pageSizeChange: function() {
+    this.set('rangeStart', 0);
+  }.observes('pageSize')
+
+});

+ 153 - 20
ambari-web/app/models/service.js

@@ -56,52 +56,84 @@ App.ServiceModel = Em.Object.extend({
 
 App.Component = DS.Model.extend({
   componentName:DS.attr('string'),
+  label:DS.attr('string'),
+  type:DS.attr('boolean'),
   service:DS.belongsTo('App.Service'),
-  host:DS.belongsTo('App.Host')
+  host:DS.belongsTo('App.Host'),
+  workStatus:DS.attr('string')
 });
 
 App.Component.FIXTURES = [
   {
     id:1,
     component_name:'NameNode',
+    label: 'NN',
+    type: true,
     service_id:1,
-    host_id:1
+    host_id:1,
+    work_status:true
   },
   {
     id:2,
     component_name:'SNameNode',
+    label: 'SNN',
+    type: true,
     service_id:1,
-    host_id:2
+    host_id:2,
+    work_status:false
   },
   {
     id:3,
     component_name:'DataNode',
+    label: 'DN',
     service_id:1,
+    type: false,
     host_id:2
   },
   {
     id:4,
-    component_name:'100Tracker',
+    component_name:'JobTracker',
+    label: 'TT',
+    type: true,
     service_id:2,
-    host_id:4
+    host_id:4,
+    work_status:true
   },
   {
     id:5,
-    component_name:'jobTaskTracker',
+    component_name:'TaskTracker',
+    label: 'JT',
+    type: false,
     service_id:2,
     host_id:4
+  },
+  {
+    id:6,
+    component_name:'HBase Master',
+    label: 'HBM',
+    type: true,
+    service_id:3,
+    host_id:4
+  },
+  {
+    id:7,
+    component_name:'Region Server',
+    label: 'RS',
+    type: false,
+    service_id:3,
+    host_id:2
   }
 ];
-// COMPONENTS:
-//- HbaseMaster, 100 Region Servers
-//Zookeeper - 3 Zookeeper Servers
-//Oozie - Oozie Master
-//Hive - Hive Metastore
 
 App.Service = DS.Model.extend({
-  serviceName:DS.attr('string'),
-  label:DS.attr('string'),
-  components:DS.hasMany('App.Component')
+  serviceName: DS.attr('string'),
+  label: DS.attr('string'),
+  components: DS.hasMany('App.Component'),
+  serviceAudit: DS.hasMany('App.ServiceAudit'),
+  healthStatus: DS.attr('string'),
+  workStatus: DS.attr('boolean'),
+  alerts: DS.hasMany('App.Alert'),
+  quickLinks: DS.hasMany('App.QuickLinks')
 });
 
 App.Service.FIXTURES = [
@@ -109,33 +141,134 @@ App.Service.FIXTURES = [
     id:1,
     service_name:'hdfs',
     label:'HDFS',
-    components:[1, 2, 3]
+    components: [1, 2, 3],
+    service_audit: [1, 2, 3],
+    health_status: 'LIVE',
+    work_status: true,
+    alerts: [1, 2],
+    quick_links: [1, 2, 3, 4]
   },
   {
     id:2,
     service_name:'mapreduce',
     label:'MapReduce',
-    components:[4, 5]
+    components: [4, 5],
+    service_audit: [4, 5, 6],
+    health_status: 'LIVE',
+    work_status: true,
+    alerts: [3, 4],
+    quick_links: [5, 6, 7, 8, 9, 10]
   },
   {
     id:3,
     service_name:'hbase',
-    label:'HBase'
+    label:'HBase',
+    components: [6, 7],
+    health_status: 'DEAD',
+    work_status: false,
+    alerts: [5, 6],
+    quick_links: [11, 12, 13, 14]
   },
   {
     id:4,
     service_name:'zookeeper',
-    label:'Zookeeper'
+    label:'Zookeeper',
+    health_status: 'DEAD',
+    work_status: false,
+    alerts: [7, 8]
   },
   {
     id:5,
     service_name:'oozie',
-    label:'Oozie'
+    label:'Oozie',
+    health_status: 'DEAD',
+    work_status: false,
+    alerts: [9, 10]
   },
   {
     id:6,
     service_name:'hive',
-    label:'Hive'
+    label:'Hive',
+    health_status: 'DEAD',
+    work_status: false,
+    alerts: [11, 12]
   }
 ];
 
+App.QuickLinks = DS.Model.extend({
+  label: DS.attr('string'),
+  url: DS.attr('string')
+});
+
+App.QuickLinks.FIXTURES = [
+  {
+    id: 1,
+    label: 'NameNode UI',
+    url: ''
+  },
+  {
+    id: 2,
+    label: 'NameNode logs',
+    url: ''
+  },
+  {
+    id: 3,
+    label: 'NameNode JMX',
+    url: ''
+  },
+  {
+    id: 4,
+    label: 'Thread Stacks',
+    url: ''
+  },
+  {
+    id: 5,
+    label: 'JobTracker UI',
+    url: ''
+  },
+  {
+    id: 6,
+    label: 'Scheduling Info',
+    url: ''
+  },
+  {
+    id: 7,
+    label: 'Running Jobs',
+    url: ''
+  },
+  {
+    id: 8,
+    label: 'Retired Jobs',
+    url: ''
+  },
+  {
+    id: 9,
+    label: 'JobHistory Server',
+    url: ''
+  },
+  {
+    id: 10,
+    label: 'JobTracker Logs',
+    url: ''
+  },
+  {
+    id: 11,
+    label: 'HBase Master UI',
+    url: ''
+  },
+  {
+    id: 12,
+    label: 'HBase Logs',
+    url: ''
+  },
+  {
+    id: 13,
+    label: 'Zookeeper Info',
+    url: ''
+  },
+  {
+    id: 14,
+    label: 'HBase Master JMX',
+    url: ''
+  }
+];

+ 65 - 0
ambari-web/app/models/service_audit.js

@@ -0,0 +1,65 @@
+/**
+ * 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.ServiceAudit = DS.Model.extend({
+  date: DS.attr('date'),
+  service: DS.belongsTo('App.Service'),
+  operationName: DS.attr('string'),
+  user: DS.belongsTo('App.User')
+});
+
+App.ServiceAudit.FIXTURES = [
+  {
+    id: 1,
+    date: 'September 12, 2012 17:00',
+    operation_name: 'Reconfigure',
+    user_id: 2
+  },
+  {
+    id: 2,
+    date: 'September 13, 2012 17:00',
+    operation_name: 'Start',
+    user_id: 1
+  },
+  {
+    id: 3,
+    date: 'September 14, 2012 17:00',
+    operation_name: 'Install',
+    user_id: 1
+  },
+  {
+    id: 4,
+    date: 'September 12, 2012 17:00',
+    operation_name: 'Reconfigure',
+    user_id: 2
+  },
+  {
+    id: 5,
+    date: 'September 13, 2012 17:00',
+    operation_name: 'Start',
+    user_id: 1
+  },
+  {
+    id: 6,
+    date: 'September 14, 2012 17:00',
+    operation_name: 'Install',
+    user_id: 1
+  }
+];

+ 20 - 0
ambari-web/app/models/service_metrics.js

@@ -0,0 +1,20 @@
+/**
+ * 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');

+ 48 - 4
ambari-web/app/models/user.js

@@ -18,9 +18,53 @@
 
 var App = require('app');
 
-App.userModel = Em.Object.extend({
+App.UserModel = Em.Object.extend({
+  userName:null,
+  id:0
+});
 
-  firstName : null,
-  id  : 0
+App.User = DS.Model.extend({
+  userName:DS.attr('string'),
+  admin:DS.attr('boolean'),
+  password:DS.attr('string'),
+  auditItems:DS.hasMany('App.ServiceAudit')
+});
 
-});
+App.UserForm = App.Form.extend({
+  className:App.User,
+  fieldsOptions:[
+    { name:"userName", displayName:"Username" },
+    { name:"password", displayName:"Password", displayType:"password", disableRequiredOnExistent:true },
+    { name:"passwordRetype", displayName:"Retype Password", displayType:"passwordRetype", disableRequiredOnExistent:true },
+    { name:"admin", displayName:"Admin", displayType:"checkbox", isRequired:false }
+  ],
+  fields:[],
+  disableUsername:function () {
+    var field = this.getField("userName");
+    if (field) field.set("disabled", this.get('isObjectNew') ? false : "disabled");
+  }.observes('isObjectNew')
+});
+
+App.User.FIXTURES = [
+  {
+    id:1,
+    user_name:'admin',
+    password: 'admin',
+    admin:1
+  },
+  {
+    id:2,
+    user_name:'vrossi',
+    admin:1
+  },
+  {
+    id:3,
+    user_name:'casey.stoner',
+    admin:0
+  },
+  {
+    id:4,
+    user_name:'danip',
+    admin:0
+  }
+];

+ 220 - 21
ambari-web/app/routes/main.js

@@ -16,16 +16,10 @@
  * limitations under the License.
  */
 
-
-
 module.exports = Em.Route.extend({
-
-  route: '/main',
-
-  enter: function (router) {
-
+  route:'/main',
+  enter:function (router) {
     console.log('in /main:enter');
-
     if (router.getAuthenticated()) {
       // TODO: redirect to last known state
       /*
@@ -40,7 +34,12 @@ module.exports = Em.Route.extend({
     }
   },
 
-  connectOutlets: function (router, context) {
+  index: Ember.Route.extend({
+    route: '/',
+    redirectsTo: 'dashboard'
+  }),
+
+  connectOutlets:function (router, context) {
     router.get('applicationController').connectOutlet('main');
   },
 
@@ -54,14 +53,159 @@ module.exports = Em.Route.extend({
   hosts:Em.Route.extend({
     route:'/hosts',
     connectOutlets:function (router, context) {
-      router.get('mainController').connectOutlet('mainHosts');
+      router.get('mainController').connectOutlet('mainHost');
+    },
+
+    showDetails:Em.Router.transitionTo('hostDetails.index')
+
+  }),
+
+  hostDetails:Em.Route.extend({
+    route:'/hosts/:host_id',
+    connectOutlets:function (router, host) {
+      router.get('mainController').connectOutlet('mainHostDetails', host);
+    },
+
+    index:Ember.Route.extend({
+      route:'/',
+      redirectsTo:'summary'
+    }),
+
+    backToHostsList:function (router, event) {
+      router.transitionTo('hosts');
+    },
+
+    summary:Em.Route.extend({
+      route:'/summary',
+      connectOutlets:function (router, context) {
+        router.get('mainHostDetailsController').connectOutlet('mainHostSummary');
+      }
+    }),
+
+    metrics:Em.Route.extend({
+      route:'/metrics',
+      connectOutlets:function (router, context) {
+        router.get('mainHostDetailsController').connectOutlet('mainHostMetrics');
+      }
+    }),
+
+    audit:Em.Route.extend({
+      route:'/audit',
+      connectOutlets:function (router, context) {
+        router.get('mainHostDetailsController').connectOutlet('mainHostAudit');
+      }
+    }),
+
+    hostNavigate:function (router, event) {
+      var parent = event.view._parentView;
+      parent.deactivateChildViews();
+      event.view.set('active', "active");
+      router.transitionTo(event.context);
     }
   }),
 
   admin:Em.Route.extend({
     route:'/admin',
+    enter:function (router) {
+      Ember.run.next(function () {
+        router.transitionTo('adminUser');
+      });
+    },
+
+    adminUser:Em.Route.extend({
+      route:'/user',
+      enter:function (router) {
+        Ember.run.next(function () {
+          router.transitionTo('all');
+        });
+      },
+      connectOutlets:function (router) {
+        console.log("ADMIN USER RECONNECTED");
+      },
+
+      all:Em.Route.extend({
+        route:'/',
+        connectOutlets:function (router) {
+          router.get('mainAdminController').connectOutlet('mainAdminUser');
+        }
+      }),
+
+      gotoUsers:Em.Router.transitionTo("all"),
+
+      createUser:Em.Route.extend({
+        route:'/create',
+        connectOutlets:function (router) {
+          router.get('mainAdminController').connectOutlet('mainAdminUserEdit', {});
+        }
+      }),
+
+      gotoCreateUser:Em.Router.transitionTo("createUser"),
+
+      editUser:Em.Route.extend({
+        route:'/edit/:userName',
+        connectOutlets:function (router, user) {
+          console.log(user);
+          router.get('mainAdminController').connectOutlet('mainAdminUserEdit', user);
+        }
+      }),
+
+      gotoEditUser:function (router, event) {
+        router.transitionTo("editUser", event.context);
+      }
+    }),
+
+    adminAuthentication:Em.Route.extend({
+      route:'/authentication',
+      connectOutlets:function (router) {
+        router.get('mainAdminController').connectOutlet('mainAdminAuthentication');
+      }
+    }),
+
+    adminSecurity:Em.Route.extend({
+      route:'/security',
+      connectOutlets:function (router) {
+        router.get('mainAdminController').connectOutlet('mainAdminSecurity');
+      }
+    }),
+
+    adminAdvanced:Em.Route.extend({
+      route:'/advanced',
+      connectOutlets:function (router) {
+        router.get('mainAdminController').connectOutlet('mainAdminAdvanced');
+      }
+    }),
+
+    adminAudit:Em.Route.extend({
+      route:'/audit',
+      connectOutlets:function (router) {
+        router.get('mainAdminController').connectOutlet('mainAdminAudit');
+      }
+    }),
+
     connectOutlets:function (router, context) {
       router.get('mainController').connectOutlet('mainAdmin');
+    },
+
+//    adminDetails:Em.Route.extend({
+//      route:'/:route',
+//      connectOutlets:function (router, menu) {
+//        router.get('mainAdminController').connectOutlet('mainAdmin' + menu.route.capitalize(), menu);
+//      }
+//    }),
+
+//    advanced:Em.Route.extend({
+//      route:'/:name',
+//      connectOutlets:function (router, service) {
+//        router.get('mainServiceController').connectOutlet('mainServiceItem', service);
+//      }
+//    }),
+
+    adminNavigate:function (router, object) {
+      object.view._parentView.activateView(object.context.route);
+      console.log(object.context.route);
+      Em.run.next(function () {
+        router.transitionTo('admin' + object.context.route.capitalize());
+      });
     }
   }),
 
@@ -69,40 +213,95 @@ module.exports = Em.Route.extend({
     route:'/dashboard',
     connectOutlets:function (router, context) {
       router.get('mainController').connectOutlet('mainDashboard');
+    },
+    selectService: Em.Route.transitionTo('services.service'),
+    selectHost: Em.Router.transitionTo('hostDetails.index'),
+    filterHosts: function(router, component) {
+      router.get('mainHostController').set('filters.components', [component.context.get('id')]);
+      router.transitionTo('hosts');
     }
   }),
 
-  service:Em.Route.extend({
+  services:Em.Route.extend({
     route:'/services',
+    index:Ember.Route.extend({
+      route:'/'
+    }),
     enter:function (router) {
       Ember.run.next(function () {
         var service = router.get('mainServiceItemController.content');
         if (!service) {
           service = App.Service.find(1); // getting the first service to display
         }
-        router.transitionTo('advanced', service);
+        router.transitionTo('service', service);
       });
     },
-
     connectOutlets:function (router, context) {
       router.get('mainController').connectOutlet('mainService');
     },
-
-    advanced:Em.Route.extend({
-      route:'/:name',
+    service:Em.Route.extend({
+      route:'/:service_id',
       connectOutlets:function (router, service) {
+//        if (service.name == "undefined") {
+//          service = App.Service.find(1);
+//        }
         router.get('mainServiceController').connectOutlet('mainServiceItem', service);
+        router.transitionTo('summary');
+      },
+      index:Ember.Route.extend({
+        route:'/'
+      }),
+      summary:Em.Route.extend({
+        route:'/summary',
+        connectOutlets:function (router, context) {
+          var item = router.get('mainServiceItemController.content');
+          router.get('mainServiceItemController').connectOutlet('mainServiceInfoSummary', item);
+        }
+      }),
+      metrics:Em.Route.extend({
+        route:'/metrics',
+        connectOutlets:function (router, context) {
+          var item = router.get('mainServiceItemController.content');
+          router.get('mainServiceItemController').connectOutlet('mainServiceInfoMetrics', item);
+        }
+      }),
+      configs:Em.Route.extend({
+        route:'/configs',
+        connectOutlets:function (router, context) {
+          var item = router.get('mainServiceItemController.content');
+          router.get('mainServiceItemController').connectOutlet('mainServiceInfoConfigs', item);
+        }
+      }),
+      audit:Em.Route.extend({
+        route:'/audit',
+        connectOutlets:function (router, context) {
+          var item = router.get('mainServiceItemController.content');
+          router.get('mainServiceItemController').connectOutlet('mainServiceInfoAudit', item);
+        }
+      }),
+      selectService: Em.Route.transitionTo('services.service'),
+      selectHost: Em.Router.transitionTo('hostDetails.index'),
+      filterHosts: function(router, component) {
+        router.get('mainHostController').set('filters.components', [component.context.get('id')]);
+        router.transitionTo('hosts');
+      },
+      showInfo:function (router, event) {
+        var parent = event.view._parentView;
+        parent.deactivateChildViews();
+        event.view.set('active', "active");
+        router.transitionTo(event.context);
       }
     }),
-
-    showService: Em.Router.transitionTo('advanced')
+    connectOutlets:function (router, context) {
+      router.get('mainController').connectOutlet('mainService');
+    },
+    showService:Em.Router.transitionTo('service')
   }),
 
   navigate:function (router, event) {
     var parent = event.view._parentView;
-    parent.deactivateChildViews();
-    event.view.set('active', "active");
-    router.transitionTo(event.context);
+    parent.deactivateChildViews(event.context);
+    router.transitionTo(event.context.routing);
   }
 
   // TODO: create new routes here

+ 112 - 2
ambari-web/app/styles/app.css

@@ -140,7 +140,7 @@
     background: #F6FAFD;
 }
 .service-block {
-    padding: 10px;
+    margin-top: 20px;
 }
 .service-configuration {
     padding: 10px;
@@ -176,6 +176,7 @@
 .service-button {
     text-align: right;
     margin-bottom: 5px;
+    margin-top: -57px;
 }
 .add-service-button {
     position: relative;
@@ -203,6 +204,32 @@
 #hosts .table thead{
     background: #EDF5FC;
 }
+#hosts .table th,#hosts .table td{
+    width: 130px;
+}
+#hosts .table th.first,#hosts .table td.first{
+    width: 30px;
+}
+#hosts .table td.first label{
+    padding-top: 3px;
+}
+#hosts .table td.first label span{
+    display: block;
+    height: 13px;
+    margin: 3px 0 0 3px;
+    width: 13px;
+}
+#hosts .table ul.filter-components li{
+    display: block;
+    padding: 3px 0 3px 5px;
+    line-height: 20px;
+}
+#hosts .table ul.filter-components li input[type="checkbox"]{
+    margin-top: 0;
+    margin-right: 2px;
+    margin-bottom: 2px;
+    margin: 0 2px 2px;
+}
 #hosts .nav-pills li.disabled{
     display: block;
     margin: 2px 0;
@@ -212,4 +239,87 @@
 #hosts .box-footer .footer-pagination{
     float: right;
 }
-/*End Hosts*/
+#hosts .box-footer .footer-pagination .nav{
+    margin-bottom: 0;
+}
+#hosts .box-footer .footer-pagination .dropdown{
+    margin-top: 3px;
+}#hosts .box-footer .footer-pagination .dropdown{
+     margin-top: 3px;
+ }
+#hosts .box-footer .footer-pagination .dropdown select{
+    width: 60px;
+}
+#hosts .box-footer .footer-pagination .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;
+}
+#hosts .box-footer .footer-pagination .page-listing a:hover{
+    text-decoration: none;
+}
+#hosts .box-footer .footer-pagination .page-listing{
+    width: 100px;
+}
+
+#host-details .back{
+    display: block;
+    width: 105px;
+    margin-bottom: 5px;
+}
+#host-details .box-header .host-title{
+    margin:0;
+    padding-left: 17px;
+}
+#host-details .box-header .button-section{
+    margin-bottom: 5px;
+}
+#host-details hr{
+    margin-bottom: 0;
+    clear: both;
+}
+#host-details .content{
+    padding: 10px;
+    background: #F6FAFD;
+}
+#host-details .host-configuration .dl-horizontal dt{
+    width: 90px;
+    line-height: 20px;
+}
+#host-details .host-configuration .dl-horizontal dd{
+    margin-left: 100px;
+    line-height: 20px;
+}
+#host-details .host-components{
+    padding: 10px;
+    padding-bottom: 0;
+    border: 1px solid #DEDEDE;
+    background: #fff;
+}
+#host-details .host-components .btn{
+    margin:0 5px 10px 0;
+}
+/*End Hosts*/
+/*fieldset begin*/
+.fieldset {
+    border: 2px solid black;
+    padding: 10px;
+} 
+.fieldset legend {
+    border-bottom: none;
+    width: auto;
+    font-size: 14px;
+}
+/*fieldset end*/
+/*Start Carousel*/
+.carousel-inner {
+    height: 80px;
+}
+/*End Carousel*//*End Hosts*/
+

+ 74 - 0
ambari-web/app/styles/application.less

@@ -130,6 +130,76 @@ a:focus {
     outline: none;
 }
 
+@status-live-marker: url("../img/health-status-live.png");
+@status-dead-marker: url("../img/health-status-dead.png");
+
+/*Dashboard*/
+
+.services {
+  margin-left: 5px;
+  .tab-marker-position {
+    padding-left: 25px;
+    background-position: 6px 5px;
+    background-repeat: no-repeat;
+    list-style: none;
+  }
+  .health-status-LIVE {
+    .tab-marker-position;
+    background-image: @status-live-marker;
+  }
+  .health-status-DEAD {
+    .tab-marker-position;
+    background-image: @status-dead-marker;
+  }
+}
+
+
+/*Services*/
+.nav-tabs {
+  .tab-marker-position {
+    padding-left: 25px;
+    padding-right: 25px;
+    background-position: 8px 12px;
+    background-repeat: no-repeat;
+  }
+  .health-status-LIVE {
+    .tab-marker-position;
+    background-image: @status-live-marker;
+  }
+  .health-status-DEAD {
+    .tab-marker-position;
+    background-image: @status-dead-marker;
+  }
+}
+.nav-pills.move {
+  float: right;
+  margin-top: -48px;
+}
+/*End Services*/
+
+/*Hosts*/
+#hosts {
+  .health-status-LIVE {
+    background-image: @status-live-marker;
+  }
+  .health-status-DEAD {
+    background-image: @status-dead-marker;
+  }
+}
+#host-details {
+  .health-status-LIVE {
+    background-image: @status-live-marker;
+    background-repeat:no-repeat;
+    background-position: 0px 4px;
+  }
+  .health-status-DEAD {
+    background-image: @status-dead-marker;
+    background-repeat:no-repeat;
+    background-position: 0px 4px;
+  }
+}
+/*End Hosts*/
+
 /*assign masters*/
 
 .assign-masters {
@@ -218,3 +288,7 @@ a:focus {
 
 /*end assign masters*/
 
+/*Dashboard*/
+.alerts-count {
+  margin-left: 5px;
+}

+ 20 - 0
ambari-web/app/templates/common/form.hbs

@@ -0,0 +1,20 @@
+<!--
+* 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.
+-->
+{{#each field in view.fields}}
+  {{view App.FormFieldTemplate fieldBinding="field"}}
+{{/each}}

+ 24 - 0
ambari-web/app/templates/common/form/checkbox.hbs

@@ -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.
+-->
+
+<div class="controls">
+  <label class="checkbox" for="input{{unbound view.field.name}}">
+    {{view view.field.viewClass valueBinding="view.field.value" }} {{unbound view.field.displayName}}
+  </label>
+  <span class="help-inline">{{view.field.errorMessage}}</span>
+</div>

+ 25 - 0
ambari-web/app/templates/common/form/field.hbs

@@ -0,0 +1,25 @@
+<!--
+* 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.
+-->
+
+<label class="control-label"
+       for="input{{unbound view.field.name}}">{{unbound view.field.displayName}}</label>
+
+<div class="controls">
+  {{view view.field.viewClass valueBinding="view.field.value" }}
+  <span class="help-inline">{{view.field.errorMessage}}</span>
+</div>

+ 18 - 0
ambari-web/app/templates/common/grid/header.hbs

@@ -0,0 +1,18 @@
+<!--
+* 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.
+-->
+{{view.label}}<i {{action doFilter target="view"}} class="icon-filter"></i>

+ 6 - 3
ambari-web/app/templates/installer/slave_hosts.hbs

@@ -1,9 +1,12 @@
 {{#if view.hasNoHosts}}
 No host assigned
-{{/if}}
+{{else}}
+<a href="#" {{action showEditSlaveComponentGroups view.serviceConfig.category target="App.router.slaveComponentGroupsController"}}>
 {{#if view.hasOneHost}}
-{{value}}
+  {{hosts.firstObject.hostname}}
 {{/if}}
 {{#if view.hasMultipleHosts}}
-<a href="#" {{action showEditSlaveComponentGroups view.serviceConfig.category target="App.router.slaveComponentGroupsController"}}>{{hosts.firstObject.hostname}} and {{view.otherLength}}</a>
+  {{hosts.firstObject.hostname}} and {{view.otherLength}}
+{{/if}}
+</a>
 {{/if}}

+ 4 - 2
ambari-web/app/templates/main/admin.hbs

@@ -16,5 +16,7 @@
 * limitations under the License.
 -->
 
-<h5>Admin</h5>
-<div>Here we are</div>
+{{view App.MainAdminMenuView}}
+<div class="span9">
+  {{outlet}}
+</div>

+ 27 - 0
ambari-web/app/templates/main/admin/advanced.hbs

@@ -0,0 +1,27 @@
+<!--
+* 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.
+-->
+
+<h5>{{t admin.advanced.title}}<i class="icon-question-sign"></i></h5>
+<div class="row">
+  {{t admin.advanced.caution}}
+</div>
+<div class="row">
+  <button {{action uninstall target="App.router.mainAdminAdvancedController"}} class="btn"><i class="icon-trash"></i>&nbsp;{{t admin.advanced.button.uninstallIncludingData}}</button>
+  <br/>
+  <button {{action uninstall view.params target="App.router.mainAdminAdvancedController"}} class="btn"><i class="icon-trash"></i>&nbsp;{{t admin.advanced.button.uninstallKeepData}}</button>
+</div>

+ 19 - 0
ambari-web/app/templates/main/admin/advanced/uninstall.hbs

@@ -0,0 +1,19 @@
+<!--
+* 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.
+-->
+
+Confirm Uninstall

+ 37 - 0
ambari-web/app/templates/main/admin/audit.hbs

@@ -0,0 +1,37 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<table class="table">
+  <thead>
+  <tr>
+    {{#each column in view.columns}}
+      {{view column}}
+    {{/each}}
+  </tr>
+  </thead>
+</table>
+<div class="pagination">
+  <ul>
+    <li><a href="#">Prev</a></li>
+    <li><a href="#">1</a></li>
+    <li><a href="#">2</a></li>
+    <li><a href="#">3</a></li>
+    <li><a href="#">4</a></li>
+    <li><a href="#">Next</a></li>
+  </ul>
+</div>

+ 49 - 0
ambari-web/app/templates/main/admin/authentication.hbs

@@ -0,0 +1,49 @@
+<!--
+* 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.
+-->
+
+{{view App.FormFieldTemplate fieldBinding="view.form.field.method"}}
+
+{{#if view.ldapChecked}}
+  {{view App.FormFieldTemplate fieldBinding="view.form.field.primaryServer"}}
+  {{view App.FormFieldTemplate fieldBinding="view.form.field.secondaryServer"}}
+  {{view App.FormFieldTemplate fieldBinding="view.form.field.useSsl"}}
+  {{view App.FormFieldTemplate fieldBinding="view.form.field.bindMethod"}}
+  {{#if view.useCredentials}}
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.bindUser"}}
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.password"}}
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.passwordRetype"}}
+  {{/if}}
+
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.searchBaseDn"}}
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.usernameAttribute"}}
+
+    <h5>{{t admin.authentication.form.configurationTest}}</h5>
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.userDN"}}
+    {{view App.FormFieldTemplate fieldBinding="view.form.field.userPassword"}}
+
+    <button {{action testConfiguration on="click" target="view.form" }} class="btn">{{t admin.authentication.form.testConfiguration}}</button>
+
+    {{#if view.form.testConfigurationMessage}}
+      <p {{bindAttr class="view.form.testConfigurationClass"}}>{{view.form.testConfigurationMessage}}</p>
+    {{/if}}
+{{/if}}
+<div class="span3"></div>
+<div>
+  <button {{action updateValues target="view.form"}} class="btn">{{t form.cancel}}</button>
+  <button {{action save view.form target="App.router.mainAdminAuthenticationController"}} class="btn btn-primary">{{t form.save}}</button>
+</div>

+ 25 - 0
ambari-web/app/templates/main/admin/security.hbs

@@ -0,0 +1,25 @@
+<!--
+* 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.
+-->
+
+<h5>{{t admin.security.title}}<i class="icon-question-sign"></i></h5>
+<div class="row">
+  <button class="btn">
+    <i class="icon-lock"></i>
+    {{t admin.security.button.enable}}
+  </button>
+</div>

+ 42 - 0
ambari-web/app/templates/main/admin/user.hbs

@@ -0,0 +1,42 @@
+<!--
+* 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.
+-->
+
+{{#if view.ldapUser}}
+  <p class="text-info">{{t admin.users.ldapAuthentionUsed}}.</p>
+{{else}}
+<table class="table table-bordered span5">
+  <thead>
+  <tr>
+    <th>ID (test)</th>
+    <th>{{t admin.users.username}}</th>
+    <th>{{t admin.users.privileges}}<i class="icon-question-sign"></i></th>
+    <th></th>
+  </tr>
+  </thead>
+  <tbody>
+  {{#each user in view.users}}
+  {{view App.MainAdminUserRowView userBinding="user"}}
+  {{/each}}
+  </tbody>
+</table>
+<div class="span2">
+  <button class="btn" {{action gotoCreateUser on="click"}} >
+    <i class="icon-plus"></i>{{t admin.users.addButton}}
+  </button>
+</div>
+{{/if}}

+ 34 - 0
ambari-web/app/templates/main/admin/user/edit.hbs

@@ -0,0 +1,34 @@
+<!--
+* 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.
+-->
+
+<form class="form-horizontal">
+  {{#each field in view.userForm.fields}}
+  <div class="control-group">
+    <label class="control-label" for="input{{unbound field.name}}">{{unbound field.displayName}}</label>
+    <div class="controls">
+        {{view field.viewClass valueBinding="field.value" disabledBinding="field.disabled"}}
+      <span class="help-inline">{{field.errorMessage}}</span>
+    </div>
+  </div>
+  {{/each}}
+  <div class="control-group">
+    <button type="submit" class="btn" {{action gotoUsers}}>{{t form.cancel}}</button>
+    <button type="submit"
+            class="btn btn-primary" {{action create target="view"}}>{{view.userForm.saveButtonText}}</button>
+  </div>
+</form>

+ 27 - 0
ambari-web/app/templates/main/admin/user/row.hbs

@@ -0,0 +1,27 @@
+<!--
+* 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.
+-->
+
+<tr>
+  <td>{{user.id}}</td>
+  <td>{{user.userName}}</td>
+  <td>{{view Ember.Checkbox disabledBinding="view.disableCheckBoxes" checkedBinding="user.admin"}}</td>
+  <td>
+    <a href="#" {{action gotoEditUser user on="click"}}>{{t admin.users.edit}}</a>&nbsp;
+    <a href="#" {{action deleteRecord user target="App.router.mainAdminUserController" }}>{{t admin.users.delete}}</a>
+  </td>
+</tr>

+ 79 - 104
ambari-web/app/templates/main/dashboard.hbs

@@ -17,107 +17,82 @@
 -->
 
 <div class="row">
-	<div class="span6">
-		<div class="row">
-			<div class="span6">
-				<div class="box">
-					<div class="box-header">
-						<h4>Summary</h4>
-					</div>
-					<div id="myCarousel" class="carousel">
-						<div class="carousel-inner">
-							<div class="active item">
-								Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempor facilisis nisl, a tempor mi dictum vitae. In sed elit erat. Fusce lorem diam, lacinia in placerat vitae, posuere fringilla sem. Quisque dignissim, ligula tincidunt rhoncus gravida, sem mauris pharetra justo, at consectetur orci ante eu elit. Maecenas sem enim, scelerisque eget consequat vel, ornare vitae velit. Nullam mattis neque eu ipsum tincidunt pellentesque. Morbi sed mi ac ligula rhoncus auctor ac a enim. Etiam commodo sagittis volutpat. Mauris posuere rhoncus consectetur. Pellentesque quis sodales dui. Donec porta ipsum at nunc lacinia dictum. Cras faucibus ullamcorper sapien, sed egestas tellus interdum a. Suspendisse scelerisque pulvinar orci, vitae auctor tellus fermentum sit amet.
-							</div>
-							<div class="item">
-								Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempor facilisis nisl, a tempor mi dictum vitae. In sed elit erat. Fusce lorem diam, lacinia in placerat vitae, posuere fringilla sem. Quisque dignissim, ligula tincidunt rhoncus gravida, sem mauris pharetra justo, at consectetur orci ante eu elit. Maecenas sem enim, scelerisque eget consequat vel, ornare vitae velit. Nullam mattis neque eu ipsum tincidunt pellentesque. Morbi sed mi ac ligula rhoncus auctor ac a enim. Etiam commodo sagittis volutpat. Mauris posuere rhoncus consectetur. Pellentesque quis sodales dui. Donec porta ipsum at nunc lacinia dictum. Cras faucibus ullamcorper sapien, sed egestas tellus interdum a. Suspendisse scelerisque pulvinar orci, vitae auctor tellus fermentum sit amet.
-								Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempor facilisis nisl, a tempor mi dictum vitae. In sed elit erat. Fusce lorem diam, lacinia in placerat vitae, posuere fringilla sem. Quisque dignissim, ligula tincidunt rhoncus gravida, sem mauris pharetra justo, at consectetur orci ante eu elit. Maecenas sem enim,
-							</div>
-							<div class="item">
-								Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempor facilisis nisl, a tempor mi dictum vitae. In sed elit erat. Fusce lorem diam, lacinia in placerat vitae, posuere fringilla sem. Quisque dignissim, ligula tincidunt rhoncus gravida, sem mauris pharetra justo, at consectetur orci ante eu elit. Maecenas sem enim, scelerisque eget consequat vel, ornare vitae velit. Nullam mattis neque eu ipsum tincidunt pellentesque. Morbi sed mi ac ligula rhoncus auctor ac a enim. Etiam commodo sagittis volutpat. Mauris posuere rhoncus consectetur. Pellentesque quis sodales dui. Donec porta ipsum at nunc lacinia dictum. Cras faucibus ullamcorper sapien, sed egestas tellus interdum a. Suspendisse scelerisque pulvinar orci, vitae auctor tellus fermentum sit amet.
-								Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempor facilisis nisl, a tempor mi dictum vitae. In sed elit erat. Fusce lorem diam, lacinia in placerat vitae, posuere fringilla sem. Quisque dignissim,
-							</div>
-						</div>
-						<a class="carousel-control left" href="#myCarousel" data-slide="prev">&lsaquo;</a>
-						<a class="carousel-control right" href="#myCarousel" data-slide="next">&rsaquo;</a>
-					</div>
-					<div class="box-footer"></div>
-				</div>
-			</div>
-		</div>
-		<div class="row">
-			<div class="span6">
-				<div class="box">
-					<div class="box-header">
-						<h4>Services</h4>
-					</div>
-					<ul>
-						{{#each view.services}}
-							<li><a href="#">{{label}}</a></li>
-						{{/each}}
-					</ul>
-				</div>
-			</div>
-		</div>
-	</div>
-	<div class="span6">
-		<div class="box">
-			<div class="box-header">
-				<h4>Alerts</h4>
-				<div class="btn-group">
-					<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">HDFS <span class="caret"></span></button>
-					<ul class="dropdown-menu">
-						<li><a href="#">HDFS</a></li>
-						<li><a href="#">MapReduce</a></li>
-						<li><a href="#">HBase</a></li>
-						<li><a href="#">Zookeeper</a></li>
-						<li><a href="#">Oozie</a></li>
-						<li><a href="#">Hive</a></li>
-					</ul>
-				</div>
-			</div>
-			<ul class="alerts">
-				<li class="status-ok">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-ok">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-ok">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-corrupt">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-ok">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-corrupt">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-corrupt">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-ok">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-				<li class="status-corrupt">
-					<p class="title">Corrupt/Missing Blocks <a href="#">HDFS</a><span class="date-time">Sep 11, 2012 14:22</span></p>
-					<p class="message">OK: corrupt_blocks: <0>, missing_blocks: <0>, total_blocks: <282></p>
-				</li>
-			</ul>
-			<div class="box-footer">
-				<hr />
-				<a class="go-to" href="#">Go to Nagios</a>
-			</div>
-		</div>
-	</div>
-</div>
+  <div class="span6">
+    <div class="row">
+      <div class="span6">
+        <div class="box">
+          <div class="box-header">
+            <h4>Summary</h4>
+          </div>
+          <div id="myCarousel" class="carousel">
+            <div class="carousel-inner">
+              <div class="active item">
+
+              </div>
+              <div class="item">
+
+              </div>
+              <div class="item">
+
+              </div>
+            </div>
+            <a class="carousel-control left" href="#myCarousel" data-slide="prev">&lsaquo;</a>
+            <a class="carousel-control right" href="#myCarousel" data-slide="next">&rsaquo;</a>
+          </div>
+          <div class="box-footer"></div>
+        </div>
+      </div>
+    </div>
+    <div class="row">
+      <div class="span6">
+        <div class="box">
+          <div class="box-header">
+            <h4>Services</h4>
+          </div>
+          <ul class="services">
+            {{#each service in controller.services}}
+              <li class="health-status-{{unbound service.healthStatus}}">
+                <a {{action selectService service href=true}} href="javascript:void(null)">{{service.label}}</a> -
+                {{#each component in service.components}}
+                  {{#if component.type}}
+                    <a {{action selectHost component.host href=true}} href="javascript:void(null)">{{component.componentName}}</a>,
+                  {{else}}
+                    <a {{action filterHosts component}} href="javascript:void(null)">{{component.componentName}}</a>
+                  {{/if}}
+                {{/each}}
+              </li>
+            {{/each}}
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="span6">
+    <div class="box">
+      <div class="box-header">
+        <h4>Alerts</h4>
+        <div class="btn-group">
+          <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">{{controller.alertsFilteredBy}} <span class="caret"></span></button>
+          <ul class="dropdown-menu">
+            <li><a {{action alertsFilter target="controller"}} href="javascript:void(null)">All</a></li>
+            {{#each service in controller.services}}
+              <li><a {{action alertsFilter service target="controller"}} href="javascript:void(null)">{{service.label}}</a></li>
+            {{/each}}
+          </ul>
+        </div>
+      </div>
+      <ul class="alerts">
+        {{#each controller.alerts}}
+        <li class="status-{{unbound status}}">
+          <p><span class="title">{{title}}</span> <a href="javascript:void(null)">{{service.label}}</a><span class="date-time">{{date}}</span></p>
+          <p><span>{{status}}:</span> <span>{{message}}</span></p>
+        </li>
+        {{/each}}
+      </ul>
+      <div class="box-footer">
+        <hr />
+        <a class="go-to" href="javascript:void(null)">Go to Nagios</a>
+      </div>
+    </div>
+  </div>
+</div>

+ 129 - 0
ambari-web/app/templates/main/host.hbs

@@ -0,0 +1,129 @@
+<!--
+* 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="hosts" class="box">
+    <div class="box-header">
+        <div class="button-section">
+            <div class="btn-group">
+                <button {{bindAttr disabled="controller.isDisabled"}} class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
+                    Rack
+                    <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                    {{#each clusters}}
+                    <li>
+                      <a href="javascript:void(null)" data-toggle="modal" {{action "assignedToRackPopup" this target="controller"}}>
+                        {{clusterName}}
+                      </a>
+                    </li>
+                    {{/each}}
+                </ul>
+            </div>
+            <button {{bindAttr disabled="controller.isDisabled"}} class="btn btn-primary decommission" data-toggle="modal" {{action "decommissionButtonPopup" target="controller"}}>
+              Decommission
+            </button>
+            <button {{bindAttr disabled="controller.isDisabled"}} class="btn btn-primary" data-toggle="modal" {{action "deleteButtonPopup" target="controller"}}>
+              Delete
+            </button>
+            <button class="btn btn-inverse add-host-button" disabled="disabled">
+                <i class="icon-plus icon-white"></i>
+                Add New Host
+            </button>
+        </div>
+    </div>
+    <table class="table table-bordered table-striped">
+        <thead>
+        <tr>
+            <th class="first">
+                <label class="checkbox">
+                  {{view Ember.Checkbox checkedBinding="allChecked" class="checkbox"}}
+                </label>
+            </th>
+            <th>
+              <a href="#" {{action sortByName target="controller" }}>Name</a>
+            </th>
+            <th>Rack</th>
+            <th>CPU</th>
+            <th>RAM</th>
+            <th>Disk Usage</th>
+            <th>Load Avg</th>
+            <th>
+                <div class="btn-group">
+                    <button class="btn btn-info dropdown-toggle" data-toggle="dropdown">
+                        Components
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu filter-components">
+                        {{#each component in allComponents}}
+                        <li>
+                            <label>
+                                {{view view.ComponentCheckboxView checkedBinding="this.isChecked"contentBinding="component.id"}}                                {{component.componentName}}
+                            </label>
+                        </li>
+                        {{/each}}
+                    </ul>
+                </div>
+            </th>
+        </tr>
+        </thead>
+        <tbody>
+        {{#each host in controller}}
+        <tr>
+            <td class="first">
+                <label class="checkbox">
+                  {{view view.HostCheckboxView checkedBinding="host.isChecked" contentBinding="host"}}
+                  <span class="health-status-{{unbound host.healthStatus}}"></span>
+                </label>
+            </td>
+            <td><a href="#" {{action showDetails host}}>{{unbound host.hostName}}</a></td>
+            <td>{{host.cluster.clusterName}}</td>
+            <td>{{host.cpu}}</td>
+            <td>{{host.memory}}</td>
+            <td>{{host.diskUsage}}</td>
+            <td>{{host.loadAvg}}</td>
+            <td>
+                {{#each component in host.components}}
+                  {{component.label}},
+                {{/each}}
+            </td>
+        </tr>
+        {{/each}}
+        </tbody>
+    </table>
+    <div class="box-footer">
+        <hr />
+        <div class="footer-pagination">
+            <ul class="nav nav-pills">
+                <li class="disabled">Show Hosts</li>
+                <li class="dropdown">
+                    {{view Em.Select contentBinding="pageSizeRange"
+                    selectionBinding="pageSize"
+                    optionValuePath="this"}}
+                </li>
+                <li class="disabled">{{startPosition}}-{{rangeStop}} of {{total}}</li>
+                <li class="disabled page-listing">
+                    {{#if hasPrevious}}
+                    <a href="#" {{action showPreviousPage target="controller"}}>previous</a>
+                    {{/if}}
+                    {{#if hasNext}}
+                    <a href="#" {{action showNextPage target="controller"}}>next</a>
+                    {{/if}}
+                </li>
+            </ul>
+        </div>
+    </div>
+</div>

+ 19 - 0
ambari-web/app/templates/main/host/audit.hbs

@@ -0,0 +1,19 @@
+<!--
+* 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.
+-->
+<h5>Audit</h5>
+

+ 40 - 0
ambari-web/app/templates/main/host/details.hbs

@@ -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.
+-->
+<div id="host-details" class="row">
+    <a class="btn back" {{action backToHostsList}}>← Back to Hosts</a>
+    <div class="box ">
+        <div class="box-header">
+            <div class="span1 host-title health-status-{{unbound view.content.healthStatus}}">{{unbound view.content.hostName}}</div>
+            <div class="button-section pull-right clearfix">
+              <button {{bindAttr disabled="controller.startComponents"}} class="btn btn-success" data-toggle="modal" {{action "startConfirmPopup" target="controller"}}>
+                <i class="icon-play"></i>
+                Start
+              </button>
+              <button {{bindAttr disabled="controller.stopComponents"}} class="btn btn-danger" data-toggle="modal" {{action "stopConfirmPopup" target="controller"}}>
+                <i class="icon-stop"></i>
+                Stop
+              </button>
+            </div>
+            <hr />
+        </div>
+        <div class="content">
+            {{view App.MainHostMenuView}}
+            {{outlet}}
+        </div>
+    </div>
+</div>

+ 19 - 0
ambari-web/app/templates/main/host/metrics.hbs

@@ -0,0 +1,19 @@
+<!--
+* 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.
+-->
+<h5>Metrics</h5>
+

+ 41 - 0
ambari-web/app/templates/main/host/summary.hbs

@@ -0,0 +1,41 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+<div class="row">
+    <div class="span5 host-configuration">
+        <dl class="dl-horizontal">
+            <dt>IP:</dt><dd>{{view.content.ip}}</dd>
+            <dt>CPU:</dt><dd>{{view.content.cpu}}</dd>
+            <dt>OS:</dt><dd>type</dd>
+            <dt>Disk Usage:</dt><dd>{{view.content.diskUsage}}</dd>
+            <dt>Memory:</dt><dd>{{view.content.memory}}</dd>
+            <dt>Load Avg:</dt><dd>{{view.content.loadAvg}}</dd>
+            <dt>Agent:</dt><dd>running</dd>
+        </dl>
+    </div>
+    {{#if view.content.components.length}}
+    <div class="span3 host-components pull-right">
+        {{#each component in view.content.components}}
+          <button class="btn btn-{{bind view.buttonClass}}">
+            {{component.componentName}}
+            <i class="icon-{{unbound view.content.iconClass}}"></i>
+          </button>
+        {{/each}}
+    </div>
+    {{/if}}
+</div>
+

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

@@ -16,7 +16,7 @@
 * limitations under the License.
 -->
 <ul class="nav nav-tabs">
-	{{#each view.items}}
-	<li {{bindAttr class="active"}} ><a {{action navigate routing }} href="#">{{unbound label}}</a></li>
-	{{/each}}
+    {{#each view.items}}
+    <li {{bindAttr class="active"}} ><a {{action navigate routing }} href="#">{{unbound label}}</a></li>
+    {{/each}}
 </ul>

+ 51 - 0
ambari-web/app/templates/main/service/info/audit.hbs

@@ -0,0 +1,51 @@
+<!--
+* 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.
+-->
+
+<h5>Audit</h5>
+<table class="table table-bordered table-striped">
+  <thead>
+		<tr>
+      <th>Date/Time</th>
+			<th>Category</th>
+			<th>Operation</th>
+			<th>
+        <div class="btn-group">
+          <button class="btn dropdown-toggle" data-toggle="dropdown">Performed By <span class="caret"></span></button>
+          <ul class="dropdown-menu">
+            <li><label>{{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}All</label></li>
+            {{#each controller.performedBy}}
+              <li><label>{{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}{{userName}}</label></li>
+            {{/each}}
+            {{!view Ember.Checkbox checkedBinding="manualInstall"}}
+            {{!view Ember.Checkbox checkedBinding="localRepo"}}
+          </ul>
+        </div>
+      </th>
+		</tr>
+	</thead>
+	<tbody>
+    {{#each controller.content.serviceAudit}}
+      <tr>
+        <td>{{date}}</td>
+        <td>{{controller.content.label}}</td>
+        <td>{{controller.content.label}} {{operationName}}</td>
+        <td>{{user.userName}}</td>
+      </tr>
+    {{/each}}
+	</tbody>
+</table>

+ 136 - 0
ambari-web/app/templates/main/service/info/configs.hbs

@@ -0,0 +1,136 @@
+<!--
+* 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>
+    <fieldset class="fieldset">
+     <legend>General</legend>
+        <div class="row">
+           <div class="span2"> <b>Some HDFS config</b> </div>
+           <div class="span2"><input type="text"></div>
+        </div>
+    </fieldset>
+
+</div>
+
+<br>
+
+<div>
+       <fieldset class="fieldset">
+        <legend>NameNode</legend>
+          <div class="row">
+            <div class="span2"><b>NameNodeSet</b> </div>
+            <div class="span2">host0001.com.com</div>
+
+        </div>
+<br>
+        <div class="row">
+            <div class="span2"><b>NameNode directories</b> dfs.name.dir </div>
+            <div class="span2"><textarea placeholder="/grid/hadoop/namenode"></textarea></div>
+
+        </div>
+<br>
+        <div class="row">
+            <div class="span2"><b>Some NameNode config</b> dfs.name.some </div>
+            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="2048"><span class="add-on">MB</span></div>
+            <div class="span2"></div>
+
+        </div>
+    </fieldset>
+</div>
+<br>
+<div>
+    <fieldset class="fieldset">
+        <legend>SNameNode</legend>
+        <div class="row">
+            <div class="span2"><b>Some NameNode host</b> </div>
+            <div class="span2">host0002.com.com</div>
+        </div>
+    </fieldset>
+</div>
+<br>
+<div>
+    <fieldset class="fieldset">
+        <legend>DataNode (Default)</legend>
+        <div class="row">
+            <div class="span2"><b>DataNode hosts</b> </div>
+            <div class="span3"><a href="#">host003.com.com and 89 more</a> </div>
+
+        </div>
+        <br>
+        <div class="row">
+            <div class="span2"><b>DataNode directories</b> dfs.data.dir</div>
+             <div class="span2"><textarea placeholder="/grid/0/hadoop/datanode
+                                                      /grid/1/hadoop/datanode
+                                                      /grid/2/hadoop/datanode"></textarea></div>
+
+        </div>
+        <br>
+        <div class="row">
+            <div class="span2"><b>Some DataNode config</b> dfs.data.some </div>
+            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="1024"><span class="add-on">MB</span></div>
+            <div class="span2"></div>
+
+        </div>
+        <br>
+        <div class="row">
+            <div class="span2"><b>Another DataNode config</b> dfs.data.another</div>
+            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="512"><span class="add-on">MB</span></div>
+
+        </div>
+   </fieldset>
+</div>
+<br>
+<div>
+    <fieldset class="fieldset">
+        <legend>DataNode Group A</legend>
+        <div class="row">
+            <div class="span2"><b>DataNode hosts</b> </div>
+            <div class="span3"><a href="#">host0090.com.com and 90 more</a> </div>
+
+        </div>
+        <br>
+        <div class="row">
+            <div class="span2"><b>DataNode directories</b> dfs.data.dir</div>
+            <div class="span2"><textarea placeholder="/grid/0/hadoop/datanode
+                                                      /grid/1/hadoop/datanode
+                                                      /grid/2/hadoop/datanode
+                                                      /grid/3/hadoop/datanode"></textarea></div>
+
+        </div>
+        <br>
+        <div class="row">
+            <div class="span2"><b>Some DataNode config</b> dfs.data.another</div>
+            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="2048"><span class="add-on">MB</span></div>
+            <div class="span2"></div>
+        </div>
+        <br>
+        <div class="row">
+            <div class="span2"><b>Another DataNode config</b> dfs.data.another</div>
+            <div class="span2 input-append"><input class="span2" id="appendedInput" type="text" placeholder="128"><span class="add-on">MB</span></div>
+        </div>
+    </fieldset>
+</div>
+<br>
+      <p align="right"> Need a different settings on certain DataNodes? <a href="#">Add a DataNode group</a>
+      <br>
+      <br>
+      <input class="btn btn-primary" type="button" value="Save and apply changes">
+    </p>
+     </div>
+{{outlet}}

+ 20 - 0
ambari-web/app/templates/main/service/info/metrics.hbs

@@ -0,0 +1,20 @@
+<!--
+* 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.
+-->
+
+<h5>Metrics</h5>
+{{outlet}}

+ 66 - 0
ambari-web/app/templates/main/service/info/summary.hbs

@@ -0,0 +1,66 @@
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+<div class="row service-block">
+	<div class="span6">
+    <ul class="nav nav-pills move">
+      <li class="dropdown">
+        <a class="dropdown-toggle" data-toggle="dropdown" href="#">Quick Links <b class="caret"></b></a>
+        <ul class="dropdown-menu">
+          {{#each controller.content.quickLinks}}
+            <a href="javascript:void(null)">{{label}}</a>
+          {{/each}}
+        </ul>
+      </li>
+    </ul>
+		<h4>Service Summary</h4>
+		<div class="service-content">
+			{{#each component in controller.content.components}}
+        {{#if component.type}}
+          <div class="service-links">{{component.componentName}}:<a {{action selectHost component.host href=true}} href="javascript:void(null)">{{component.host.hostName}}</a></div>
+        {{else}}
+          <div class="service-links">{{component.componentName}}:<a {{action filterHosts component}} href="javascript:void(null)">{{component.componentName}}</a></div>
+        {{/if}}
+			{{/each}}
+			Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the
+			industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and
+			scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into
+			electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of
+			Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like
+			Aldus PageMaker including versions of Lorem Ipsum.
+		</div>
+	</div>
+	<div class="span6">
+		<div class="box">
+			<div class="box-header">
+				<h4>Alerts</h4>
+			</div>
+			<ul class="alerts">
+				{{#each controller.content.alerts}}
+				<li class="status-{{unbound status}}">
+					<p><span class="title">{{title}}</span> <a href="javascript:void(null)">{{service.label}}</a><span class="date-time">{{date}}</span></p>
+					<p><span>{{status}}:</span> <span>{{message}}</span></p>
+				</li>
+				{{/each}}
+			</ul>
+			<div class="box-footer">
+				<hr />
+				<a class="go-to" href="javascript:void(null)">Go to Nagios</a>
+			</div>
+		</div>
+	</div>
+</div>

+ 27 - 72
ambari-web/app/templates/main/service/item.hbs

@@ -15,84 +15,39 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
+
 <div class="add-service-button">
-    <a class="btn btn-inverse" href="#">
+    <a class="btn btn-inverse" href="javascript:void(null)">
         <i class="icon-plus icon-white"></i>
         Add Service
     </a>
 </div>
+{{view App.MainServiceInfoMenuView}}
 <div class="service-button">
-    <a class="btn" href="#">
+  {{#if controller.content.workStatus}}
+    <a href="javascript:void(null)" class="btn disabled">
+      <i class="icon-play"></i>
+      Start
+    </a>
+    <a href="javascript:void(null)" class="btn btn-danger" data-toggle="modal" {{action "stopConfirmPopup" target="controller"}}>
+      <i class="icon-stop"></i>
+      Stop
+    </a>
+  {{else}}
+    <a href="javascript:void(null)" class="btn btn-success" data-toggle="modal" {{action "startConfirmPopup" target="controller"}}>
+      <i class="icon-play"></i>
+      Start
+    </a>
+    <a href="javascript:void(null)" class="btn disabled">
+      <i class="icon-stop"></i>
+      Stop
+    </a>
+  {{/if}}
+  {{#if showRebalancer}}
+    <a class="btn" href="javascript:void(null)">
         <i class="icon-play-circle"></i>
-        Run HDFS Rebalancer
+        Run Rebalancer
     </a>
+  {{/if}}
 </div>
-
-<div class="row box service-summary">
-    <div class="span8 service-block">
-        <h4>Service Summary</h4>
-
-        <div class="service-content">
-            {{#each controller.content.components}}
-            <div class="service-links">{{componentName}}: <a href="#">{{host.hostName}}</a></div>
-            {{/each}}
-            Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the
-            industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and
-            scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into
-            electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of
-            Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like
-            Aldus PageMaker including versions of Lorem Ipsum.
-        </div>
-    </div>
-    <div class="span3 service-block">
-        <div class="row">
-            <div class="span3">
-                <h4>Hosts</h4>
-
-                <div class="service-links">
-                    <a href="#">mycompanysite.com</a>
-                    <a href="#">mycompanysite.com</a>
-                    <a href="#">mycompanysite.com</a>
-                </div>
-            </div>
-        </div>
-        <div class="row">
-            <div class="span3">
-                <h4>Links</h4>
-
-                <div class="service-links">
-                    <a href="#">mycompanysite.com</a>
-                    <a href="#">mycompanysite.com</a>
-                    <a href="#">mycompanysite.com</a>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-<div class="row">
-    <div class="box">
-        <div class="box-header">
-            <h4>Service-Level Configuration</h4>
-        </div>
-        <div class="service-configuration service-summary">
-            <h5>Summary</h5>
-            <dl class="dl-horizontal">
-                <dt>Hostname:</dt>
-                <dd>ip-12-12-12-1232.cp2</dd>
-                <dt>IP:</dt>
-                <dd>123.123.135.567</dd>
-                <dt>CPU:</dt>
-                <dd>2.2 GHz</dd>
-                <dt>OS:</dt>
-                <dd>type</dd>
-                <dt>Disk:</dt>
-                <dd>total runtime</dd>
-                <dt>Memory:</dt>
-                <dd>total runtime usage</dd>
-                <dt>Agent:</dt>
-                <dd>running</dd>
-            </dl>
-
-        </div>
-    </div>
-</div>
+{{outlet}}

+ 27 - 0
ambari-web/app/utils/helper.js

@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+String.prototype.capitalize = function()
+{
+  return this.charAt(0).toUpperCase() + this.slice(1);
+}
+
+Em.CoreObject.reopen({
+  t: function(key, attrs){
+    return Em.I18n.t(key, attrs)
+  }
+});

+ 19 - 1
ambari-web/app/utils/validator.js

@@ -34,6 +34,24 @@ module.exports = {
     }
     var floatRegex = /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/;
     return floatRegex.test(value);
-  }
+  },
+
+  isIpAddress: function(value) {
+    var ipRegex = /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:[0-9]{1,5}$/;
+    return ipRegex.test(value);
+  },
 
+  empty:function (e) {
+    switch (e) {
+      case "":
+      case 0:
+      case "0":
+      case null:
+      case false:
+      case typeof this == "undefined":
+        return true;
+      default :
+        return false;
+    }
+}
 };

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

@@ -22,16 +22,36 @@
 
 require('views/application');
 require('views/common/modal_popup');
+require('views/common/form/field');
 require('views/login');
 require('views/main');
 require('views/main/menu');
 require('views/main/charts');
-require('views/main/hosts');
+require('views/main/host');
+require('views/main/host/details');
+require('views/main/host/menu');
+require('views/main/host/summary');
+require('views/main/host/metrics');
+require('views/main/host/audit');
 require('views/main/admin');
+require('views/main/admin/advanced');
+require('views/main/admin/advanced/password');
+require('views/main/admin/audit');
+require('views/main/admin/authentication');
+require('views/main/admin/menu');
+require('views/main/admin/security');
+require('views/main/admin/user');
+require('views/main/admin/user/edit');
+require('views/main/admin/user/row');
 require('views/main/dashboard');
 require('views/main/service');
 require('views/main/service/menu');
 require('views/main/service/item');
+require('views/main/service/info/menu');
+require('views/main/service/info/summary');
+require('views/main/service/info/metrics');
+require('views/main/service/info/configs');
+require('views/main/service/info/audit');
 require('views/installer');
 require('views/installer/step1_view');
 require('views/installer/step2_view');

+ 45 - 0
ambari-web/app/views/common/form/field.js

@@ -0,0 +1,45 @@
+/**
+ * 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.FormFieldTemplate = Em.View.extend({
+  templateDir: 'templates/common/form/',
+  defaultTemplate: 'field',
+  classNames: ["control-group"],
+  init: function(){
+    this._super();
+    this.updateTemplate();
+  },
+  updateTemplate: function(){
+    var field = this.get('field');
+    if(field) {
+      var templateName = '';
+      switch(field.get('displayType')) {
+        case 'checkbox':
+          templateName = field.get('displayType');
+          break;
+        default:
+          templateName = this.get('defaultTemplate');
+          break;
+      }
+
+      this.set('templateName', require(this.get('templateDir') + templateName));
+    }
+  }.observes('field')
+});

+ 1 - 1
ambari-web/app/views/main/admin.js

@@ -19,5 +19,5 @@
 var App = require('app');
 
 App.MainAdminView = Em.View.extend({
-    templateName: require('templates/main/admin')
+    templateName: require('templates/main/admin'),
 });

+ 24 - 0
ambari-web/app/views/main/admin/advanced.js

@@ -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.MainAdminAdvancedView = Em.View.extend({
+  templateName: require('templates/main/admin/advanced'),
+  params: {keepData: 1}
+});

+ 27 - 0
ambari-web/app/views/main/admin/advanced/password.js

@@ -0,0 +1,27 @@
+/**
+ * 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.MainAdminAdvancedPasswordView = App.Form.extend({
+  fieldsOptions:[
+    { name:"password", displayName:"Password", displayType:"password", disableRequiredOnExistent:true },
+    { name:"passwordRetype", displayName:"Retype Password", displayType:"passwordRetype", disableRequiredOnExistent:true }
+  ],
+  fields: []
+});

+ 115 - 0
ambari-web/app/views/main/admin/audit.js

@@ -0,0 +1,115 @@
+/**
+ * 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 validator = require('utils/validator');
+
+App.GridHeader = Em.View.extend({
+  templateName:require('templates/common/grid/header'),
+  tagName:'th',
+  filterable:true,
+  getGrid:function () {
+    return this.get('grid');
+  },
+  doFilter:function () {
+    console.log(this.get('grid'));
+  },
+  click:function (event) {
+    // will be called when when an instance's
+    // rendered element is clicked
+  }
+});
+
+App.MainAdminAuditView = Em.View.extend({
+  _columns:{},
+  columns:[],
+  initComleted:false,
+  collection:[],
+  templateName:require('templates/main/admin/audit'),
+  fieldNames:[],
+  init:function () {
+    this._super();
+    if (!this.columns.length) { // init completed on this
+      this.prepareColumns();
+      this.prepareFilters();
+      this.prepareCollection();
+    }
+  },
+  prepareCollection:function () {
+    this.set('collection', App.ServiceAudit.find());
+  },
+
+  addColumn:function (options) {
+    options.grid = this;
+    if (validator.empty(options.name)) {
+      throw "define column name";
+    }
+
+    if (this.get('_columns.' + options.name)) {
+      throw "column with this '" + options.name + "' already exists";
+    }
+
+    var field = App.GridHeader.extend(options);
+    this.columns.push(field);
+
+//    console.log("FI:", field.filterable);
+    if (field.filterable || 1) { // .filterable - field not working :(
+      this.fieldNames.push(options.name);
+    }
+  },
+  prepareColumns:function () {
+    this.addColumn({
+      name:"date",
+      label:Em.I18n.t("admin.audit.grid.date")
+    });
+    this.addColumn({
+      name:"operationName",
+      label:Em.I18n.t("admin.audit.grid.operationName")
+    });
+  },
+  prepareFilters:function () {
+    var collection = this.get('collection');
+    var fieldNames = this.get('fieldNames');
+    var options = {};
+
+    if (collection && collection.content && collection.content.length) {
+      collection.forEach(function (i, object) {
+        console.warn("INTO");
+        console.warn(object, object.content);
+        $.each(fieldNames, function (j, field) {
+          if (!options[field]) {
+            options[field] = [];
+          }
+//          var value = object.get(field); repair this
+//          options[field].push({value:value});
+        });
+      })
+
+      console.warn("SORT OPTIONS:", options);
+      this.set('fieldNames', false);
+//      indexOf
+
+//      console.warn("LENGTH:" + collection.content.length);
+//      console.warn("fieldNames:", this.get('fieldNames'));
+    }
+//    var fieldNames = this.get('fieldNames');
+
+//    $.each(this.get('collection'), function(){})
+
+  }.observes('collection')
+});

+ 41 - 0
ambari-web/app/views/main/admin/authentication.js

@@ -0,0 +1,41 @@
+/**
+ * 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.MainAdminAuthenticationView = Em.View.extend({
+  templateName:require('templates/main/admin/authentication'),
+  form:App.AuthenticationForm.create({}),
+  pushAuthenticationToForm:function () {
+    var auth = App.Authentication.find(1);
+    App.router.set('mainAdminAuthenticationController.content', auth);
+    this.form.set('object', auth);
+  },
+  didInsertElement: function (){
+    this._super();
+    this.pushAuthenticationToForm();
+  },
+
+  ldapChecked:function () {
+    return this.get('form.field.method.value');
+  }.property('form.field.method.value'),
+
+  useCredentials:function () {
+    return this.get('form.field.bindMethod.value');
+  }.property('form.field.bindMethod.value')
+});

+ 58 - 0
ambari-web/app/views/main/admin/menu.js

@@ -0,0 +1,58 @@
+/**
+ * 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.MainAdminMenuView = Em.CollectionView.extend({
+  content:[
+    {
+      route:'user',
+      label:'Users'
+    },
+    {
+      route:'authentication',
+      label:'Authentication'
+    },
+    {
+      route:'security',
+      label:'Security'
+    },
+    {
+      route:'audit',
+      label:'Audit'
+    },
+    {
+      route:'advanced',
+      label:'Advanced'
+    }
+  ],
+  tagName: "ul",
+  classNames: ["nav", "nav-list", "span2"],
+
+  activateView:function (route) {
+    $.each(this._childViews, function () {
+      this.set('active', (this.get('content.route') == route ? "active" : ""));
+    });
+  },
+
+  itemViewClass:Em.View.extend({
+    classNameBindings:["active"],
+    active:"",
+    template:Ember.Handlebars.compile('<a {{action adminNavigate view.content }} href="#"> {{unbound view.content.label}}</a>')
+  })
+});

+ 23 - 0
ambari-web/app/views/main/admin/security.js

@@ -0,0 +1,23 @@
+/**
+ * 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.MainAdminSecurityView = Em.View.extend({
+  templateName: require('templates/main/admin/security')
+});

+ 40 - 0
ambari-web/app/views/main/admin/user.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');
+
+App.MainAdminUserView = Em.View.extend({
+  templateName: require('templates/main/admin/user'),
+  users: App.User.find(),
+//  users: function(){
+//    return App.router.get('mainAdminUserController.content');
+//  }.property('mainAdminUserController.content'),
+  delete: function(event, context){
+    console.log("EVENT:");
+    console.log(event);
+
+    console.log("CONTEXT:");
+    console.log(context);
+  },
+  ldapUser: function(){
+    var auth = App.router.get('mainAdminAuthenticationController.content');
+    return auth.get('method');
+  }.property('App.router.mainAdminAuthenticationController.content')
+
+
+});

+ 43 - 0
ambari-web/app/views/main/admin/user/edit.js

@@ -0,0 +1,43 @@
+/**
+ * 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.MainAdminUserEditView = Em.View.extend({
+  templateName: require('templates/main/admin/user/edit'),
+  userId: false,
+  create: function(event){
+    var form = this.get("userForm");
+    if(form.isValid() && form.save()) {
+      App.router.transitionTo("all");
+    }
+  },
+
+  willInsertElement: function() {
+    this.setFormObject();
+    this._super();
+  },
+
+  setFormObject: function(){
+    console.log("submit new user");
+    var user = App.router.get('mainAdminUserEditController.content');
+    this.userForm.set('object', user);
+  }.observes('App.router.mainAdminUserEditController.content'),
+
+  userForm: App.UserForm.create({})
+});

+ 24 - 0
ambari-web/app/views/main/admin/user/row.js

@@ -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.MainAdminUserRowView = Em.View.extend({
+  templateName: require('templates/main/admin/user/row'),
+  disableCheckBoxes: "disabled"
+});

+ 1 - 4
ambari-web/app/views/main/dashboard.js

@@ -19,8 +19,5 @@
 var App = require('app');
 
 App.MainDashboardView = Em.View.extend({
-  templateName: require('templates/main/dashboard'),
-  services:function(){
-    return App.router.get('mainServiceController.content');
-  }.property('App.router.mainServiceController.content')
+  templateName: require('templates/main/dashboard')
 });

+ 42 - 0
ambari-web/app/views/main/host.js

@@ -0,0 +1,42 @@
+/**
+ * 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.MainHostView = Em.View.extend({
+  templateName: require('templates/main/host'),
+  content: [],
+
+  ComponentCheckboxView: Em.Checkbox.extend({
+    content: null,
+    isChecked: false,
+    change: function(event) {
+      this.set('isChecked', !this.get('isChecked'));
+      App.router.get('mainHostController').setFilters(this.get('isChecked'), this.get('content'));
+    }
+  }),
+  HostCheckboxView: Em.Checkbox.extend({
+    content: null,
+    isChecked: false,
+    change: function(event) {
+      this.set('isChecked', !this.get('content.isChecked'));
+      App.router.get('mainHostController').onHostChecked(this.get('isChecked'), this.get('content.id'));
+    }
+  })
+
+});

+ 26 - 0
ambari-web/app/views/main/host/audit.js

@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.MainHostAuditView = Em.View.extend({
+  templateName: require('templates/main/host/audit'),
+  content:function(){
+    return App.router.get('mainHostDetailsController.content');
+  }.property('App.router.mainHostDetailsController.content')
+});

+ 26 - 0
ambari-web/app/views/main/host/details.js

@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.MainHostDetailsView = Em.View.extend({
+  templateName: require('templates/main/host/details'),
+  content:function(){
+    return App.router.get('mainHostDetailsController.content');
+  }.property('App.router.mainHostDetailsController.content')
+});

+ 49 - 0
ambari-web/app/views/main/host/menu.js

@@ -0,0 +1,49 @@
+/**
+ * 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.MainHostMenuView = Em.CollectionView.extend({
+  tagName: 'ul',
+  classNames: ["nav", "nav-tabs"],
+  content:[
+    { label:'Summary', routing:'summary'},
+    { label:'Metrics', routing:'metrics'},
+    { label:'Audit', routing:'audit'}
+  ],
+
+  init: function(){ this._super(); this.activateView(); },
+
+  activateView:function () {
+    $.each(this._childViews, function () {
+      this.set('active', (this.get('content.routing') == 'summary' ? "active" : ""));
+    });
+  },
+
+  deactivateChildViews: function() {
+    $.each(this._childViews, function(){
+      this.set('active', "");
+    });
+  },
+
+  itemViewClass: Em.View.extend({
+    classNameBindings: ["active"],
+    active: "",
+    template: Ember.Handlebars.compile('<a {{action hostNavigate view.content.routing }} href="#"> {{unbound view.content.label}}</a>')
+  })
+});

+ 26 - 0
ambari-web/app/views/main/host/metrics.js

@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.MainHostMetricsView = Em.View.extend({
+  templateName: require('templates/main/host/metrics'),
+  content:function(){
+    return App.router.get('mainHostDetailsController.content');
+  }.property('App.router.mainHostDetailsController.content')
+});

+ 29 - 0
ambari-web/app/views/main/host/summary.js

@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.MainHostSummaryView = Em.View.extend({
+  templateName: require('templates/main/host/summary'),
+  content:function(){
+    return App.router.get('mainHostDetailsController.content');
+  }.property('App.router.mainHostDetailsController.content'),
+  buttonClass: function(){
+    return this.get('startComponents') ? 'success' : 'danger';
+  }.property('startComponents')
+});

+ 14 - 5
ambari-web/app/views/main/menu.js

@@ -18,6 +18,10 @@
 
 var App = require('app');
 
+/**
+ * this menu extended by other with modifying content and itemViewClass.template
+ * @type {*}
+ */
 App.MainMenuView = Em.CollectionView.extend({
   tagName: 'ul',
   classNames: ["nav", "nav-tabs"],
@@ -25,20 +29,25 @@ App.MainMenuView = Em.CollectionView.extend({
     { label:'My Cluster', routing:'cluster'},
     { label:'Dashboard', routing:'dashboard', active:"active"},
     { label:'Charts', routing:'charts'},
-    { label:'Services', routing:'service'},
+    { label:'Services', routing:'services'},
     { label:'Hosts', routing:'hosts'},
     { label:'Admin', routing:'admin'}
   ],
 
-  deactivateChildViews: function() {
-    $.each(this._childViews, function(){
-      this.set('active', "");
+  deactivateChildViews:function (content) {
+    $.each(this._childViews, function () {
+      this.set('active', this.get('content') == content ? "active" : "");
     });
   },
 
   itemViewClass: Em.View.extend({
     classNameBindings: ["active"],
     active: "",
-    template: Ember.Handlebars.compile('<a {{action navigate view.content.routing }} href="#"> {{unbound view.content.label}}</a>')
+    alertsCount: function() {
+      if(this.get('content').routing == 'dashboard'){
+        return App.router.get('mainDashboardController.alertsCount');
+      }
+    }.property(),
+    template: Ember.Handlebars.compile('<a {{action navigate view.content}} href="#"> {{unbound view.content.label}}{{#if view.alertsCount}}<span class="label label-important alerts-count">{{view.alertsCount}}</span>{{/if}}</a>')
   })
 });

+ 24 - 0
ambari-web/app/views/main/service/info/audit.js

@@ -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.MainServiceInfoAuditView = Em.View.extend({
+  templateName: require('templates/main/service/info/audit'),
+  content: App.ServiceAudit.find()
+});

+ 26 - 0
ambari-web/app/views/main/service/info/configs.js

@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.MainServiceInfoConfigsView = Em.View.extend({
+  templateName: require('templates/main/service/info/configs'),
+  alerts: function(){
+    return App.router.get('mainAlertController.content');
+  }.property('App.router.mainAlertController.content')
+});

+ 50 - 0
ambari-web/app/views/main/service/info/menu.js

@@ -0,0 +1,50 @@
+/**
+ * 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.MainServiceInfoMenuView = Em.CollectionView.extend({
+  tagName: 'ul',
+  classNames: ["nav", "nav-tabs"],
+  content:[
+    { label:'Summary', routing:'summary', active:"active"},
+    { label:'Metrics', routing:'metrics'},
+    { label:'Configs', routing:'configs'},
+    { label:'Audit', routing:'audit'}
+  ],
+
+  init: function(){ this._super(); this.activateView(); },
+
+  activateView:function () {
+    $.each(this._childViews, function () {
+      this.set('active', (this.get('content.routing') == 'summary' ? "active" : ""));
+    });
+  },
+
+  deactivateChildViews: function() {
+    $.each(this._childViews, function(){
+      this.set('active', "");
+    });
+  },
+
+  itemViewClass: Em.View.extend({
+    classNameBindings: ["active"],
+    active: "",
+    template: Ember.Handlebars.compile('<a {{action showInfo view.content.routing }} href="#"> {{unbound view.content.label}}</a>')
+  })
+});

+ 26 - 0
ambari-web/app/views/main/service/info/metrics.js

@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.MainServiceInfoMetricsView = Em.View.extend({
+  templateName: require('templates/main/service/info/metrics'),
+  alerts: function(){
+    return App.router.get('mainAlertController.content');
+  }.property('App.router.mainAlertController.content')
+});

+ 23 - 0
ambari-web/app/views/main/service/info/summary.js

@@ -0,0 +1,23 @@
+/**
+ * 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.MainServiceInfoSummaryView = Em.View.extend({
+  templateName: require('templates/main/service/info/summary')
+});

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

@@ -26,7 +26,7 @@ App.MainServiceMenuView = Em.CollectionView.extend({
   init: function(){ this._super(); this.activateView(); },
 
   tagName:'ul',
-  classNames:["nav", "nav-tabs"],
+  classNames:["nav", "nav-tabs", "nav-services"],
 
   activateView:function () {
     var service = App.router.get('mainServiceItemController.content');
@@ -38,6 +38,6 @@ App.MainServiceMenuView = Em.CollectionView.extend({
   itemViewClass:Em.View.extend({
     classNameBindings:["active"],
     active:"",
-    template:Ember.Handlebars.compile('<a {{action showService view.content}} href="#"> {{unbound view.content.label}}</a>')
+    template:Ember.Handlebars.compile('<a {{action showService view.content}} href="#" class="health-status-{{unbound view.content.healthStatus}}"> {{unbound view.content.label}}</a>')
   })
 });