Browse Source

AMBARI-7509. Slider View: Create Slider App wizard should have entries for multiple new features. (onechiporenko)

Oleg Nechiporenko 11 years ago
parent
commit
9074f83574

+ 23 - 29
contrib/views/slider/src/main/resources/ui/app/controllers/createAppWizard/step1_controller.js

@@ -28,12 +28,6 @@ App.CreateAppWizardStep1Controller = Ember.Controller.extend({
    */
   newApp: null,
 
-  /**
-   * Name for new App
-   * @type {String}
-   */
-  newAppName: '',
-
   /**
    * List of available types for App
    * @type {Array}
@@ -62,10 +56,7 @@ App.CreateAppWizardStep1Controller = Ember.Controller.extend({
    * Define if there are existing App types
    * @type {Boolean}
    */
-  isAppTypesError: function(){
-    return !this.get('availableTypes.content.length');
-  }.property('availableTypes.content.length'),
-
+  isAppTypesError: Em.computed.equal('availableTypes.content.length', 0),
   /**
    * Define description depending on selected App type
    * @type {string}
@@ -77,32 +68,36 @@ App.CreateAppWizardStep1Controller = Ember.Controller.extend({
 
   /**
    * Define if submit button is disabled
-   * <code>newAppName</code> should pass validation and be not empty
+   * <code>newApp.name</code> should pass validation and be not empty
    * @type {bool}
    */
   isSubmitDisabled: function () {
-    return !this.get('newAppName') || this.get('isNameError') || this.get('isAppTypesError');
-  }.property('newAppName', 'isNameError', 'isAppTypesError'),
-
-  /**
-   * Load all required data for step
-   * @method loadStep
-   */
-  loadStep: function () {
-    this.initializeNewApp();
-    this.loadAvailableTypes();
-  },
+    return !this.get('newApp.name') || this.get('isNameError') || this.get('isAppTypesError');
+  }.property('newApp.name', 'isNameError', 'isAppTypesError'),
 
   /**
    * Initialize new App and set it to <code>newApp</code>
    * @method initializeNewApp
    */
   initializeNewApp: function () {
-    var newApp = Ember.Object.create({
-      name: '',
-      appType: null,
-      configs: {}
+    var app = this.get('appWizardController.newApp'),
+      properties = Em.A(['name', 'includeFilePatterns', 'excludeFilePatterns', 'frequency', 'queueName', 'specialLabel', 'selectedYarnLabel']),
+      newApp = Ember.Object.create({
+        appType: null,
+        configs: {}
+      });
+
+    properties.forEach(function(p) {
+      newApp.set(p, '');
     });
+    newApp.set('selectedYarnLabel', 0);
+
+    if (app) {
+      properties.forEach(function(p) {
+        newApp.set(p, app.get(p));
+      });
+    }
+
     this.set('newApp', newApp);
   },
 
@@ -121,7 +116,7 @@ App.CreateAppWizardStep1Controller = Ember.Controller.extend({
    * @return {Boolean}
    */
   nameValidator: function () {
-    var newAppName = this.get('newAppName');
+    var newAppName = this.get('newApp.name');
     if (newAppName) {
       // new App name should consist only of letters, numbers, '-', '_' and first character should be a letter
       if (!/^[A-Za-z][A-Za-z0-9_\-]*$/.test(newAppName)) {
@@ -138,7 +133,7 @@ App.CreateAppWizardStep1Controller = Ember.Controller.extend({
     }
     this.set('isNameError', false);
     return true;
-  }.observes('newAppName'),
+  }.observes('newApp.name'),
 
   /**
    * Save new application data to wizard controller
@@ -147,7 +142,6 @@ App.CreateAppWizardStep1Controller = Ember.Controller.extend({
   saveApp: function () {
     var newApp = this.get('newApp');
     newApp.set('appType', this.get('selectedType'));
-    newApp.set('name', this.get('newAppName'));
     newApp.set('configs', this.get('selectedType.configs'));
     newApp.set('predefinedConfigNames', Em.keys(this.get('selectedType.configs')));
     this.set('appWizardController.newApp', newApp);

+ 16 - 15
contrib/views/slider/src/main/resources/ui/app/controllers/createAppWizard/step2_controller.js

@@ -24,7 +24,8 @@ App.CreateAppWizardStep2Controller = Ember.ArrayController.extend({
 
   /**
    * List of app type components
-   * @type {App.SliderAppTypeComponent}
+   * @type {Em.Object[]}
+   * @see <code>loadTypeComponents</code> for information about elements type
    */
   content: [],
 
@@ -53,17 +54,7 @@ App.CreateAppWizardStep2Controller = Ember.ArrayController.extend({
    * <code>isError</code> should be true
    * @type {bool}
    */
-  isSubmitDisabled: function () {
-    return this.get('isError');
-  }.property('isError'),
-
-  /**
-   * Load all required data for step
-   * @method loadStep
-   */
-  loadStep: function () {
-    this.initializeNewApp();
-  },
+  isSubmitDisabled: Em.computed.alias('isError'),
 
   /**
    * Initialize new App to use it scope of controller
@@ -75,16 +66,26 @@ App.CreateAppWizardStep2Controller = Ember.ArrayController.extend({
     this.loadTypeComponents();
   },
 
+  /**
+   * @type {Em.Object}
+   */
+  typeComponent: Em.Object.extend({
+    yarnLabelChecked: false,
+    yarnLabelNotChecked: Em.computed.not('yarnLabelChecked'),
+    yarnLabel: ''
+  }),
+
   /**
    * Fill <code>content</code> with objects created from <code>App.SliderAppTypeComponent</code>
    * @method loadTypeComponents
    */
   loadTypeComponents: function () {
-    var content = [];
-    var allTypeComponents = this.get('newApp.appType.components');
+    var content = [],
+        component = this.get('typeComponent'),
+        allTypeComponents = this.get('newApp.appType.components');
     if (allTypeComponents && allTypeComponents.get('length')) {
       allTypeComponents.forEach(function (typeComponent) {
-        content.push(Ember.Object.create({
+        content.push(component.create({
           displayName: typeComponent.get('displayName'),
           name: typeComponent.get('name'),
           priority: typeComponent.get('priority'),

+ 19 - 0
contrib/views/slider/src/main/resources/ui/app/routes/create_app_wizard.js

@@ -33,3 +33,22 @@ App.CreateAppWizardRoute = Ember.Route.extend({
     }
   }
 });
+
+App.CreateAppWizardStep1Route = Em.Route.extend({
+
+  setupController: function(controller, model) {
+    controller.set('model', model);
+    controller.initializeNewApp();
+    controller.loadAvailableTypes();
+  }
+
+});
+
+App.CreateAppWizardStep2Route = Em.Route.extend({
+
+  setupController: function(controller, model) {
+    controller.set('model', model);
+    controller.initializeNewApp();
+  }
+
+});

+ 276 - 0
contrib/views/slider/src/main/resources/ui/app/styles/app.less

@@ -0,0 +1,276 @@
+/**
+ * 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.
+ */
+
+@import-once 'common.less';
+
+.app-page {
+  .wrap-tabs {
+    margin-top: 30px;
+  }
+  .quick-links-wrapper {
+    .nav-pills.move {
+      float: right;
+      width:135px;
+      &>li {
+        position: absolute;
+      }
+    }
+    .dropdown-submenu {
+      &> a:after {
+        border-left-color: #333;
+      }
+    }
+    .nav li.dropdown.open {
+      .dropdown-toggle{
+        color: #005580;
+        background-color: #eeeeee;
+        border-color: #eeeeee;
+        -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+        -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+        box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+      }
+      a:hover .caret {
+        border-top-color: #005580;
+        border-bottom-color: #005580;
+      }
+      .caret {
+        border-top-color: #005580;
+        border-bottom-color: #005580;
+      }
+    }
+  }
+}
+
+.app_summary {
+  padding-left: 0;
+  table {
+    &.no-borders {
+      td {
+        border-width: 0;
+      }
+    }
+    td:nth-child(2) span{
+      word-break: break-all;
+    }
+  }
+  .panel-heading {
+    font-weight: 700;
+  }
+  .panel-summary {
+    min-height: 400px;
+    td:first-child {
+      text-align: right;
+    }
+  }
+  .panel-components {
+    .status {
+      display: inline-block;
+      width: 25px;
+    }
+    .icon-ok-sign {
+      color: #5ab400;
+    }
+    .icon-warning-sign {
+      color: #ff0000;
+    }
+    .panel-body{
+      /*max-height: 400px;
+      overflow-x: auto;*/
+    }
+  }
+  .panel-link {
+    margin-top: -5px;
+    margin-right: -7px;
+  }
+}
+
+.chart-container {
+  cursor: default;
+
+  position: relative;
+  margin: 20px 15px 0px 15px;
+
+  .chart {
+    position: relative;
+    z-index: 1;
+  }
+  .chart-y-axis {
+    position: absolute;
+    top: 0;
+    bottom: 0px;
+    width: 100px;
+    z-index: 2;
+    margin-top: 15px;
+  }
+  .chart-x-axis {
+    position: absolute;
+    top: 180px;
+    left: 35%;
+    width: 30%;
+    z-index: 2;
+  }
+  .x_tick {
+    margin-top: 5px;
+    .title {
+      padding: 0 2px 0 2px;
+      opacity: 1 !important;
+      top: 148px;
+    }
+  }
+  svg {
+    g {
+      g:nth-child(1) {
+        display: none;
+      }
+    }
+  }
+  text {
+    font-weight: 700;
+    opacity: 1 !important;
+  }
+  .chart-legend {
+    font-family: 'Courier New';
+    position: absolute;
+    top: 180px;
+    z-index: 3;
+  }
+  .rickshaw_legend {
+    background-color: #999 !important;
+    li:hover {
+      background-color: #999 !important;
+    }
+  }
+  .rickshaw_legend:empty {
+    padding: 0;
+  }
+  .rickshaw_graph {
+    .x_tick {
+      .title {
+        bottom: -6px;
+        opacity: 0.75;
+      }
+    }
+  }
+  .chart-overlay {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    width: 100%;
+    z-index: 5;
+  }
+  .chart-title {
+    text-align: center;
+    margin-top: 20px;
+  }
+}
+
+.app_configs {
+  a.accordion-toggle {
+    display: block;
+  }
+  .panel-heading{
+    .icon{
+      width: 24px;
+    }
+  }
+  .row {
+    .table-row();
+    textarea {
+      height: 200px;
+      padding-left: 5px;
+      padding-right: 5px;
+      resize: none;
+    }
+    textarea[disabled] {
+      cursor: not-allowed;
+      background-color: #eeeeee;
+    }
+    input[disabled] {
+      cursor: not-allowed;
+      background-color: #eeeeee;
+    }
+    .property-name {
+      word-wrap: break-word;
+    }
+  }
+}
+
+.app-alerts {
+  overflow-y: auto;
+  ul {
+    padding-left: 0;
+    margin-bottom: 0;
+  }
+  li {
+    border-bottom: 1px solid #eee;
+    list-style: none;
+    padding: 5px;
+    background-position: 14px 9px;
+    background-repeat: no-repeat;
+    .date-time {
+      float: right;
+    }
+    p {
+      margin-bottom: 2px;
+    }
+    .container-fluid {
+      padding-left: 10px;
+      padding-right: 10px;
+    }
+    .title {
+      font-weight: normal;
+      font-size: 13px;
+    }
+    .row-fluid [class*="span"] {
+      min-height: 0px;
+    }
+    .date-time {
+      color: #999;
+      font-style: italic;
+      font-size: small;
+      text-align: right;
+    }
+    .message {
+      font-size: 12px;
+      color: #777;
+      word-break: break-all;
+      padding-right: 15px;
+    }
+    .serviceLink {
+      padding-left: 7px;
+    }
+  }
+  .icon-ok {
+    color: #5AB400;
+  }
+  .icon-remove {
+    color: #FF4B4B;
+  }
+  .icon-warning-sign {
+    color: #FDB82F;
+  }
+  .icon-question-sign {
+    color: #999;
+  }
+}
+
+.flex-popup {
+  .row {
+    .table-row();
+  }
+}

File diff suppressed because it is too large
+ 0 - 270
contrib/views/slider/src/main/resources/ui/app/styles/application.less


File diff suppressed because it is too large
+ 217 - 0
contrib/views/slider/src/main/resources/ui/app/styles/apps-table.less


+ 102 - 0
contrib/views/slider/src/main/resources/ui/app/styles/common.less

@@ -0,0 +1,102 @@
+/**
+ * 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-row() {
+  margin: 10px 0;
+}
+
+html {
+  overflow-y: scroll;
+}
+.icon-minus-sign {
+  color: #FF4B4B;
+}
+.tooltip {
+  z-index: 1500;
+}
+.popover {
+  max-width: 800px;
+  &.bottom {
+    left: 5px;
+  }
+}
+
+.slider-name-popover {
+  max-width: 600px !important;
+  .row {
+    .table-row();
+  }
+}
+
+a {
+  cursor: pointer;
+}
+
+select {
+  background-color: #ffffff;
+  border: 1px solid #cccccc;
+  color: #555555;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+}
+
+.well {
+  border-radius: 0px;
+  -webkit-border-radius: 0px;
+  -moz-border-radius: 0px;
+  -webkit-box-shadow: none;
+  -moz-box-shadow: none;
+  box-shadow: none;
+}
+
+.nav-pills {
+  &>li {
+    &> a {
+      border-radius: 0px;
+      -webkit-border-radius: 0px;
+      -moz-border-radius: 0px;
+    }
+    &.active {
+      &> a, &> a:hover, &> a:focus {
+        background-color: #666666;
+
+      }
+    }
+  }
+}
+
+.slider-header {
+  overflow: hidden;
+  .box-header {
+    padding-top: 20px;
+  }
+}
+
+
+
+.modal {
+  overflow-y: hidden;
+}
+.modal-backdrop {
+  opacity: 0.8;
+}
+.modal-backdrop.in {
+  opacity:0;
+}

+ 164 - 0
contrib/views/slider/src/main/resources/ui/app/styles/old-bootstrap.less

@@ -0,0 +1,164 @@
+/**
+ * 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.
+ */
+
+
+.btn-area {
+  .btn{
+    display: inline-block;
+    padding: 4px 14px;
+    margin-bottom: 0;
+    font-size: 14px;
+    line-height: 20px;
+    color: #333333;
+    text-align: center;
+    text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+    vertical-align: middle;
+    cursor: pointer;
+    background-color: #f5f5f5;
+    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+    background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+    background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+    background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+    background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+    background-repeat: repeat-x;
+    border: 1px solid #bbbbbb;
+    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+    border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+    border-bottom-color: #a2a2a2;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+    -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+  }
+  .btn:hover {
+    color: #333333;
+    text-decoration: none;
+    background-color: #e6e6e6;
+    background-position: 0 -15px;
+    -webkit-transition: background-position 0.1s linear;
+    -moz-transition: background-position 0.1s linear;
+    -o-transition: background-position 0.1s linear;
+    transition: background-position 0.1s linear;
+  }
+  .btn.active, .btn:active {
+    background-color: #e6e6e6;
+    background-color: #d9d9d9 \9;
+    background-image: none;
+    outline: 0;
+    -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+    -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+  }
+  .btn-success {
+    color: #ffffff;
+    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+    background-color: #5bb75b;
+    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+    background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+    background-image: -o-linear-gradient(top, #62c462, #51a351);
+    background-image: linear-gradient(to bottom, #62c462, #51a351);
+    background-image: -moz-linear-gradient(top, #62c462, #51a351);
+    background-repeat: repeat-x;
+    border-color: #51a351 #51a351 #387038;
+    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+    filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+    filter: progid:dximagetransform.microsoft.gradient(enabled=false);
+  }
+  .btn.btn-success:hover, .btn-success:active, .btn-success.active, .btn-success.disabled, .btn-success[disabled] {
+    color: #ffffff;
+    background-color: #51a351;
+  }
+}
+
+.modal-header {
+  padding: 9px 15px;
+  border-bottom: 1px solid #eee;
+}
+.modal-title {
+  line-height: 30px;
+  font-size: 24px;
+  font-family: inherit;
+  font-weight: bold;
+  color: inherit;
+  text-rendering: optimizelegibility;
+}
+.modal-body{
+  padding: 15px;
+}
+.modal-footer {
+  margin-top: 0px;
+  padding: 14px 15px 15px;
+  margin-bottom: 0;
+  text-align: right;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  -webkit-border-radius: 0 0 6px 6px;
+  -moz-border-radius: 0 0 6px 6px;
+  border-radius: 0 0 6px 6px;
+  -webkit-box-shadow: inset 0 1px 0 #ffffff;
+  -moz-box-shadow: inset 0 1px 0 #ffffff;
+  box-shadow: inset 0 1px 0 #ffffff;
+
+  .btn-area();
+
+}
+.slider-app-title {
+  font-style: italic;
+  cursor: pointer;
+}
+
+.api-error {
+  max-height: 403px;
+  word-wrap: break-word;
+  overflow: auto;
+}
+
+.dropdown-submenu {
+  position:relative;
+}
+.dropdown-submenu>.dropdown-menu {
+  top:0;
+  left:-100%;
+  margin-top:-6px;
+  margin-left:-1px;
+  -webkit-border-radius:6px 0 6px 6px;
+  -moz-border-radius:6px 0 6px 6px;
+  border-radius:6px 0 6px 6px;
+}
+.dropdown-submenu:hover>.dropdown-menu {
+  display:block;
+}
+.dropdown-submenu>a:before {
+  display:block;
+  content:" ";
+  float:left;
+  width:0;
+  height:0;
+  border-color:transparent;
+  border-style:solid;
+  border-width:5px 5px 5px 0px;
+  border-right-color:#cccccc;
+  margin-top:5px;
+  margin-left:-10px;
+}
+.dropdown-submenu:hover>a:after {
+  border-left-color:#ffffff;
+}

+ 205 - 0
contrib/views/slider/src/main/resources/ui/app/styles/wizard.less

@@ -0,0 +1,205 @@
+/**
+ * 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.
+ */
+
+@import-once 'common.less';
+
+#createAppWizard {
+  width: 80%;
+  margin: 0 0 auto;
+  left: 10%;
+  .wizard-nav {
+    padding-left: 0px;
+  }
+  h5 {
+    font-weight: bold;
+  }
+  .slider-modal-body {
+    height: 90%;
+    max-height: 90%;
+    .wizard-content{
+      min-height: 95%;
+      padding-bottom: 49px;
+      background-color: #ffffff;
+    }
+    .container-fluid {
+      height: 100%;
+      .row {
+        height: 100%;
+      }
+      .btn-area {
+        position: absolute;
+        right: 19px;
+        bottom: 19px;
+        left: 19px;
+      }
+    }
+  }
+  .next-btn {
+    margin-left: 5px;
+  }
+  #configs-text-area {
+    margin-bottom: 10px;
+    height: 225px;
+  }
+  #step4 {
+    ul {
+      list-style: none;
+    }
+    pre {
+      margin-left: 30px;
+      max-height: 124px;
+    }
+  }
+  #step2 {
+    .table-container {
+      max-height: 248px;
+      border: 1px solid #e3e3e3;
+      padding: 5px;
+      border-radius: 4px;
+      overflow: hidden;
+      .components-table {
+        width: 100%;
+        border-spacing: 10px;
+        border-collapse: separate;
+        input[type="text"]{
+          width: 100px;
+        }
+      }
+      margin-bottom: 30px;
+    }
+  }
+  #step1 {
+    select {
+      padding: 4px 0;
+    }
+    .row {
+      .table-row();
+    }
+    .app-types-alert {
+      margin-top: 20px;
+    }
+  }
+  .pseudo-label {
+    display: inline-block;
+  }
+  .app-wiz-configs {
+    .accordion-toggle {
+      display: block;
+    }
+    .panel-heading{
+      .icon{
+        width: 23px;
+      }
+    }
+  }
+}
+
+
+.slider-modal {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  z-index: 1050;
+  width: 560px;
+  margin: -250px 0 0 -280px;
+  overflow: auto;
+  background-color: #ffffff;
+  border: 1px solid #999;
+  border: 1px solid rgba(0, 0, 0, 0.3);
+  *border: 1px solid #999;
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+  border-radius: 6px;
+  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+  -webkit-background-clip: padding-box;
+  -moz-background-clip: padding-box;
+  background-clip: padding-box;
+}
+
+.slider-modal.fade {
+  top: -25%;
+  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;
+  -moz-transition: opacity 0.3s linear, top 0.3s ease-out;
+  -o-transition: opacity 0.3s linear, top 0.3s ease-out;
+  transition: opacity 0.3s linear, top 0.3s ease-out;
+}
+
+.slider-modal.fade.in {
+  top: 50%;
+}
+
+.slider-modal-header {
+  padding: 9px 15px;
+  border-bottom: 1px solid #eee;
+}
+
+.slider-modal-header .close {
+  margin-top: 2px;
+}
+
+.slider-modal-header h3 {
+  margin: 0;
+  line-height: 30px;
+}
+
+.slider-modal-body {
+  max-height: 400px;
+  padding: 15px;
+  overflow-y: auto;
+}
+
+.slider-modal-form {
+  margin-bottom: 0;
+}
+
+.slider-modal-footer {
+  padding: 14px 15px 15px;
+  margin-bottom: 0;
+  text-align: right;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  -webkit-border-radius: 0 0 6px 6px;
+  -moz-border-radius: 0 0 6px 6px;
+  border-radius: 0 0 6px 6px;
+  *zoom: 1;
+  -webkit-box-shadow: inset 0 1px 0 #ffffff;
+  -moz-box-shadow: inset 0 1px 0 #ffffff;
+  box-shadow: inset 0 1px 0 #ffffff;
+}
+
+.slider-modal-footer:before,
+.slider-modal-footer:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.modal-footer:after {
+  clear: both;
+}
+
+.slider-modal-footer .btn + .btn {
+  margin-bottom: 0;
+  margin-left: 5px;
+}
+
+.slider-modal-footer .btn-group .btn + .btn {
+  margin-left: -1px;
+}

+ 132 - 24
contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step1.hbs

@@ -16,34 +16,142 @@
 * limitations under the License.
 }}
 <div id="step1">
-  <h4>{{t wizard.step1.header}}</h4>
-  <div class="row">
-    <div class="col-xs-6">
-      {{view view.availableTypesSelect contentBinding="controller.availableTypes" optionLabelPath="content.displayName" multiple="true" class="type-select"}}
+  <form role="form" class="form-horizontal">
+    <!-- Available Applications -->
+    <h3>{{t wizard.step1.header}}</h3>
+    <div class="form-group row">
+      <div class="col-xs-3">
+        <label class="control-label">{{t wizard.step1.appTypes}}</label>
+      </div>
+      <div class="col-xs-7">
+        {{view
+          Em.Select
+          contentBinding="controller.availableTypes"
+          optionLabelPath="content.displayName"
+          class="form-control type-select"
+          valueBinding="controller.selectedType"
+        }}
+      </div>
     </div>
-    <div class="col-xs-6">
-      <div {{bind-attr class=":control-group controller.isNameError:error"}}>
-        <label>{{t common.name}}: {{input id="app-name-input" valueBinding="controller.newAppName"}}</label>
+    <div class="form-group row">
+      <div class="col-xs-3">
+        <label class=" control-label">{{t wizard.step1.description}}</label>
       </div>
-      {{#if controller.isNameError}}
-        <div class="alert alert-danger">
-          {{controller.nameErrorMessage}}
+      <div class="col-xs-7">
+        <span class="pseudo-label control-label">{{controller.typeDescription}}</span>
+      </div>
+    </div>
+    <div class="form-group row">
+      <div class="col-xs-3">
+        <div {{bind-attr class=":control-group controller.isNameError:error"}}>
+          <label class="control-label">{{t common.name}}</label>
         </div>
-      {{/if}}
-      <h5>{{t wizard.step1.description}}:</h5>
-      <p>
-        {{controller.typeDescription}}
-      </p>
+      </div>
+      <div class="col-xs-7">
+        {{input id="app-name-input" class="form-control" valueBinding="controller.newApp.name"}}
+      </div>
     </div>
+    {{#if controller.isNameError}}
+      <div class="row">
+        <div class="col-xs-12 alert alert-danger">
+          {{controller.nameErrorMessage}}
+        </div>
+      </div>
+    {{/if}}
     {{#if controller.isAppTypesError}}
-      <div class="col-xs-12">
-          <div class="alert alert-info app-types-alert">
-              {{t wizard.step1.noAppTypesError}}
-          </div>
+      <div class="row">
+        <div class="col-xs-12 alert alert-info app-types-alert">
+          {{t wizard.step1.noAppTypesError}}
+        </div>
       </div>
     {{/if}}
-  </div>
-  <div class="btn-area">
-    <button class="btn btn-success pull-right next-btn" {{bind-attr disabled="controller.isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
-  </div>
-</div>
+    <!-- Available Applications end -->
+    <!-- Scheduler Options -->
+    <hr />
+    <div class="row">
+      <h3>{{t wizard.step1.schedulerOptions.label}}</h3>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">{{t wizard.step1.schedulerOptions.queueName}}</label>
+      </div>
+      <div class="col-xs-7">
+        {{input class="form-control" valueBinding="controller.newApp.queueName"}}
+      </div>
+    </div>
+    <!-- Scheduler Options end -->
+    <!-- YARN Labels -->
+    <hr />
+    <div class="row">
+      <h3>{{t wizard.step1.yarnLabels.label}}</h3>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">
+          {{view view.radioButton name="yarnLabel" selectionBinding="controller.newApp.selectedYarnLabel" value=0 class="radio-inline"}}
+          {{t wizard.step1.yarnLabels.options.anyHost}}
+        </label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">
+          {{view view.radioButton name="yarnLabel" selectionBinding="controller.newApp.selectedYarnLabel" value=1 class="radio-inline"}}
+          {{t wizard.step1.yarnLabels.options.nonLabeledHost}}
+        </label>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">
+          {{view view.radioButton name="yarnLabel" selectionBinding="controller.newApp.selectedYarnLabel" value=2 class="radio-inline"}}
+          {{t wizard.step1.yarnLabels.options.specifyLabel}}
+        </label>
+      </div>
+      <div class="col-xs-7">
+        {{input type="text" class="form-control" disabledBinding="view.specLabelEnabled" valueBinding="controller.newApp.specialLabel"}}
+      </div>
+    </div>
+    <!-- YARN Labels end -->
+    <!-- Log Aggregation -->
+    <hr />
+    <div class="row">
+      <h3>{{t wizard.step1.logAggregation.label}}</h3>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">{{t wizard.step1.logAggregation.filePatterns.include}}</label>
+      </div>
+      <div class="col-xs-7">
+        {{input class="form-control" valueBinding="controller.newApp.includeFilePatterns"}}
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">{{t wizard.step1.logAggregation.filePatterns.exclude}}</label>
+      </div>
+      <div class="col-xs-7">
+        {{input class="form-control" valueBinding="controller.newApp.excludeFilePatterns"}}
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-xs-3">
+        <label class="control-label">{{t common.frequency}}</label>
+      </div>
+      <div class="col-xs-7">
+        <div class="input-group">
+          {{input class="form-control" valueBinding="controller.newApp.frequency"}}
+          <div class="input-group-addon">{{t common.minutes}}</div>
+        </div>
+      </div>
+    </div>
+    <!-- Log Aggregation end -->
+    <div class="btn-area">
+      <button
+        class="btn btn-success pull-right next-btn"
+        {{bind-attr disabled="controller.isSubmitDisabled"}}
+        {{action submit target="controller"}}>{{t common.next}} &rarr;
+      </button>
+    </div>
+  </form>
+</div>

+ 14 - 9
contrib/views/slider/src/main/resources/ui/app/templates/createAppWizard/step2.hbs

@@ -24,15 +24,10 @@
       <thead>
       <tr>
         <th></th>
-        <th>
-          {{t wizard.step2.table.instances}}
-        </th>
-        <th>
-          {{t wizard.step2.table.memory}}
-        </th>
-        <th>
-          {{t wizard.step2.table.cpu}}
-        </th>
+        <th>{{t wizard.step2.table.instances}}</th>
+        <th>{{t wizard.step2.table.memory}}</th>
+        <th>{{t wizard.step2.table.cpu}}</th>
+        <th colspan="2">{{t wizard.step2.table.yarnLabels}}</th>
       </tr>
       </thead>
       <tbody>
@@ -42,6 +37,16 @@
           <td>{{input valueBinding="numInstances"}}</td>
           <td>{{input valueBinding="yarnMemory"}}</td>
           <td>{{input valueBinding="yarnCPU"}}</td>
+          <td>
+            <div {{bs-bind-tooltip content=view.checkBoxPopover}}>
+              {{input type="checkbox" checkedBinding="yarnLabelChecked" class="checkbox-inline"}}
+            </div>
+          </td>
+          <td>
+            <div {{bs-bind-tooltip content=view.yarnLabelPopover}}>
+              {{input valueBinding="yarnLabel" disabledBinding="yarnLabelNotChecked"}}
+            </div>
+          </td>
         </tr>
       {{/each}}
       </tbody>

+ 16 - 1
contrib/views/slider/src/main/resources/ui/app/translations.js

@@ -54,7 +54,9 @@ Em.I18n.translations = {
     'remove': 'Remove',
     'send': 'Send',
     'error': 'Error',
-    'yarn.app.id': 'YARN Application ID'
+    'yarn.app.id': 'YARN Application ID',
+    'frequency': 'Frequency',
+    'minutes': 'Minutes'
   },
 
   'error.config_is_empty': 'Config <strong>{0}</strong> should not be empty',
@@ -110,7 +112,17 @@ Em.I18n.translations = {
   'wizard.name': 'Create App',
   'wizard.step1.name': 'Select Type',
   'wizard.step1.header': 'Available Applications',
+  'wizard.step1.appTypes': 'Application Types',
   'wizard.step1.description': 'Description',
+  'wizard.step1.schedulerOptions.label': 'Scheduler Options (optional)',
+  'wizard.step1.schedulerOptions.queueName': 'Queue name',
+  'wizard.step1.yarnLabels.label': 'YARN Labels',
+  'wizard.step1.yarnLabels.options.anyHost': 'Any host',
+  'wizard.step1.yarnLabels.options.nonLabeledHost': 'Non-labeled host',
+  'wizard.step1.yarnLabels.options.specifyLabel': 'Specify label',
+  'wizard.step1.logAggregation.label': 'Log Aggregation',
+  'wizard.step1.logAggregation.filePatterns.include': 'Include File Patterns',
+  'wizard.step1.logAggregation.filePatterns.exclude': 'Exclude File Patterns',
   'wizard.step1.typeDescription': 'Deploys {0} cluster on YARN.',
   'wizard.step1.nameFormatError': 'App Name should consist only of letters, numbers, \'-\', \'_\' and first character should be a letter.',
   'wizard.step1.nameRepeatError': 'App with entered Name already exists.',
@@ -120,6 +132,9 @@ Em.I18n.translations = {
   'wizard.step2.table.instances': 'Number of Instances',
   'wizard.step2.table.memory': 'YARN Memory (MB)',
   'wizard.step2.table.cpu': 'YARN	CPU	Cores',
+  'wizard.step2.table.yarnLabels': 'YARN Lables',
+  'wizard.step2.table.popoverCheckbox': 'Check box to enable YARN labels on component',
+  'wizard.step2.table.popoverLabel': 'Provide YARN label to make component run on labeled hosts. Empty value would make component run on non-labeled hosts.',
   'wizard.step2.error.numbers': 'All fields should be filled. Only integer numbers allowed.',
   'wizard.step3.name': 'Configuration',
   'wizard.step3.header.beginning': 'Provide	configuration	details	for	',

+ 25 - 22
contrib/views/slider/src/main/resources/ui/app/views/createAppWizard/step1_view.js

@@ -18,26 +18,29 @@
 
 App.CreateAppWizardStep1View = Ember.View.extend({
 
-  didInsertElement: function () {
-    this.get('controller').loadStep();
-  },
-
-  availableTypesSelect: Ember.Select.extend({
-
-    /**
-     * Forbid user to select more than one App type
-     * Set selected type to <code>controller.selectedType</code>
-     */
-    setSelection: function () {
-      var content = this.get('content');
-      var selection = this.get('selection');
-      if (content.get('length') && !selection.length) {
-        this.set('selection', content.objectAt(0));
-      }
-      if (selection.length > 1) {
-        this.set('selection', [selection[0]])
-      }
-      this.set('controller.selectedType', this.get('selection')[0])
-    }.observes('content.length', 'selection.length', 'selection.@each')
-  })
+  radioButton: Ember.TextField.extend({
+
+    tagName: "input",
+
+    type: "radio",
+
+    attributeBindings: ["name", "type", "value", "checked:checked:"],
+
+    click: function () {
+      this.set("selection", this.get('value'));
+    },
+
+    checked: function () {
+      return this.get("value") == this.get("selection");
+    }.property()
+
+  }),
+
+  /**
+   * Enable "Special-label" text-field only when "spec-label"-radio is checked
+   * @type {bool}
+   */
+  specLabelEnabled: Ember.computed.lt('controller.newApp.selectedYarnLabel', '2')
+
+
 });

+ 12 - 3
contrib/views/slider/src/main/resources/ui/app/views/createAppWizard/step2_view.js

@@ -18,7 +18,16 @@
 
 App.CreateAppWizardStep2View = Ember.View.extend({
 
-  didInsertElement: function () {
-    this.get('controller').loadStep();
-  }
+  /**
+   * Message shown in the checkbox popover
+   * @type {string}
+   */
+  checkBoxPopover: Em.I18n.t('wizard.step2.table.popoverCheckbox'),
+
+  /**
+   * Message shown in the label-input popover
+   * @type {string}
+   */
+  yarnLabelPopover: Em.I18n.t('wizard.step2.table.popoverLabel')
+
 });

Some files were not shown because too many files changed in this diff