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