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 to="/health/event-logs">
32            {{ $t('appHeader.health') }}
33            <status-icon :status="healthStatusIcon" />
34          </b-nav-item>
35          <b-nav-item to="/control/server-power-operations">
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 class="nav-item">
47            <b-dropdown id="app-header-user" variant="link" right>
48              <template v-slot:button-content>
49                <icon-avatar />
50                {{ username }}
51              </template>
52              <b-dropdown-item to="/profile-settings"
53                >{{ $t('appHeader.profileSettings') }}
54              </b-dropdown-item>
55              <b-dropdown-item @click="logout">{{
56                $t('appHeader.logOut')
57              }}</b-dropdown-item>
58            </b-dropdown>
59          </li>
60        </b-navbar-nav>
61      </b-navbar>
62    </header>
63    <loading-bar />
64  </div>
65</template>
66
67<script>
68import IconAvatar from '@carbon/icons-vue/es/user--avatar/20';
69import IconClose from '@carbon/icons-vue/es/close/20';
70import IconMenu from '@carbon/icons-vue/es/menu/20';
71import IconRenew from '@carbon/icons-vue/es/renew/20';
72import StatusIcon from '../Global/StatusIcon';
73import LoadingBar from '../Global/LoadingBar';
74
75export default {
76  name: 'AppHeader',
77  components: {
78    IconAvatar,
79    IconClose,
80    IconMenu,
81    IconRenew,
82    StatusIcon,
83    LoadingBar
84  },
85  data() {
86    return {
87      isNavigationOpen: false
88    };
89  },
90  computed: {
91    hostStatus() {
92      return this.$store.getters['global/hostStatus'];
93    },
94    healthStatus() {
95      return this.$store.getters['eventLog/healthStatus'];
96    },
97    hostStatusIcon() {
98      switch (this.hostStatus) {
99        case 'on':
100          return 'success';
101        case 'error':
102          return 'danger';
103        case 'diagnosticMode':
104          return 'warning';
105        case 'off':
106        default:
107          return 'secondary';
108      }
109    },
110    healthStatusIcon() {
111      switch (this.healthStatus) {
112        case 'OK':
113          return 'success';
114        case 'Warning':
115          return 'warning';
116        case 'Critical':
117          return 'danger';
118        default:
119          return 'secondary';
120      }
121    },
122    username() {
123      return this.$store.getters['global/username'];
124    }
125  },
126  created() {
127    this.getHostInfo();
128    this.getEvents();
129  },
130  mounted() {
131    this.$root.$on(
132      'change:isNavigationOpen',
133      isNavigationOpen => (this.isNavigationOpen = isNavigationOpen)
134    );
135  },
136  methods: {
137    getHostInfo() {
138      this.$store.dispatch('global/getHostStatus');
139    },
140    getEvents() {
141      this.$store.dispatch('eventLog/getEventLogData');
142    },
143    refresh() {
144      this.$emit('refresh');
145    },
146    logout() {
147      this.$store.dispatch('authentication/logout');
148    },
149    toggleNavigation() {
150      this.$root.$emit('toggle:navigation');
151    }
152  }
153};
154</script>
155
156<style lang="scss">
157@import 'src/assets/styles/helpers';
158
159.app-header {
160  .link-skip-nav {
161    position: absolute;
162    top: -60px;
163    left: 0.5rem;
164    z-index: $zindex-popover;
165    transition: $duration--moderate-01 $exit-easing--expressive;
166    &:focus {
167      top: 0.5rem;
168      transition-timing-function: $entrance-easing--expressive;
169    }
170  }
171  .navbar-dark {
172    .navbar-text,
173    .nav-link,
174    .btn-link {
175      color: $white !important;
176      fill: currentColor;
177    }
178  }
179
180  .nav-item {
181    fill: $light;
182  }
183
184  .navbar {
185    padding: 0;
186    height: $header-height;
187
188    .btn-link {
189      padding: $spacer / 2;
190    }
191  }
192
193  .navbar-nav {
194    padding: 0 $spacer;
195  }
196
197  .nav-trigger {
198    fill: $light;
199    width: $header-height;
200    height: $header-height;
201    transition: none;
202
203    svg {
204      margin: 0;
205    }
206
207    &:hover {
208      fill: $light;
209      background-color: $dark;
210    }
211
212    @include media-breakpoint-up($responsive-layout-bp) {
213      display: none;
214    }
215  }
216
217  .dropdown {
218    .dropdown-menu {
219      margin-top: 7px;
220    }
221  }
222}
223</style>
224