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 @@ 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 @@