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