xref: /openbmc/webui-vue/src/components/AppHeader/AppHeader.vue (revision de23ea23d88451a2fa2774ec72053772603c23ae)
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
3951abe87fSEd Tanous              svg-inline
4003505916SMateusz Gapski              class="header-logo"
4103505916SMateusz Gapski              src="@/assets/images/logo-header.svg"
4203505916SMateusz Gapski              :alt="altLogo"
4303505916SMateusz Gapski            />
441f8117f8SSurenNeware          </b-navbar-brand>
4514172d74Skennyneedsmilky          <div v-if="isNavTagPresent" :key="routerKey" class="pl-2 nav-tags">
464dd7eabfSSukanya Pandey            <span>|</span>
474dd7eabfSSukanya Pandey            <span class="pl-3 asset-tag">{{ assetTag }}</span>
484dd7eabfSSukanya Pandey            <span class="pl-3">{{ modelType }}</span>
494dd7eabfSSukanya Pandey            <span class="pl-3">{{ serialNumber }}</span>
50c5c2ae99SSukanya Pandey          </div>
51b8b6f791SYoshie Muranaka        </b-navbar-nav>
52dc04feb5SYoshie Muranaka        <!-- Right aligned nav items -->
53057232b8SSurenNeware        <b-navbar-nav class="ml-auto helper-menu">
54965cf673SDerick Montague          <b-nav-item
55828dda9bSDerick Montague            to="/logs/event-logs"
56965cf673SDerick Montague            data-test-id="appHeader-container-health"
57965cf673SDerick Montague          >
581ace1d91SYoshie Muranaka            <status-icon :status="healthStatusIcon" />
59057232b8SSurenNeware            {{ $t('appHeader.health') }}
60b8b6f791SYoshie Muranaka          </b-nav-item>
61965cf673SDerick Montague          <b-nav-item
6268cbbe90SSandeepa Singh            to="/operations/server-power-operations"
63965cf673SDerick Montague            data-test-id="appHeader-container-power"
64965cf673SDerick Montague          >
6571114febSDerick Montague            <status-icon :status="serverStatusIcon" />
66057232b8SSurenNeware            {{ $t('appHeader.power') }}
67b8b6f791SYoshie Muranaka          </b-nav-item>
686859203cSDerick Montague          <!-- Using LI elements instead of b-nav-item to support semantic button elements -->
696859203cSDerick Montague          <li class="nav-item">
70965cf673SDerick Montague            <b-button
71965cf673SDerick Montague              id="app-header-refresh"
72965cf673SDerick Montague              variant="link"
73965cf673SDerick Montague              data-test-id="appHeader-button-refresh"
74965cf673SDerick Montague              @click="refresh"
75965cf673SDerick Montague            >
76a5cbc449SSurenNeware              <icon-renew :title="$t('appHeader.titleRefresh')" />
77057232b8SSurenNeware              <span class="responsive-text">{{ $t('appHeader.refresh') }}</span>
786859203cSDerick Montague            </b-button>
796859203cSDerick Montague          </li>
80b1f559f0SSukanya Pandey          <li class="nav-item">
81965cf673SDerick Montague            <b-dropdown
82965cf673SDerick Montague              id="app-header-user"
83965cf673SDerick Montague              variant="link"
84965cf673SDerick Montague              right
85965cf673SDerick Montague              data-test-id="appHeader-container-user"
86965cf673SDerick Montague            >
87602e98aaSDerick Montague              <template #button-content>
88a5cbc449SSurenNeware                <icon-avatar :title="$t('appHeader.titleProfile')" />
89057232b8SSurenNeware                <span class="responsive-text">{{ username }}</span>
90b1f559f0SSukanya Pandey              </template>
91965cf673SDerick Montague              <b-dropdown-item
92965cf673SDerick Montague                to="/profile-settings"
93965cf673SDerick Montague                data-test-id="appHeader-link-profile"
94b1f559f0SSukanya Pandey                >{{ $t('appHeader.profileSettings') }}
95b1f559f0SSukanya Pandey              </b-dropdown-item>
96965cf673SDerick Montague              <b-dropdown-item
97965cf673SDerick Montague                data-test-id="appHeader-link-logout"
98965cf673SDerick Montague                @click="logout"
99965cf673SDerick Montague              >
100965cf673SDerick Montague                {{ $t('appHeader.logOut') }}
101965cf673SDerick Montague              </b-dropdown-item>
102b1f559f0SSukanya Pandey            </b-dropdown>
1036859203cSDerick Montague          </li>
104b8b6f791SYoshie Muranaka        </b-navbar-nav>
105a2988f40SDerick Montague      </b-navbar>
106a2988f40SDerick Montague    </header>
1073be801aaSYoshie Muranaka    <loading-bar />
108a2988f40SDerick Montague  </div>
109a2988f40SDerick Montague</template>
110a2988f40SDerick Montague
111a2988f40SDerick Montague<script>
112dd6aa0aaSSukanya Pandeyimport BVToastMixin from '@/components/Mixins/BVToastMixin';
113e2fd1567SDerick Montagueimport IconAvatar from '@carbon/icons-vue/es/user--avatar/20';
11474f8687dSYoshie Muranakaimport IconClose from '@carbon/icons-vue/es/close/20';
11574f8687dSYoshie Muranakaimport IconMenu from '@carbon/icons-vue/es/menu/20';
116e2fd1567SDerick Montagueimport IconRenew from '@carbon/icons-vue/es/renew/20';
11761859097SSurenNewareimport StatusIcon from '@/components/Global/StatusIcon';
11861859097SSurenNewareimport LoadingBar from '@/components/Global/LoadingBar';
119883a0d59SEd Tanousimport { useI18n } from 'vue-i18n';
120fb6c6de9SKonstantinimport { mapState } from 'vuex';
121*de23ea23SSurya Vimport i18n from '@/i18n';
12274f8687dSYoshie Muranaka
123a2988f40SDerick Montagueexport default {
124e2fd1567SDerick Montague  name: 'AppHeader',
1253be801aaSYoshie Muranaka  components: {
1263be801aaSYoshie Muranaka    IconAvatar,
1273be801aaSYoshie Muranaka    IconClose,
1283be801aaSYoshie Muranaka    IconMenu,
1293be801aaSYoshie Muranaka    IconRenew,
1303be801aaSYoshie Muranaka    StatusIcon,
131602e98aaSDerick Montague    LoadingBar,
1323be801aaSYoshie Muranaka  },
133dd6aa0aaSSukanya Pandey  mixins: [BVToastMixin],
13414172d74Skennyneedsmilky  props: {
13500cb42b6SKenneth Fullbright    routerKey: {
13600cb42b6SKenneth Fullbright      type: Number,
13700cb42b6SKenneth Fullbright      default: 0,
13800cb42b6SKenneth Fullbright    },
13914172d74Skennyneedsmilky  },
14074f8687dSYoshie Muranaka  data() {
14174f8687dSYoshie Muranaka    return {
142883a0d59SEd Tanous      $t: useI18n().t,
14303505916SMateusz Gapski      isNavigationOpen: false,
144932aff93SDerick Montague      altLogo: process.env.VUE_APP_COMPANY_NAME || 'Built on OpenBMC',
14574f8687dSYoshie Muranaka    };
14674f8687dSYoshie Muranaka  },
147b8b6f791SYoshie Muranaka  computed: {
148fb6c6de9SKonstantin    ...mapState('authentication', ['consoleWindow']),
1494dd7eabfSSukanya Pandey    isNavTagPresent() {
1504dd7eabfSSukanya Pandey      return this.assetTag || this.modelType || this.serialNumber;
1514dd7eabfSSukanya Pandey    },
152c5c2ae99SSukanya Pandey    assetTag() {
153c5c2ae99SSukanya Pandey      return this.$store.getters['global/assetTag'];
154c5c2ae99SSukanya Pandey    },
1554dd7eabfSSukanya Pandey    modelType() {
1564dd7eabfSSukanya Pandey      return this.$store.getters['global/modelType'];
1574dd7eabfSSukanya Pandey    },
1584dd7eabfSSukanya Pandey    serialNumber() {
1594dd7eabfSSukanya Pandey      return this.$store.getters['global/serialNumber'];
1604dd7eabfSSukanya Pandey    },
161dd6aa0aaSSukanya Pandey    isAuthorized() {
162dd6aa0aaSSukanya Pandey      return this.$store.getters['global/isAuthorized'];
163dd6aa0aaSSukanya Pandey    },
164aeb19816SDamian Celico    userPrivilege() {
165aeb19816SDamian Celico      return this.$store.getters['global/userPrivilege'];
166aeb19816SDamian Celico    },
16771114febSDerick Montague    serverStatus() {
16871114febSDerick Montague      return this.$store.getters['global/serverStatus'];
169dc04feb5SYoshie Muranaka    },
1701ace1d91SYoshie Muranaka    healthStatus() {
1711ace1d91SYoshie Muranaka      return this.$store.getters['eventLog/healthStatus'];
1721ace1d91SYoshie Muranaka    },
17371114febSDerick Montague    serverStatusIcon() {
17471114febSDerick Montague      switch (this.serverStatus) {
175e2fd1567SDerick Montague        case 'on':
176e2fd1567SDerick Montague          return 'success';
177e2fd1567SDerick Montague        case 'error':
178e2fd1567SDerick Montague          return 'danger';
179a3cbc659SYoshie Muranaka        case 'diagnosticMode':
180a3cbc659SYoshie Muranaka          return 'warning';
181e2fd1567SDerick Montague        case 'off':
182dc04feb5SYoshie Muranaka        default:
183e2fd1567SDerick Montague          return 'secondary';
184dc04feb5SYoshie Muranaka      }
1851ace1d91SYoshie Muranaka    },
1861ace1d91SYoshie Muranaka    healthStatusIcon() {
1871ace1d91SYoshie Muranaka      switch (this.healthStatus) {
188ce9a3ef3SYoshie Muranaka        case 'OK':
1891ace1d91SYoshie Muranaka          return 'success';
190ce9a3ef3SYoshie Muranaka        case 'Warning':
1911ace1d91SYoshie Muranaka          return 'warning';
192ce9a3ef3SYoshie Muranaka        case 'Critical':
1931ace1d91SYoshie Muranaka          return 'danger';
1941ace1d91SYoshie Muranaka        default:
1951ace1d91SYoshie Muranaka          return 'secondary';
1961ace1d91SYoshie Muranaka      }
197b1f559f0SSukanya Pandey    },
198b1f559f0SSukanya Pandey    username() {
199b1f559f0SSukanya Pandey      return this.$store.getters['global/username'];
200602e98aaSDerick Montague    },
201b8b6f791SYoshie Muranaka  },
202dd6aa0aaSSukanya Pandey  watch: {
203fb6c6de9SKonstantin    consoleWindow() {
204883a0d59SEd Tanous      if (this.consoleWindow === false) this.$eventBus.$consoleWindow?.close();
205fb6c6de9SKonstantin    },
206dd6aa0aaSSukanya Pandey    isAuthorized(value) {
207dd6aa0aaSSukanya Pandey      if (value === false) {
208*de23ea23SSurya V        this.errorToast(i18n.global.t('global.toast.unAuthDescription'), {
209*de23ea23SSurya V          title: i18n.global.t('global.toast.unAuthTitle'),
210f92e2969SYoshie Muranaka        });
211dd6aa0aaSSukanya Pandey      }
212602e98aaSDerick Montague    },
213dd6aa0aaSSukanya Pandey  },
21409e45cd4SDerick Montague  created() {
215d624dae9SYoshie Muranaka    // Reset auth state to check if user is authenticated based
216d624dae9SYoshie Muranaka    // on available browser cookies
217d624dae9SYoshie Muranaka    this.$store.dispatch('authentication/resetStoreState');
2184dd7eabfSSukanya Pandey    this.getSystemInfo();
2191ace1d91SYoshie Muranaka    this.getEvents();
22009e45cd4SDerick Montague  },
22174f8687dSYoshie Muranaka  mounted() {
22274f8687dSYoshie Muranaka    this.$root.$on(
223edb8a774SSukanya Pandey      'change-is-navigation-open',
2248132399cSEd Tanous      (isNavigationOpen) => (this.isNavigationOpen = isNavigationOpen),
22574f8687dSYoshie Muranaka    );
22674f8687dSYoshie Muranaka  },
227b8b6f791SYoshie Muranaka  methods: {
2284dd7eabfSSukanya Pandey    getSystemInfo() {
2294dd7eabfSSukanya Pandey      this.$store.dispatch('global/getSystemInfo');
230e080a1a7SDerick Montague    },
2311ace1d91SYoshie Muranaka    getEvents() {
2321ace1d91SYoshie Muranaka      this.$store.dispatch('eventLog/getEventLogData');
2331ace1d91SYoshie Muranaka    },
234eb154bbcSYoshie Muranaka    refresh() {
235eb154bbcSYoshie Muranaka      this.$emit('refresh');
236eb154bbcSYoshie Muranaka    },
237e080a1a7SDerick Montague    logout() {
238c031b698SDerick Montague      this.$store.dispatch('authentication/logout');
23974f8687dSYoshie Muranaka    },
24074f8687dSYoshie Muranaka    toggleNavigation() {
241edb8a774SSukanya Pandey      this.$root.$emit('toggle-navigation');
242602e98aaSDerick Montague    },
24380267970SDerick Montague    setFocus(event) {
24480267970SDerick Montague      event.preventDefault();
24580267970SDerick Montague      this.$root.$emit('skip-navigation');
24680267970SDerick Montague    },
247602e98aaSDerick Montague  },
248a2988f40SDerick Montague};
249a2988f40SDerick Montague</script>
250a2988f40SDerick Montague
251b1f559f0SSukanya Pandey<style lang="scss">
2527d6b44cbSEd Tanous@import '@/assets/styles/bmc/helpers/_index.scss';
2537d6b44cbSEd Tanous@import '@/assets/styles/bootstrap/_helpers.scss';
2547d6b44cbSEd Tanous
2557d4b53bcSDerick Montague@mixin focus-box-shadow($padding-color: $navbar-color, $outline-color: $white) {
2568132399cSEd Tanous  box-shadow:
2578132399cSEd Tanous    inset 0 0 0 3px $padding-color,
2588132399cSEd Tanous    inset 0 0 0 5px $outline-color;
2597d4b53bcSDerick Montague}
260b1f559f0SSukanya Pandey.app-header {
26175b48321SDerick Montague  .link-skip-nav {
26275b48321SDerick Montague    position: absolute;
26375b48321SDerick Montague    top: -60px;
26475b48321SDerick Montague    left: 0.5rem;
2657d6b44cbSEd Tanous    //z-index: $zindex-popover;
2667d6b44cbSEd Tanous    //transition: $duration--moderate-01 $exit-easing--expressive;
26775b48321SDerick Montague    &:focus {
26875b48321SDerick Montague      top: 0.5rem;
2697d6b44cbSEd Tanous      //transition-timing-function: $entrance-easing--expressive;
27075b48321SDerick Montague    }
27175b48321SDerick Montague  }
2721ace1d91SYoshie Muranaka  .navbar-text,
2736859203cSDerick Montague  .nav-link,
2746859203cSDerick Montague  .btn-link {
2751f8117f8SSurenNeware    color: color('white') !important;
2766859203cSDerick Montague    fill: currentColor;
2771f8117f8SSurenNeware    padding: 0.68rem 1rem !important;
2781f8117f8SSurenNeware
2791f8117f8SSurenNeware    &:hover {
2801f8117f8SSurenNeware      background-color: theme-color-level(light, 10);
2811f8117f8SSurenNeware    }
2821f8117f8SSurenNeware    &:active {
2831f8117f8SSurenNeware      background-color: theme-color-level(light, 9);
2841f8117f8SSurenNeware    }
2851f8117f8SSurenNeware    &:focus {
2867d4b53bcSDerick Montague      @include focus-box-shadow;
2877d4b53bcSDerick Montague      outline: 0;
2881ace1d91SYoshie Muranaka    }
2891ace1d91SYoshie Muranaka  }
2906859203cSDerick Montague
291dc04feb5SYoshie Muranaka  .nav-item {
29201da8187SYoshie Muranaka    fill: theme-color('light');
293dc04feb5SYoshie Muranaka  }
29474f8687dSYoshie Muranaka
29574f8687dSYoshie Muranaka  .navbar {
29674f8687dSYoshie Muranaka    padding: 0;
29721d6de00SMateusz Gapski    background-color: $navbar-color;
2987d6b44cbSEd Tanous
299057232b8SSurenNeware    @include media-breakpoint-up($responsive-layout-bp) {
30074f8687dSYoshie Muranaka      height: $header-height;
301057232b8SSurenNeware    }
3026859203cSDerick Montague
303057232b8SSurenNeware    .helper-menu {
304057232b8SSurenNeware      @include media-breakpoint-down(sm) {
30501da8187SYoshie Muranaka        background-color: gray('800');
306057232b8SSurenNeware        width: 100%;
307057232b8SSurenNeware        justify-content: flex-end;
308057232b8SSurenNeware
309057232b8SSurenNeware        .nav-link,
310057232b8SSurenNeware        .btn {
311057232b8SSurenNeware          padding: $spacer / 1.125 $spacer / 2;
312057232b8SSurenNeware        }
3137d4b53bcSDerick Montague
3147d4b53bcSDerick Montague        .nav-link:focus,
3157d4b53bcSDerick Montague        .btn:focus {
3167d4b53bcSDerick Montague          @include focus-box-shadow($gray-800);
3177d4b53bcSDerick Montague        }
318057232b8SSurenNeware      }
319057232b8SSurenNeware
320057232b8SSurenNeware      .responsive-text {
321057232b8SSurenNeware        @include media-breakpoint-down(xs) {
3224dd7eabfSSukanya Pandey          @include sr-only;
323057232b8SSurenNeware        }
324057232b8SSurenNeware      }
325057232b8SSurenNeware    }
32674f8687dSYoshie Muranaka  }
32774f8687dSYoshie Muranaka
32874f8687dSYoshie Muranaka  .navbar-nav {
3294dd7eabfSSukanya Pandey    @include media-breakpoint-up($responsive-layout-bp) {
33074f8687dSYoshie Muranaka      padding: 0 $spacer;
3314dd7eabfSSukanya Pandey    }
3321f8117f8SSurenNeware    align-items: center;
3331f8117f8SSurenNeware
3341f8117f8SSurenNeware    .navbar-brand,
3351f8117f8SSurenNeware    .nav-link {
3361f8117f8SSurenNeware      transition: $focus-transition;
3371f8117f8SSurenNeware    }
3384dd7eabfSSukanya Pandey    .nav-tags {
339c5c2ae99SSukanya Pandey      color: theme-color-level(light, 3);
3404dd7eabfSSukanya Pandey      @include media-breakpoint-down(xs) {
3414dd7eabfSSukanya Pandey        @include sr-only;
3424dd7eabfSSukanya Pandey      }
3434dd7eabfSSukanya Pandey      .asset-tag {
3444dd7eabfSSukanya Pandey        @include media-breakpoint-down($responsive-layout-bp) {
3454dd7eabfSSukanya Pandey          @include sr-only;
3464dd7eabfSSukanya Pandey        }
3474dd7eabfSSukanya Pandey      }
348c5c2ae99SSukanya Pandey    }
34974f8687dSYoshie Muranaka  }
35074f8687dSYoshie Muranaka
35174f8687dSYoshie Muranaka  .nav-trigger {
35201da8187SYoshie Muranaka    fill: theme-color('light');
35374f8687dSYoshie Muranaka    width: $header-height;
35474f8687dSYoshie Muranaka    height: $header-height;
35574f8687dSYoshie Muranaka    transition: none;
3561f8117f8SSurenNeware    display: inline-flex;
3571f8117f8SSurenNeware    flex: 0 0 20px;
3581f8117f8SSurenNeware    align-items: center;
35974f8687dSYoshie Muranaka
36074f8687dSYoshie Muranaka    svg {
36174f8687dSYoshie Muranaka      margin: 0;
36274f8687dSYoshie Muranaka    }
36374f8687dSYoshie Muranaka
36474f8687dSYoshie Muranaka    &:hover {
36501da8187SYoshie Muranaka      fill: theme-color('light');
3661f8117f8SSurenNeware      background-color: theme-color-level(light, 10);
36774f8687dSYoshie Muranaka    }
36874f8687dSYoshie Muranaka
369057232b8SSurenNeware    &.open {
37001da8187SYoshie Muranaka      background-color: gray('800');
371057232b8SSurenNeware    }
372057232b8SSurenNeware
37374f8687dSYoshie Muranaka    @include media-breakpoint-up($responsive-layout-bp) {
37474f8687dSYoshie Muranaka      display: none;
37574f8687dSYoshie Muranaka    }
376dc04feb5SYoshie Muranaka  }
377b1f559f0SSukanya Pandey
378b1f559f0SSukanya Pandey  .dropdown-menu {
379057232b8SSurenNeware    margin-top: 0;
3801f8117f8SSurenNeware
3811f8117f8SSurenNeware    @include media-breakpoint-only(md) {
3821f8117f8SSurenNeware      margin-top: 4px;
383b1f559f0SSukanya Pandey    }
384b1f559f0SSukanya Pandey  }
385057232b8SSurenNeware
386057232b8SSurenNeware  .navbar-expand {
387057232b8SSurenNeware    @include media-breakpoint-down(sm) {
388057232b8SSurenNeware      flex-flow: wrap;
389057232b8SSurenNeware    }
390057232b8SSurenNeware  }
391057232b8SSurenNeware}
3921f8117f8SSurenNeware
3931f8117f8SSurenNeware.navbar-brand {
3941f8117f8SSurenNeware  padding: $spacer/2;
3951f8117f8SSurenNeware  height: $header-height;
3961f8117f8SSurenNeware  line-height: 1;
3971f8117f8SSurenNeware  &:focus {
3988132399cSEd Tanous    box-shadow:
3998132399cSEd Tanous      inset 0 0 0 3px $navbar-color,
4008132399cSEd Tanous      inset 0 0 0 5px color('white');
4011f8117f8SSurenNeware    outline: 0;
4021f8117f8SSurenNeware  }
4031f8117f8SSurenNeware}
404b8b6f791SYoshie Muranaka</style>
405