Browse Source

[frontend] Add the option to not show a header in the HueTable component

Johan Ahlen 4 years ago
parent
commit
f56f76e094

+ 2 - 2
desktop/core/src/desktop/js/components/HueTable.d.ts

@@ -15,8 +15,8 @@
 // limitations under the License.
 
 export interface Column<T> {
-  label: string;
-  key: string | number;
+  label?: string;
+  key: keyof T | string | number;
   cssClass?: string;
   htmlValue?: boolean;
   headerCssClass?: string;

+ 133 - 0
desktop/core/src/desktop/js/components/HueTable.scss

@@ -0,0 +1,133 @@
+/*
+ Licensed to Cloudera, Inc. under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  Cloudera, Inc. 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 './styles/colors';
+@import './styles/mixins';
+
+.hue-table-container {
+  overflow-x: auto;
+  width: 100%;
+  margin: 0 0 15px 0;
+
+  .hue-table {
+    line-height: 14px;
+    table-layout: auto;
+    border-collapse: separate;
+
+    &.header-less {
+      border-collapse: collapse;
+      tbody > tr:first-child {
+        border-top: 1px solid $fluid-gray-300;
+      }
+    }
+
+    thead,
+    tbody {
+      tr {
+        height: 40px;
+
+        th,
+        td {
+          @include nowrap-ellipsis;
+
+          height: 16px;
+          max-width: 300px;
+          padding: 12px;
+          border-bottom: 1px solid $fluid-gray-300;
+          text-align: left;
+
+          &.column-flush {
+            width: 100%;
+          }
+        }
+      }
+    }
+
+    thead {
+      tr {
+        th {
+          background-color: $fluid-white;
+          color: $fluid-gray-700;
+          font-size: 13px;
+          font-weight: 500;
+          white-space: nowrap;
+
+          &.sticky-first-col {
+            background-color: $fluid-white;
+            position: sticky;
+            position: -webkit-sticky;
+            left: 0;
+            z-index: 102;
+          }
+
+          .sort-header {
+            display: flex;
+            cursor: pointer;
+            align-items: center;
+            letter-spacing: normal;
+            outline: 0;
+          }
+        }
+      }
+    }
+
+    tbody {
+      tr {
+        td {
+          color: $fluid-gray-900;
+          font-size: 14px;
+
+          &.sticky-first-col {
+            @include position-sticky;
+
+            background-color: $fluid-white;
+            left: 0;
+            z-index: 100;
+          }
+
+          &:last-of-type {
+            padding-right: 8px;
+          }
+        }
+      }
+
+      &.clickable-rows tr {
+        cursor: pointer;
+
+        &:hover {
+          background-color: $fluid-blue-050;
+        }
+      }
+    }
+
+    &.sticky-header {
+      thead th {
+        @include position-sticky;
+
+        top: 0;
+        z-index: 101;
+
+        &.sticky-first-col {
+          @include position-sticky;
+
+          top: 0;
+        }
+      }
+    }
+  }
+}

+ 23 - 111
desktop/core/src/desktop/js/components/HueTable.vue

@@ -19,14 +19,17 @@
 <!-- eslint-disable vue/no-v-html -->
 <template>
   <div ref="tableContainer" class="hue-table-container" @scroll="onContainerScroll">
-    <table class="hue-table" :class="{ 'sticky-header': stickyHeader }">
+    <table
+      class="hue-table"
+      :class="{ 'sticky-header': stickyHeader && showHeader, 'header-less': !showHeader }"
+    >
       <caption>
         <!-- Because of Web:TableWithoutCaptionCheck -->
         {{
           caption
         }}
       </caption>
-      <thead>
+      <thead v-if="showHeader">
         <tr class="header-row">
           <th
             v-for="(column, colIndex) in columns"
@@ -34,14 +37,14 @@
             :class="cellClass(column.headerCssClass, colIndex)"
             scope="col"
           >
-            {{ column.label }}
+            {{ column.label || column.key }}
           </th>
           <!-- To fill the blank space to the right when table width is smaller than available horizontal space -->
           <th class="column-flush" scope="col" />
         </tr>
       </thead>
-      <tbody>
-        <tr v-for="(row, rowIndex) in rows" :key="rowIndex" @click="$emit('row-clicked', row)">
+      <tbody :class="{ 'clickable-rows': clickableRows }">
+        <tr v-for="(row, rowIndex) in rows" :key="rowIndex" @click="onRowClick(row)">
           <td
             v-for="(column, colIndex) in columns"
             :key="colIndex"
@@ -64,6 +67,7 @@
 <script lang="ts">
   import { defineComponent, PropType } from 'vue';
 
+  import './HueTable.scss';
   import { Column, Row } from './HueTable';
 
   export default defineComponent({
@@ -83,6 +87,11 @@
         type: String,
         default: undefined
       },
+      showHeader: {
+        type: Boolean,
+        required: false,
+        default: true
+      },
       stickyHeader: {
         type: Boolean,
         required: false,
@@ -92,6 +101,10 @@
         type: Boolean,
         required: false,
         default: false
+      },
+      clickableRows: {
+        type: Boolean,
+        default: false
       }
     },
 
@@ -101,18 +114,15 @@
       hasCellSlot(column: Column<unknown>): boolean {
         return !!this.$slots[this.cellSlotName(column)];
       },
-
       cellSlotName(column: Column<unknown>): string {
         return 'cell-' + column.key;
       },
-
       onContainerScroll(): void {
         const containerEl = <HTMLElement>this.$refs.tableContainer;
         if (containerEl.scrollHeight === containerEl.scrollTop + containerEl.clientHeight) {
           this.$emit('scroll-to-end');
         }
       },
-
       cellClass(cellClass: string | undefined, index: number): string | null {
         // This prevents rendering of empty class="" for :class="[x,y]" when x and y are undefined
         // Possibly fixed in Vue 3
@@ -122,110 +132,12 @@
           return 'sticky-first-col';
         }
         return cellClass || null;
+      },
+      onRowClick(row: Row): void {
+        if (this.clickableRows) {
+          this.$emit('row-clicked', row);
+        }
       }
     }
   });
 </script>
-
-<style lang="scss" scoped>
-  @import './styles/colors';
-  @import './styles/mixins';
-
-  .hue-table-container {
-    overflow-x: auto;
-    width: 100%;
-    margin: 0 0 15px 0;
-
-    .hue-table {
-      line-height: 14px;
-      table-layout: auto;
-      border-collapse: separate;
-
-      thead,
-      tbody {
-        tr {
-          height: 40px;
-
-          th,
-          td {
-            @include nowrap-ellipsis;
-
-            height: 16px;
-            max-width: 300px;
-            padding: 12px;
-            border-bottom: 1px solid $fluid-gray-300;
-            text-align: left;
-
-            &.column-flush {
-              width: 100%;
-            }
-          }
-        }
-      }
-
-      thead {
-        tr {
-          th {
-            background-color: $fluid-white;
-            color: $fluid-gray-700;
-            font-size: 13px;
-            font-weight: 500;
-            white-space: nowrap;
-
-            &.sticky-first-col {
-              background-color: $fluid-white;
-              position: sticky;
-              position: -webkit-sticky;
-              left: 0;
-              z-index: 102;
-            }
-
-            .sort-header {
-              display: flex;
-              cursor: pointer;
-              align-items: center;
-              letter-spacing: normal;
-              outline: 0;
-            }
-          }
-        }
-      }
-
-      tbody {
-        tr {
-          td {
-            color: $fluid-gray-900;
-            font-size: 14px;
-
-            &.sticky-first-col {
-              @include position-sticky;
-
-              background-color: $fluid-white;
-              left: 0;
-              z-index: 100;
-            }
-
-            &:last-of-type {
-              padding-right: 8px;
-            }
-          }
-        }
-      }
-
-      &.sticky-header {
-        thead th {
-          @include position-sticky;
-
-          top: 0;
-          z-index: 101;
-
-          &.sticky-first-col {
-            @include position-sticky;
-
-            top: 0;
-          }
-        }
-      }
-    }
-  }
-</style>

+ 15 - 5
desktop/core/src/desktop/js/components/__snapshots__/HueTable.test.ts.snap

@@ -36,7 +36,9 @@ exports[`HueTable.vue should render a sticky table with header and column css 1`
         />
       </tr>
     </thead>
-    <tbody>
+    <tbody
+      class=""
+    >
       
       <tr>
         
@@ -176,7 +178,9 @@ exports[`HueTable.vue should render a table 1`] = `
         />
       </tr>
     </thead>
-    <tbody>
+    <tbody
+      class=""
+    >
       
       <tr>
         
@@ -360,7 +364,9 @@ exports[`HueTable.vue should render a table with a custom component for a cell 1
         />
       </tr>
     </thead>
-    <tbody>
+    <tbody
+      class=""
+    >
       
       <tr>
         
@@ -446,7 +452,9 @@ exports[`HueTable.vue should render a table with adapter 1`] = `
         />
       </tr>
     </thead>
-    <tbody>
+    <tbody
+      class=""
+    >
       
       <tr>
         
@@ -586,7 +594,9 @@ exports[`HueTable.vue should render a table with array rows 1`] = `
         />
       </tr>
     </thead>
-    <tbody>
+    <tbody
+      class=""
+    >
       
       <tr>