Fix sensors table header and body alignment

- Update markup to use semenatic table
- Update table to flex based layout to support responsive
  table design

Tested: Small screen and large screen layout in Chrome,
        Firefox, and Safari. Safari has issues with the
        sticky header, which is an acceptable trade off
        and meets cross-browser standards.

Signed-off-by: Derick Montague <derick.montague@ibm.com>
Change-Id: I8ea323e45a2659562f229d4fd6d4e53887664cad
diff --git a/app/server-health/controllers/sensors-overview-controller.html b/app/server-health/controllers/sensors-overview-controller.html
index 90bdcc2..8669c33 100644
--- a/app/server-health/controllers/sensors-overview-controller.html
+++ b/app/server-health/controllers/sensors-overview-controller.html
@@ -1,16 +1,12 @@
 <loader loading="loading"></loader>
-<div id="sensors-overview">
-  <div class="row column">
-    <h1>Sensors</h1>
-  </div>
-  <section class="row column">
-    <div class="page-header">
-      <h2 class="inline">All sensors present in the system</h2>
+<div id="sensors" class="sensors">
+  <h1>Sensors</h1>
+  <div class="page-header">
+    <h2 class="inline">All sensors present in the system</h2>
       <a ng-href="data:text/json;charset=utf-8,{{export_data}}" class="btn btn-tertiary float-right" download="{{export_name}}"><icon file="icon-export.svg"></icon>Export</a>
-    </div>
-  </section>
-  <section class="row column">
-    <!-- search -->
+  </div>
+
+  <div>
     <p class="content-label" aria-label="sensors filter">Filter sensors</p>
     <div class="content__search">
       <label for="content__search-input">Sensors Search</label>
@@ -19,7 +15,7 @@
         <button class="clear-input" ng-click="clear()">&#10005;</button>
         <input id="content__search-submit" type="submit" class="btn btn-primary content__search-submit" value="Filter" ng-click="doSearchOnClick()"/>
       </div>
-    </div>  <!-- end search -->
+    </div>
 
     <div class="toggle-filter">
       <p class="content-label">FILTER BY SEVERITY</p>
@@ -36,37 +32,73 @@
           ng-class="selectedSeverity.normal ? 'btn-primary' : 'btn-secondary'">Normal
       </button>
     </div>
+  </div>
 
-  </section>
-
-  <section class="row column" ng-show="filteredSensorData.length == 0">
-    <!-- message -->
+  <div ng-show="filteredSensorData.length == 0">
     <span ng-if="selectedSeverity.all">{{messages.NO_SENSOR_DATA}}</span>
     <span ng-if="selectedSeverity.critical">{{messages.CRITICAL_NO_SENSOR_DATA}}</span>
     <span ng-if="selectedSeverity.warning">{{messages.WARNING_NO_SENSOR_DATA}}</span>
     <span ng-if="selectedSeverity.normal">{{messages.NORMAL_NO_SENSOR_DATA}}</span>
-    <!-- end message -->
-  </section>
+  </div>
 
-  <section id="sensor-categories" class="row column" ng-show="filteredSensorData.length">
-    <div class="row column header-row fixed-table-header">
-      <div class="column large-12 header__actions-bar">
-        <p class="inline sensor__title">Sensors ({{filteredSensorData.length}})</p>
-        <p class="inline sensor__reading">Low critical</p>
-        <p class="inline sensor__reading">Low warning</p>
-        <p class="inline sensor__reading sensor__heading-current">Current</p>
-        <p class="inline sensor__reading">High warning</p>
-        <p class="inline sensor__reading">High critical</p>
-      </div>
-    </div>
-    <!-- sensor -->
-    <div class="sensor__readings-row" ng-repeat="sensor in data|filter:filterBySeverity|filter:filterBySearchTerms|orderBy:'+custom_order' as filteredSensorData">
-      <p class="inline sensor__title"><span class="icon" ng-class="{'icon__critical': sensor.status == 'critical', 'icon__warning': sensor.status == 'warning', 'icon__normal': sensor.status == 'normal'}" aria-label="sensor.status" ></span>{{sensor.title}}</p>
-      <p class="inline sensor__reading"><span class="sensor__label">Low critical</span>{{sensor.CriticalLow}}<span class="content-label">{{sensor.unit}}<span ng-if="sensor.unit == 'C'">&deg;</span></p>
-      <p class="inline sensor__reading"><span class="sensor__label">Low warning</span>{{sensor.WarningLow}}<span class="content-label">{{sensor.unit}}<span ng-if="sensor.unit == 'C'">&deg;</span></p>
-      <p class="inline sensor__reading sensor__current" ng-class="{'sensor__critical': sensor.status == 'critical', 'sensor__warn': sensor.status == 'warning', 'sensor__normal': sensor.status == 'normal'}"><span class="sensor__label">Current</span>{{sensor.Value}}<span class="content-label">{{sensor.unit}}<span ng-if="sensor.unit == 'C'">&deg;</span></span></p>
-      <p class="inline sensor__reading"><span class="sensor__label">High warning</span>{{sensor.WarningHigh}}<span class="content-label">{{sensor.unit}}<span ng-if="sensor.unit == 'C'">&deg;</span></p>
-      <p class="inline sensor__reading"><span class="sensor__label">High critical</span>{{sensor.CriticalHigh}}<span class="content-label">{{sensor.unit}}<span ng-if="sensor.unit == 'C'">&deg;</span></p>
-    </div>
-  </section>
+  <table id="sensor-categories" class="sensors__table" cellpadding="0" cellspacing="0" ng-show="filteredSensorData.length">
+    <thead class="sensors__thead fixed-table-header">
+      <tr class="sensors__thead-row">
+        <th class="sensors__thead-cell">Sensors ({{filteredSensorData.length}})<th>
+        <th class="sensors__thead-cell">Low critical<th>
+        <th class="sensors__thead-cell">Low warning<th>
+        <th class="sensors__thead-cell sensor__heading-current">Current<th>
+        <th class="sensors__thead-cell">High warning<th>
+        <th class="sensors__thead-cell">High critical<th>
+      </tr>
+    </thead>
+    <tbody class="sensors__tbody">
+      <tr class="sensors__tbody-row" ng-repeat="sensor in data|filter:filterBySeverity|filter:filterBySearchTerms|orderBy:'+custom_order' as filteredSensorData">
+        <th class="sensors__tbody-header">
+          <span class="icon" ng-class="{'icon__critical': sensor.status == 'critical', 'icon__warning': sensor.status == 'warning', 'icon__normal': sensor.status == 'normal'}" aria-label="Sensor status: {{sensor.status}}" ></span>
+          <span>{{sensor.title}}</span>
+        </th>
+        <td class="sensors__tbody-cell">
+          <span class="sensors__tbody-cell__title">Low critical</span>
+          <span class="sensors__tbody-cell__content">
+              <span class="sensors__tbody-info">{{sensor.CriticalLow}}</span>
+              <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
+            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
+          </span>
+        </td>
+        <td class="sensors__tbody-cell">
+          <span class="sensors__tbody-cell__title">Low warning</span>
+          <span class="sensors__tbody-cell__content">
+              <span class="sensors__tbody-info">{{sensor.WarningLow}}</span>
+              <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
+            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
+          </span>
+        </td>
+        <td class="sensors__tbody-cell sensors__tbody-current" ng-class="{'sensors__tbody-current--critical': sensor.status == 'critical', 'sensors__tbody-current--warn': sensor.status == 'warning', 'sensors__tbody-current--normal': sensor.status == 'normal'}">
+          <span class="sensors__tbody-cell__title">Current</span>
+          <span class="sensors__tbody-cell__content">
+              <span class="sensors__tbody-info">{{sensor.Value}}</span>
+              <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
+            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
+          </span>
+        </td>
+        <td class="sensors__tbody-cell">
+          <span class="sensors__tbody-cell__title">High warning</span>
+          <span class="sensors__tbody-cell__content">
+            <span class="sensors__tbody-info">{{sensor.WarningHigh}}</span>
+            <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
+            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
+          </span>
+        </td>
+        <td class="sensors__tbody-cell">
+          <span class="sensors__tbody-cell__title">High critical</span>
+          <span class="sensors__tbody-cell__content">
+            <span class="sensors__tbody-info">{{sensor.CriticalHigh}}</span>
+            <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
+            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
+          </span>
+        </td>
+      </tr>
+    </tbody>
+  </table>
 </div>
diff --git a/app/server-health/styles/sensors.scss b/app/server-health/styles/sensors.scss
index 6c81766..260c2a7 100644
--- a/app/server-health/styles/sensors.scss
+++ b/app/server-health/styles/sensors.scss
@@ -1,155 +1,151 @@
-@mixin state-label {
-  text-transform: uppercase;
-  font-weight: 700;
-  font-size: .8em;
+.sensors {
+  max-width: 1196px;
 }
 
-$title-minWidth: 210px;
-
-.header__actions-bar {
-  padding-left: 1.5em;
-  padding-right: 1em;
-  font-weight: 700;
-  .sensor__title {
-    margin-left: 1.5em;
-  }
-  .sensor__reading {
-    margin-right: .2em;
-  }
-  .sensor__heading-current {
-    padding-right: 1em;
-  }
+.sensors__table {
+  display: block;
+  border-collapse: collapse;
 }
 
-.sensor__heading-current {
-  margin: 0;
+.sensors__thead {
+  display: block;
+}
+
+.sensors__thead-row {
+  display: block;
+  background: $darkblue;
+  color: $white;
+  margin-bottom: 1rem;
+
   @include mediaQuery(medium) {
-    margin-left: 10px;
-    margin-right: 10px;
+    display: flex;
+    margin-bottom: 0;
   }
 }
 
-.sensor__label {
-  float: left;
+.sensors__thead-cell {
+  display: block;
+  padding: 1rem;
+  font-weight: 700;
+
+  &:not(:first-child) {
+    display: none;
+  }
+
+  @include mediaQuery(medium) {
+    flex: 1;
+
+    &:not(:first-child) {
+      display: block;
+      flex-grow: 0;
+      flex-shrink: 0;
+      flex-basis: 0;
+      min-width: 16%;
+    }
+  }
+}
+
+.sensors__tbody {
+  display: block;
+}
+
+.sensors__tbody-row {
+  display: flex;
+  flex-direction: column;
+  border: 1px solid $medgrey;
+  margin-bottom: 1rem;
+
+  @include mediaQuery(medium) {
+    display: flex;
+    flex-direction: row;
+    margin-bottom: 0;
+  }
+}
+
+.sensors__tbody-header {
+  display: block;
+  background: darken($lightgrey, 5%);
+  padding: 0.5rem 1rem;
+  font-weight: 700;
+  .icon.icon__normal {
+    display: none;
+  }
+
+  @include mediaQuery(medium) {
+    flex: 1;
+    align-items: center;
+    background: transparent;
+    font-weight: 400;
+    margin-top: 0.5rem;
+    margin-bottom: 0.5rem;
+  }
+}
+
+.sensors__tbody-cell {
+  display: flex;
+  justify-content: space-between;
+  padding: 0.5rem 1rem;
+  @include fontCourierBold;
+
+  @include mediaQuery(medium) {
+    flex-grow: 0;
+    flex-shrink: 0;
+    flex-basis: 0;
+    align-items: center;
+    min-width: 16%;
+    justify-content: flex-start;
+    margin-top: 0.5rem;
+    margin-bottom: 0.5rem;
+  }
+}
+
+.sensors__tbody-cell__title {
   font-weight: 300;
+
   @include mediaQuery(medium) {
     display: none;
   }
 }
 
-.sensor__title {
-  min-width: 28%;
-  margin-bottom: 0;
-}
+.sensors__tbody-unit {
+  display: inline-block;
+  color: $darkgrey;
+  margin-left: 0.5em;
+  font-weight: 700;
+  text-transform: uppercase;
 
-.sensor__reading {
-  width: 100%;
-  text-align: right;
-  margin-bottom: 0;
-  display: none;
   @include mediaQuery(medium) {
-    display: inline-block;
-    width: auto;
-    min-width: calc(70% * (1 / 5) - 18px);
+    margin-left: 0;
   }
 }
 
-.sensor__readings-row {
-  width: 100%;
-  position: relative;
-  display: block;
-  margin: 0;
-  background: $white;
-  text-decoration: none;
-  border: 1px solid $medgrey;
-  background: lighten($lightgrey,1%);
-  margin-top: 1em;
-  @include mediaQuery(medium) {
-    padding: .3em 1em .3em 1.5em;
-    margin-top: 0;
-    border-top: 0;
-    background: transparent;
-  }
-  .sensor__title {
+.sensors__tbody-degree {
+  display: inline-block;
+  margin-left: -8px;
+}
+
+.sensors__tbody-current {
+  background: darken($thresh-normal, 3%);
+
+  .sensors__tbody-cell__title {
     font-weight: 700;
-    background: darken($lightgrey, 5%);
-    min-width: 100%;
-    padding: .8em;
-    @include mediaQuery(medium) {
-      min-width: 30%;
-      background: transparent;
-      padding: .5em .5em .5em 0;
-    }
-    .icon__normal {
-      width: 0;
-    }
   }
-  .content-label {
-    font-size: 1em;
-    margin-left: .8em;
-    color: $darkgrey;
-  }
-  .sensor__reading {
-    @include fontCourierBold;
-    display: block;
-    padding: .3em .8em;
-    @include mediaQuery(medium) {
-      display: inline-block;
-      padding: 0;
-    }
-  }
-  .sensor__current {
-    background: darken($thresh-normal, 3%);
-    margin: 0;
-    @include mediaQuery(medium) {
-      background: $thresh-normal;
-      padding: .7em .3em;
-      margin-left: 10px;
-      min-width: 109px;
-    }
-    @include mediaQuery(large) {
-      background: $thresh-normal;
-      padding: .7em;
-      margin-left: .3em;
-      margin-right: .3em;
-      min-width: 150px;
-    }
-    .sensor__label {
-      font-weight: 700;
-      @include mediaQuery(medium) {
-        font-weight:300;
-      }
-    }
-  }
-  .sensor__critical {
-    background: $thresh-critical;
+}
+
+.sensors__tbody-current--critical {
+  background: $thresh-critical;
+  color: $white;
+
+  .sensors__tbody-unit {
     color: $white;
-    .content-label {
-      color: $white;
-    }
   }
-  .sensor__warn {
-    background: $thresh-warning;
+}
+
+.sensors__tbody-current--warn {
+  background: $thresh-warning;
+  color: $black;
+
+  .sensors__tbody-unit {
     color: $black;
-    .content-label {
-      color: $black;
-    }
-  }
-
-}
-
-// Sensors
-
-#sensors, #sensors-overview {
-
-  .toggle-filter {
-    margin-bottom: 20px;
-    font-size: 0.9em;
-  }
-  .column, .columns {
-    padding-left: 0px;
-    padding-right: 0px;
   }
 }
-
-//end sensor details