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