xref: /openbmc/webui-vue/src/components/AppHeader/AppHeader.vue (revision dd6aa0aa8f12426c681f5991f2e9a21b379e86c3)
1a2988f40SDerick Montague<template>
2a2988f40SDerick Montague  <div>
36859203cSDerick Montague    <header id="page-header">
46859203cSDerick Montague      <a role="link" class="link-skip-nav btn btn-light" href="#main-content">
5e0b76c33SYoshie Muranaka        {{ $t('appHeader.skipToContent') }}
6dc04feb5SYoshie Muranaka      </a>
76859203cSDerick Montague
821d6de00SMateusz Gapski      <b-navbar type="dark" :aria-label="$t('appHeader.applicationHeader')">
9dc04feb5SYoshie Muranaka        <!-- Left aligned nav items -->
1074f8687dSYoshie Muranaka        <b-button
116859203cSDerick Montague          id="app-header-trigger"
1274f8687dSYoshie Muranaka          class="nav-trigger"
1374f8687dSYoshie Muranaka          aria-hidden="true"
1474f8687dSYoshie Muranaka          type="button"
1574f8687dSYoshie Muranaka          variant="link"
16057232b8SSurenNeware          :class="{ open: isNavigationOpen }"
1774f8687dSYoshie Muranaka          @click="toggleNavigation"
1874f8687dSYoshie Muranaka        >
19a5cbc449SSurenNeware          <icon-close
20a5cbc449SSurenNeware            v-if="isNavigationOpen"
21a5cbc449SSurenNeware            :title="$t('appHeader.titleHideNavigation')"
22a5cbc449SSurenNeware          />
23a5cbc449SSurenNeware          <icon-menu
24a5cbc449SSurenNeware            v-if="!isNavigationOpen"
25a5cbc449SSurenNeware            :title="$t('appHeader.titleShowNavigation')"
26a5cbc449SSurenNeware          />
2774f8687dSYoshie Muranaka        </b-button>
28dc04feb5SYoshie Muranaka        <b-navbar-nav>
2976ccbbc9SDixsie Wolmers          <b-nav-item to="/" data-test-id="appHeader-container-overview">
3003505916SMateusz Gapski            <img
3103505916SMateusz Gapski              class="header-logo"
3203505916SMateusz Gapski              src="@/assets/images/logo-header.svg"
3303505916SMateusz Gapski              :alt="altLogo"
3403505916SMateusz Gapski            />
3576ccbbc9SDixsie Wolmers          </b-nav-item>
36b8b6f791SYoshie Muranaka        </b-navbar-nav>
37dc04feb5SYoshie Muranaka        <!-- Right aligned nav items -->
38057232b8SSurenNeware        <b-navbar-nav class="ml-auto helper-menu">
39965cf673SDerick Montague          <b-nav-item
40965cf673SDerick Montague            to="/health/event-logs"
41965cf673SDerick Montague            data-test-id="appHeader-container-health"
42965cf673SDerick Montague          >
431ace1d91SYoshie Muranaka            <status-icon :status="healthStatusIcon" />
44057232b8SSurenNeware            {{ $t('appHeader.health') }}
45b8b6f791SYoshie Muranaka          </b-nav-item>
46965cf673SDerick Montague          <b-nav-item
47965cf673SDerick Montague            to="/control/server-power-operations"
48965cf673SDerick Montague            data-test-id="appHeader-container-power"
49965cf673SDerick Montague          >
50dc04feb5SYoshie Muranaka            <status-icon :status="hostStatusIcon" />
51057232b8SSurenNeware            {{ $t('appHeader.power') }}
52b8b6f791SYoshie Muranaka          </b-nav-item>
536859203cSDerick Montague          <!-- Using LI elements instead of b-nav-item to support semantic button elements -->
546859203cSDerick Montague          <li class="nav-item">
55965cf673SDerick Montague            <b-button
56965cf673SDerick Montague              id="app-header-refresh"
57965cf673SDerick Montague              variant="link"
58965cf673SDerick Montague              data-test-id="appHeader-button-refresh"
59965cf673SDerick Montague              @click="refresh"
60965cf673SDerick Montague            >
61a5cbc449SSurenNeware              <icon-renew :title="$t('appHeader.titleRefresh')" />
62057232b8SSurenNeware              <span class="responsive-text">{{ $t('appHeader.refresh') }}</span>
636859203cSDerick Montague            </b-button>
646859203cSDerick Montague          </li>
65b1f559f0SSukanya Pandey          <li class="nav-item">
66965cf673SDerick Montague            <b-dropdown
67965cf673SDerick Montague              id="app-header-user"
68965cf673SDerick Montague              variant="link"
69965cf673SDerick Montague              right
70965cf673SDerick Montague              data-test-id="appHeader-container-user"
71965cf673SDerick Montague            >
72b1f559f0SSukanya Pandey              <template v-slot:button-content>
73a5cbc449SSurenNeware                <icon-avatar :title="$t('appHeader.titleProfile')" />
74057232b8SSurenNeware                <span class="responsive-text">{{ username }}</span>
75b1f559f0SSukanya Pandey              </template>
76965cf673SDerick Montague              <b-dropdown-item
77965cf673SDerick Montague                to="/profile-settings"
78965cf673SDerick Montague                data-test-id="appHeader-link-profile"
79b1f559f0SSukanya Pandey                >{{ $t('appHeader.profileSettings') }}
80b1f559f0SSukanya Pandey              </b-dropdown-item>
81965cf673SDerick Montague              <b-dropdown-item
82965cf673SDerick Montague                data-test-id="appHeader-link-logout"
83965cf673SDerick Montague                @click="logout"
84965cf673SDerick Montague              >
85965cf673SDerick Montague                {{ $t('appHeader.logOut') }}
86965cf673SDerick Montague              </b-dropdown-item>
87b1f559f0SSukanya Pandey            </b-dropdown>
886859203cSDerick Montague          </li>
89b8b6f791SYoshie Muranaka        </b-navbar-nav>
90a2988f40SDerick Montague      </b-navbar>
91a2988f40SDerick Montague    </header>
923be801aaSYoshie Muranaka    <loading-bar />
93a2988f40SDerick Montague  </div>
94a2988f40SDerick Montague</template>
95a2988f40SDerick Montague
96a2988f40SDerick Montague<script>
97*dd6aa0aaSSukanya Pandeyimport BVToastMixin from '@/components/Mixins/BVToastMixin';
98e2fd1567SDerick Montagueimport IconAvatar from '@carbon/icons-vue/es/user--avatar/20';
9974f8687dSYoshie Muranakaimport IconClose from '@carbon/icons-vue/es/close/20';
10074f8687dSYoshie Muranakaimport IconMenu from '@carbon/icons-vue/es/menu/20';
101e2fd1567SDerick Montagueimport IconRenew from '@carbon/icons-vue/es/renew/20';
10261859097SSurenNewareimport StatusIcon from '@/components/Global/StatusIcon';
10361859097SSurenNewareimport LoadingBar from '@/components/Global/LoadingBar';
10474f8687dSYoshie Muranaka
105a2988f40SDerick Montagueexport default {
106e2fd1567SDerick Montague  name: 'AppHeader',
1073be801aaSYoshie Muranaka  components: {
1083be801aaSYoshie Muranaka    IconAvatar,
1093be801aaSYoshie Muranaka    IconClose,
1103be801aaSYoshie Muranaka    IconMenu,
1113be801aaSYoshie Muranaka    IconRenew,
1123be801aaSYoshie Muranaka    StatusIcon,
1133be801aaSYoshie Muranaka    LoadingBar
1143be801aaSYoshie Muranaka  },
115*dd6aa0aaSSukanya Pandey  mixins: [BVToastMixin],
11674f8687dSYoshie Muranaka  data() {
11774f8687dSYoshie Muranaka    return {
11803505916SMateusz Gapski      isNavigationOpen: false,
11903505916SMateusz Gapski      altLogo: `${process.env.VUE_APP_COMPANY_NAME} logo`
12074f8687dSYoshie Muranaka    };
12174f8687dSYoshie Muranaka  },
122b8b6f791SYoshie Muranaka  computed: {
123*dd6aa0aaSSukanya Pandey    isAuthorized() {
124*dd6aa0aaSSukanya Pandey      return this.$store.getters['global/isAuthorized'];
125*dd6aa0aaSSukanya Pandey    },
126b8b6f791SYoshie Muranaka    hostStatus() {
127e2fd1567SDerick Montague      return this.$store.getters['global/hostStatus'];
128dc04feb5SYoshie Muranaka    },
1291ace1d91SYoshie Muranaka    healthStatus() {
1301ace1d91SYoshie Muranaka      return this.$store.getters['eventLog/healthStatus'];
1311ace1d91SYoshie Muranaka    },
132dc04feb5SYoshie Muranaka    hostStatusIcon() {
133dc04feb5SYoshie Muranaka      switch (this.hostStatus) {
134e2fd1567SDerick Montague        case 'on':
135e2fd1567SDerick Montague          return 'success';
136e2fd1567SDerick Montague        case 'error':
137e2fd1567SDerick Montague          return 'danger';
138a3cbc659SYoshie Muranaka        case 'diagnosticMode':
139a3cbc659SYoshie Muranaka          return 'warning';
140e2fd1567SDerick Montague        case 'off':
141dc04feb5SYoshie Muranaka        default:
142e2fd1567SDerick Montague          return 'secondary';
143dc04feb5SYoshie Muranaka      }
1441ace1d91SYoshie Muranaka    },
1451ace1d91SYoshie Muranaka    healthStatusIcon() {
1461ace1d91SYoshie Muranaka      switch (this.healthStatus) {
147ce9a3ef3SYoshie Muranaka        case 'OK':
1481ace1d91SYoshie Muranaka          return 'success';
149ce9a3ef3SYoshie Muranaka        case 'Warning':
1501ace1d91SYoshie Muranaka          return 'warning';
151ce9a3ef3SYoshie Muranaka        case 'Critical':
1521ace1d91SYoshie Muranaka          return 'danger';
1531ace1d91SYoshie Muranaka        default:
1541ace1d91SYoshie Muranaka          return 'secondary';
1551ace1d91SYoshie Muranaka      }
156b1f559f0SSukanya Pandey    },
157b1f559f0SSukanya Pandey    username() {
158b1f559f0SSukanya Pandey      return this.$store.getters['global/username'];
159b8b6f791SYoshie Muranaka    }
160b8b6f791SYoshie Muranaka  },
161*dd6aa0aaSSukanya Pandey  watch: {
162*dd6aa0aaSSukanya Pandey    isAuthorized(value) {
163*dd6aa0aaSSukanya Pandey      if (value === false) {
164*dd6aa0aaSSukanya Pandey        this.errorToast(
165*dd6aa0aaSSukanya Pandey          this.$t('global.toast.unAuthDescription'),
166*dd6aa0aaSSukanya Pandey          this.$t('global.toast.unAuthTitle')
167*dd6aa0aaSSukanya Pandey        );
168*dd6aa0aaSSukanya Pandey      }
169*dd6aa0aaSSukanya Pandey    }
170*dd6aa0aaSSukanya Pandey  },
17109e45cd4SDerick Montague  created() {
17209e45cd4SDerick Montague    this.getHostInfo();
1731ace1d91SYoshie Muranaka    this.getEvents();
17409e45cd4SDerick Montague  },
17574f8687dSYoshie Muranaka  mounted() {
17674f8687dSYoshie Muranaka    this.$root.$on(
17774f8687dSYoshie Muranaka      'change:isNavigationOpen',
17874f8687dSYoshie Muranaka      isNavigationOpen => (this.isNavigationOpen = isNavigationOpen)
17974f8687dSYoshie Muranaka    );
18074f8687dSYoshie Muranaka  },
181b8b6f791SYoshie Muranaka  methods: {
182b8b6f791SYoshie Muranaka    getHostInfo() {
183e2fd1567SDerick Montague      this.$store.dispatch('global/getHostStatus');
184e080a1a7SDerick Montague    },
1851ace1d91SYoshie Muranaka    getEvents() {
1861ace1d91SYoshie Muranaka      this.$store.dispatch('eventLog/getEventLogData');
1871ace1d91SYoshie Muranaka    },
188eb154bbcSYoshie Muranaka    refresh() {
189eb154bbcSYoshie Muranaka      this.$emit('refresh');
190eb154bbcSYoshie Muranaka    },
191e080a1a7SDerick Montague    logout() {
192c031b698SDerick Montague      this.$store.dispatch('authentication/logout');
19374f8687dSYoshie Muranaka    },
19474f8687dSYoshie Muranaka    toggleNavigation() {
19574f8687dSYoshie Muranaka      this.$root.$emit('toggle:navigation');
196b8b6f791SYoshie Muranaka    }
197a2988f40SDerick Montague  }
198a2988f40SDerick Montague};
199a2988f40SDerick Montague</script>
200a2988f40SDerick Montague
201b1f559f0SSukanya Pandey<style lang="scss">
202b1f559f0SSukanya Pandey.app-header {
20375b48321SDerick Montague  .link-skip-nav {
20475b48321SDerick Montague    position: absolute;
20575b48321SDerick Montague    top: -60px;
20675b48321SDerick Montague    left: 0.5rem;
20774f8687dSYoshie Muranaka    z-index: $zindex-popover;
20874f8687dSYoshie Muranaka    transition: $duration--moderate-01 $exit-easing--expressive;
20975b48321SDerick Montague    &:focus {
21075b48321SDerick Montague      top: 0.5rem;
21174f8687dSYoshie Muranaka      transition-timing-function: $entrance-easing--expressive;
21275b48321SDerick Montague    }
21375b48321SDerick Montague  }
2141ace1d91SYoshie Muranaka  .navbar-dark {
2151ace1d91SYoshie Muranaka    .navbar-text,
2166859203cSDerick Montague    .nav-link,
2176859203cSDerick Montague    .btn-link {
218a5cbc449SSurenNeware      color: theme-color('light') !important;
2196859203cSDerick Montague      fill: currentColor;
2201ace1d91SYoshie Muranaka    }
2211ace1d91SYoshie Muranaka  }
2226859203cSDerick Montague
223dc04feb5SYoshie Muranaka  .nav-item {
22401da8187SYoshie Muranaka    fill: theme-color('light');
225dc04feb5SYoshie Muranaka  }
22674f8687dSYoshie Muranaka
22774f8687dSYoshie Muranaka  .navbar {
22874f8687dSYoshie Muranaka    padding: 0;
22921d6de00SMateusz Gapski    background-color: $navbar-color;
230057232b8SSurenNeware    @include media-breakpoint-up($responsive-layout-bp) {
23174f8687dSYoshie Muranaka      height: $header-height;
232057232b8SSurenNeware    }
2336859203cSDerick Montague
2346859203cSDerick Montague    .btn-link {
2356859203cSDerick Montague      padding: $spacer / 2;
2366859203cSDerick Montague    }
237057232b8SSurenNeware
23803505916SMateusz Gapski    .header-logo {
23903505916SMateusz Gapski      width: auto;
24003505916SMateusz Gapski      height: $header-height;
24103505916SMateusz Gapski      padding: $spacer/2 0;
24203505916SMateusz Gapski    }
24303505916SMateusz Gapski
244057232b8SSurenNeware    .helper-menu {
245057232b8SSurenNeware      @include media-breakpoint-down(sm) {
24601da8187SYoshie Muranaka        background-color: gray('800');
247057232b8SSurenNeware        width: 100%;
248057232b8SSurenNeware        justify-content: flex-end;
249057232b8SSurenNeware
250057232b8SSurenNeware        .nav-link,
251057232b8SSurenNeware        .btn {
252057232b8SSurenNeware          padding: $spacer / 1.125 $spacer / 2;
253057232b8SSurenNeware        }
254057232b8SSurenNeware      }
255057232b8SSurenNeware
256057232b8SSurenNeware      .responsive-text {
257057232b8SSurenNeware        @include media-breakpoint-down(xs) {
258057232b8SSurenNeware          display: none;
259057232b8SSurenNeware        }
260057232b8SSurenNeware      }
261057232b8SSurenNeware    }
26274f8687dSYoshie Muranaka  }
26374f8687dSYoshie Muranaka
26474f8687dSYoshie Muranaka  .navbar-nav {
26574f8687dSYoshie Muranaka    padding: 0 $spacer;
26674f8687dSYoshie Muranaka  }
26774f8687dSYoshie Muranaka
26874f8687dSYoshie Muranaka  .nav-trigger {
26901da8187SYoshie Muranaka    fill: theme-color('light');
27074f8687dSYoshie Muranaka    width: $header-height;
27174f8687dSYoshie Muranaka    height: $header-height;
27274f8687dSYoshie Muranaka    transition: none;
27374f8687dSYoshie Muranaka
27474f8687dSYoshie Muranaka    svg {
27574f8687dSYoshie Muranaka      margin: 0;
27674f8687dSYoshie Muranaka    }
27774f8687dSYoshie Muranaka
27874f8687dSYoshie Muranaka    &:hover {
27901da8187SYoshie Muranaka      fill: theme-color('light');
28001da8187SYoshie Muranaka      background-color: theme-color('dark');
28174f8687dSYoshie Muranaka    }
28274f8687dSYoshie Muranaka
283057232b8SSurenNeware    &.open {
28401da8187SYoshie Muranaka      background-color: gray('800');
285057232b8SSurenNeware    }
286057232b8SSurenNeware
28774f8687dSYoshie Muranaka    @include media-breakpoint-up($responsive-layout-bp) {
28874f8687dSYoshie Muranaka      display: none;
28974f8687dSYoshie Muranaka    }
290dc04feb5SYoshie Muranaka  }
291b1f559f0SSukanya Pandey
292b1f559f0SSukanya Pandey  .dropdown {
293b1f559f0SSukanya Pandey    .dropdown-menu {
294057232b8SSurenNeware      margin-top: 0;
295057232b8SSurenNeware      @include media-breakpoint-up(md) {
296b1f559f0SSukanya Pandey        margin-top: 7px;
297b1f559f0SSukanya Pandey      }
298b1f559f0SSukanya Pandey    }
299b1f559f0SSukanya Pandey  }
300057232b8SSurenNeware
301057232b8SSurenNeware  .navbar-expand {
302057232b8SSurenNeware    @include media-breakpoint-down(sm) {
303057232b8SSurenNeware      flex-flow: wrap;
304057232b8SSurenNeware    }
305057232b8SSurenNeware  }
306057232b8SSurenNeware}
307b8b6f791SYoshie Muranaka</style>
308