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