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