summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAppaRao Puli <apparao.puli@linux.intel.com>2018-11-14 20:33:30 +0530
committerGunnar Mills <gmills@us.ibm.com>2019-03-19 21:34:35 +0000
commitb1289ec99faa6345bb402a6887df82bb7dd9a7c0 (patch)
treeba87f093e12732bb634b3aac0cd1a626a8fe7d4c
parentdde251d5ad547c0c7536b6b930e1bad8c2ef2752 (diff)
downloadphosphor-webui-b1289ec99faa6345bb402a6887df82bb7dd9a7c0.tar.gz
phosphor-webui-b1289ec99faa6345bb402a6887df82bb7dd9a7c0.zip
WebUI system logs implementation
This commit implements the webui logs page which will show all system logs depends on user selection( SEL or Event or Oem). This is based out of redfish systems log services. - View logs with pagination. - Search filter for logs view. - Sort option with Type, Id, Severity, Date. - Clear logs. - Export logs. UnitTest: - Existing bmcweb send the system logs of EntryType "Event". So Loaded UI, selected Type "Event" and validated all the above mentioned operations. Change-Id: I0384e475f7913ca66b6db5d64831583fb382f8d5 Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
-rw-r--r--app/common/directives/app-header.js13
-rw-r--r--app/common/directives/app-navigation.html22
-rw-r--r--app/common/services/api-utils.js48
-rw-r--r--app/common/services/dataService.js5
-rw-r--r--app/index.js1
-rw-r--r--app/server-health/controllers/syslog-controller.html100
-rw-r--r--app/server-health/controllers/syslog-controller.js122
-rw-r--r--app/server-health/index.js5
-rw-r--r--app/server-health/styles/index.scss1
-rw-r--r--app/server-health/styles/syslog.scss309
10 files changed, 616 insertions, 10 deletions
diff --git a/app/common/directives/app-header.js b/app/common/directives/app-header.js
index 0e0a6e6..9e10619 100644
--- a/app/common/directives/app-header.js
+++ b/app/common/directives/app-header.js
@@ -95,10 +95,23 @@ window.angular && (function(angular) {
});
};
+ $scope.loadSystemName = function() {
+ // Dynamically get ComputerSystems Name/serial
+ // which differs across OEM's
+ APIUtils.getRedfishSysName().then(
+ function(res) {
+ dataService.setSystemName(res);
+ },
+ function(error) {
+ console.log(JSON.stringify(error));
+ });
+ };
+
function loadData() {
$scope.loadServerStatus();
$scope.loadNetworkInfo();
$scope.loadServerHealth();
+ $scope.loadSystemName();
}
loadData();
diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html
index 2f3ded7..a45a24b 100644
--- a/app/common/directives/app-navigation.html
+++ b/app/common/directives/app-navigation.html
@@ -72,32 +72,34 @@
<a href="#/server-health/inventory-overview" tabindex="7">Hardware status</a></li>
<li ng-class="{'active': (path == '/server-health/sensors-overview' || path == '/server-health/sensors')}">
<a href="#/server-health/sensors-overview" ng-click="closeSubnav()" tabindex="8">Sensors</a></li>
+ <li ng-class="{'active': (path == '/server-health/sys-log')}" ng-show="dataService.configJson.redfishSupportEnabled">
+ <a href="#/server-health/sys-log" ng-click="closeSubnav()" tabindex="9">System Logs</a></li>
</ul>
<ul class="nav__second-level btn-control" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'server-control')}">
<li ng-class="{'active': (path == '/server-control' || path == '/server-control/power-operations')}">
- <a href="#/server-control/power-operations" tabindex="9" ng-click="closeSubnav()">Server power operations</a>
+ <a href="#/server-control/power-operations" tabindex="10" ng-click="closeSubnav()">Server power operations</a>
</li>
<li ng-class="{'active': (path == '/server-control/power-usage')}">
- <a href="#/server-control/power-usage" tabindex="10" ng-click="closeSubnav()">Manage power usage</a></li>
+ <a href="#/server-control/power-usage" tabindex="11" ng-click="closeSubnav()">Manage power usage</a></li>
<li ng-class="{'active': (path == '/server-control/server-led')}">
- <a href="#/server-control/server-led" tabindex="11" ng-click="closeSubnav()">Server LED</a></li>
+ <a href="#/server-control/server-led" tabindex="12" ng-click="closeSubnav()">Server LED</a></li>
<li ng-class="{'active': (path == '/server-control/bmc-reboot')}">
- <a href="#/server-control/bmc-reboot" tabindex="12" ng-click="closeSubnav()">Reboot BMC</a></li>
+ <a href="#/server-control/bmc-reboot" tabindex="13" ng-click="closeSubnav()">Reboot BMC</a></li>
<li ng-class="{'active': (path == '/server-control/remote-console')}">
- <a href="#/server-control/remote-console" tabindex="13" ng-click="closeSubnav()">Serial over LAN console</a></li>
+ <a href="#/server-control/remote-console" tabindex="14" ng-click="closeSubnav()">Serial over LAN console</a></li>
</ul>
<ul class="nav__second-level btn-firmware" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'configuration')}">
<li ng-class="{'active': (path == '/configuration' || path == '/configuration/network')}">
- <a href="#/configuration/network" tabindex="14" ng-click="closeSubnav()">Network settings</a></li>
+ <a href="#/configuration/network" tabindex="15" ng-click="closeSubnav()">Network settings</a></li>
<li ng-class="{'active': (path == '/configuration' || path == '/configuration/snmp')}">
- <a href="#/configuration/snmp" tabindex="15" ng-click="closeSubnav()">SNMP settings</a></li>
+ <a href="#/configuration/snmp" tabindex="16" ng-click="closeSubnav()">SNMP settings</a></li>
<li ng-class="{'active': (path == '/configuration' || path == '/configuration/firmware')}">
- <a href="#/configuration/firmware" tabindex="16" ng-click="closeSubnav()">Firmware</a></li>
+ <a href="#/configuration/firmware" tabindex="17" ng-click="closeSubnav()">Firmware</a></li>
<li ng-class="{'active': (path == '/configuration' || path == '/configuration/date-time')}">
- <a href="#/configuration/date-time" tabindex="17" ng-click="closeSubnav()">Date and time settings</a></li>
+ <a href="#/configuration/date-time" tabindex="18" ng-click="closeSubnav()">Date and time settings</a></li>
</ul>
<ul class="nav__second-level btn-users" ng-style="navStyle" ng-class="{opened: (showSubMenu && firstLevel == 'users')}">
<li ng-class="{'active': (path == '/users' || path == '/users/manage-accounts')}">
- <a href="#/users/manage-accounts" tabindex="18" ng-click="closeSubnav()">Manage user accounts</a></li>
+ <a href="#/users/manage-accounts" tabindex="19" ng-click="closeSubnav()">Manage user account</a></li>
</ul>
</nav>
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 503fcd1..743d3fa 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -57,6 +57,54 @@ window.angular && (function(angular) {
return ip.match(
/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/);
},
+ getRedfishSysName: function() {
+ return $http({
+ method: 'GET',
+ url: DataService.getHost() + '/redfish/v1/Systems',
+ withCredentials: true
+ })
+ .then(
+ function(response) {
+ var sysUrl = response.data['Members'][0]['@odata.id'];
+ return sysUrl.split('/').pop(-1);
+ },
+ function(error) {
+ console.log(JSON.stringify(error));
+ });
+ },
+ getSystemLogs: function(recordType) {
+ var uri = '/redfish/v1/Systems/' + DataService.systemName +
+ '/LogServices/EventLog/Entries';
+ return $http({
+ method: 'GET',
+ url: DataService.getHost() + uri,
+ withCredentials: true
+ })
+ .then(
+ function(response) {
+ var logEntries = [];
+ angular.forEach(response.data['Members'], function(log) {
+ if (log.hasOwnProperty('EntryType')) {
+ if (log['EntryType'] == recordType) {
+ logEntries.push(log);
+ }
+ }
+ });
+ return logEntries;
+ },
+ function(error) {
+ console.log(JSON.stringify(error));
+ });
+ },
+ clearSystemLogs: function() {
+ var uri = '/redfish/v1/Systems/' + DataService.systemName +
+ '/LogServices/EventLog/Actions/LogService.ClearLog';
+ return $http({
+ method: 'POST',
+ url: DataService.getHost() + uri,
+ withCredentials: true
+ });
+ },
deleteObject: function(path) {
return $http({
method: 'POST',
diff --git a/app/common/services/dataService.js b/app/common/services/dataService.js
index 76ab381..9017227 100644
--- a/app/common/services/dataService.js
+++ b/app/common/services/dataService.js
@@ -34,6 +34,7 @@ window.angular && (function(angular) {
this.errorModalDetails = {};
this.ignoreHttpError = false;
+ this.systemName = '';
this.configJson = require('../../../config.json');
@@ -134,6 +135,10 @@ window.angular && (function(angular) {
this.deactivateErrorModal = function() {
this.displayErrorModal = false;
};
+
+ this.setSystemName = function(sysName) {
+ this.systemName = sysName;
+ };
}
]);
})(window.angular);
diff --git a/app/index.js b/app/index.js
index c9fed83..3b1089d 100644
--- a/app/index.js
+++ b/app/index.js
@@ -74,6 +74,7 @@ import server_health_index from './server-health/index.js';
import inventory_overview_controller from './server-health/controllers/inventory-overview-controller.js';
import log_controller from './server-health/controllers/log-controller.js';
import sensors_overview_controller from './server-health/controllers/sensors-overview-controller.js';
+import syslog_controller from './server-health/controllers/syslog-controller.js';
import redfish_index from './redfish/index.js';
import redfish_controller from './redfish/controllers/redfish-controller.js';
diff --git a/app/server-health/controllers/syslog-controller.html b/app/server-health/controllers/syslog-controller.html
new file mode 100644
index 0000000..b503bd0
--- /dev/null
+++ b/app/server-health/controllers/syslog-controller.html
@@ -0,0 +1,100 @@
+<loader loading="loading"></loader>
+<div id="sys-log">
+ <section id="sys-log__events" class="table row column">
+ <div class="row column">
+ <h1>System Logs</h1>
+ <div class="page-header">
+ <p class="inline h4">Select system log type: </p>
+ <div class="inline dropdown__wrapper" >
+ <button type="button" class="dropdown__button" ng-click="showLogDropdown = !showLogDropdown"><strong>{{selectedRecordType}}</strong></button>
+ <ul class="dropdown__list inline" ng-show="showLogDropdown">
+ <li ng-repeat="recordType in recordTypeList">
+ <button type="button" ng-click="selectRecordType(recordType);">{{recordType}}</button>
+ </li>
+ </ul>
+ </div>
+ <a ng-href="data:text/json;charset=utf-8,{{sysLogs}}" class="inline btn-export float-right" download="systemLogs.json" ng-show="sysLogs.length">Export </a>
+ <button class="inline clear-input float-right btn-secondary" ng-click="confirm = !confirm" ng-show="sysLogs.length">&#10005; Clear {{selectedRecordType}} Logs</button>
+ <div class="inline__confirm event__confirm" ng-show="confirm">
+ <div class="inline__confirm-message">
+ <p class="h3">Are you sure you want to <strong class="ng-binding">clear {{selectedRecordType}} logs</strong>?
+ </p>
+ </div>
+ <div class="inline__confirm-buttons">
+ <button class="btn-primary" ng-click="clearSystemLogEntries()">Yes</button>
+ <button class="btn-primary" ng-click="confirm = false">No</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+ <section class="row column">
+ <p class="content-label">Filter {{selectedRecordType}} Logs</p>
+ <div class="content__search">
+ <label for="content__search-input">Search</label>
+ <input id="content__search-input" type="text" ng-model="customSearch" ng-keydown="doSearchOnEnter($event)"/>
+ <div class="search-submit__wrapper">
+ <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>
+ </section>
+ <section id="sys-log__events" class="table row column" ng-show="sysLogs.length">
+ <div class="table row column">
+ <div class="table__head">
+ <div class="table__row">
+ <div class="table__cell sys-log__col-wrapper sys-log__col-id">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('Id', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('Id', true)"></button>
+ </div>
+ ID
+ </div>
+ <div class="table__cell sys-log__col-wrapper">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('Created', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('Created', true)"></button>
+ </div>
+ Timestamp
+ </div>
+ <div class="table__cell sys-log__col-wrapper">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('Name', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('Name', true)"></button>
+ </div>
+ Name
+ </div>
+ <div class="table__cell sys-log__col-wrapper">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('SensorType', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('SensorType', true)"></button>
+ </div>
+ Type
+ </div>
+ <div class="table__cell sys-log__col-wrapper sys-log__col-sev">
+ <div class="column small-2 sort_button_wrapper">
+ <button class="sort-ascending" ng-click="sortBy('Severity', false)"></button>
+ <button class="sort-descending" ng-click="sortBy('Severity', true)"></button>
+ </div>
+ Severity
+ </div>
+ <div class="table__cell sys-log__col-wrapper sys-log__col-desc">Description</div>
+ </div>
+ </div>
+ <div class="table__body">
+ <div class="table__row" dir-paginate="log in (sysLogs | filter:filterBySearchTerms | orderBy:sortKey:reverse) | itemsPerPage:itemsPerPage">
+ <div class="table__cell sys-log__col-wrapper sys-log__col-id">{{log.Id}}</div>
+ <div class="table__cell sys-log__col-wrapper">{{log.Created | localeDate}}</div>
+ <div class="table__cell sys-log__col-wrapper">{{log.Name}}</div>
+ <div class="table__cell sys-log__col-wrapper">{{log.SensorType}}</div>
+ <div class="table__cell sys-log__col-wrapper sys-log__col-sev">{{log.Severity}}</div>
+ <div class="table__cell sys-log__col-wrapper sys-log__col-desc">{{log.Message}}</div>
+ </div>
+ </div>
+ </div>
+ <dir-pagination-controls></dir-pagination-controls>
+ </section>
+ <section id="sys-log__events" class="table row column" ng-show="!sysLogs.length">
+ <p>There are no {{selectedRecordType}} logs to display at this time.</p>
+ </section>
+</div> <!-- end event log -->
diff --git a/app/server-health/controllers/syslog-controller.js b/app/server-health/controllers/syslog-controller.js
new file mode 100644
index 0000000..cec1d99
--- /dev/null
+++ b/app/server-health/controllers/syslog-controller.js
@@ -0,0 +1,122 @@
+/**
+ * Controller for log
+ *
+ * @module app/serverHealth
+ * @exports sysLogController
+ * @name sysLogController
+ */
+
+window.angular && (function(angular) {
+ 'use strict';
+ angular.module('app.serverHealth')
+ .config([
+ 'paginationTemplateProvider',
+ function(paginationTemplateProvider) {
+ paginationTemplateProvider.setString(
+ require('../../common/directives/dirPagination.tpl.html'));
+ }
+ ])
+ .controller('sysLogController', [
+ '$scope', 'APIUtils', 'Constants',
+ function($scope, APIUtils, Constants) {
+ $scope.itemsPerPage = Constants.PAGINATION.LOG_ITEMS_PER_PAGE;
+ $scope.loading = true;
+ $scope.sysLogs = [];
+ $scope.customSearch = '';
+ $scope.searchTerms = [];
+ $scope.sortKey = 'Id';
+ $scope.showLogDropdown = false;
+ $scope.recordTypeList =
+ ['SEL', 'Event', 'Oem']; // From Redfish specification.
+ $scope.selectedRecordType = 'SEL'; // Default Select to SEL.
+
+ $scope.selectRecordType = function(recordType) {
+ $scope.selectedRecordType = recordType;
+ $scope.showLogDropdown = false;
+ APIUtils.getSystemLogs(recordType)
+ .then(
+ function(res) {
+ $scope.sysLogs = res;
+ $scope.filterTypes.push('All');
+ $scope.sysLogs.forEach(function(log) {
+ if ($scope.filterTypes.indexOf(log.SensorType) < 0) {
+ $scope.filterTypes.push(log.SensorType);
+ }
+ });
+ },
+ function(error) {
+ console.log(JSON.stringify(error));
+ })
+ .finally(function() {
+ $scope.loading = false;
+ });
+ };
+
+ $scope.clearSystemLogEntries = function() {
+ $scope.confirm = false;
+ APIUtils.clearSystemLogs()
+ .then(
+ function(res) {
+ console.log(JSON.stringify(res));
+ },
+ function(error) {
+ console.log(JSON.stringify(error));
+ })
+ .finally(function() {
+ $scope.selectRecordType($scope.selectedRecordType);
+ });
+ };
+
+ $scope.sortBy = function(keyname, isReverse) {
+ $scope.sortKey = keyname;
+ $scope.reverse = isReverse;
+ };
+
+ $scope.clear = function() {
+ $scope.customSearch = '';
+ $scope.searchTerms = [];
+ };
+
+ $scope.doSearchOnEnter = function(event) {
+ var search =
+ $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+ if (event.keyCode === 13 && search.length >= 2) {
+ $scope.searchTerms = $scope.customSearch.split(' ');
+ } else {
+ if (search.length == 0) {
+ $scope.searchTerms = [];
+ }
+ }
+ };
+
+ $scope.doSearchOnClick = function() {
+ var search =
+ $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
+ if (search.length >= 2) {
+ $scope.searchTerms = $scope.customSearch.split(' ');
+ } else {
+ if (search.length == 0) {
+ $scope.searchTerms = [];
+ }
+ }
+ };
+
+ $scope.filterBySearchTerms = function(log) {
+ if (!$scope.searchTerms.length) return true;
+
+ for (var i = 0, length = $scope.searchTerms.length; i < length;
+ i++) {
+ // TODO: Form it while getting data
+ var search_text = log.Id + ' ' + log.Name.toLowerCase() + ' ' +
+ log.Message.toLowerCase();
+ if (search_text.indexOf($scope.searchTerms[i].toLowerCase()) ==
+ -1)
+ return false;
+ }
+ return true;
+ };
+
+ setTimeout($scope.selectRecordType($scope.selectedRecordType), 2000);
+ }
+ ]);
+})(angular);
diff --git a/app/server-health/index.js b/app/server-health/index.js
index 088105b..96172d8 100644
--- a/app/server-health/index.js
+++ b/app/server-health/index.js
@@ -42,6 +42,11 @@ window.angular && (function(angular) {
'controller': 'sensorsOverviewController',
authenticated: true
})
+ .when('/server-health/sys-log', {
+ 'template': require('./controllers/syslog-controller.html'),
+ 'controller': 'sysLogController',
+ authenticated: true
+ })
.when('/server-health', {
'template': require('./controllers/log-controller.html'),
'controller': 'logController',
diff --git a/app/server-health/styles/index.scss b/app/server-health/styles/index.scss
index 009e991..f120af0 100644
--- a/app/server-health/styles/index.scss
+++ b/app/server-health/styles/index.scss
@@ -1,3 +1,4 @@
@import "./inventory.scss";
@import "./log.scss";
@import "./sensors.scss";
+@import "./syslog.scss";
diff --git a/app/server-health/styles/syslog.scss b/app/server-health/styles/syslog.scss
new file mode 100644
index 0000000..c225e55
--- /dev/null
+++ b/app/server-health/styles/syslog.scss
@@ -0,0 +1,309 @@
+// Event Log SCSS
+#sys-log {
+
+ // Dropwdowns filter
+ .dropdown__date.row {
+ padding: .5em;
+ }
+
+ //Timezone select
+ .sys-log__timezone,
+ .sys-log__timezone button {
+ position: relative;
+ text-transform: uppercase;
+ color: $lightbg__primary;
+ font-size: .9em;
+ font-weight: 700;
+ border: 0;
+ }
+ .content__search {
+ float: none;
+ @include mediaQuery(x-large) {
+ @include fastTransition-all;
+ }
+ }
+}
+
+.sort_button_wrapper {
+ padding-top:.3em;
+}
+.sys-log__filters {
+ position: relative;
+ padding-bottom: .5em;
+ padding-top: .5em;
+
+ @media (min-width: 1333px) {
+ float: right;
+ display: inline-block;
+ }
+}
+
+.accord-trigger {
+ position: absolute;
+ right: 1em;
+ top: .3em;
+}
+
+#sys-log__events,
+.sys-log__events {
+ display: block;
+ margin-top: 1.6em;
+ position: relative;
+ .header__actions-bar {
+ .btn-export,
+ .btn-delete,
+ .btn-resolve {
+ color: $white;
+ }
+ }
+ .inline__confirm {
+ height: auto;
+ margin-left: 0;
+ left: 0;
+ padding: 1em 2em 1em 2em
+ }
+ .inline__confirm-message {
+ margin-top: 5px;
+ margin-bottom: -10px;
+ }
+ .inline__confirm-buttons .btn-primary {
+ padding: .5em 2em;
+ min-height: 25px;
+ margin-top: .5em;
+ @include mediaQuery(medium) {
+ margin-top: 0;
+ }
+ }
+ .sys-log__col-wrapper {
+ word-wrap: break-word;
+ white-space: initial;
+ }
+ .col-logged-events {
+ span {
+ display: inline-block;
+ font-weight: 700;
+ margin-right: .3em;
+ }
+ }
+ .sys-log__col-id {
+ max-width: 10%;
+ }
+ .sys-log__col-sev {
+ max-width: 12%;
+ }
+ .sys-log__col-desc {
+ min-width: 30%;
+ max-width: 40%;
+ }
+
+ .dropdown__button {
+ margin-bottom: 1.2em;
+ }
+ .dropdown__list {
+ margin-top: -17px;
+ }
+ .dropdown__button {
+ width: 25em;
+ margin-top: 0;
+ text-align: left;
+ border: 0.1em solid;
+ }
+ .dropdown__wrapper {
+ width: 25em;
+ margin-top: 0.4em;
+ text-align: left;
+ }
+ //Export log
+ .btn-export, .btn-meta-copy,
+ .btn-delete,
+ .btn-resolve {
+ color: black;
+ font-size: .9em;
+ font-weight: 700;
+ position: relative;
+ padding: 0 0 1em 2em;
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ .btn-resolve.disabled:hover,
+ .btn-delete.disabled:hover{
+ cursor: default;
+ text-decoration: none;
+ }
+ .btn-export {
+ margin-top: 7px;
+ padding-bottom: 0;
+ }
+ .btn-export:before {
+ content: '\21E5';
+ position: absolute;
+ font-size: 1.7em;
+ vertical-align: middle;
+ transform: rotate(90deg);
+ display: inline-block;
+ left: 2px;
+ top: -5px;
+ }
+ .btn-meta-copy,
+ .btn-delete,
+ .btn-resolve {
+ margin-left: 5px;
+ padding: .5em .5em;
+ }
+
+ // Single event log card
+ .sys-log__single-event {
+ border: 1px solid $medgrey;
+ padding: 1em 1em 1em .7em;
+ margin: .5em 0 .5em 0;
+ position: relative;
+ overflow: hidden;
+ @include fastTransition-all;
+ &.active {
+ background-color: $lightgrey;
+ @include slowTransition-all;
+ }
+ }
+ .sys-log__event-info {
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ //Event description
+ .event__description {
+ font-weight: 400;
+ margin-left: 1em;
+ flex:35%;
+ @include mediaQuery(small) {
+ margin-left: 4.5em;
+ margin-right: 1em;
+ }
+ word-break: break-all;
+ }
+
+ //Event ID
+ .event__id {
+ @include fontCourierBold;
+ font-size: .9em;
+ color: $darkgrey;
+ margin-right: 1em;
+ }
+
+ .event__timestamp {
+ text-align: right;
+ @include fontCourierBold;
+ font-size: .9em;
+ color: $darkgrey;
+ max-width: 18em;
+ @media (min-width: 1105px) {
+ float: right;
+ }
+ }
+
+ // Event metadata row
+ .event__metadata-row {
+ max-height: 0;
+ overflow: hidden;
+ transition: max-height .5s linear;
+ &.active {
+ max-height: 1000px;
+ @include mediaQuery(small) {
+ max-height: 1000px;
+ }
+ @include mediaQuery(medium) {
+ max-height: 1000px;
+ }
+ }
+ }
+
+ //Event metadata
+ .event__metadata {
+ height: 200px;
+ overflow-y: scroll;
+ border: 1px solid $medgrey;
+ padding: .5em .5em 0;
+ background: $white;
+ display: block;
+ margin-bottom: 1.5em;
+ &::-webkit-scrollbar {
+ -webkit-appearance: none;
+ width: 7px;
+ }
+ &::-webkit-scrollbar-thumb {
+ border-radius: 4px;
+ background-color: rgba(0, 0, 0, .5);
+ -webkit-box-shadow: 0 0 1px rgba(255, 255, 255, .5);
+ }
+ }
+
+ //Event Related Items
+ .event__related {
+ width: 100%;
+ }
+ .event__related-label {
+ font-weight: 700;
+ margin-right: 1.2em;
+ padding-top: .3em;
+ float: left;
+ }
+ .event__related-item {
+ margin-right: 1em;
+ padding-top: .3em;
+ display: inline-block;
+ float: left;
+ clear: both;
+ }
+ .event__actions {
+ margin-left: -1em;
+ margin-top: .5em;
+ @include mediaQuery(medium) {
+ float: right;
+ margin-top: -5px;
+ }
+ }
+ .event__icon {
+ width: 20px;
+ height: 20px;
+ font-weight: normal;
+ margin-right: .5em;
+ margin-top: -3px;
+ display: inline-block;
+ }
+ .sort-ascending {
+ display: block;
+ padding: 0;
+ transform: rotate(-90deg);
+ font-size: 1em;
+ color: lighten($darkgrey, 10%);
+ &:hover {
+ color: $darkbg__accent;
+ }
+ &:after {
+ content: '\276F'
+ }
+ &:focus {
+ outline: 0;
+ color: $darkbg__accent;
+ }
+ }
+ .sort-descending {
+ display: block;
+ padding: 0;
+ transform: rotate(-90deg);
+ font-size: 1em;
+ color: lighten($darkgrey, 10%);
+ &:hover {
+ color: $darkbg__accent;
+ }
+ &:after {
+ content: '\276e'
+ }
+ &:focus {
+ outline: 0;
+ color: $darkbg__accent;
+ }
+ }
+}
+//end sys-log__events
OpenPOWER on IntegriCloud