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