xref: /openbmc/webui-vue/src/components/AppHeader/AppHeader.vue (revision 9e36f522b94511c1d77335493c09e68975db031c)
1<template>
2  <div>
3    <header id="page-header">
4      <a role="link" class="link-skip-nav btn btn-light" href="#main-content">
5        {{ $t('appHeader.skipToContent') }}
6      </a>
7
8      <b-navbar
9        variant="dark"
10        type="dark"
11        :aria-label="$t('appHeader.applicationHeader')"
12      >
13        <!-- Left aligned nav items -->
14        <b-button
15          id="app-header-trigger"
16          class="nav-trigger"
17          aria-hidden="true"
18          title="Open navigation"
19          type="button"
20          variant="link"
21          @click="toggleNavigation"
22        >
23          <icon-close v-if="isNavigationOpen" />
24          <icon-menu v-if="!isNavigationOpen" />
25        </b-button>
26        <b-navbar-nav>
27          <b-nav-text>{{ $t('appHeader.bmcSystemManagement') }}</b-nav-text>
28        </b-navbar-nav>
29        <!-- Right aligned nav items -->
30        <b-navbar-nav class="ml-auto">
31          <b-nav-item>
32            {{ $t('appHeader.health') }}
33            <status-icon :status="healthStatusIcon" />
34          </b-nav-item>
35          <b-nav-item>
36            {{ $t('appHeader.power') }}
37            <status-icon :status="hostStatusIcon" />
38          </b-nav-item>
39          <!-- Using LI elements instead of b-nav-item to support semantic button elements -->
40          <li class="nav-item">
41            <b-button id="app-header-refresh" variant="link" @click="refresh">
42              {{ $t('appHeader.refresh') }}
43              <icon-renew />
44            </b-button>
45          </li>
46          <li>
47            <b-button id="app-header-logout" variant="link" @click="logout">
48              {{ $t('appHeader.logOut') }}
49              <icon-avatar />
50            </b-button>
51          </li>
52        </b-navbar-nav>
53      </b-navbar>
54    </header>
55  </div>
56</template>
57
58<script>
59import IconAvatar from '@carbon/icons-vue/es/user--avatar/20';
60import IconClose from '@carbon/icons-vue/es/close/20';
61import IconMenu from '@carbon/icons-vue/es/menu/20';
62import IconRenew from '@carbon/icons-vue/es/renew/20';
63import StatusIcon from '../Global/StatusIcon';
64
65export default {
66  name: 'AppHeader',
67  components: { IconAvatar, IconClose, IconMenu, IconRenew, StatusIcon },
68  data() {
69    return {
70      isNavigationOpen: false
71    };
72  },
73  computed: {
74    hostStatus() {
75      return this.$store.getters['global/hostStatus'];
76    },
77    healthStatus() {
78      return this.$store.getters['eventLog/healthStatus'];
79    },
80    hostStatusIcon() {
81      switch (this.hostStatus) {
82        case 'on':
83          return 'success';
84        case 'error':
85          return 'danger';
86        case 'off':
87        default:
88          return 'secondary';
89      }
90    },
91    healthStatusIcon() {
92      switch (this.healthStatus) {
93        case 'good':
94          return 'success';
95        case 'warning':
96          return 'warning';
97        case 'critical':
98          return 'danger';
99        default:
100          return 'secondary';
101      }
102    }
103  },
104  created() {
105    this.getHostInfo();
106    this.getEvents();
107  },
108  mounted() {
109    this.$root.$on(
110      'change:isNavigationOpen',
111      isNavigationOpen => (this.isNavigationOpen = isNavigationOpen)
112    );
113  },
114  methods: {
115    getHostInfo() {
116      this.$store.dispatch('global/getHostStatus');
117    },
118    getEvents() {
119      this.$store.dispatch('eventLog/getEventLogData');
120    },
121    refresh() {
122      this.$emit('refresh');
123    },
124    logout() {
125      this.$store.dispatch('authentication/logout');
126    },
127    toggleNavigation() {
128      this.$root.$emit('toggle:navigation');
129    }
130  }
131};
132</script>
133
134<style lang="scss" scoped>
135.link-skip-nav {
136  position: absolute;
137  top: -60px;
138  left: 0.5rem;
139  z-index: $zindex-popover;
140  transition: $duration--moderate-01 $exit-easing--expressive;
141  &:focus {
142    top: 0.5rem;
143    transition-timing-function: $entrance-easing--expressive;
144  }
145}
146.navbar-dark {
147  .navbar-text,
148  .nav-link,
149  .btn-link {
150    color: $white !important;
151    fill: currentColor;
152  }
153}
154
155.nav-item {
156  fill: $light;
157}
158
159.navbar {
160  padding: 0;
161  height: $header-height;
162  overflow: hidden;
163
164  .btn-link {
165    padding: $spacer / 2;
166  }
167}
168
169.navbar-nav {
170  padding: 0 $spacer;
171}
172
173.nav-trigger {
174  fill: $light;
175  width: $header-height;
176  height: $header-height;
177  transition: none;
178
179  svg {
180    margin: 0;
181  }
182
183  &:hover {
184    fill: $light;
185    background-color: $dark;
186  }
187
188  @include media-breakpoint-up($responsive-layout-bp) {
189    display: none;
190  }
191}
192</style>
193