Add export functionality to Sensors page

- Create TableToolbarExport component to be used as a slot
  in TableToolbar
- Allows selected table items to be exported

Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: I929347e046af8a5d5188e4c4fd9fc874e067cce5
diff --git a/src/components/Global/TableToolbar.vue b/src/components/Global/TableToolbar.vue
index 041a9c1..331f007 100644
--- a/src/components/Global/TableToolbar.vue
+++ b/src/components/Global/TableToolbar.vue
@@ -15,6 +15,7 @@
           >
             {{ action.label }}
           </b-button>
+          <slot name="export"></slot>
           <b-button
             variant="primary"
             class="d-block"
@@ -38,7 +39,7 @@
     },
     actions: {
       type: Array,
-      required: true,
+      default: () => [],
       validator: prop => {
         return prop.every(action => {
           return (
diff --git a/src/components/Global/TableToolbarExport.vue b/src/components/Global/TableToolbarExport.vue
new file mode 100644
index 0000000..ed1d980
--- /dev/null
+++ b/src/components/Global/TableToolbarExport.vue
@@ -0,0 +1,35 @@
+<template>
+  <b-link
+    class="btn btn-primary d-block align-self-center"
+    :download="download"
+    :href="href"
+  >
+    {{ $t('global.action.export') }}
+  </b-link>
+</template>
+
+<script>
+export default {
+  props: {
+    data: {
+      type: Array,
+      default: () => []
+    },
+    fileName: {
+      type: String,
+      default: 'data'
+    }
+  },
+  computed: {
+    dataForExport() {
+      return JSON.stringify(this.data);
+    },
+    download() {
+      return `${this.fileName}.json`;
+    },
+    href() {
+      return `data:text/json;charset=utf-8,${this.dataForExport}`;
+    }
+  }
+};
+</script>
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 9a34b65..4b80328 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -11,6 +11,7 @@
       "download": "Download",
       "edit": "Edit",
       "enable": "Enable",
+      "export": "Export",
       "filter": "Filter",
       "replace": "Replace",
       "save": "Save",
diff --git a/src/views/Health/Sensors/Sensors.vue b/src/views/Health/Sensors/Sensors.vue
index fe9d397..6de5c9e 100644
--- a/src/views/Health/Sensors/Sensors.vue
+++ b/src/views/Health/Sensors/Sensors.vue
@@ -8,7 +8,22 @@
     </b-row>
     <b-row>
       <b-col xl="12">
+        <table-toolbar
+          ref="toolbar"
+          :selected-items-count="selectedRows.length"
+          @clearSelected="clearSelectedRows($refs.table)"
+        >
+          <template v-slot:export>
+            <table-toolbar-export
+              :data="selectedRows"
+              :file-name="$t('appPageTitle.sensors')"
+            />
+          </template>
+        </table-toolbar>
         <b-table
+          ref="table"
+          selectable
+          no-select-on-click
           sort-icon-left
           no-sort-reset
           sticky-header="75vh"
@@ -17,7 +32,23 @@
           :fields="fields"
           :sort-desc="true"
           :sort-compare="sortCompare"
+          @row-selected="onRowSelected($event, filteredSensors.length)"
         >
+          <!-- Checkbox column -->
+          <template v-slot:head(checkbox)>
+            <b-form-checkbox
+              v-model="tableHeaderCheckboxModel"
+              :indeterminate="tableHeaderCheckboxIndeterminate"
+              @change="onChangeHeaderCheckbox($refs.table)"
+            />
+          </template>
+          <template v-slot:cell(checkbox)="row">
+            <b-form-checkbox
+              v-model="row.rowSelected"
+              @change="toggleSelectRow($refs.table, row.index)"
+            />
+          </template>
+
           <template v-slot:cell(status)="{ value }">
             <status-icon :status="statusIcon(value)" />
             {{ value }}
@@ -47,7 +78,11 @@
 import PageTitle from '../../../components/Global/PageTitle';
 import StatusIcon from '../../../components/Global/StatusIcon';
 import TableFilter from '../../../components/Global/TableFilter';
+import TableToolbar from '@/components/Global/TableToolbar';
+import TableToolbarExport from '@/components/Global/TableToolbarExport';
+
 import TableFilterMixin from '../../../components/Mixins/TableFilterMixin';
+import BVTableSelectableMixin from '@/components/Mixins/BVTableSelectableMixin';
 
 const SENSOR_STATUS = ['OK', 'Warning', 'Critical'];
 
@@ -60,12 +95,23 @@
 
 export default {
   name: 'Sensors',
-  components: { PageTitle, StatusIcon, TableFilter },
-  mixins: [TableFilterMixin],
+  components: {
+    PageTitle,
+    StatusIcon,
+    TableFilter,
+    TableToolbar,
+    TableToolbarExport
+  },
+  mixins: [TableFilterMixin, BVTableSelectableMixin],
   data() {
     return {
       fields: [
         {
+          key: 'checkbox',
+          sortable: false,
+          label: ''
+        },
+        {
           key: 'name',
           sortable: true,
           label: this.$t('pageSensors.table.name')