1<template> 2 <div class="app-container"> 3 <app-header 4 ref="focusTarget" 5 class="app-header" 6 :router-key="routerKey" 7 @refresh="refresh" 8 /> 9 <app-navigation class="app-navigation" /> 10 <page-container class="app-content"> 11 <router-view ref="routerView" :key="routerKey" /> 12 <!-- Scroll to top button --> 13 <button-back-to-top /> 14 </page-container> 15 </div> 16</template> 17 18<script> 19import AppHeader from '@/components/AppHeader'; 20import AppNavigation from '@/components/AppNavigation'; 21import PageContainer from '@/components/Global/PageContainer'; 22import ButtonBackToTop from '@/components/Global/ButtonBackToTop'; 23import JumpLinkMixin from '@/components/Mixins/JumpLinkMixin'; 24 25export default { 26 name: 'App', 27 components: { 28 AppHeader, 29 AppNavigation, 30 PageContainer, 31 ButtonBackToTop, 32 }, 33 mixins: [JumpLinkMixin], 34 data() { 35 return { 36 routerKey: 0, 37 }; 38 }, 39 watch: { 40 $route: function () { 41 this.$nextTick(function () { 42 this.setFocus(this.$refs.focusTarget.$el); 43 }); 44 }, 45 }, 46 mounted() { 47 require('@/eventBus').default.$on('refresh-application', () => 48 this.refresh(), 49 ); 50 setInterval(() => { 51 if (!localStorage.getItem('storedUsername')) { 52 this.$eventBus.$consoleWindow?.close(); 53 this.refresh(); 54 } 55 }, 10000); 56 }, 57 beforeUnmount() { 58 require('@/eventBus').default.$off( 59 'refresh-application', 60 this.handleRefreshApplication, 61 ); 62 }, 63 methods: { 64 handleRefreshApplication() { 65 this.refresh(); 66 }, 67 refresh() { 68 // Clear all toast messages 69 document.querySelectorAll('.toast').forEach((toast) => { 70 const toastId = toast.id; 71 if (toastId) { 72 this.$bvToast.hide(toastId); 73 } 74 }); 75 // Changing the component :key value will trigger 76 // a component re-rendering and 'refresh' the view 77 this.routerKey += 1; 78 }, 79 }, 80}; 81</script> 82 83<style lang="scss" scoped> 84.app-container { 85 display: grid; 86 grid-template-columns: 100%; 87 grid-template-rows: auto; 88 grid-template-areas: 89 'header' 90 'content'; 91 92 @include media-breakpoint-up($responsive-layout-bp) { 93 grid-template-columns: $navigation-width 1fr; 94 grid-template-areas: 95 'header header' 96 'navigation content'; 97 } 98} 99 100.app-header { 101 grid-area: header; 102 position: sticky; 103 top: 0; 104 z-index: $zindex-fixed + 1; 105} 106 107.app-navigation { 108 grid-area: navigation; 109} 110 111.app-content { 112 grid-area: content; 113 background-color: $white; 114} 115</style> 116