From 56ee769fd5a3df93eb275859a712700a7ba54944 Mon Sep 17 00:00:00 2001 From: Yoshie Muranaka Date: Thu, 28 May 2020 13:28:29 -0700 Subject: Add Hardware status page and system table Adds ability to see system information in table format with a row expansion details view. Modified tables styles to add table borders. Created global mixin for table data formatting: - Show '--' for undefined or empty string values - Map Redfish health status options to status-icon values Signed-off-by: Yoshie Muranaka Change-Id: I5b45c37997647f5a265c1e84eb53f0b51699ee20 --- .../styles/vendor-overrides/bootstrap/_tables.scss | 63 +++++++++-- src/components/AppNavigation/AppNavigation.vue | 2 +- src/components/Mixins/TableDataFormatter.js | 25 +++++ src/locales/en-US.json | 17 +++ src/router/index.js | 8 ++ src/store/index.js | 4 +- src/store/modules/Health/SystemStore.js | 39 +++++++ src/views/Health/HardwareStatus/HardwareStatus.vue | 34 ++++++ .../HardwareStatus/HardwareStatusTableStystem.vue | 120 +++++++++++++++++++++ src/views/Health/HardwareStatus/index.js | 2 + 10 files changed, 301 insertions(+), 13 deletions(-) create mode 100644 src/components/Mixins/TableDataFormatter.js create mode 100644 src/store/modules/Health/SystemStore.js create mode 100644 src/views/Health/HardwareStatus/HardwareStatus.vue create mode 100644 src/views/Health/HardwareStatus/HardwareStatusTableStystem.vue create mode 100644 src/views/Health/HardwareStatus/index.js diff --git a/src/assets/styles/vendor-overrides/bootstrap/_tables.scss b/src/assets/styles/vendor-overrides/bootstrap/_tables.scss index 2372d257..b20feb0d 100644 --- a/src/assets/styles/vendor-overrides/bootstrap/_tables.scss +++ b/src/assets/styles/vendor-overrides/bootstrap/_tables.scss @@ -1,22 +1,63 @@ -table { +.table { position: relative; z-index: $zindex-dropdown; - .status-icon svg { - width: 1rem; - height: auto; - } -} -.table-light { td { - border-top: none; + border-top: 1px solid $gray-300; border-bottom: 1px solid $gray-300; + &:first-of-type { + border-left: 1px solid $gray-300; + } + &:last-of-type { + border-right: 1px solid $gray-300; + } } -} -.thead-light.thead-light { - th { + // thead-light added for specificiy + .thead-light th { border: none; color: $dark; } + + .status-icon svg { + width: 1rem; + height: auto; + } + + .b-table-has-details { + td { + border-bottom: none; + } + .table-row-expand svg { + transform: rotate(180deg); + } + } + + .b-table-details { + background-color: $light; + td { + padding-left: calc(50px + (#{$table-cell-padding} * 2)); + } + dl { + margin: 0; + } + dt { + display: inline-block; + margin-right: $spacer / 2; + } + dd { + display: inline-block; + } + } + + .table-row-expand { + width: 50px; + .btn { + padding: 0; + width: 50px; + } + svg { + fill: $dark; + } + } } \ No newline at end of file diff --git a/src/components/AppNavigation/AppNavigation.vue b/src/components/AppNavigation/AppNavigation.vue index 8103558e..09c1eb8b 100644 --- a/src/components/AppNavigation/AppNavigation.vue +++ b/src/components/AppNavigation/AppNavigation.vue @@ -18,7 +18,7 @@ {{ $t('appNavigation.eventLogs') }} - + {{ $t('appNavigation.hardwareStatus') }} diff --git a/src/components/Mixins/TableDataFormatter.js b/src/components/Mixins/TableDataFormatter.js new file mode 100644 index 00000000..5dbe40ad --- /dev/null +++ b/src/components/Mixins/TableDataFormatter.js @@ -0,0 +1,25 @@ +const TableDataFormatter = { + methods: { + tableFormatter(value) { + if (value === undefined || value === '') { + return '--'; + } else { + return value; + } + }, + statusIcon(status) { + switch (status) { + case 'OK': + return 'success'; + case 'Warning': + return 'warning'; + case 'Critical': + return 'danger'; + default: + return ''; + } + } + } +}; + +export default TableDataFormatter; diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 8a722e39..8072770f 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -124,6 +124,23 @@ "successDelete": "Successfully deleted %{count} log. | Successfully deleted %{count} logs." } }, + "pageHardwareStatus": { + "system": "System", + "table": { + "id": "ID", + "health": "Health", + "partNumber": "Part number", + "serialNumber": "Serial number", + "assetTag": "Asset tag", + "description": "Description", + "indicatorLed": "Indicator LED", + "model": "Model", + "powerState": "Power state", + "statusHealthRollup": "Status (Health rollup)", + "statusState": "Status (State)", + "systemType": "System 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 e35e0f59..f67d5ee4 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -31,6 +31,14 @@ const routes = [ title: 'appPageTitle.eventLogs' } }, + { + path: '/health/hardware-status', + name: 'hardware-status', + component: () => import('@/views/Health/HardwareStatus'), + meta: { + title: 'appPageTitle.hardwareStatus' + } + }, { path: '/health/sensors', name: 'sensors', diff --git a/src/store/index.js b/src/store/index.js index ad55030a..ea1e9b3b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -15,6 +15,7 @@ import NetworkSettingStore from './modules/Configuration/NetworkSettingsStore'; import EventLogStore from './modules/Health/EventLogStore'; import SensorsStore from './modules/Health/SensorsStore'; import ServerLedStore from './modules/Control/ServerLedStore'; +import SystemStore from './modules/Health/SystemStore'; import WebSocketPlugin from './plugins/WebSocketPlugin'; @@ -38,7 +39,8 @@ export default new Vuex.Store({ eventLog: EventLogStore, sensors: SensorsStore, sslCertificates: SslCertificatesStore, - serverLed: ServerLedStore + serverLed: ServerLedStore, + system: SystemStore }, plugins: [WebSocketPlugin] }); diff --git a/src/store/modules/Health/SystemStore.js b/src/store/modules/Health/SystemStore.js new file mode 100644 index 00000000..9c4c477d --- /dev/null +++ b/src/store/modules/Health/SystemStore.js @@ -0,0 +1,39 @@ +import api from '@/store/api'; + +const SystemStore = { + namespaced: true, + state: { + systems: [] + }, + getters: { + systems: state => state.systems + }, + mutations: { + setSystemInfo: (state, data) => { + const system = {}; + system.assetTag = data.AssetTag; + system.description = data.Description; + system.health = data.Status.Health; + system.id = data.Id; + system.indicatorLed = data.IndicatorLED; + system.model = data.Model; + system.partNumber = data.PartNumber; + system.powerState = data.PowerState; + system.serialNumber = data.SerialNumber; + system.healthRollup = data.Status.HealthRollup; + system.statusState = data.Status.State; + system.systemType = data.SystemType; + state.systems = [system]; + } + }, + actions: { + async getSystem({ commit }) { + return await api + .get('/redfish/v1/Systems/system') + .then(({ data }) => commit('setSystemInfo', data)) + .catch(error => console.log(error)); + } + } +}; + +export default SystemStore; diff --git a/src/views/Health/HardwareStatus/HardwareStatus.vue b/src/views/Health/HardwareStatus/HardwareStatus.vue new file mode 100644 index 00000000..9f34b534 --- /dev/null +++ b/src/views/Health/HardwareStatus/HardwareStatus.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/views/Health/HardwareStatus/HardwareStatusTableStystem.vue b/src/views/Health/HardwareStatus/HardwareStatusTableStystem.vue new file mode 100644 index 00000000..3894eceb --- /dev/null +++ b/src/views/Health/HardwareStatus/HardwareStatusTableStystem.vue @@ -0,0 +1,120 @@ + + + diff --git a/src/views/Health/HardwareStatus/index.js b/src/views/Health/HardwareStatus/index.js new file mode 100644 index 00000000..25d4551c --- /dev/null +++ b/src/views/Health/HardwareStatus/index.js @@ -0,0 +1,2 @@ +import HardwareStatus from './HardwareStatus.vue'; +export default HardwareStatus; -- cgit v1.2.3