xref: /openbmc/webui-vue/src/components/AppHeader/AppHeader.vue (revision 828dda9b187684902710bb11621eca27bf0c6eec)
1a2988f40SDerick Montague<template>
2a2988f40SDerick Montague  <div>
36859203cSDerick Montague    <header id="page-header">
480267970SDerick Montague      <a
580267970SDerick Montague        class="link-skip-nav btn btn-light"
680267970SDerick Montague        href="#main-content"
780267970SDerick Montague        @click="setFocus"
880267970SDerick Montague      >
9e0b76c33SYoshie Muranaka        {{ $t('appHeader.skipToContent') }}
10dc04feb5SYoshie Muranaka      </a>
116859203cSDerick Montague
1221d6de00SMateusz Gapski      <b-navbar type="dark" :aria-label="$t('appHeader.applicationHeader')">
13dc04feb5SYoshie Muranaka        <!-- Left aligned nav items -->
1474f8687dSYoshie Muranaka        <b-button
156859203cSDerick Montague          id="app-header-trigger"
1674f8687dSYoshie Muranaka          class="nav-trigger"
1774f8687dSYoshie Muranaka          aria-hidden="true"
1874f8687dSYoshie Muranaka          type="button"
1974f8687dSYoshie Muranaka          variant="link"
20057232b8SSurenNeware          :class="{ open: isNavigationOpen }"
2174f8687dSYoshie Muranaka          @click="toggleNavigation"
2274f8687dSYoshie Muranaka        >
23a5cbc449SSurenNeware          <icon-close
24a5cbc449SSurenNeware            v-if="isNavigationOpen"
25a5cbc449SSurenNeware            :title="$t('appHeader.titleHideNavigation')"
26a5cbc449SSurenNeware          />
27a5cbc449SSurenNeware          <icon-menu
28a5cbc449SSurenNeware            v-if="!isNavigationOpen"
29a5cbc449SSurenNeware            :title="$t('appHeader.titleShowNavigation')"
30a5cbc449SSurenNeware          />
3174f8687dSYoshie Muranaka        </b-button>
32dc04feb5SYoshie Muranaka        <b-navbar-nav>
33c5c2ae99SSukanya Pandey          <b-navbar-brand
34c5c2ae99SSukanya Pandey            class="mr-0"
35c5c2ae99SSukanya Pandey            to="/"
36c5c2ae99SSukanya Pandey            data-test-id="appHeader-container-overview"
37c5c2ae99SSukanya Pandey          >
3803505916SMateusz Gapski            <img
3903505916SMateusz Gapski              class="header-logo"
4003505916SMateusz Gapski              src="@/assets/images/logo-header.svg"
4103505916SMateusz Gapski              :alt="altLogo"
4203505916SMateusz Gapski            />
431f8117f8SSurenNeware          </b-navbar-brand>
44c5c2ae99SSukanya Pandey          <div v-if="assetTag" class="asset-tag">
45c5c2ae99SSukanya Pandey            <span class="pr-2">|</span>
46c5c2ae99SSukanya Pandey            <span>{{ assetTag }}</span>
47c5c2ae99SSukanya Pandey          </div>
48b8b6f791SYoshie Muranaka        </b-navbar-nav>
49dc04feb5SYoshie Muranaka        <!-- Right aligned nav items -->
50057232b8SSurenNeware        <b-navbar-nav class="ml-auto helper-menu">
51965cf673SDerick Montague          <b-nav-item
52*828dda9bSDerick Montague            to="/logs/event-logs"
53965cf673SDerick Montague            data-test-id="appHeader-container-health"
54965cf673SDerick Montague          >
551ace1d91SYoshie Muranaka            <status-icon :status="healthStatusIcon" />
56057232b8SSurenNeware            {{ $t('appHeader.health') }}
57b8b6f791SYoshie Muranaka          </b-nav-item>
58965cf673SDerick Montague          <b-nav-item
59965cf673SDerick Montague            to="/control/server-power-operations"
60965cf673SDerick Montague            data-test-id="appHeader-container-power"
61965cf673SDerick Montague          >
6271114febSDerick Montague            <status-icon :status="serverStatusIcon" />
63057232b8SSurenNeware            {{ $t('appHeader.power') }}
64b8b6f791SYoshie Muranaka          </b-nav-item>
656859203cSDerick Montague          <!-- Using LI elements instead of b-nav-item to support semantic button elements -->
666859203cSDerick Montague          <li class="nav-item">
67965cf673SDerick Montague            <b-button
68965cf673SDerick Montague              id="app-header-refresh"
69965cf673SDerick Montague              variant="link"
70965cf673SDerick Montague              data-test-id="appHeader-button-refresh"
71965cf673SDerick Montague              @click="refresh"
72965cf673SDerick Montague            >
73a5cbc449SSurenNeware              <icon-renew :title="$t('appHeader.titleRefresh')" />
74057232b8SSurenNeware              <span class="responsive-text">{{ $t('appHeader.refresh') }}</span>
756859203cSDerick Montague            </b-button>
766859203cSDerick Montague          </li>
77b1f559f0SSukanya Pandey          <li class="nav-item">
78965cf673SDerick Montague            <b-dropdown
79965cf673SDerick Montague              id="app-header-user"
80965cf673SDerick Montague              variant="link"
81965cf673SDerick Montague              right
82965cf673SDerick Montague              data-test-id="appHeader-container-user"
83965cf673SDerick Montague            >
84602e98aaSDerick Montague              <template #button-content>
85a5cbc449SSurenNeware                <icon-avatar :title="$t('appHeader.titleProfile')" />
86057232b8SSurenNeware                <span class="responsive-text">{{ username }}</span>
87b1f559f0SSukanya Pandey              </template>
88965cf673SDerick Montague              <b-dropdown-item
89965cf673SDerick Montague                to="/profile-settings"
90965cf673SDerick Montague                data-test-id="appHeader-link-profile"
91b1f559f0SSukanya Pandey                >{{ $t('appHeader.profileSettings') }}
92b1f559f0SSukanya Pandey              </b-dropdown-item>
93965cf673SDerick Montague              <b-dropdown-item
94965cf673SDerick Montague                data-test-id="appHeader-link-logout"
95965cf673SDerick Montague                @click="logout"
96965cf673SDerick Montague              >
97965cf673SDerick Montague                {{ $t('appHeader.logOut') }}
98965cf673SDerick Montague              </b-dropdown-item>
99b1f559f0SSukanya Pandey            </b-dropdown>
1006859203cSDerick Montague          </li>
101b8b6f791SYoshie Muranaka        </b-navbar-nav>
102a2988f40SDerick Montague      </b-navbar>
103a2988f40SDerick Montague    </header>
1043be801aaSYoshie Muranaka    <loading-bar />
105a2988f40SDerick Montague  </div>
106a2988f40SDerick Montague</template>
107a2988f40SDerick Montague
108a2988f40SDerick Montague<script>
109dd6aa0aaSSukanya Pandeyimport BVToastMixin from '@/components/Mixins/BVToastMixin';
110e2fd1567SDerick Montagueimport IconAvatar from '@carbon/icons-vue/es/user--avatar/20';
11174f8687dSYoshie Muranakaimport IconClose from '@carbon/icons-vue/es/close/20';
11274f8687dSYoshie Muranakaimport IconMenu from '@carbon/icons-vue/es/menu/20';
113e2fd1567SDerick Montagueimport IconRenew from '@carbon/icons-vue/es/renew/20';
11461859097SSurenNewareimport StatusIcon from '@/components/Global/StatusIcon';
11561859097SSurenNewareimport LoadingBar from '@/components/Global/LoadingBar';
11674f8687dSYoshie Muranaka
117a2988f40SDerick Montagueexport default {
118e2fd1567SDerick Montague  name: 'AppHeader',
1193be801aaSYoshie Muranaka  components: {
1203be801aaSYoshie Muranaka    IconAvatar,
1213be801aaSYoshie Muranaka    IconClose,
1223be801aaSYoshie Muranaka    IconMenu,
1233be801aaSYoshie Muranaka    IconRenew,
1243be801aaSYoshie Muranaka    StatusIcon,
125602e98aaSDerick Montague    LoadingBar,
1263be801aaSYoshie Muranaka  },
127dd6aa0aaSSukanya Pandey  mixins: [BVToastMixin],
12874f8687dSYoshie Muranaka  data() {
12974f8687dSYoshie Muranaka    return {
13003505916SMateusz Gapski      isNavigationOpen: false,
131602e98aaSDerick Montague      altLogo: `${process.env.VUE_APP_COMPANY_NAME} logo`,
13274f8687dSYoshie Muranaka    };
13374f8687dSYoshie Muranaka  },
134b8b6f791SYoshie Muranaka  computed: {
135c5c2ae99SSukanya Pandey    assetTag() {
136c5c2ae99SSukanya Pandey      return this.$store.getters['global/assetTag'];
137c5c2ae99SSukanya Pandey    },
138dd6aa0aaSSukanya Pandey    isAuthorized() {
139dd6aa0aaSSukanya Pandey      return this.$store.getters['global/isAuthorized'];
140dd6aa0aaSSukanya Pandey    },
14171114febSDerick Montague    serverStatus() {
14271114febSDerick Montague      return this.$store.getters['global/serverStatus'];
143dc04feb5SYoshie Muranaka    },
1441ace1d91SYoshie Muranaka    healthStatus() {
1451ace1d91SYoshie Muranaka      return this.$store.getters['eventLog/healthStatus'];
1461ace1d91SYoshie Muranaka    },
14771114febSDerick Montague    serverStatusIcon() {
14871114febSDerick Montague      switch (this.serverStatus) {
149e2fd1567SDerick Montague        case 'on':
150e2fd1567SDerick Montague          return 'success';
151e2fd1567SDerick Montague        case 'error':
152e2fd1567SDerick Montague          return 'danger';
153a3cbc659SYoshie Muranaka        case 'diagnosticMode':
154a3cbc659SYoshie Muranaka          return 'warning';
155e2fd1567SDerick Montague        case 'off':
156dc04feb5SYoshie Muranaka        default:
157e2fd1567SDerick Montague          return 'secondary';
158dc04feb5SYoshie Muranaka      }
1591ace1d91SYoshie Muranaka    },
1601ace1d91SYoshie Muranaka    healthStatusIcon() {
1611ace1d91SYoshie Muranaka      switch (this.healthStatus) {
162ce9a3ef3SYoshie Muranaka        case 'OK':
1631ace1d91SYoshie Muranaka          return 'success';
164ce9a3ef3SYoshie Muranaka        case 'Warning':
1651ace1d91SYoshie Muranaka          return 'warning';
166ce9a3ef3SYoshie Muranaka        case 'Critical':
1671ace1d91SYoshie Muranaka          return 'danger';
1681ace1d91SYoshie Muranaka        default:
1691ace1d91SYoshie Muranaka          return 'secondary';
1701ace1d91SYoshie Muranaka      }
171b1f559f0SSukanya Pandey    },
172b1f559f0SSukanya Pandey    username() {
173b1f559f0SSukanya Pandey      return this.$store.getters['global/username'];
174602e98aaSDerick Montague    },
175b8b6f791SYoshie Muranaka  },
176dd6aa0aaSSukanya Pandey  watch: {
177dd6aa0aaSSukanya Pandey    isAuthorized(value) {
178dd6aa0aaSSukanya Pandey      if (value === false) {
179f92e2969SYoshie Muranaka        this.errorToast(this.$t('global.toast.unAuthDescription'), {
180f92e2969SYoshie Muranaka          title: this.$t('global.toast.unAuthTitle'),
181f92e2969SYoshie Muranaka        });
182dd6aa0aaSSukanya Pandey      }
183602e98aaSDerick Montague    },
184dd6aa0aaSSukanya Pandey  },
18509e45cd4SDerick Montague  created() {
186d624dae9SYoshie Muranaka    // Reset auth state to check if user is authenticated based
187d624dae9SYoshie Muranaka    // on available browser cookies
188d624dae9SYoshie Muranaka    this.$store.dispatch('authentication/resetStoreState');
18971114febSDerick Montague    this.getServerInfo();
1901ace1d91SYoshie Muranaka    this.getEvents();
19109e45cd4SDerick Montague  },
19274f8687dSYoshie Muranaka  mounted() {
19374f8687dSYoshie Muranaka    this.$root.$on(
194edb8a774SSukanya Pandey      'change-is-navigation-open',
195602e98aaSDerick Montague      (isNavigationOpen) => (this.isNavigationOpen = isNavigationOpen)
19674f8687dSYoshie Muranaka    );
19774f8687dSYoshie Muranaka  },
198b8b6f791SYoshie Muranaka  methods: {
19971114febSDerick Montague    getServerInfo() {
20071114febSDerick Montague      this.$store.dispatch('global/getServerStatus');
201e080a1a7SDerick Montague    },
2021ace1d91SYoshie Muranaka    getEvents() {
2031ace1d91SYoshie Muranaka      this.$store.dispatch('eventLog/getEventLogData');
2041ace1d91SYoshie Muranaka    },
205eb154bbcSYoshie Muranaka    refresh() {
206eb154bbcSYoshie Muranaka      this.$emit('refresh');
207eb154bbcSYoshie Muranaka    },
208e080a1a7SDerick Montague    logout() {
209c031b698SDerick Montague      this.$store.dispatch('authentication/logout');
21074f8687dSYoshie Muranaka    },
21174f8687dSYoshie Muranaka    toggleNavigation() {
212edb8a774SSukanya Pandey      this.$root.$emit('toggle-navigation');
213602e98aaSDerick Montague    },
21480267970SDerick Montague    setFocus(event) {
21580267970SDerick Montague      event.preventDefault();
21680267970SDerick Montague      this.$root.$emit('skip-navigation');
21780267970SDerick Montague    },
218602e98aaSDerick Montague  },
219a2988f40SDerick Montague};
220a2988f40SDerick Montague</script>
221a2988f40SDerick Montague
222b1f559f0SSukanya Pandey<style lang="scss">
2237d4b53bcSDerick Montague@mixin focus-box-shadow($padding-color: $navbar-color, $outline-color: $white) {
2247d4b53bcSDerick Montague  box-shadow: inset 0 0 0 3px $padding-color, inset 0 0 0 5px $outline-color;
2257d4b53bcSDerick Montague}
226b1f559f0SSukanya Pandey.app-header {
22775b48321SDerick Montague  .link-skip-nav {
22875b48321SDerick Montague    position: absolute;
22975b48321SDerick Montague    top: -60px;
23075b48321SDerick Montague    left: 0.5rem;
23174f8687dSYoshie Muranaka    z-index: $zindex-popover;
23274f8687dSYoshie Muranaka    transition: $duration--moderate-01 $exit-easing--expressive;
23375b48321SDerick Montague    &:focus {
23475b48321SDerick Montague      top: 0.5rem;
23574f8687dSYoshie Muranaka      transition-timing-function: $entrance-easing--expressive;
23675b48321SDerick Montague    }
23775b48321SDerick Montague  }
2381ace1d91SYoshie Muranaka  .navbar-text,
2396859203cSDerick Montague  .nav-link,
2406859203cSDerick Montague  .btn-link {
2411f8117f8SSurenNeware    color: color('white') !important;
2426859203cSDerick Montague    fill: currentColor;
2431f8117f8SSurenNeware    padding: 0.68rem 1rem !important;
2441f8117f8SSurenNeware
2451f8117f8SSurenNeware    &:hover {
2461f8117f8SSurenNeware      background-color: theme-color-level(light, 10);
2471f8117f8SSurenNeware    }
2481f8117f8SSurenNeware    &:active {
2491f8117f8SSurenNeware      background-color: theme-color-level(light, 9);
2501f8117f8SSurenNeware    }
2511f8117f8SSurenNeware    &:focus {
2527d4b53bcSDerick Montague      @include focus-box-shadow;
2537d4b53bcSDerick Montague      outline: 0;
2541ace1d91SYoshie Muranaka    }
2551ace1d91SYoshie Muranaka  }
2566859203cSDerick Montague
257dc04feb5SYoshie Muranaka  .nav-item {
25801da8187SYoshie Muranaka    fill: theme-color('light');
259dc04feb5SYoshie Muranaka  }
26074f8687dSYoshie Muranaka
26174f8687dSYoshie Muranaka  .navbar {
26274f8687dSYoshie Muranaka    padding: 0;
26321d6de00SMateusz Gapski    background-color: $navbar-color;
264057232b8SSurenNeware    @include media-breakpoint-up($responsive-layout-bp) {
26574f8687dSYoshie Muranaka      height: $header-height;
266057232b8SSurenNeware    }
2676859203cSDerick Montague
268057232b8SSurenNeware    .helper-menu {
269057232b8SSurenNeware      @include media-breakpoint-down(sm) {
27001da8187SYoshie Muranaka        background-color: gray('800');
271057232b8SSurenNeware        width: 100%;
272057232b8SSurenNeware        justify-content: flex-end;
273057232b8SSurenNeware
274057232b8SSurenNeware        .nav-link,
275057232b8SSurenNeware        .btn {
276057232b8SSurenNeware          padding: $spacer / 1.125 $spacer / 2;
277057232b8SSurenNeware        }
2787d4b53bcSDerick Montague
2797d4b53bcSDerick Montague        .nav-link:focus,
2807d4b53bcSDerick Montague        .btn:focus {
2817d4b53bcSDerick Montague          @include focus-box-shadow($gray-800);
2827d4b53bcSDerick Montague        }
283057232b8SSurenNeware      }
284057232b8SSurenNeware
285057232b8SSurenNeware      .responsive-text {
286057232b8SSurenNeware        @include media-breakpoint-down(xs) {
287057232b8SSurenNeware          display: none;
288057232b8SSurenNeware        }
289057232b8SSurenNeware      }
290057232b8SSurenNeware    }
29174f8687dSYoshie Muranaka  }
29274f8687dSYoshie Muranaka
29374f8687dSYoshie Muranaka  .navbar-nav {
29474f8687dSYoshie Muranaka    padding: 0 $spacer;
2951f8117f8SSurenNeware    align-items: center;
2961f8117f8SSurenNeware
2971f8117f8SSurenNeware    .navbar-brand,
2981f8117f8SSurenNeware    .nav-link {
2991f8117f8SSurenNeware      transition: $focus-transition;
3001f8117f8SSurenNeware    }
301c5c2ae99SSukanya Pandey    .asset-tag {
302c5c2ae99SSukanya Pandey      color: theme-color-level(light, 3);
303c5c2ae99SSukanya Pandey    }
30474f8687dSYoshie Muranaka  }
30574f8687dSYoshie Muranaka
30674f8687dSYoshie Muranaka  .nav-trigger {
30701da8187SYoshie Muranaka    fill: theme-color('light');
30874f8687dSYoshie Muranaka    width: $header-height;
30974f8687dSYoshie Muranaka    height: $header-height;
31074f8687dSYoshie Muranaka    transition: none;
3111f8117f8SSurenNeware    display: inline-flex;
3121f8117f8SSurenNeware    flex: 0 0 20px;
3131f8117f8SSurenNeware    align-items: center;
31474f8687dSYoshie Muranaka
31574f8687dSYoshie Muranaka    svg {
31674f8687dSYoshie Muranaka      margin: 0;
31774f8687dSYoshie Muranaka    }
31874f8687dSYoshie Muranaka
31974f8687dSYoshie Muranaka    &:hover {
32001da8187SYoshie Muranaka      fill: theme-color('light');
3211f8117f8SSurenNeware      background-color: theme-color-level(light, 10);
32274f8687dSYoshie Muranaka    }
32374f8687dSYoshie Muranaka
324057232b8SSurenNeware    &.open {
32501da8187SYoshie Muranaka      background-color: gray('800');
326057232b8SSurenNeware    }
327057232b8SSurenNeware
32874f8687dSYoshie Muranaka    @include media-breakpoint-up($responsive-layout-bp) {
32974f8687dSYoshie Muranaka      display: none;
33074f8687dSYoshie Muranaka    }
331dc04feb5SYoshie Muranaka  }
332b1f559f0SSukanya Pandey
333b1f559f0SSukanya Pandey  .dropdown-menu {
334057232b8SSurenNeware    margin-top: 0;
3351f8117f8SSurenNeware
3361f8117f8SSurenNeware    @include media-breakpoint-only(md) {
3371f8117f8SSurenNeware      margin-top: 4px;
338b1f559f0SSukanya Pandey    }
339b1f559f0SSukanya Pandey  }
340057232b8SSurenNeware
341057232b8SSurenNeware  .navbar-expand {
342057232b8SSurenNeware    @include media-breakpoint-down(sm) {
343057232b8SSurenNeware      flex-flow: wrap;
344057232b8SSurenNeware    }
345057232b8SSurenNeware  }
346057232b8SSurenNeware}
3471f8117f8SSurenNeware
3481f8117f8SSurenNeware.navbar-brand {
3491f8117f8SSurenNeware  padding: $spacer/2;
3501f8117f8SSurenNeware  height: $header-height;
3511f8117f8SSurenNeware  line-height: 1;
3521f8117f8SSurenNeware  &:focus {
3531f8117f8SSurenNeware    box-shadow: inset 0 0 0 3px $navbar-color, inset 0 0 0 5px color('white');
3541f8117f8SSurenNeware    outline: 0;
3551f8117f8SSurenNeware  }
3561f8117f8SSurenNeware}
357b8b6f791SYoshie Muranaka</style>
358