xref: /openbmc/webui-vue/src/components/AppNavigation/AppNavigation.vue (revision a88f752908a6188f72274550e0cfe1418cb27f63)
1<template>
2  <div>
3    <div class="nav-container" :class="{ open: isNavigationOpen }">
4      <nav ref="nav" :aria-label="$t('appNavigation.primaryNavigation')">
5        <b-nav vertical>
6          <b-nav-item to="/">
7            <icon-overview />
8            {{ $t('appNavigation.overview') }}
9          </b-nav-item>
10
11          <li class="nav-item">
12            <b-button v-b-toggle.health-menu variant="link">
13              <icon-health />
14              {{ $t('appNavigation.health') }}
15              <icon-expand class="icon-expand" />
16            </b-button>
17            <b-collapse id="health-menu" tag="ul" class="nav-item__nav">
18              <b-nav-item to="/health/event-logs">
19                {{ $t('appNavigation.eventLogs') }}
20              </b-nav-item>
21              <b-nav-item to="/health/hardware-status">
22                {{ $t('appNavigation.hardwareStatus') }}
23              </b-nav-item>
24              <b-nav-item to="/health/sensors">
25                {{ $t('appNavigation.sensors') }}
26              </b-nav-item>
27            </b-collapse>
28          </li>
29
30          <li class="nav-item">
31            <b-button v-b-toggle.control-menu variant="link">
32              <icon-control />
33              {{ $t('appNavigation.control') }}
34              <icon-expand class="icon-expand" />
35            </b-button>
36            <b-collapse id="control-menu" tag="ul" class="nav-item__nav">
37              <b-nav-item to="/control/manage-power-usage">
38                {{ $t('appNavigation.managePowerUsage') }}
39              </b-nav-item>
40              <b-nav-item to="/control/reboot-bmc">
41                {{ $t('appNavigation.rebootBmc') }}
42              </b-nav-item>
43              <b-nav-item to="/control/serial-over-lan">
44                {{ $t('appNavigation.serialOverLan') }}
45              </b-nav-item>
46              <b-nav-item to="/control/server-led">
47                {{ $t('appNavigation.serverLed') }}
48              </b-nav-item>
49              <b-nav-item to="/control/server-power-operations">
50                {{ $t('appNavigation.serverPowerOperations') }}
51              </b-nav-item>
52            </b-collapse>
53          </li>
54
55          <li class="nav-item">
56            <b-button v-b-toggle.configuration-menu variant="link">
57              <icon-configuration />
58              {{ $t('appNavigation.configuration') }}
59              <icon-expand class="icon-expand" />
60            </b-button>
61            <b-collapse id="configuration-menu" tag="ul" class="nav-item__nav">
62              <b-nav-item to="/configuration/date-time-settings">
63                {{ $t('appNavigation.dateTimeSettings') }}
64              </b-nav-item>
65              <b-nav-item href="javascript:void(0)">
66                {{ $t('appNavigation.firmware') }}
67              </b-nav-item>
68              <b-nav-item to="/configuration/network-settings">
69                {{ $t('appNavigation.networkSettings') }}
70              </b-nav-item>
71              <b-nav-item href="javascript:void(0)">
72                {{ $t('appNavigation.snmpSettings') }}
73              </b-nav-item>
74            </b-collapse>
75          </li>
76
77          <li class="nav-item">
78            <b-button v-b-toggle.access-control-menu variant="link">
79              <icon-access-control />
80              {{ $t('appNavigation.accessControl') }}
81              <icon-expand class="icon-expand" />
82            </b-button>
83            <b-collapse id="access-control-menu" tag="ul" class="nav-item__nav">
84              <b-nav-item to="/access-control/ldap">
85                {{ $t('appNavigation.ldap') }}
86              </b-nav-item>
87              <b-nav-item to="/access-control/local-user-management">
88                {{ $t('appNavigation.localUserManagement') }}
89              </b-nav-item>
90              <b-nav-item to="/access-control/ssl-certificates">
91                {{ $t('appNavigation.sslCertificates') }}
92              </b-nav-item>
93            </b-collapse>
94          </li>
95        </b-nav>
96      </nav>
97    </div>
98    <transition name="fade">
99      <div
100        v-if="isNavigationOpen"
101        id="nav-overlay"
102        class="nav-overlay"
103        @click="toggleIsOpen"
104      ></div>
105    </transition>
106  </div>
107</template>
108
109<script>
110import IconAnalytics from '@carbon/icons-vue/es/analytics/16';
111import IconDataCheck from '@carbon/icons-vue/es/data--check/16';
112import IconSettingsAdjust from '@carbon/icons-vue/es/settings--adjust/16';
113import IconSettings from '@carbon/icons-vue/es/settings/16';
114import IconPassword from '@carbon/icons-vue/es/password/16';
115import IconChevronUp from '@carbon/icons-vue/es/chevron--up/16';
116
117export default {
118  name: 'AppNavigation',
119  components: {
120    iconOverview: IconAnalytics,
121    iconHealth: IconDataCheck,
122    iconControl: IconSettingsAdjust,
123    iconConfiguration: IconSettings,
124    iconAccessControl: IconPassword,
125    iconExpand: IconChevronUp
126  },
127  data() {
128    return {
129      isNavigationOpen: false
130    };
131  },
132  watch: {
133    $route: function() {
134      this.isNavigationOpen = false;
135    },
136    isNavigationOpen: function(isNavigationOpen) {
137      this.$root.$emit('change:isNavigationOpen', isNavigationOpen);
138    }
139  },
140  mounted() {
141    this.$root.$on('toggle:navigation', () => this.toggleIsOpen());
142  },
143  methods: {
144    toggleIsOpen() {
145      this.isNavigationOpen = !this.isNavigationOpen;
146    }
147  }
148};
149</script>
150
151<style scoped lang="scss">
152@import 'src/assets/styles/helpers';
153
154svg {
155  fill: currentColor;
156  height: 1.2rem;
157  width: 1.2rem;
158  margin-left: 0 !important; //!important overriding button specificity
159  vertical-align: text-bottom;
160  &:not(.icon-expand) {
161    margin-right: $spacer;
162  }
163}
164
165.nav {
166  padding-top: $spacer / 4;
167  @include media-breakpoint-up($responsive-layout-bp) {
168    padding-top: $spacer;
169  }
170}
171
172.nav-item__nav {
173  list-style: none;
174  padding-left: 0;
175  margin-left: 0;
176
177  .nav-item {
178    outline: none;
179  }
180
181  .nav-link {
182    padding-left: $spacer * 4;
183    outline: none;
184
185    &:not(.nav-link--current) {
186      font-weight: normal;
187    }
188  }
189}
190
191.btn-link {
192  width: 100%;
193  text-align: left;
194  text-decoration: none !important;
195  border-radius: 0;
196
197  &.collapsed {
198    .icon-expand {
199      transform: rotate(180deg);
200    }
201  }
202}
203
204.icon-expand {
205  float: right;
206  margin-top: $spacer / 4;
207}
208
209.btn-link,
210.nav-link {
211  position: relative;
212  font-weight: $headings-font-weight;
213  padding-left: $spacer; // defining consistent padding for links and buttons
214  padding-right: $spacer;
215  color: $secondary;
216
217  &:hover {
218    background-color: $primary-nav-hover;
219    color: $dark;
220  }
221
222  &:focus {
223    box-shadow: $btn-focus-box-shadow;
224    color: $dark;
225  }
226}
227
228.nav-link--current,
229.nav-link--current:hover,
230.nav-link--current:focus {
231  font-weight: $headings-font-weight;
232  background-color: $secondary;
233  color: $light;
234  cursor: default;
235
236  &::before {
237    content: '';
238    position: absolute;
239    top: 0;
240    bottom: 0;
241    left: 0;
242    width: 4px;
243    background-color: $primary;
244  }
245}
246
247.nav-container {
248  position: fixed;
249  width: $navigation-width;
250  top: $header-height;
251  bottom: 0;
252  left: 0;
253  z-index: $zindex-fixed;
254  overflow-y: auto;
255  background-color: $container-bgd;
256  transform: translateX(-$navigation-width);
257  transition: transform $exit-easing--productive $duration--moderate-02;
258  @include media-breakpoint-down(md) {
259    z-index: $zindex-fixed + 2;
260  }
261
262  &.open,
263  &:focus-within {
264    transform: translateX(0);
265    transition-timing-function: $entrance-easing--productive;
266  }
267
268  @include media-breakpoint-up($responsive-layout-bp) {
269    transition-duration: $duration--fast-01;
270    transform: translateX(0);
271  }
272}
273
274.nav-overlay {
275  position: fixed;
276  top: $header-height;
277  bottom: 0;
278  left: 0;
279  right: 0;
280  z-index: $zindex-fixed + 1;
281  background-color: $black;
282  opacity: 0.5;
283
284  &.fade-enter-active {
285    transition: opacity $duration--moderate-02 $entrance-easing--productive;
286  }
287
288  &.fade-leave-active {
289    transition: opacity $duration--fast-02 $exit-easing--productive;
290  }
291
292  &.fade-enter,
293  &.fade-leave-to {
294    opacity: 0;
295  }
296
297  @include media-breakpoint-up($responsive-layout-bp) {
298    display: none;
299  }
300}
301</style>
302