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-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-dateTimeSettings" 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-networkSettings" 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-accessControl" 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-localUserManagement" 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-sslCertificates" 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"> 216svg { 217 fill: currentColor; 218 height: 1.2rem; 219 width: 1.2rem; 220 margin-left: 0 !important; //!important overriding button specificity 221 vertical-align: text-bottom; 222 &:not(.icon-expand) { 223 margin-right: $spacer; 224 } 225} 226 227.nav { 228 padding-top: $spacer / 4; 229 @include media-breakpoint-up($responsive-layout-bp) { 230 padding-top: $spacer; 231 } 232} 233 234.nav-item__nav { 235 list-style: none; 236 padding-left: 0; 237 margin-left: 0; 238 239 .nav-item { 240 outline: none; 241 } 242 243 .nav-link { 244 padding-left: $spacer * 4; 245 outline: none; 246 247 &:not(.nav-link--current) { 248 font-weight: normal; 249 } 250 } 251} 252 253.btn-link { 254 width: 100%; 255 text-align: left; 256 text-decoration: none !important; 257 border-radius: 0; 258 259 &.collapsed { 260 .icon-expand { 261 transform: rotate(180deg); 262 } 263 } 264} 265 266.icon-expand { 267 float: right; 268 margin-top: $spacer / 4; 269} 270 271.btn-link, 272.nav-link { 273 position: relative; 274 font-weight: $headings-font-weight; 275 padding-left: $spacer; // defining consistent padding for links and buttons 276 padding-right: $spacer; 277 color: theme-color('secondary'); 278 279 &:hover { 280 background-color: gray('300'); 281 color: theme-color('dark'); 282 } 283 284 &:focus { 285 box-shadow: $btn-focus-box-shadow; 286 color: theme-color('dark'); 287 } 288} 289 290.nav-link--current, 291.nav-link--current:hover, 292.nav-link--current:focus { 293 font-weight: $headings-font-weight; 294 background-color: theme-color('secondary'); 295 color: theme-color('light'); 296 cursor: default; 297 298 &::before { 299 content: ''; 300 position: absolute; 301 top: 0; 302 bottom: 0; 303 left: 0; 304 width: 4px; 305 background-color: theme-color('primary'); 306 } 307} 308 309.nav-container { 310 position: fixed; 311 width: $navigation-width; 312 top: $header-height; 313 bottom: 0; 314 left: 0; 315 z-index: $zindex-fixed; 316 overflow-y: auto; 317 background-color: gray('200'); 318 transform: translateX(-$navigation-width); 319 transition: transform $exit-easing--productive $duration--moderate-02; 320 @include media-breakpoint-down(md) { 321 z-index: $zindex-fixed + 2; 322 } 323 324 &.open, 325 &:focus-within { 326 transform: translateX(0); 327 transition-timing-function: $entrance-easing--productive; 328 } 329 330 @include media-breakpoint-up($responsive-layout-bp) { 331 transition-duration: $duration--fast-01; 332 transform: translateX(0); 333 } 334} 335 336.nav-overlay { 337 position: fixed; 338 top: $header-height; 339 bottom: 0; 340 left: 0; 341 right: 0; 342 z-index: $zindex-fixed + 1; 343 background-color: $black; 344 opacity: 0.5; 345 346 &.fade-enter-active { 347 transition: opacity $duration--moderate-02 $entrance-easing--productive; 348 } 349 350 &.fade-leave-active { 351 transition: opacity $duration--fast-02 $exit-easing--productive; 352 } 353 354 &.fade-enter, 355 &.fade-leave-to { 356 opacity: 0; 357 } 358 359 @include media-breakpoint-up($responsive-layout-bp) { 360 display: none; 361 } 362} 363</style> 364