Add Event log page

Add basic event log table with the ability to sort by column
(ID, Severity, Type, Date) and filter by severity.

- Updated existing translation for eventLog to eventLogs

Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: Ic233593cc8804d9dcefb2b5740dfac3d52899b02
diff --git a/src/components/AppNavigation/AppNavigation.vue b/src/components/AppNavigation/AppNavigation.vue
index 2081609..b7a3e07 100644
--- a/src/components/AppNavigation/AppNavigation.vue
+++ b/src/components/AppNavigation/AppNavigation.vue
@@ -15,8 +15,8 @@
               <icon-expand class="icon-expand" />
             </b-button>
             <b-collapse id="health-menu" tag="ul" class="nav-item__nav">
-              <b-nav-item href="javascript:void(0)">
-                {{ $t('appNavigation.eventLog') }}
+              <b-nav-item to="/health/event-logs">
+                {{ $t('appNavigation.eventLogs') }}
               </b-nav-item>
               <b-nav-item href="javascript:void(0)">
                 {{ $t('appNavigation.hardwareStatus') }}
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 2ff9841..9f74ca0 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -58,7 +58,7 @@
     "accessControl": "Access Control",
     "configuration": "Configuration",
     "control": "Control",
-    "eventLog": "@:appPageTitle.eventLog",
+    "eventLogs": "@:appPageTitle.eventLogs",
     "firmware": "@:appPageTitle.firmware",
     "hardwareStatus": "@:appPageTitle.hardwareStatus",
     "health": "Health",
@@ -76,7 +76,7 @@
     "sslCertificates": "@:appPageTitle.sslCertificates"
   },
   "appPageTitle": {
-    "eventLog": "Event log",
+    "eventLogs": "Event logs",
     "firmware": "Firmware",
     "hardwareStatus": "Hardware status",
     "ldap": "LDAP",
@@ -93,6 +93,16 @@
     "sslCertificates": "SSL Certificates",
     "unauthorized": "Unauthorized"
   },
+  "pageEventLogs": {
+    "table": {
+      "date": "Date",
+      "description": "Description",
+      "emptyMessage": "There are no logs to show",
+      "id": "ID",
+      "severity": "Severity",
+      "type": "Type"
+    }
+  },
   "pageLdap": {
     "pageDescription": "Configure LDAP settings and manage role groups",
     "roleGroups": "Role groups",
diff --git a/src/router/index.js b/src/router/index.js
index fc36101..30532a5 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -24,6 +24,14 @@
         }
       },
       {
+        path: '/health/event-logs',
+        name: 'event-logs',
+        component: () => import('@/views/Health/EventLogs'),
+        meta: {
+          title: 'appPageTitle.eventLogs'
+        }
+      },
+      {
         path: '/health/sensors',
         name: 'sensors',
         component: () => import('@/views/Health/Sensors'),
diff --git a/src/views/Health/EventLogs/EventLogs.vue b/src/views/Health/EventLogs/EventLogs.vue
new file mode 100644
index 0000000..883b55c
--- /dev/null
+++ b/src/views/Health/EventLogs/EventLogs.vue
@@ -0,0 +1,131 @@
+<template>
+  <b-container fluid="xl">
+    <page-title />
+    <b-row>
+      <b-col class="text-right">
+        <table-filter :filters="tableFilters" @filterChange="onFilterChange" />
+      </b-col>
+    </b-row>
+    <b-row>
+      <b-col>
+        <b-table
+          :fields="fields"
+          :items="filteredLogs"
+          sort-icon-left
+          no-sort-reset
+          sort-desc
+          show-empty
+          sort-by="date"
+          :sort-compare="onSortCompare"
+          :empty-text="$t('pageEventLogs.table.emptyMessage')"
+        >
+          <template v-slot:cell(severity)="{ value }">
+            <status-icon :status="getStatus(value)" />
+            {{ value }}
+          </template>
+          <template v-slot:cell(date)="{ value }">
+            {{ value | formatDate }} {{ value | formatTime }}
+          </template>
+        </b-table>
+      </b-col>
+    </b-row>
+  </b-container>
+</template>
+
+<script>
+import PageTitle from '@/components/Global/PageTitle';
+import StatusIcon from '@/components/Global/StatusIcon';
+import TableFilter from '@/components/Global/TableFilter';
+
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
+import TableFilterMixin from '@/components/Mixins/TableFilterMixin';
+
+const SEVERITY = ['OK', 'Warning', 'Critical'];
+
+export default {
+  components: { PageTitle, StatusIcon, TableFilter },
+  mixins: [LoadingBarMixin, TableFilterMixin],
+  data() {
+    return {
+      fields: [
+        {
+          key: 'id',
+          label: this.$t('pageEventLogs.table.id'),
+          sortable: true
+        },
+        {
+          key: 'severity',
+          label: this.$t('pageEventLogs.table.severity'),
+          sortable: true
+        },
+        {
+          key: 'type',
+          label: this.$t('pageEventLogs.table.type'),
+          sortable: true
+        },
+        {
+          key: 'date',
+          label: this.$t('pageEventLogs.table.date'),
+          sortable: true
+        },
+        {
+          key: 'description',
+          label: this.$t('pageEventLogs.table.description')
+        }
+      ],
+      tableFilters: [
+        {
+          label: this.$t('pageEventLogs.table.severity'),
+          values: SEVERITY
+        }
+      ],
+      activeFilters: []
+    };
+  },
+  computed: {
+    allLogs() {
+      return this.$store.getters['eventLog/allEvents'];
+    },
+    filteredLogs: {
+      get: function() {
+        return this.getFilteredTableData(this.allLogs, this.activeFilters);
+      },
+      set: function(newVal) {
+        return newVal;
+      }
+    }
+  },
+  created() {
+    this.startLoader();
+    this.$store
+      .dispatch('eventLog/getEventLogData')
+      .finally(() => this.endLoader());
+  },
+  methods: {
+    getStatus(serverity) {
+      switch (serverity) {
+        case SEVERITY[2]:
+          return 'danger';
+        case SEVERITY[1]:
+          return 'warning';
+        case SEVERITY[0]:
+          return 'success';
+        default:
+          return '';
+      }
+    },
+    onFilterChange({ activeFilters }) {
+      this.activeFilters = activeFilters;
+      this.filteredLogs = this.getFilteredTableData(
+        this.allLogs,
+        activeFilters
+      );
+    },
+    onSortCompare(a, b, key) {
+      if (key === 'severity') {
+        return SEVERITY.indexOf(a.status) - SEVERITY.indexOf(b.status);
+      }
+    }
+  }
+};
+</script>
diff --git a/src/views/Health/EventLogs/index.js b/src/views/Health/EventLogs/index.js
new file mode 100644
index 0000000..521efde
--- /dev/null
+++ b/src/views/Health/EventLogs/index.js
@@ -0,0 +1,2 @@
+import EventLogs from './EventLogs.vue';
+export default EventLogs;
diff --git a/src/views/Overview/OverviewEvents.vue b/src/views/Overview/OverviewEvents.vue
index 64ba7fc..5a95048 100644
--- a/src/views/Overview/OverviewEvents.vue
+++ b/src/views/Overview/OverviewEvents.vue
@@ -4,8 +4,7 @@
       {{ $t('pageOverview.events.noHighEventsMsg') }}
     </div>
     <div v-else>
-      <!-- TODO: link to event log -->
-      <b-button variant="link" href="#" class="float-right">
+      <b-button variant="link" to="/health/event-logs" class="float-right">
         {{ $t('pageOverview.events.viewAllButton') }}
       </b-button>
       <b-table