diff --git a/frontend/package.json b/frontend/package.json
index 2487afe4..4af4db93 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -15,6 +15,7 @@
"dependencies": {
"@bcgov/bc-sans": "^2.0.0",
"@js-joda/core": "^5.5.3",
+ "@vueuse/core": "^10.5.0",
"axios": "^1.4.0",
"http-status-codes": "^2.2.0",
"lodash": "^4.17.21",
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 5dab932d..335a5d40 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -2,14 +2,17 @@
+
-
+
@@ -27,7 +30,6 @@ import TheNavBar from '@/components/TheNavBar.vue'
import TheSnackBar from '@/components/TheSnackBar.vue'
import { useAppStore } from '@/stores/app'
import { useAuthStore } from '@/stores/auth'
-import HttpStatus from 'http-status-codes'
export default {
name: 'App',
@@ -40,8 +42,10 @@ export default {
TheFooter,
TheMenu,
},
+
data() {
return {
+ showMenu: true,
showToTopBtn: false,
deactivateMultipleDraggableDialog: null,
}
@@ -49,6 +53,9 @@ export default {
computed: {
...mapState(useAuthStore, ['jwtToken', 'isAuthenticated', 'userInfo', 'isAuthorizedWebsocketUser']),
...mapState(useAppStore, ['pageTitle', 'showNavBar']),
+ mobile() {
+ return this.$vuetify.display.mobile
+ },
},
watch: {
/*
@@ -59,6 +66,10 @@ export default {
isAuthorizedWebsocketUser() {
this.handleWebSocket()
},
+ mobile() {
+ // Reset the menu state on mobile change
+ this.showMenu = false
+ },
},
mounted() {
this.handleWebSocket()
@@ -85,6 +96,9 @@ export default {
methods: {
...mapActions(useAppStore, ['getConfig']),
...mapActions(useAuthStore, ['getJwtToken']),
+ handleMenuToggled() {
+ this.showMenu = !this.showMenu
+ },
handleWebSocket() {
if (this.isAuthenticated && this.isAuthorizedWebsocketUser) {
this.$webSocketsConnect()
@@ -105,6 +119,14 @@ export default {
diff --git a/frontend/src/components/TheNavBar.vue b/frontend/src/components/TheNavBar.vue
index 1657ce4d..0a7a8050 100644
--- a/frontend/src/components/TheNavBar.vue
+++ b/frontend/src/components/TheNavBar.vue
@@ -39,8 +39,8 @@
Menu
@@ -49,11 +49,11 @@
-
+
diff --git a/frontend/src/components/ui/AppMenuItem.vue b/frontend/src/components/ui/AppMenuItem.vue
index e0652b35..efd90a1a 100644
--- a/frontend/src/components/ui/AppMenuItem.vue
+++ b/frontend/src/components/ui/AppMenuItem.vue
@@ -19,7 +19,7 @@ export default {
.menu-item {
cursor: pointer;
font-size: 1em;
- height: 3em;
+ height: 2em;
}
.menu-item-active {
background-color: #003366;
diff --git a/frontend/src/main.js b/frontend/src/main.js
index 40f95d69..ffa40706 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -1,44 +1,19 @@
import 'regenerator-runtime/runtime'
-import '@mdi/font/css/materialdesignicons.css'
import '@bcgov/bc-sans/css/BCSans.css'
-import 'vuetify/styles'
+import '@/assets/css/main.css'
+import '@/assets/css/reset.css'
import moment from 'moment'
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import { createMetaManager } from 'vue-meta'
-import * as components from 'vuetify/components'
-import * as directives from 'vuetify/directives'
-import { createVuetify } from 'vuetify/dist/vuetify'
+import vuetify from '@/plugins/vuetify'
import webSocketService from '@/services/web-socket-service'
import App from './App.vue'
import router from './router'
-const myCustomLightTheme = {
- dark: false,
- colors: {
- primary: '#003366',
- },
-}
-
-const vuetify = createVuetify({
- icons: {
- defaultSet: 'mdi',
- },
- theme: {
- defaultTheme: 'myCustomLightTheme',
- themes: {
- myCustomLightTheme,
- },
- },
- components: {
- ...components,
- ...directives,
- },
-})
-
const app = createApp(App)
const pinia = createPinia()
diff --git a/frontend/src/plugins/vuetify.js b/frontend/src/plugins/vuetify.js
index 3a786700..4abf2458 100644
--- a/frontend/src/plugins/vuetify.js
+++ b/frontend/src/plugins/vuetify.js
@@ -1,38 +1,35 @@
-import '@fortawesome/fontawesome-free/css/all.css';
-import '@mdi/font/css/materialdesignicons.css';
-import Vue from 'vue';
-import Vuetify from 'vuetify/lib';
-import { Ripple } from 'vuetify/lib/directives';
+import '@mdi/font/css/materialdesignicons.css'
+import 'vuetify/styles'
-Vue.use(Vuetify, {
- directives: {
- Ripple
- }
-});
+import * as components from 'vuetify/components'
+import * as directives from 'vuetify/directives'
+import { createVuetify } from 'vuetify/dist/vuetify'
+import { aliases, mdi } from 'vuetify/iconsets/mdi'
-export default new Vuetify({
- theme: {
- light: true,
- dark: false
+const myCustomLightTheme = {
+ dark: false,
+ colors: {
+ primary: '#003366',
+ },
+}
+
+export default createVuetify({
+ components,
+ directives,
+ display: {
+ mobileBreakpoint: 'md',
},
icons: {
- iconfont: 'fa',
- values: {
- login: 'fas fa-user-clock',
- fast: 'fas fa-shipping-fast',
- sign_in: 'fas fa-sign-in-alt',
- info1: 'fas fa-info-circle',
- downArrow: 'fas fa-angle-down',
- upArrow: 'fas fa-angle-up',
- user: 'far fa-user',
- copy: 'fas fa-copy',
- search: 'fas fa-search',
- error: 'fas fa-exclamation-triangle',
- lock: 'fas fa-lock',
- info2: 'fas fa-info-circle fa-10x',
- question: 'fas fa-question-circle fa-10x',
- plus: 'fas fa-plus-circle',
- minus: 'fas fa-minus-circle',
- }
- }
-});
+ defaultSet: 'mdi',
+ aliases,
+ sets: {
+ mdi,
+ },
+ },
+ theme: {
+ defaultTheme: 'myCustomLightTheme',
+ themes: {
+ myCustomLightTheme,
+ },
+ },
+})
diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js
index e8be3e89..62876fed 100644
--- a/frontend/src/router/index.js
+++ b/frontend/src/router/index.js
@@ -1,5 +1,8 @@
import { createRouter, createWebHistory } from 'vue-router'
+import { useAppStore } from '@/stores/app'
+import { useAuthStore } from '@/stores/auth'
+import { PAGE_TITLES } from '@/utils/constants'
import BackendSessionExpiredView from '@/views/BackendSessionExpiredView.vue'
import ErrorView from '@/views/ErrorView.vue'
import HomeView from '@/views/HomeView.vue'
@@ -7,35 +10,14 @@ import Impersonate from '@/views/ImpersonateView.vue'
import LoginView from '@/views/LoginView.vue'
import LogoutView from '@/views/LogoutView.vue'
import MinistryLoginView from '@/views/MinistryLoginView.vue'
-import { PAGE_TITLES } from '@/utils/constants'
import SessionExpiredView from '@/views/SessionExpiredView.vue'
import UnAuthorizedPageView from '@/views/UnAuthorizedPageView.vue'
import UnAuthorizedView from '@/views/UnAuthorizedView.vue'
-import { useAppStore } from '@/stores/app'
-import { useAuthStore } from '@/stores/auth'
const router = createRouter({
history: createWebHistory(),
base: import.meta.env.BASE_URL,
routes: [
- {
- path: '/impersonate',
- name: 'impersonate',
- component: Impersonate,
- meta: {
- pageTitle: 'Impersonate a BCeID User',
- requiresAuth: true,
- },
- },
- {
- path: '/internal',
- name: 'ministry login',
- component: MinistryLoginView,
- meta: {
- pageTitle: PAGE_TITLES.LOGIN,
- requiresAuth: false,
- },
- },
{
path: '/',
name: 'home',
@@ -54,6 +36,15 @@ const router = createRouter({
pageTitle: PAGE_TITLES.LOGIN,
},
},
+ {
+ path: '/internal',
+ name: 'ministry login',
+ component: MinistryLoginView,
+ meta: {
+ pageTitle: PAGE_TITLES.LOGIN,
+ requiresAuth: false,
+ },
+ },
{
path: '/logout',
name: 'logout',
@@ -62,6 +53,15 @@ const router = createRouter({
requiresAuth: false,
},
},
+ {
+ path: '/impersonate',
+ name: 'impersonate',
+ component: Impersonate,
+ meta: {
+ pageTitle: 'Impersonate a BCeID User',
+ requiresAuth: true,
+ },
+ },
{
path: '/session-expired',
name: 'session-expired',
@@ -197,6 +197,11 @@ router.beforeEach((to, _from, next) => {
appStore.setPageTitle('')
}
+ // TODO (weskubo)
+ // 1. Don't allow access to Logout page if not logged in
+ // 2. Don't allow access to Login if Logged in
+ // 3. Don't allow access to Internal if logged in
+
const authStore = useAuthStore()
if (to.meta.requiresAuth) {
authStore
@@ -226,6 +231,7 @@ router.beforeEach((to, _from, next) => {
.catch((err) => {
if (!authStore.userInfo) {
next('/login')
+ return
}
next('/token-expired')
})
diff --git a/frontend/src/stores/auth.js b/frontend/src/stores/auth.js
index 1cb478e9..7138fb07 100644
--- a/frontend/src/stores/auth.js
+++ b/frontend/src/stores/auth.js
@@ -1,7 +1,8 @@
-import { ApiRoutes } from '@/utils/constants'
+import { defineStore } from 'pinia'
+
import ApiService from '@/common/apiService'
import AuthService from '@/common/authService'
-import { defineStore } from 'pinia'
+import { ApiRoutes } from '@/utils/constants'
export const useAuthStore = defineStore('auth', {
namespaced: true,
diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js
index 860c39bb..5b54f2c0 100644
--- a/frontend/src/utils/constants.js
+++ b/frontend/src/utils/constants.js
@@ -15,13 +15,6 @@ export const ApiRoutes = Object.freeze({
USER: baseRoot + '/user',
})
-export const PATHS = Object.freeze({
- ROOT: {
- HOME: '/',
- IMPERSONATE: '/impersonate',
- },
-})
-
export const ACCOUNT_TYPE = Object.freeze({
FACILITY: 100000001,
ORGANIZATION: 100000000,
diff --git a/frontend/src/views/ImpersonateView.vue b/frontend/src/views/ImpersonateView.vue
index 47854761..43223fcc 100644
--- a/frontend/src/views/ImpersonateView.vue
+++ b/frontend/src/views/ImpersonateView.vue
@@ -23,7 +23,6 @@