You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ja...@apache.org on 2014/07/21 22:48:57 UTC

[2/4] AMBARI-6519. View: Capacity Scheduler view. (jaimin)

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html b/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html
new file mode 100644
index 0000000..ce0972c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html
@@ -0,0 +1,48 @@
+<!--
+   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.
+-->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Capacity Scheduler</title>
+  <link rel="stylesheet" href="stylesheets/vendor.css">
+  <link rel="stylesheet" href="stylesheets/app.css">
+  <script src="javascripts/vendor.js"></script>
+  <script src="javascripts/app.js"></script>
+  <script>
+      $(document).ready(function() {
+          require('initialize');
+      });
+  </script>
+</head>
+<body>
+  <script type="text/x-handlebars">
+  <div class="wrap">
+    <div class="container-fluid">
+      <div class="row">
+        {{outlet}}
+      </div>
+    </div>
+  </div>
+  </script>
+
+
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js
new file mode 100644
index 0000000..eb743c4
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.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.
+ */
+
+require('components/capacityBar');
+require('components/capacityInput');
+require('components/totalCapacity');
+require('components/queueListItem');
+require('components/pathInput');
+require('components/radioButton');
+require('components/userGroupInput');
+require('components/escapeAcl');
+require('components/confirmDelete');

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js
new file mode 100644
index 0000000..22d511b
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.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.CapacityBarComponent = Em.Component.extend({
+  layoutName:'components/capacityBar',
+  classNames:['capacity-bar'],
+  mark:function () {
+    if (this.$().parent().hasClass('active')) {
+      Ember.run.next(this, 'addInClass');
+    };
+  }.on('didInsertElement'),
+  addInClass:function () {
+    this.$().children().addClass('in');
+  },
+  capacityWidth: function() {
+    return  (Number(this.get('capacityValue'))<=100)?('width: '+this.get('capacityValue')+'%'):'width: 100%';
+  }.property('capacityValue'),
+  maxCapacityWidth: function() {
+    var val = Number(this.get('maxCapacityValue')) - Number(this.get('capacityValue'));
+    return  (val<=100)?('width: '+val+'%'):'width: 100%';
+  }.property('maxCapacityValue','capacityValue'),
+  showMaxCapacity:function () {
+    return this.get('maxCapacityValue') > this.get('capacityValue');
+  }.property('maxCapacityValue','capacityValue')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js
new file mode 100644
index 0000000..b46933a
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js
@@ -0,0 +1,94 @@
+/**
+ * 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.FocusInputComponent = Ember.TextField.extend({
+  becomeFocused: function() {
+    this.$().focus().val(this.value);
+  }.on('didInsertElement'),
+  cancel:function () {
+    this.get('targetObject').send(this.get('revert'),'cancel');
+  }
+});
+
+App.IntInputComponent = Ember.TextField.extend({
+  classNames:['form-control'],
+  maxVal:null,
+  intVal:function () {
+    var val = parseFloat(this.get('value'))||0;
+    var maxVal = this.get('maxVal');
+    val = (maxVal && maxVal < val)?maxVal:val;
+    this.set('value', val);
+  }.on('change'),
+  checkNumber:function () {
+    var val = this.get('value'),
+        num = Number(val),
+        str = String(val);
+    if (typeof val !== "number" && !isNaN(num) && str == num.toString()) {
+      this.set('value', Number(val));
+    };
+  }.observes('value')
+});
+
+App.CapacityInputComponent = App.IntInputComponent.extend({
+  
+  totalCapacity:null,
+  queue:null,
+
+  keyDown: function(evt) {
+    var newChar, val = this.get('value')||0;
+    val = val.toString();
+    
+    if ((evt.keyCode > 64 && evt.keyCode < 91) || 
+      (evt.keyCode > 185 && evt.keyCode < 193) || 
+      (evt.keyCode > 218 && evt.keyCode < 223)) {
+      return false;
+    };
+
+    if (evt.keyCode > 95 && evt.keyCode < 106) {
+      newChar = (evt.keyCode - 96).toString();
+    } else {
+      newChar = String.fromCharCode(evt.keyCode);
+    }
+
+    if (newChar.match(/[0-9]/)) {
+      val = val.substring(0, evt.target.selectionStart) + newChar + val.substring(evt.target.selectionEnd);
+    };
+
+    return parseFloat(val)<=100;
+  },
+});
+
+App.MaxCapacityInputComponent = App.CapacityInputComponent.extend({
+  isInvalid:false,
+  invalid:function (c,o) {
+    var queue = this.get('queue'),
+        max_capacity = Number(queue.get('maximum_capacity')),
+        capacity = Number(queue.get('capacity'));
+    if (o == 'queue.capacity' && max_capacity < capacity) {
+      return queue.set('maximum_capacity',capacity);
+    };
+    if (max_capacity < capacity && queue.get('isDirty')) {
+      queue.get('errors').add('maximum_capacity', 'Maximum capacity must be greater then capacity');
+    } else {
+      queue.get('errors').remove('maximum_capacity');
+    }
+  }.observes('queue.maximum_capacity','queue.capacity')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js
new file mode 100644
index 0000000..5b465bc
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.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.
+ */
+
+var App = require('app');
+
+var bound;
+
+bound = function(fnName) {
+  return Ember.computed(fnName,function() {
+    return this.get(fnName).bind(this);
+  });
+};
+
+App.ClickElsewhereMixin = Ember.Mixin.create({
+  onClickElsewhere: Ember.K,
+  clickHandler: bound("elsewhereHandler"),
+  elsewhereHandler: function(e) {
+    var $target, element, thisIsElement;
+    element = this.get("element");
+    $target = $(e.target);
+    thisIsElement = $target.closest(element).length === 1;
+    if (!thisIsElement) {
+      return this.onClickElsewhere(event);
+    }
+  },
+  didInsertElement: function() {
+    this._super.apply(this, arguments);
+    return $(window).on("click", this.get("clickHandler"));
+  },
+  willDestroyElement: function() {
+    $(window).off("click", this.get("clickHandler"));
+    return this._super.apply(this, arguments);
+  }
+});
+
+App.ComfirmDeleteComponent = Em.Component.extend(App.ClickElsewhereMixin,{
+  confirm:false,
+  onClickElsewhere:function () {
+    this.set('confirm',false);
+  },
+  actions: {
+    delete: function() {
+      if (this.get('confirm')) {
+        this.toggleProperty('confirm');
+        this.sendAction('action', this.get('param'));
+      } else {
+        this.toggleProperty('confirm');
+      };
+    }
+  },
+  tagName:'a',
+  tooltip:function () {
+    var element = this.$();
+    if (this.get('confirm')) {
+      element.tooltip({
+        placement:'left',
+        title:'Click again to confirm'
+      }).tooltip('show');
+    } else {
+      element.tooltip('destroy')
+    };
+  }.observes('confirm'),
+  click:function (e) {
+    this.send('delete');
+  },
+  didChange:function () {
+    this.set('confirm',false);
+  }.observes('param'),
+
+  classNames:['pull-right rm-queue'],
+  layout:Em.Handlebars.compile('<span class="fa-stack"> <i class="fa fa-times fa-stack-2x"></i> {{#if confirm}} <i class="fa fa-check fa-stack-1x fa-stack-bottom green"></i> {{/if}} </span> ')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js
new file mode 100644
index 0000000..b5a3e07
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+
+Ember.Handlebars.helper('escapeACL', function(value) {
+  var output = '';
+  
+  value = value || '';
+
+  if (value.trim() == '') {
+    output = '<span class="label label-danger"> <i class="fa fa-ban fa-fw"></i>  Nobody </span> ';
+  } else if (value.trim() == '*') {
+    output = '<label class="label label-success"> <i class="fa fa-asterisk fa-fw"></i> Anyone</label>';
+  } else {
+    var ug = value.split(' ');
+    var users = ug[0].split(',')||[]; 
+    var groups = (ug.length == 2)?ug[1].split(',')||[]:[];
+
+    output += ' <span class="users"> '
+
+    users.forEach(function (user) {
+      output += (user)?'<span class="label label-primary"><i class="fa fa-user fa-fw"></i> '+ user +'</span> ':'';
+    });
+
+    output += ' </span> <span class="groups"> '
+
+    groups.forEach(function (group) {
+      output += (group)?'<span class="label label-primary"><i class="fa fa-users fa-fw"></i> '+ group +'</span> ':'';
+    });
+    output += ' </span> '
+  }
+  return new Ember.Handlebars.SafeString(output);
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js
new file mode 100644
index 0000000..ccdd5f1
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js
@@ -0,0 +1,61 @@
+/**
+ * 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.PathInputComponent = Em.Component.extend({
+  layoutName:'components/pathInput',
+  actions:{
+    add:function () {
+      var path = this.get('path'),
+          basedir = path.substr(0,path.lastIndexOf('.'));
+
+      if (this.get('pathMap').contains(path)) {
+        this.sendAction('action',path);
+        this.set('activeFlag',false);
+      } else if (this.get('pathMap').contains(basedir)) {
+        this.sendAction('action',basedir,path.substr(path.lastIndexOf('.')+1));
+        this.set('activeFlag',false);
+      }
+    },
+    cancel:function () {
+      this.set('activeFlag',false);
+    }
+  }, 
+  queues:[],
+  activeFlag:false,
+  pathMap:Em.computed.mapBy('queues','path'),
+  path:'',
+  inputFieldView: Em.TextField.extend({
+    classNames:['form-control newQPath'],
+    action:'add',
+    pathSource:[],
+    placeholder:"Enter queue path...",
+    typeaheadInit:function () {
+      $(this.get('element')).typeahead({
+          source: this.get('pathSource'),
+          matcher: function (item) {
+            return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+          },
+          minLength:0,
+          items:100,
+          scrollHeight:5
+      }).focus();
+    }.observes('pathSource').on('didInsertElement'),
+  })
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js
new file mode 100644
index 0000000..c9bf813
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.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.RecurceQueuesComponent = Ember.View.extend({
+  templateName: "components/queueListItem",
+  depth:0,
+  parent:'',
+  leaf:function () {
+    return this.get('controller.arrangedContent')
+      .filterBy('depth',this.get('depth'))
+      .filterBy('parentPath',this.get('parent'));
+  }.property('depth','parent','controller.content.length','controller.content.@each.name'),
+  childDepth:function () {
+    return this.get('leaf.firstObject.depth')+1;
+  }.property('depth'),
+  didInsertElement:function () {
+    Ember.run.scheduleOnce('afterRender',null, this.setFirstAndLast, this);
+  },
+  setFirstAndLast:function (item) {
+    var items = item.$().parents('.queue-list').find('.list-group-item');
+    items.first().addClass('first');
+    items.last().addClass('last');
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js
new file mode 100644
index 0000000..30fd531
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js
@@ -0,0 +1,46 @@
+/**
+ * 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.RadioButtonInputComponent = Ember.View.extend({
+    tagName : "input",
+    type : "radio",
+    attributeBindings : [ "type", "value", "checked:checked" ],
+    click : function() {
+      this.set("selection", this.get('value'))
+    }
+});
+
+App.RadioButtonComponent = Em.Component.extend({
+  tagName:'label',
+  classNames:['btn btn-default'],
+  classNameBindings:['isActive:active'],
+
+  //arguments
+  selection:null,
+  label:null,
+  value:null, 
+  click : function() {
+    this.set("selection", this.get('value'))
+  },
+  isActive : function() {
+    return this.get("value") == this.get("selection");   
+  }.property("selection"),
+  layout:Em.Handlebars.compile('{{label}} {{radio-button-input selection=selection value=value checked=isActive}}')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js
new file mode 100644
index 0000000..aad6682
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js
@@ -0,0 +1,98 @@
+/**
+ * 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.TotalCapacityComponent = Ember.Component.extend({
+  layoutName:'components/totalCapacity',
+
+  actions:{
+    toggleEdit:function () {
+      this.toggleProperty('isEdit');
+    },
+    addQueue:function (path) {
+      this.sendAction('addQueue',path);
+    },
+    createQueue:function (queue) {
+      this.sendAction('createQueue',queue);
+    },
+    deleteQueue:function (queue) {
+      this.sendAction('deleteQueue',queue);
+    },
+  },
+
+  /**
+   * passed params
+   */
+  currentQueue:null,
+  allQueues:[],
+  allQueuesArranged:[],
+
+  isEdit:false,
+
+  disableEdit:function () {
+    this.set('isEdit',false);
+  }.observes('allQueues'),
+
+  currentPrPath:Em.computed.alias('currentQueue.parentPath'),
+
+  leafQueuesCapacity: Ember.computed.map('leafQueues.@each.capacity', function (queue) {
+    return Number(queue.get('capacity')); 
+  }),
+
+  totalCapacity: Ember.computed.sum('leafQueuesCapacity'),
+
+  leafQueues:function () {
+    return this.allQueuesArranged.filterBy('parentPath',this.get('currentPrPath')).filterBy('isNew',false);
+  }.property('allQueuesArranged.length','currentPrPath'),
+
+  newLeafQueues:function () {
+    return this.allQueues.filterBy('parentPath',this.get('currentPrPath')).filterBy('isNew',true);
+  }.property('allQueues.length','currentPrPath'),
+  
+  parentQueue:function () {
+    return this.allQueues.findBy('path',this.get('currentPrPath'));
+  }.property('allQueues','currentPrPath'),
+
+  currentInLeaf:function (argument) {
+    var leaf = this.get('leafQueues');
+    leaf.setEach('isCurrent',false);
+    if(!this.get('currentQueue.currentState.stateName').match(/root.deleted/)) {
+      this.get('currentQueue').set('isCurrent',true);
+    }
+  }.observes('leafQueues','currentQueue').on('init'),
+
+  newQueueNameField: Em.TextField.extend({
+    queue:null,
+    classNames:['form-control'],
+    classNameBindings:['isValid::input-error'],
+    isValid:Em.computed.bool('queue.isValid')
+  })
+});
+
+App.CapacityEditFormView = Em.View.extend({
+  mark:function () {
+    this.addObserver('controller.target.isEdit',this,'slide');
+    if (!this.get('controller.target.isEdit')) {
+      this.$('.capacity-edit-form').hide();
+    };
+  }.on('didInsertElement'),
+  slide:function () {
+    this.$('.capacity-edit-form').slideToggle(100);
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js
new file mode 100644
index 0000000..ff0300d
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.UserGroupInputComponent = Em.Component.extend({
+  layoutName:'components/userGroupInput',
+
+  users:null,
+  groups:null,
+
+  splitter:function () {
+    if (this.ug == '*') return;
+    var ug = this.ug || '';
+    var spl = ug.split(' ');
+    this.setProperties({
+      users:spl[0],
+      groups:spl[1]
+    });
+  }.observes('ug').on('init'),
+
+  setter:function () {
+    this.set('ug',[this.get('users'),this.get('groups')].join(' '));
+  }.observes('users','groups'),
+
+  noSpace:function (e) {
+    return (e.keyCode==32)?false:true;
+  },
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js
new file mode 100644
index 0000000..0101a82
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.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.
+ */
+
+require('controllers/queue');
+require('controllers/queues');
+require('controllers/trace');

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js
new file mode 100644
index 0000000..91e3903
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js
@@ -0,0 +1,186 @@
+/**
+ * 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 _runState = 'RUNNING';
+var _stopState = 'STOPPED';
+
+App.QueueController = Ember.ObjectController.extend({
+  needs:['queues'],
+  actions:{
+    setState:function (state) {
+      var state = (state === "running")?_runState:_stopState;
+      this.content.set('state',state);
+    },
+    createQ:function (record) {
+      this.get('controllers.queues').send('createQ',this.get('content'));
+    },
+    addQ:function (path) {
+      this.get('controllers.queues').send('addQ',path);
+    },
+    delQ:function (record) {
+      this.get('controllers.queues').send('delQ',this.get('content'));
+    },
+    renameQ:function (opt) {
+      if (opt == 'ask') {
+        this.content.addObserver('name',this,this.setQueuePath);
+        this.toggleProperty('isRenaming');
+        return;
+      };
+      if (opt == 'cancel') {
+        this.send('rollbackProp','name');
+        this.send('rollbackProp','id');
+        this.send('rollbackProp','path');
+        this.content.removeObserver('name',this,this.setQueuePath);
+        this.toggleProperty('isRenaming');
+        return;
+      };
+      if (opt) {
+        var self = this;
+        this.store.filter('queue',function (q) {
+          return q.id === self.content.id;
+        }).then(function(queues){
+          if (queues.get('length') > 1) {
+            return self.content.get('errors').add('path', 'Queue already exists');
+          };
+          self.toggleProperty('isRenaming');
+          self.content.removeObserver('name',self,self.setQueuePath);
+          self.transitionToRoute('queue',self.content.id);
+        })
+      }
+
+    },
+    toggleEditRA:function () {
+      this.toggleProperty('isEditRA');
+    },
+    toggleEditACL:function () {
+      this.toggleProperty('isEditACL');
+    },
+    rollbackProp:function(prop){
+      attributes = this.content.changedAttributes();
+      if (attributes.hasOwnProperty(prop)) {
+        this.content.set(prop,attributes[prop][0]);
+      }
+    }
+  },
+  setQueuePath:function (queue,o) {
+    var name = queue.get(o);
+    var parentPath = queue.get('parentPath');
+
+    queue.setProperties({
+      name:name.replace(/\s|\./g, ''),
+      path:parentPath+'.'+name,
+      id:(parentPath+'.'+name).dasherize(),
+    });
+
+    if (name == '') {
+      queue.get('errors').add('path', 'This field is required');
+    }
+  },
+
+  isRenaming:false,
+
+  unsetRenaming:function () {
+    this.set('isRenaming',false);
+  }.observes('content'),
+
+  isRoot:Ember.computed.equal('content.id', 'root'),
+  isRunning:Ember.computed.equal('content.state', _runState),
+  allQueues:Em.computed.alias('controllers.queues.content'),
+  allQueuesArranged:Em.computed.alias('controllers.queues.arrangedContent'),
+
+  isEditRA:false,
+  isEditACL:false,
+
+  acl_administer_queue:null,
+  aaq_anyone:Ember.computed.equal('acl_administer_queue', '*'),
+  aaq_dirty:function () {
+    var attributes = this.content.changedAttributes();
+    return attributes.hasOwnProperty('acl_administer_queue');
+  }.property('content.acl_administer_queue'),
+
+  acl_administer_jobs:null,
+  aaj_anyone:Ember.computed.equal('acl_administer_jobs', '*'),
+  aaj_dirty:function () {
+    var attributes = this.content.changedAttributes();
+    return attributes.hasOwnProperty('acl_administer_jobs');
+  }.property('content.acl_administer_jobs'),
+
+  acl_submit_applications:null,
+  asa_anyone:Ember.computed.equal('acl_submit_applications', '*'),
+  asa_dirty:function () {
+    var attributes = this.content.changedAttributes();
+    return attributes.hasOwnProperty('acl_submit_applications');
+  }.property('content.acl_submit_applications'),
+
+  aclSerializer:function (c,o) {
+    var acl = o.substr(o.indexOf('.')+1);
+    var aclProp = c.get(o);
+    var aclVal;
+    switch(aclProp) {
+      case '*': 
+        aclVal = '*'; 
+        break;
+      
+      default:
+        aclVal = 'custom'; 
+    }
+    c.set(acl,aclVal);
+  }.observes('content.acl_administer_queue','content.acl_administer_jobs','content.acl_submit_applications'),
+
+  aclDeserializer:function (c,o) {
+    var aclVal = c.get(o);
+    var aclProp;
+    switch(aclVal) {
+      case '*': 
+        aclProp = '*'; 
+        this.set('content.'+o,aclProp);
+        break;
+      
+      default:
+        if (this.get('content.'+o)=='*') {
+          this.set('content.'+o,' ');
+        }
+    }
+  }.observes('acl_administer_queue','acl_administer_jobs','acl_submit_applications'),
+
+  capacityControl:function () {
+    var leafQueues = this.get('leafQueues');
+    var total = 0;
+
+    leafQueues.forEach(function (queue) {
+      total+=Number(queue.get('capacity'));
+    });
+    leafQueues.setEach('overCapacity',total>100)
+  }.observes('content.capacity','leafQueues.@each.capacity'),
+  leafQueues:function () {
+    return this.get('allQueues').filterBy('parentPath',this.get('content.parentPath'));
+  }.property('allQueues.length','content.parentPath'),
+
+  queueNamesControl:function (c,o) {
+    var leaf = c.get('leafQueues');
+    var parent = c.get('allQueues').filterBy('path',c.get('content.parentPath')).get('firstObject');
+    if (parent) parent.set('queueNames',leaf.mapBy('name').join());
+  }.observes('allQueues.length','allQueues.@each.name'),
+
+  pathErrors:Ember.computed.mapBy('content.errors.path','message')
+  
+});
+
+App.ErrorController = Ember.ObjectController.extend();

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js
new file mode 100644
index 0000000..cdbf41b
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js
@@ -0,0 +1,154 @@
+/**
+ * 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 cmp = Ember.computed;
+
+App.QueuesController = Ember.ArrayController.extend({
+  sortProperties: ['name'],
+  sortAscending: true,
+  actions:{
+    goToQueue:function (queue) {
+      this.transitionToRoute('queue',queue)
+    },
+    askPath:function () {
+      this.set('isWaitingPath',true);
+    },
+    addQ:function (parentPath,name) {
+      if (!parentPath || this.get('hasNewQueue')) {
+        return;
+      };
+      name = name || '';
+      var newQueue = this.store.createRecord('queue',{
+        name:name,
+        parentPath: parentPath,
+        depth: parentPath.split('.').length,
+        isNewQueue:true
+      });
+      this.set('newQueue',newQueue);
+      this.send('goToQueue',newQueue);
+    },
+    createQ:function (record) {
+      record.save().then(Em.run.bind(this,this.set,'newQueue',null));
+    },
+    delQ:function (record) {
+      if (record.get('isNew')) {
+        this.set('newQueue',null);
+      };
+      if (!record.get('isNewQueue')) {
+        this.set('hasDeletedQueues',true);
+      };
+      if (record.isCurrent) {
+        this.transitionToRoute('queue',record.get('parentPath'));
+      };
+      this.store.deleteRecord(record);
+    },
+    saveConfig:function (mark) {
+      if (mark == 'restart') {
+        this.get('store').markForRestart();
+      } else if (mark == 'refresh') {
+        this.get('store').markForRefresh();
+      };
+      Em.RSVP.Promise.all([this.get('scheduler').save(),this.get('model').save()])
+        .catch(Em.run.bind(this,this.saveError));
+    },
+    toggleEditScheduler:function () {
+      this.toggleProperty('isEditScheduler');
+    },
+    clearAlert:function () {
+      this.set('alertMessage',null);
+    }
+  },
+
+  alertMessage:null,
+  saveError:function (error) {
+    var response = JSON.parse(error.responseText);
+    this.set('alertMessage',response);
+  },
+
+  isEditScheduler:false,
+
+  isWaitingPath:false,
+  /**
+   * check if RM needs refresh
+   * @type {bool}
+   */
+  needRefresh: cmp.any('hasChanges', 'hasNewQueues','dirtyScheduler'),
+
+  /**
+   * props for 'needRefresh'
+   */
+  dirtyQueues: cmp.filterBy('content', 'isDirty', true),
+  dirtyScheduler: cmp.bool('scheduler.isDirty'),
+  newQueues: cmp.filterBy('content', 'isNewQueue', true),
+  hasChanges: cmp.notEmpty('dirtyQueues.[]'),
+  hasNewQueues: cmp.notEmpty('newQueues.[]'),
+  
+  /**
+   * check if RM needs restart 
+   * @type {bool}
+   */
+  needRestart: cmp.any('hasDeletedQueues', 'hasRenamedQueues'),
+  
+  /**
+   * props for 'needRestart'
+   */
+  hasDeletedQueues:false,
+  hasRenamedQueues: cmp.notEmpty('renamedQueues.[]'),
+  renamedQueues:function () {
+    return this.content.filter(function(queue){
+      var attr = queue.changedAttributes();
+      return attr.hasOwnProperty('name') && !queue.get('isNewQueue');
+    });
+  }.property('content.@each.name'),
+
+  /**
+   * check if can save configs
+   * @type {bool}
+   */
+  canNotSave: cmp.any('hasOverCapacity', 'hasUncompetedAddings','hasNotValid'),
+
+  /**
+   * props for canNotSave
+   */
+  notValid:cmp.filterBy('content','isValid',false),
+  overCapacityQ:cmp.filterBy('content','overCapacity',true),
+  uncompetedAddings:cmp.filterBy('content', 'isNew', true),
+  hasNotValid:cmp.notEmpty('notValid.[]'),
+  hasOverCapacity:cmp.notEmpty('overCapacityQ.[]'),
+  hasUncompetedAddings:cmp.notEmpty('uncompetedAddings.[]'),
+
+  newQueue:null,
+  hasNewQueue: cmp.bool('newQueue'),
+  trackNewQueue:function () {
+    var newQueue = this.get('newQueue');
+    if (Em.isEmpty(newQueue)){
+      return;
+    };
+    var name = newQueue.get('name');
+    var parentPath = newQueue.get('parentPath');
+
+    this.get('newQueue').setProperties({
+      name:name.replace(/\s/g, ''),
+      path:parentPath+'.'+name,
+      id:(parentPath+'.'+name).dasherize(),
+    });
+
+  }.observes('newQueue.name')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js
new file mode 100644
index 0000000..54c257c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.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.TraceController = Ember.ObjectController.extend({
+  needs:['queues'],
+  trace:function () {
+    return this.get('controllers.queues.alertMessage.trace')||'No trace';
+  }.property('controllers.queues.alertMessage')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js
new file mode 100644
index 0000000..ebea5ff
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.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.
+ */
+
+window.App = require('app');
+
+// Set this value to true to run in test mode with local data
+App.testMode = false;
+
+// adapters
+require('adapters');
+
+//components
+require('components');
+
+//controllers
+require('controllers');
+
+// templates
+require('templates');
+
+// models
+require('models');
+
+// routes
+require('router');

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js
new file mode 100644
index 0000000..89bbdaa
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js
@@ -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.
+ */
+
+require('models/queue');

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
new file mode 100644
index 0000000..4b951d3
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
@@ -0,0 +1,64 @@
+/**
+ * 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.Scheduler = DS.Model.extend({
+  maximum_am_resource_percent: DS.attr('number', { defaultValue: 0 }),
+  maximum_applications: DS.attr('number', { defaultValue: 0 }),
+  node_locality_delay: DS.attr('number', { defaultValue: 0 })
+});
+
+/**
+ * Represents the queue.
+ *
+ */
+App.Queue = DS.Model.extend({
+  name: DS.attr('string'),
+  parentPath: DS.attr('string'),
+  depth: DS.attr('number'),
+  path: DS.attr('string'),
+
+  // cs props
+  
+  // queue props
+  state: DS.attr('string', { defaultValue: 'RUNNING' }),
+
+  capacity: DS.attr('number', { defaultValue: 0 }),
+  maximum_capacity: DS.attr('number', { defaultValue: 0 }),
+  unfunded_capacity: DS.attr('number', { defaultValue: 0 }),
+  
+  acl_administer_queue: DS.attr('string', { defaultValue: '*' }),
+  acl_administer_jobs: DS.attr('string', { defaultValue: '*' }),
+  acl_submit_applications: DS.attr('string', { defaultValue: '*' }),
+  
+  minimum_user_limit_percent: DS.attr('number', { defaultValue: 0 }),
+  user_limit_factor: DS.attr('number', { defaultValue: 0 }),
+  
+  queueNames: DS.attr('string'),
+  queueNamesArray:function () {
+    return (this.get('queueNames.length')>0)?this.get('queueNames').split(','):[];
+  }.property('queueNames'),
+
+  
+
+  overCapacity:false,
+
+  //new queue flag
+  isNewQueue:DS.attr('boolean', {defaultValue: false})
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
new file mode 100644
index 0000000..fc9108c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
@@ -0,0 +1,122 @@
+/**
+ * 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.Router.map(function() {
+  this.resource('queues', { path: '/queues' }, function() {
+    this.resource('queue', { path: '/:queue_id' });
+    this.resource('trace', { path: '/log' });
+  });
+});
+
+
+/**
+ * The queues route.
+ *
+ * /queues
+ */
+App.TraceRoute = Ember.Route.extend({
+  model: function() {
+    return this.controllerFor('queues').get('alertMessage');
+  }
+});
+
+/**
+ * The queues route.
+ *
+ * /queues
+ */
+App.QueuesRoute = Ember.Route.extend({
+  actions:{
+  },
+  model: function() {
+    return this.store.find('queue');
+  },
+  setupController:function (c,model) {
+    c.set('model',model);
+    this.store.find('scheduler','scheduler').then(function (s) {
+      c.set('scheduler',s);
+    });
+  }
+});
+
+/**
+ * The queue route.
+ *
+ * /queues/:id
+ */
+App.QueueRoute = Ember.Route.extend({
+  model: function(params,tr) {
+    var queues = this.modelFor('queues') || this.store.find('queue'),
+        filterQueues = function (queues) {
+          return queues.filterBy('id',params.queue_id).get('firstObject');
+        };
+
+    return (queues instanceof DS.PromiseArray)?queues.then(filterQueues):filterQueues(queues);
+  },
+  afterModel:function (model) {
+    if (!model) {
+      this.transitionTo('queues');
+    }
+  },
+  
+  actions: {
+    refreshQueue: function() {
+    var x = "{ \"RequestInfo\" : { \"command\" : \"REFRESHQUEUES\", \"context\" : \"Refresh YARN Capacity Scheduler\" }, "
+    x = x + "\"Requests/resource_filters\":[{\"service_name\":\"YARN\",\"component_name\":\"RESOURCEMANAGER\",\"hosts\":\"c6403.ambari.apache.org\"}]}";
+    
+      App.Adapter.ajaxPost("/api/v1/clusters/MyCluster/requests", x);
+    },
+    willTransition:function (tr) {
+      if (this.get('controller.isRenaming')) {
+        tr.abort();
+      };
+    }
+  }
+
+});
+
+/**
+ * Routes index to /queues path
+ *
+ */
+App.IndexRoute = Ember.Route.extend({
+  beforeModel: function() {
+    this.transitionTo('queues');
+  }
+});
+
+/**
+ * Loading spinner page.
+ *
+ */
+App.LoadingRoute = Ember.Route.extend();
+
+/**
+ * Error page.
+ *
+ */
+App.ErrorRoute = Ember.Route.extend({
+  setupController:function (controller,model) {
+    var response = JSON.parse(model.responseText);
+    controller.set('model',response);
+  }
+});
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less b/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
new file mode 100644
index 0000000..94e3996
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
@@ -0,0 +1,238 @@
+/**
+ * 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.
+ */
+
+.wrap {
+  padding: 15px;
+}
+
+.btn {
+  padding: 6px 10px;
+  transition: background-color .08s linear 0s;
+}
+
+.input-error  {
+  color: #a94442;
+  border-color: #a94442;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.input-error:focus {
+  border-color: #843534;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+}
+
+.gray {
+  color: #999;
+}
+
+.green {
+  color: #5cb85c;
+}
+
+.blue {
+  color: #428bca;
+}
+
+.red {
+  color: #d9534f;
+}
+
+.add-queue {
+  margin-bottom: 5px;
+}
+
+.rm-queue {
+  cursor: pointer;
+  .gray;
+  transition: color .1s linear;
+  &:hover {
+    .red;
+  } 
+}
+
+.fa-stack-bottom {
+  text-align: right;
+  bottom: 0;
+  line-height: 1em;
+  //opacity: 0.9;
+  text-shadow: 0px -1px 3px #111;
+}
+
+.queue-list{
+  .badge {
+    color: #999;
+    background-color: #fff;
+    margin-left: 5px;
+  }
+    .progress {
+      height: 3px;
+      margin: 0;
+    }
+    .spacer {
+      height: 25px;
+    }
+    .spacer.col-md-0 {
+      height: 0;
+    }
+    .capacity-bar {
+      display: inline-block;
+      float: right;
+      margin-top: 8px;
+      width: 20%;
+    }
+  .list-group-item {
+    cursor: pointer;
+    transition: background-color .1s linear 0s;
+  }
+  .list-group-item.last {
+    border-bottom-left-radius: 4px;
+    border-bottom-right-radius: 4px;
+  }
+  .list-group-item.first {
+    border-top-left-radius: 4px;
+    border-top-right-radius: 4px;
+  }
+}
+
+.path-input {
+  .btn-cancel {
+    border-radius: 0;
+  }
+}
+
+.user-group-input.has-feedback  {
+  .form-control-feedback {
+    top: -2px;
+    right: 15px;
+    opacity: 0.4;
+  }
+}
+
+.btn-group-save {
+  table-layout: auto;
+  .btn-group {
+    width: 100%;
+    .btn-save {
+      border-top-left-radius: 4px !important;
+      border-bottom-left-radius: 4px !important;
+    }
+  }
+}
+
+.form-acl {
+  .users .label,.groups .label {
+    border-radius: 0;
+  }
+  .users .label:first-child,.groups .label:first-child {
+    border-top-left-radius: .25em;
+    border-bottom-left-radius: .25em;
+  }
+  .users .label:last-child,.groups .label:last-child {
+    border-top-right-radius: .25em;
+    border-bottom-right-radius: .25em;
+  }
+  .label {
+    vertical-align: text-top;
+  }
+}
+
+.panel-capacity {
+  .new-queue {
+    .input-row {
+      margin-bottom: 5px;
+    } 
+  }
+  .progress{
+    background-color: #ddd;
+    .marks {
+      width: 100%;
+      top: 20px;
+      position: absolute;
+      label {
+        width: 25%;
+        display: block;
+        text-align: center;
+        position: absolute;
+        margin-left: -12.5%;
+        div {
+          position: absolute;
+          left: 50%;
+          top: -5px;
+          height: 20px;
+          border-left: solid 1px #fff; 
+          -webkit-box-shadow:0px 0px 2px 1px rgba(0, 0, 0, .15);
+          box-shadow:0px 0px 2px 1px rgba(0, 0, 0, .15);
+        }
+      }
+    }
+  }
+  .panel-title {
+    position: relative;
+    a {
+      position: absolute;
+      right: 0;
+      color: #428bca;
+    }
+  }
+  .panel-body.total{
+    .progress {
+      margin: 0;
+    }
+  }
+  .panel-body.queues {
+    border-top: 1px solid #dddddd;
+    background-color: #f5f5f5;
+  }
+  .queue-capacity{
+    border-bottom: 1px solid #dddddd;
+    padding-bottom: 8px;
+    padding-top: 8px;
+    &.active {
+      .progress {
+        -webkit-box-shadow: 0px 0px 0px #888888;
+        -moz-shadow: 0px 0px 0px #888888;
+        box-shadow: 0px 0px 0px #888888;
+        transition: box-shadow .25s linear 0s;
+      }
+        .progress.in {
+          -webkit-box-shadow: 3px 5px 5px #888888;
+          -moz-shadow: 3px 5px 5px #888888;
+          box-shadow: 3px 5px 5px #888888;
+        }
+    }
+    .form-inline .form-group {
+      display: inline-block;
+      margin-bottom: 0;
+      vertical-align: top;
+    }
+    .help-block {
+      display: inline;
+    }
+    /*input {
+      width: auto;
+    }*/
+  }
+}
+
+.queue-heading-row {
+  h3 {
+    margin:10px;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
new file mode 100644
index 0000000..18c06a7
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
@@ -0,0 +1,36 @@
+/**
+ * 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.
+ */
+
+// load templates
+
+require('templates/error');
+require('templates/trace');
+require('templates/loading');
+require('templates/queue');
+require('templates/queues');
+require('templates/error');
+require('templates/queues/index');
+
+require('templates/capacityEditForm');
+require('templates/schedulerPanel');
+
+require('templates/components/capacityBar');
+require('templates/components/totalCapacity');
+require('templates/components/queueListItem');
+require('templates/components/pathInput');
+require('templates/components/userGroupInput');

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs
new file mode 100644
index 0000000..9442973
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.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 {{bind-attr class=":form-inline :capacity-edit-form " }} role="form">
+  <div {{bind-attr class=":form-group" }}>
+    <label  class="control-label">Capacity: </label>
+    {{capacity-input class='input-sm' value=this.capacity totalCapacity=view.totalCapacity queue=this maxVal=100}}
+    
+  </div>
+  <div {{bind-attr class=":form-group this.isValid::has-error" }}>
+    <label class="control-label">Maximum capacity: </label>
+    {{max-capacity-input class='input-sm' value=this.maximum_capacity totalCapacity=view.totalCapacity queue=this maxVal=100}}
+    {{#each this.errors.maximum_capacity}}
+      <span class="help-block">
+        {{message}}
+      </span>
+    {{/each}}
+  </div>
+</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs
new file mode 100644
index 0000000..d860cc4
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs
@@ -0,0 +1,35 @@
+{{!
+* 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="progress progress-labelled" data-label-max="100" data-label-step="25" style="position: relative;">
+    <div {{bind-attr style="capacityWidth"  class=":progress-bar warn:progress-bar-danger:progress-bar-success"}}>
+      <span>
+        {{capacityValue}}%
+      </span>
+    </div>
+      <div class="progress-bar progress-bar-warning" {{bind-attr style="maxCapacityWidth"}}>
+      </div>
+    
+    <div class="marks">
+      <label style="left: 25%;"><div></div></label>
+      <label style="left: 50%;"><div></div></label>
+      <label style="left: 75%;"><div></div></label>
+    </div>
+
+</div>
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs
new file mode 100644
index 0000000..ec4ec4c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs
@@ -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.
+}}
+
+<div class="input-group path-input">
+  {{view inputFieldView pathSource=pathMap value=path}}
+  <span class="input-group-btn">
+    <button {{action cancel}} class="btn btn-danger" type="button">
+      <i class="fa fa-times"></i>
+    </button>
+    <button {{action add}} class="btn btn-success" type="button">
+      <i class="fa fa-check"></i>
+    </button>
+  </span>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs
new file mode 100644
index 0000000..9c23541
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs
@@ -0,0 +1,60 @@
+{{!
+* 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 view.leaf}}
+  {{#link-to "queue" this classNameBindings=":list-group-item overCapacity:list-group-item-danger isNew:list-group-item-info" }}
+    <div class="col-md-offset-{{unbound this.depth}} col-sm-offset-{{unbound this.depth}} col-xs-offset-{{unbound this.depth}}">
+      
+    {{name}} ({{capacity}}%)
+
+    <span class="badge pull-right">
+      {{#if overCapacity}}
+        <i class="fa fa-fw fa-lg red fa-warning"></i>
+      {{/if}}
+      {{#if isNewQueue }}
+        {{#if isSaving}}
+        <i class="fa fa-fw fa-lg gray fa-spinner fa-spin"></i>
+        {{else}}
+        <i class="fa fa-fw fa-lg blue fa-plus"></i> 
+        {{/if}}
+      {{else}}
+        {{#if isError}}
+          {{#if isSaving}}
+            <i class="fa fa-fw fa-lg gray fa-spinner fa-spin"></i>
+          {{else}}
+            <span> queue was not saved </span> <i class="fa fa-fw fa-lg red fa-warning"></i>
+          {{/if}}
+        {{else}}    
+          {{#if isDirty}}
+            {{#if isSaving}}
+              <i class="fa fa-fw fa-lg gray fa-spinner fa-spin"></i>
+            {{else}}
+              <i class="fa fa-fw fa-lg blue fa-pencil"></i>
+            {{/if}}
+          {{else}}
+            <i class="fa fa-fw fa-lg green fa-check"></i> 
+          {{/if}}
+        {{/if}}
+      {{/if}}
+    </span>
+    
+    </div>
+  {{/link-to}}
+
+  {{recurce-queues depth=view.childDepth parent=this.path}}
+{{/each}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs
new file mode 100644
index 0000000..c934081
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs
@@ -0,0 +1,72 @@
+{{!
+* 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="panel panel-default panel-capacity">
+  <div class="panel-heading">
+  <div class="panel-title">
+    <strong>Capacity</strong>
+    <a href="#" {{action 'toggleEdit'}} class="text-right"> 
+      {{#if view.isEdit}}
+        <i class="fa fa-edit">Hide edit</i> 
+      {{else}}
+        <i class="fa fa-edit">Show edit</i> 
+      {{/if}}
+    </a>
+  </div>
+  </div>
+  <div class="panel-body total">
+    TOTAL
+    {{capacity-bar capacityValue=totalCapacity maxCapacityValue=totalCapacity warn=leafQueues.firstObject.overCapacity}}
+  </div>
+  <div class="panel-body queues">
+    {{#each leafQueues}}
+      <div {{bind-attr class=":queue-capacity this.isCurrent:active"}}>
+        <p>
+          {{this.name}} {{#if isCurrent}} <span class="label label-default">Current</span> {{/if}}
+        </p>
+        {{capacity-bar capacityValue=this.capacity maxCapacityValue=this.maximum_capacity warn=this.overCapacity}}
+        {{render "capacityEditForm" this}}
+      </div>
+    {{/each}}
+    {{#each newLeafQueues}}
+      <div {{bind-attr class=":queue-capacity :new-queue this.isCurrent:active"}} >
+        <div class="input-row row" >
+          <div class="col-md-5">
+            <div class="input-group">
+              {{view view.newQueueNameField value=this.name queue=this placeholder="Enter queue name..."}}
+              <span class="input-group-btn">
+                <button {{action "deleteQueue" this}} {{bind-attr class=":btn :btn-danger"}} type="button">Cancel</button>
+                <button {{action "createQueue" this}} {{bind-attr class=":btn :btn-default this.isValid::disabled"}} type="button">Create</button>
+              </span>
+            </div>
+            {{#each this.errors.path}}
+              <p class="help-block red">{{this.message}}</p>
+            {{/each}}
+          </div>
+        </div>
+        {{capacity-bar capacityValue=this.capacity maxCapacityValue=this.maximum_capacity warn=this.overCapacity}}
+        {{render "capacityEditForm" this}}
+      </div>
+    {{/each}}
+    {{#if currentQueue.parentPath}}
+    <div class="queue-capacity" >
+      <button {{action "addQueue" currentQueue.parentPath}} {{bind-attr class=":btn :btn-default :btn-block hasNew:disabled"}}><i class="fa fa-plus"></i>  Add queue</button>
+    </div>
+    {{/if}}
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs
new file mode 100644
index 0000000..fab7ea8
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.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.
+}}
+
+<div class="user-group-input form-group has-feedback "> 
+  <div class="col-sm-4 control-label">
+    Users:
+  </div> 
+  <div class="col-sm-8"> 
+    {{input keyDown=noSpace disabledBinding="disabled" class="form-control input-sm" value=users placeholder="Comma-separated list of users"}}
+    <i class="fa fa-user form-control-feedback"></i>
+  </div> 
+</div> 
+<div class="form-group has-feedback user-group-input">
+  <div class="col-sm-4 control-label">
+    Groups:
+  </div> 
+  <div class="col-sm-8"> 
+    {{input keyDown=noSpace disabledBinding="disabled" class="form-control input-sm" value=groups placeholder="Comma-separated list of groups"}} 
+    <i class="fa fa-users form-control-feedback"></i>
+  </div> 
+</div>
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs
new file mode 100644
index 0000000..a45c1e7
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs
@@ -0,0 +1,35 @@
+{{!
+* 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="panel panel-danger">
+  <div class="panel-heading">
+    <div class="text-center">
+      <strong>{{content.status}}</strong>  {{content.message}}
+      {{#if content.trace}}
+        <a data-toggle="collapse" class="btn btn-danger btn-xs" href="#collapseOne">Trace <span class="caret"></span></a>
+      {{/if}}
+    </div>
+  </div>
+  <div id="collapseOne" class="panel-collapse collapse">
+    <div class="panel-body">
+      <pre>
+        {{content.trace}}
+      </pre>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs
new file mode 100644
index 0000000..8017bcf
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.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.
+}}
+
+<div class="spinner spinner-bg"></div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs
new file mode 100644
index 0000000..f92eedd
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs
@@ -0,0 +1,229 @@
+{{!
+* 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="well">
+  
+  <div class="row queue-heading-row">
+      <div class="col-md-12">
+          {{#if content.isNew}}
+            <div class="input-group">
+              {{focus-input value=content.name class="form-control" classBinding="content.isValid::input-error" action="createQ" revert="delQ" placeholder="Enter queue name..."}}
+              <span class="input-group-btn">
+                <button {{action "delQ" content target="controllers.queues"}} {{bind-attr class=":btn :btn-danger"}} type="button">Cancel</button>
+                <button {{action "createQ" content target="controllers.queues"}} {{bind-attr class=":btn :btn-default content.isValid::disabled"}} type="button">Create</button>
+              </span>
+            </div>
+            {{else}}
+              {{#unless isRenaming}}
+                <h3>
+                  {{content.name}}
+                  {{#unless isRoot}}
+                  <small>
+                    <a href="#" {{action "renameQ" 'ask'}} class="">
+                      <i class="fa fa-edit"></i>
+                    </a>
+                  </small>
+                  <small>
+                    {{comfirm-delete action="delQ" param=content}}
+                  </small>
+                  {{/unless}}
+                </h3>
+              {{else}}
+              <div class="input-group">
+                {{focus-input value=content.name class="form-control" action="renameQ" revert="renameQ" classBinding="content.isValid::input-error" placeholder="Enter queue name..."}}
+                <span class="input-group-btn">
+                  <button {{action "renameQ" 'cancel'}} {{bind-attr class=":btn :btn-danger"}} type="button">Cancel</button>
+                  <button {{action "renameQ" 'rename'}} {{bind-attr class=":btn :btn-default content.isValid::disabled"}} type="button">Rename</button>
+                </span>
+              </div>
+              {{/unless}}
+          {{/if}}
+            {{#each pathErrors}}
+                <p class="help-block red">{{this}}</p>
+            {{/each}}
+          <h4 ><small>{{content.path}}</small>
+            <div class="btn-group btn-group-xs" data-toggle="buttons" >
+              <label  {{action 'setState' 'running'}} {{bind-attr class=":btn isRunning:btn-success:btn-default isRunning:active" }}>
+                <input type="radio" name="options"> Running
+              </label>
+              <label  {{action 'setState' 'stopped'}} {{bind-attr class=":btn isRunning:btn-default:btn-danger isRunning::active" }}>
+                <input type="radio" name="options"> Stopped
+              </label>
+            </div>
+          </h4>
+      </div>
+  </div>
+  <div class="row queue-capacity-row">
+    <div class="col-md-12">
+      {{total-capacity 
+        currentQueue=content 
+        allQueues=allQueues 
+        allQueuesArranged=allQueuesArranged 
+        addQueue="addQ" 
+        createQueue="createQ" 
+        deleteQueue="delQ" 
+        hasNew=controllers.queues.hasNewQueue
+      }}
+    </div>
+  </div>
+  <div class="row queue-acl-row">
+    <div class="col-md-6">
+      <div class="panel panel-default panel-capacity">
+        <div class="panel-heading">
+          <div class="panel-title">
+            Access control
+            <a href="#" {{action 'toggleEditACL'}} class="text-right"> 
+              {{#if isEditACL}}
+                <small><i class="fa fa-edit">  Hide edit</i> </small>
+              {{else}}
+                <small><i class="fa fa-edit">Show edit</i> </small>
+              {{/if}}
+            </a>
+          </div>
+        </div>
+        <div class="panel-body">
+          <form class="form-horizontal form-acl" role="form">
+          {{#if isEditACL}}
+
+            <div class="form-group row">
+              <label class="col-lg-6 col-md-6 col-sm-4 col-xs-5 control-label">Administer Queue ACL</label>
+              <div class="col-lg-6 col-md-6 col-sm-8 col-xs-7">
+                <div class="btn-group btn-group-xs" data-toggle="buttons">
+                  {{radio-button label="Anyone" selectionBinding="acl_administer_queue" value="*"}}
+                  {{radio-button label="Custom" selectionBinding="acl_administer_queue" value="custom"}}
+                </div>
+                {{#if aaq_dirty}}
+                  <a {{action 'rollbackProp' 'acl_administer_queue'}} href="#"><i class="fa fa-undo"></i></a>
+                {{/if}}
+              </div>
+            </div>
+            {{#unless aaq_anyone}}
+              {{user-group-input ug=content.acl_administer_queue disabled=aaq_anyone}}
+            {{/unless}}
+
+            <div class="form-group row">
+              <label class="col-lg-6 col-md-6 col-sm-4 col-xs-5 control-label">Administer Jobs ACL</label>
+              <div class="col-lg-6 col-md-6 col-sm-8 col-xs-7">
+                <div class="btn-group btn-group-xs" data-toggle="buttons">
+                  {{radio-button label="Anyone" selectionBinding="acl_administer_jobs" value="*"}}
+                  {{radio-button label="Custom" selectionBinding="acl_administer_jobs" value="custom"}}
+                </div>
+                {{#if aaj_dirty}}
+                  <a {{action 'rollbackProp' 'acl_administer_jobs'}} href="#"><i class="fa fa-undo"></i></a>
+                {{/if}}
+              </div>
+            </div>
+            {{#unless aaj_anyone}}
+              {{user-group-input ug=content.acl_administer_jobs disabled=aaj_anyone}}
+            {{/unless}}
+
+
+            <div class="form-group row">
+              <label class="col-lg-6 col-md-6 col-sm-4 col-xs-5 control-label">Submit Applications ACL</label>
+              <div class="col-lg-6 col-md-6 col-sm-8 col-xs-7">
+                <div class="btn-group btn-group-xs" data-toggle="buttons">
+                  {{radio-button label="Anyone" selectionBinding="acl_submit_applications" value="*"}}
+                  {{radio-button label="Custom" selectionBinding="acl_submit_applications" value="custom"}}
+                </div>
+                {{#if asa_dirty}}
+                  <a {{action 'rollbackProp' 'acl_submit_applications'}} href="#"><i class="fa fa-undo"></i></a>
+                {{/if}}
+              </div>
+            </div>
+            {{#unless asa_anyone}}
+              {{user-group-input ug=content.acl_submit_applications disabled=asa_anyone}}
+            {{/unless}}
+            
+          {{else}}
+            <div class="form-group">
+              <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Administer Queue ACL</label>
+              <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+               <p class="form-control-static">
+                {{escapeACL content.acl_administer_queue}}
+               </p> 
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Administer Jobs ACL</label>
+              <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+               <p class="form-control-static">
+                {{escapeACL content.acl_administer_jobs}}
+               </p> 
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Submit Applications ACL</label>
+              <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+               <p class="form-control-static">
+                {{escapeACL content.acl_submit_applications}}
+               </p> 
+              </div>
+            </div>
+          {{/if}}
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <div class="col-md-6">
+      <div class="panel panel-default panel-capacity">
+        <div class="panel-heading">
+          <div class="panel-title">
+            Resource Allocation
+            <a href="#" {{action 'toggleEditRA'}} class="text-right"> 
+              {{#if isEditRA}}
+                <small><i class="fa fa-edit">  Hide edit</i> </small>
+              {{else}}
+                <small><i class="fa fa-edit">Show edit</i> </small>
+              {{/if}}
+            </a>
+          </div>
+        </div>
+        <div class="panel-body">
+          <form class="form-horizontal" role="form">
+            <div class="form-group">
+              <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">User Limit Factor</label>
+              <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+              {{#if isEditRA}}
+                {{int-input value=content.user_limit_factor class="input-sm"}}
+              {{else}}
+                <p class="form-control-static">{{content.user_limit_factor}}</p>
+              {{/if}}
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Minimum User Limit</label>
+              <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+                {{#if isEditRA}}  
+                  <div class="input-group">
+                    {{int-input value=content.minimum_user_limit_percent class="input-sm" maxVal=100}}
+                    <span class="input-group-addon">%</span>
+                  </div>
+                {{else}}
+                  <p class="form-control-static">{{content.minimum_user_limit_percent}} %</p>
+                {{/if}}
+              </div>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>