This is an automated email from the ASF dual-hosted git repository.

ababiichuk pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 6645b45  AMBARI-24619 Horizontal scroll bar on assign slaves and 
clients page is not convenient for deploy with numerous hosts. (ababiichuk)
6645b45 is described below

commit 6645b45e9bb680e41255671d3e742fe097018de6
Author: ababiichuk <ababiic...@hortonworks.com>
AuthorDate: Tue Sep 11 16:09:53 2018 +0300

    AMBARI-24619 Horizontal scroll bar on assign slaves and clients page is not 
convenient for deploy with numerous hosts. (ababiichuk)
---
 ambari-web/app/styles/common.less               |  17 +++
 ambari-web/app/styles/wizard.less               | 136 ++++++++++++++++--------
 ambari-web/app/templates/wizard/step6.hbs       |  72 ++++++-------
 ambari-web/app/views/wizard/step6_view.js       |  36 +++++--
 ambari-web/test/views/wizard/step6_view_test.js |  21 ++--
 5 files changed, 176 insertions(+), 106 deletions(-)

diff --git a/ambari-web/app/styles/common.less 
b/ambari-web/app/styles/common.less
index 249321b..03e989d 100644
--- a/ambari-web/app/styles/common.less
+++ b/ambari-web/app/styles/common.less
@@ -227,5 +227,22 @@
 @navbar-header-padding-left: 0;
 @navbar-header-font-size: 20px;
 
+/************************************************************************
+* Table styles
+***********************************************************************/
 @table-color: @gray-text;
 @table-font-size: 13px;
+@table-hover-background-color: #E7F6FC;
+@table-hover-border-color: #A7DFF2;
+@table-margin-bottom: 20px;
+@table-footer-color: #999;
+@table-footer-border: 2px solid #EEE;
+@table-cell-padding: 8px;
+
+/************************************************************************
+* Checkbox styles
+***********************************************************************/
+@checkbox-color: #1491C1;
+@checkbox-size: 10px;
+@checkbox-border-radius: 2px;
+@checkbox-top: 4px;
diff --git a/ambari-web/app/styles/wizard.less 
b/ambari-web/app/styles/wizard.less
index 8341bb6..89784a8 100644
--- a/ambari-web/app/styles/wizard.less
+++ b/ambari-web/app/styles/wizard.less
@@ -19,6 +19,7 @@
 @import 'common.less';
 
 @wizard-side-nav-width: 250px;
+@host-column-width: 210px;
 
 #enable_security {
   .step3 {
@@ -251,57 +252,106 @@
   }
   #step6 {
     .pre-scrollable {
-      max-height: 440px;
+      width: 100%;
+      overflow: auto;
       position: relative;
-      display: flex;
-      overflow-y: auto;
+      max-height: 440px;
+      border-bottom: @table-footer-border;
       #component_assign_table {
-        display: inline-block;
-        overflow-x: auto;
-        margin-left: 190px;
-        margin-bottom: 10px;
-        height: 100%;
-        tbody td, th {
-          white-space: nowrap;
-        }
-        tfoot td {
-          padding-bottom: 30px;
-        }
-        .trim_hostname {
-          .ellipsis-overflow-nowrap;
-          max-width: 180px;
-          float:left;
+        margin-bottom: 0;
+        tr {
           display: block;
-        }
-        .checkbox {
-          margin: 0;
-        }
-        .host-component-checkbox {
-          line-height: 17px;
-          font-size: 12px;
-          top: 0;
-        }
-        .freeze {
-          position: absolute;
-          left: 0;
-          width: 210px;
-          border-top-color: #eee;
-          border-bottom: 1px solid #eee;
-        }
-        td.freeze {
-          padding-bottom: 11px;
-        }
-        tr.last-row {
-          td {
-            border-bottom: 2px solid #eee;
+          padding-left: @host-column-width;
+          td, th {
+            white-space: nowrap;
+          }
+          .freeze {
+            width: @host-column-width;
+            position: absolute;
+            left: 0;
+            background-color: #fff;
+            border-left: 1px solid transparent;
+          }
+          .trim_hostname {
+            .ellipsis-overflow-nowrap;
+            max-width: 180px;
+            float: left;
+            display: block;
+          }
+          .checkbox {
+            margin: 0;
+            position: static;
+            input[type="checkbox"] {
+              + label.host-component-checkbox {
+                display: inline;
+                line-height: 17px;
+                font-size: 12px;
+                position: static;
+                padding-left: 0;
+                &:before {
+                  position: static;
+                  display: inline-block;
+                  margin-top: @checkbox-top;
+                  margin-right: @checkbox-size;
+                }
+                &:after {
+                  background-color: @checkbox-color;
+                  border-color: @checkbox-color;
+                  position: static;
+                  display: inline-block;
+                  float: left;
+                  margin-right: @checkbox-size;
+                  width: @checkbox-size;
+                  height: @checkbox-size;
+                  border-radius: @checkbox-border-radius;
+                  margin-top: -1 * (@checkbox-size + @checkbox-top);
+                  line-height: 1.2em;
+                  padding-left: 2px;
+                }
+              }
+              &:checked + label:before {
+                visibility: hidden;
+              }
+              &:not(:checked) + label:after {
+                content: '';
+                visibility: hidden;
+              }
+            }
+          }
+          &:hover {
+            &:not(:first-of-type) {
+              margin-top: -1px;
+            }
+            td.freeze {
+              background-color: @table-hover-background-color;
+              border-color: @table-hover-border-color;
+            }
+            + tr {
+              border-top-width: 0;
+            }
+          }
+          &.last-row {
+            border-bottom-color: transparent;
+            td {
+              border-bottom-color: transparent;
+            }
+            &:hover {
+              border-bottom-color: @table-hover-border-color;
+            }
           }
         }
-        .static-pagination {
-          position: absolute;
-          right: 10px;
+        .host-messages {
+          margin-left: @host-column-width;
+          padding: @table-cell-padding;
         }
       }
     }
+    .static-pagination {
+      margin-bottom: @table-margin-bottom;
+      font-size: @table-font-size;
+      color: @table-footer-color;
+      padding: @table-cell-padding;
+    }
     .spinner-overlay {
       position: absolute;
       width: 100%;
diff --git a/ambari-web/app/templates/wizard/step6.hbs 
b/ambari-web/app/templates/wizard/step6.hbs
index 9673abd..e8e851c 100644
--- a/ambari-web/app/templates/wizard/step6.hbs
+++ b/ambari-web/app/templates/wizard/step6.hbs
@@ -50,25 +50,28 @@
         </div>
       {{/if}}
 
-      <div class="pre-scrollable col-sm-12">
-        <table class="table table-hover" id="component_assign_table" {{QAAttr 
"slave-clients-table"}}>
-          <thead>
-          <tr>
-            <th class="host-column freeze">{{t common.host}}</th>
-            {{#each header in controller.headers}}
-              <th {{bindAttr class="header.name"}}>
-                <a href="#" {{QAAttr "select-all"}} {{bindAttr 
class="header.allChecked:selected:deselected header.isDisabled:remove-link" 
id="header.allId"}}
-                  {{action "selectAllNodes" header target="controller"}}>{{t 
all}}</a> &nbsp;|&nbsp; <a
-                {{QAAttr "deselect-all"}} href="#" {{bindAttr 
class="header.noChecked:selected:deselected header.isDisabled:remove-link" 
id="header.noneId"}}
-                {{action "deselectAllNodes" header target="controller"}}>{{t 
none}}</a>
-              </th>
-            {{/each}}
-          </tr>
-          </thead>
-          <tbody>
+      <div class="col-sm-12">
+        <div class="pre-scrollable">
+          <table class="table table-hover" id="component_assign_table" 
{{QAAttr "slave-clients-table"}}>
+            <thead>
+            <tr>
+              <th class="host-column freeze">{{t common.host}}</th>
+              {{#each header in controller.headers}}
+                <th {{bindAttr class="header.name"}}>
+                  <a
+                    href="#" {{QAAttr "select-all"}} {{bindAttr 
class="header.allChecked:selected:deselected header.isDisabled:remove-link" 
id="header.allId"}}
+                    {{action "selectAllNodes" header target="controller"}}>{{t 
all}}</a> &nbsp;|&nbsp; <a
+                  {{QAAttr "deselect-all"}}
+                  href="#" {{bindAttr 
class="header.noChecked:selected:deselected header.isDisabled:remove-link" 
id="header.noneId"}}
+                  {{action "deselectAllNodes" header target="controller"}}>{{t 
none}}</a>
+                </th>
+              {{/each}}
+            </tr>
+            </thead>
+            <tbody>
             {{#each host in view.pageContent}}
               <tr {{QAAttr "host-row"}} {{bindAttr 
class="host.isLast:last-row"}}>
-                {{#view App.WizardStep6HostView hostBinding="host" }}
+                {{#view App.WizardStep6HostView hostBinding="host"}}
                   <span class="trim_hostname">{{host.hostName}}</span>
                   {{#if host.hasMaster}}
                     <i {{QAAttr "has-masters"}} class="glyphicon 
glyphicon-asterisks">&#10037;</i>
@@ -77,35 +80,28 @@
                 {{#each checkbox in host.checkboxes}}
                   <td {{QAAttr "toggle-component"}} {{bindAttr 
class="checkbox.hasErrorMessage:error checkbox.hasWarnMessage:warning 
checkbox.component"}}>
                     <div class="checkbox" {{bindAttr 
data-qa="checkbox.dataQaAttr"}}>
-                        <input {{bindAttr id="checkbox.uId" 
checked="checkbox.checked" disabled="checkbox.isDisabled"}} {{action 
"checkboxClick" checkbox target="view" }}
-                                type="checkbox"/>
+                      <input {{bindAttr id="checkbox.uId" 
checked="checkbox.checked" disabled="checkbox.isDisabled"}} {{action 
"checkboxClick" checkbox target="view"}}
+                        type="checkbox"/>
                       <label class="host-component-checkbox" {{bindAttr 
for="checkbox.uId"}}>{{checkbox.title}}</label>
                     </div>
                   </td>
                 {{/each}}
               </tr>
               {{#if host.anyMessage}}
-                <tr>
-                  <td {{bindAttr colspan="view.columnCount"}} 
class="no-borders">
-                    {{#each errorMsg in host.errorMessages}}
-                        <div class="alert alert-danger">{{errorMsg}}</div>
-                    {{/each}}
-                    {{#each warnMsg in host.warnMessages}}
-                      <div class="alert alert-warning">{{warnMsg}}</div>
-                    {{/each}}
-                  </td>
-                </tr>
+                <div class="host-messages">
+                  {{#each errorMsg in host.errorMessages}}
+                    <div class="alert alert-danger">{{errorMsg}}</div>
+                  {{/each}}
+                  {{#each warnMsg in host.warnMessages}}
+                    <div class="alert alert-warning">{{warnMsg}}</div>
+                  {{/each}}
+                </div>
               {{/if}}
             {{/each}}
-          </tbody>
-          <tfoot>
-            <tr>
-              <td colspan="100">
-                {{view App.PaginationView classNames="static-pagination"}}
-              </td>
-            </tr>
-          </tfoot>
-        </table>
+            </tbody>
+          </table>
+        </div>
+        {{view App.PaginationView classNames="static-pagination"}}
       </div>
     </div>
   </div>
diff --git a/ambari-web/app/views/wizard/step6_view.js 
b/ambari-web/app/views/wizard/step6_view.js
index 8810c49..c3f9d4b 100644
--- a/ambari-web/app/views/wizard/step6_view.js
+++ b/ambari-web/app/views/wizard/step6_view.js
@@ -50,15 +50,36 @@ App.WizardStep6View = App.TableView.extend({
   didInsertElement: function () {
     this.setLabel();
     this.get('controller').loadStep();
+    this.$('.pre-scrollable').on('scroll', event => {
+      this.$('.pre-scrollable .freeze').css('transform', 
`translate(${event.target.scrollLeft}px,0)`);
+    });
     Em.run.next(this, this.adjustColumnWidth);
   },
 
   adjustColumnWidth: function() {
-    const table = $('#component_assign_table');
-    const columnsCount = this.get('controller.headers.length');
-    if (table.width() > table.find('tbody').width()) {
-      const columnWidth = Math.floor(table.width() / columnsCount);
+    const table = $('#component_assign_table'),
+      tableWrapper = $('.pre-scrollable').first(),
+      tableCells = table.find('tbody > tr:first-of-type > td');
+    let cellsWidth = 0;
+    $.each(tableCells, (i, td) => cellsWidth += $(td).width());
+    if (tableWrapper.width() > cellsWidth) {
+      const columnsCount = this.get('controller.headers.length'),
+        hostColumnWidth = 210, // from ambari-web/app/styles/wizard.less
+        columnWidth = Math.floor((table.width() - hostColumnWidth)/ 
columnsCount);
       table.find("th:not('.freeze'), td:not('.freeze')").width(columnWidth);
+      // a trick to keep checkbox abd label on the single line
+      table.find('.host-component-checkbox').css({
+        display: 'inline-block',
+        width: '0'
+      });
+    } else {
+      const tds = $('#component_assign_table > tbody > tr:first-of-type > td');
+      $.each(tds, (i, td) => {
+        const element = $(td),
+          className = element.attr('class'),
+          width = element.width();
+        $(`#component_assign_table th.${className}`).width(width);
+      });
     }
   },
 
@@ -93,12 +114,7 @@ App.WizardStep6View = App.TableView.extend({
     Em.set(checkbox, 'checked', !checkbox.checked);
     this.get('controller').checkCallback(checkbox.component);
     this.get('controller').callValidation();
-  },
-
-  columnCount: function() {
-    var hosts = this.get('controller.hosts');
-    return hosts && hosts.length > 0 ? hosts[0].get('checkboxes').length + 1 : 
1;
-  }.property('controller.hosts.@each.checkboxes')
+  }
 });
 
 App.WizardStep6HostView = Em.View.extend({
diff --git a/ambari-web/test/views/wizard/step6_view_test.js 
b/ambari-web/test/views/wizard/step6_view_test.js
index 7a4dc9f..511bb11 100644
--- a/ambari-web/test/views/wizard/step6_view_test.js
+++ b/ambari-web/test/views/wizard/step6_view_test.js
@@ -25,7 +25,12 @@ var view;
 
 function getView() {
   return App.WizardStep6View.create({
-    controller: App.WizardStep6Controller.create()
+    controller: App.WizardStep6Controller.create(),
+    $: function () {
+      return {
+        on: Em.K
+      };
+    }
   });
 }
 
@@ -141,20 +146,6 @@ describe('App.WizardStep6View', function() {
     });
   });
 
-  describe("#columnCount", function() {
-    it("hosts present", function() {
-      view.set('controller.hosts', [
-        Em.Object.create({checkboxes: [{}, {}, {}]})
-      ]);
-      view.propertyDidChange('columnCount');
-      expect(view.get('columnCount')).to.equal(4);
-    });
-    it("hosts absent", function() {
-      view.set('controller.hosts', []);
-      view.propertyDidChange('columnCount');
-      expect(view.get('columnCount')).to.equal(1);
-    });
-  });
 });
 
 describe('App.WizardStep6HostView', function() {

Reply via email to