feat(login): create dev login bypass for testing, refactor main layout for consistency and more intuitive UI
This commit is contained in:
parent
7399232ed8
commit
5a4cba5588
|
|
@ -5,7 +5,7 @@ import messages from 'src/i18n';
|
||||||
|
|
||||||
export type MessageLanguages = keyof typeof messages;
|
export type MessageLanguages = keyof typeof messages;
|
||||||
// Type-define 'en-US' as the master schema for the resource
|
// Type-define 'en-US' as the master schema for the resource
|
||||||
export type MessageSchema = typeof messages['en-ca'];
|
export type MessageSchema = typeof messages['en'];
|
||||||
|
|
||||||
// See https://vue-i18n.intlify.dev/guide/advanced/typescript.html#global-resource-schema-type-definition
|
// See https://vue-i18n.intlify.dev/guide/advanced/typescript.html#global-resource-schema-type-definition
|
||||||
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
||||||
|
|
@ -23,7 +23,7 @@ declare module 'vue-i18n' {
|
||||||
|
|
||||||
export default defineBoot(({ app }) => {
|
export default defineBoot(({ app }) => {
|
||||||
const i18n = createI18n<{ message: MessageSchema }, MessageLanguages>({
|
const i18n = createI18n<{ message: MessageSchema }, MessageLanguages>({
|
||||||
locale: 'fr-ca',
|
locale: 'fr',
|
||||||
legacy: false,
|
legacy: false,
|
||||||
messages,
|
messages,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,13 @@ export default {
|
||||||
clearFilter: 'Clear filter',
|
clearFilter: 'Clear filter',
|
||||||
},
|
},
|
||||||
navBar: {
|
navBar: {
|
||||||
navItem_1: 'Users list',
|
userMenuEmployeeList: 'Employee list',
|
||||||
navItem_2: 'Shift validations',
|
userMenuShiftValidation: 'Timesheet Approval',
|
||||||
menuItem_1: 'Profile',
|
userMenuProfile: 'Profile',
|
||||||
menuItem_2: 'Help',
|
userMenuHelp: 'Help',
|
||||||
menuItem_3: 'Log Out',
|
userMenuLogout: 'Log Out',
|
||||||
menuItem_4: 'Time Sheet',
|
userMenuTimesheet: 'Timesheet',
|
||||||
menuItem_5: 'Annual calendar',
|
userMenuCalendar: 'Calendar',
|
||||||
mobileIndexTitle: 'Hi',
|
|
||||||
},
|
},
|
||||||
notFoundPage: {
|
notFoundPage: {
|
||||||
pageTitle: 'Oops. Nothing here...',
|
pageTitle: 'Oops. Nothing here...',
|
||||||
|
|
|
||||||
|
|
@ -162,14 +162,13 @@ export default {
|
||||||
clearFilter: 'Effacer le filtre',
|
clearFilter: 'Effacer le filtre',
|
||||||
},
|
},
|
||||||
navBar: {
|
navBar: {
|
||||||
navItem_1: 'Liste des utilisateurs',
|
userMenuEmployeeList: 'Liste employés',
|
||||||
navItem_2: 'Validations des quarts de travail',
|
userMenuShiftValidation: 'Valider les heures',
|
||||||
menuItem_1: 'Profil',
|
userMenuProfile: 'Profil',
|
||||||
menuItem_2: 'Aide',
|
userMenuHelp: 'Aide',
|
||||||
menuItem_3: 'Déconnexion',
|
userMenuLogout: 'Déconnexion',
|
||||||
menuItem_4: 'Carte de temps',
|
userMenuTimesheet: 'Carte de temps',
|
||||||
menuItem_5: 'Calendrier annuel',
|
userMenuCalendar: 'Calendrier annuel',
|
||||||
mobileIndexTitle: 'Bonjour',
|
|
||||||
},
|
},
|
||||||
notFoundPage: {
|
notFoundPage: {
|
||||||
pageTitle: 'Oops. Rien ici...',
|
pageTitle: 'Oops. Rien ici...',
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@ import enCA from './en-ca';
|
||||||
import frCA from './fr-ca';
|
import frCA from './fr-ca';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'en-ca': enCA,
|
'en': enCA,
|
||||||
'fr-ca': frCA,
|
'fr': frCA,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
import { RouterView } from 'vue-router';
|
import { RouterView } from 'vue-router';
|
||||||
import HeaderBar from 'src/modules/shared/components/navigation/header-bar.vue';
|
import HeaderBar from 'src/modules/shared/components/navigation/header-bar.vue';
|
||||||
import FooterBar from 'src/modules/shared/components/navigation/footer-bar.vue';
|
import FooterBar from 'src/modules/shared/components/navigation/footer-bar.vue';
|
||||||
|
import RightDrawer from 'src/modules/shared/components/navigation/right-drawer.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-layout view="hHh lpR fFf">
|
<q-layout view="hHh lpR fFf">
|
||||||
<HeaderBar />
|
<HeaderBar />
|
||||||
|
<RightDrawer />
|
||||||
<q-page-container>
|
<q-page-container>
|
||||||
<router-view class="q-pa-sm" />
|
<router-view class="q-pa-sm" />
|
||||||
</q-page-container>
|
</q-page-container>
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
/* eslint-disable */
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
import { User } from "src/modules/users/types/user-interface";
|
|
||||||
import { AuthState } from "./types/auth-interface";
|
|
||||||
import { AuthService } from "./services/services-auth";
|
|
||||||
import { computed, ref } from "vue";
|
|
||||||
|
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
|
||||||
const user = ref ({
|
|
||||||
firstName: 'Unknown',
|
|
||||||
lastName: 'Unknown',
|
|
||||||
email: 'guest@guest.com',
|
|
||||||
role: 'guest'
|
|
||||||
} as User);
|
|
||||||
const error = ref("");
|
|
||||||
const isAuthorizedUser = computed( () => user.value.role !== 'guest');
|
|
||||||
|
|
||||||
const login = () => {
|
|
||||||
//TODO: manage customer login process
|
|
||||||
};
|
|
||||||
|
|
||||||
const oidcLogin = () => {
|
|
||||||
const oidcPopup = AuthService.oidcLogin();
|
|
||||||
if (!oidcPopup) {
|
|
||||||
error.value = "You have popups blocked on this website!";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const logout = () => {
|
|
||||||
return "logout";
|
|
||||||
};
|
|
||||||
|
|
||||||
const setUser = (currentUser: User, isBypass: boolean = false, bypassRole?: string) => {
|
|
||||||
if (isBypass) {
|
|
||||||
user.value = {
|
|
||||||
firstName: "Testing",
|
|
||||||
lastName: "Tester",
|
|
||||||
email: "testingT@targointernet.com",
|
|
||||||
role: bypassRole || "guest"} as User;
|
|
||||||
} else {
|
|
||||||
user.value = currentUser;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return { login, oidcLogin, logout, setUser };
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -1,33 +1,36 @@
|
||||||
import { useAuthStore } from "../auth-store";
|
import { useAuthStore } from "../../../stores/auth-store";
|
||||||
|
import type { User } from "src/modules/users/types/user-interface";
|
||||||
|
|
||||||
export const useAuthApi = () => {
|
export const useAuthApi = () => {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const login = () => {
|
const login = () => {
|
||||||
const response = authStore.login();
|
authStore.login();
|
||||||
return response;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const oidcLogin = () => {
|
const oidcLogin = () => {
|
||||||
return {status: 200, message: 'sent an openid connect login request'};
|
authStore.oidcLogin();
|
||||||
};
|
};
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
return {status: 200, message: 'sent a logout request'};
|
authStore.logout();
|
||||||
};
|
};
|
||||||
|
|
||||||
const isLoggedIn = () => {
|
const isAuthorizedUser = () => {
|
||||||
return {status: 200, message: 'sent a isLoggedIn request'};
|
return authStore.isAuthorizedUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
const forgotPassword = (email: string) => {
|
const setUser = (currentUser: User) => {
|
||||||
return {status: 200, message: 'sent a password reset request with email ' + email};
|
authStore.user = currentUser;
|
||||||
};
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
login,
|
login,
|
||||||
oidcLogin,
|
oidcLogin,
|
||||||
logout,
|
logout,
|
||||||
isLoggedIn,
|
isAuthorizedUser,
|
||||||
forgotPassword,
|
setUser,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -1,12 +1,28 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { useAuthStore } from '../auth-store';
|
import { useAuthApi } from '../composables/use-auth-api';
|
||||||
|
import type { User } from 'src/modules/users/types/user-interface';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authApi = useAuthApi();
|
||||||
const email = ref('');
|
const email = ref('');
|
||||||
const isShowingEmployeeLoginButton = ref(false);
|
const isShowingEmployeeLoginButton = ref(false);
|
||||||
const isRemembered = ref(false);
|
const isRemembered = ref(false);
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const setBypassUser = (bypassRole: string) => {
|
||||||
|
authApi.setUser({
|
||||||
|
firstName: "Testing",
|
||||||
|
lastName: bypassRole,
|
||||||
|
email: "testingT@targointernet.com",
|
||||||
|
role: bypassRole || "guest"
|
||||||
|
} as User);
|
||||||
|
|
||||||
|
router.push({ name: 'dashboard' }).catch( err => {
|
||||||
|
console.error('Router navigation failed: ', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
watch(email, (value) => {
|
watch(email, (value) => {
|
||||||
isShowingEmployeeLoginButton.value = value.includes('@targ');
|
isShowingEmployeeLoginButton.value = value.includes('@targ');
|
||||||
|
|
@ -31,7 +47,7 @@
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-form class="q-gutter-sm" @submit="authStore.login">
|
<q-form class="q-gutter-sm" @submit="authApi.login">
|
||||||
<q-input dense outlined label-color="primary" v-model="email" :label="$t('loginPage.email')" />
|
<q-input dense outlined label-color="primary" v-model="email" :label="$t('loginPage.email')" />
|
||||||
|
|
||||||
<q-card-section class="q-ma-none q-pa-none">
|
<q-card-section class="q-ma-none q-pa-none">
|
||||||
|
|
@ -61,7 +77,7 @@
|
||||||
<q-slide-transition>
|
<q-slide-transition>
|
||||||
<div v-if="isShowingEmployeeLoginButton">
|
<div v-if="isShowingEmployeeLoginButton">
|
||||||
<transition slow enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
|
<transition slow enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
|
||||||
<q-btn rounded push color="primary" @click="authStore.oidcLogin" :label="$t('loginPage.employeeLoginButton')" class="full-width row" icon="img:src/assets/logo-targo-simple.svg" />
|
<q-btn rounded push color="primary" @click="authApi.oidcLogin" :label="$t('loginPage.employeeLoginButton')" class="full-width row" icon="img:src/assets/logo-targo-simple.svg" />
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</q-slide-transition>
|
</q-slide-transition>
|
||||||
|
|
@ -76,10 +92,10 @@
|
||||||
<q-separator color="primary" />
|
<q-separator color="primary" />
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-btn-group push rounded>
|
<q-btn-group push rounded>
|
||||||
<q-btn push color="primary" text-color="white" label="ACCOUNTING" icon="attach_money" />
|
<q-btn push color="primary" text-color="white" label="ACCOUNTING" icon="attach_money" @click="setBypassUser('accounting')"/>
|
||||||
<q-btn push color="primary" text-color="white" label="SUPERVISOR" icon="supervisor_account"/>
|
<q-btn push color="primary" text-color="white" label="SUPERVISOR" icon="supervisor_account" @click="setBypassUser('supervisor')"/>
|
||||||
<q-btn push color="primary" text-color="white" label="HR" icon="diversity_3"/>
|
<q-btn push color="primary" text-color="white" label="HR" icon="diversity_3" @click="setBypassUser('human resources')"/>
|
||||||
<q-btn push color="primary" text-color="white" label="EMPLOYEE" icon="support_agent"/>
|
<q-btn push color="primary" text-color="white" label="EMPLOYEE" icon="support_agent" @click="setBypassUser('employee')"/>
|
||||||
</q-btn-group>
|
</q-btn-group>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,18 @@ import { api } from 'src/boot/axios';
|
||||||
|
|
||||||
export const AuthService = {
|
export const AuthService = {
|
||||||
// Will likely be deprecated and relegated to Authentik
|
// Will likely be deprecated and relegated to Authentik
|
||||||
login: (credentials: { email: string; password: string }) => {
|
login: () => {
|
||||||
// TODO: possibly add some kind of login logic, but will most likely be redirected
|
//TODO: OIDC customer sign-in, eventually
|
||||||
// to Authentik as well.
|
|
||||||
api.post('/auth/login', credentials)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
oidcLogin: () => {
|
oidcLogin: (): Window | null => {
|
||||||
// TODO: OIDC login logic
|
window.addEventListener('message', (event) => {
|
||||||
api.post('/auth/oidclogin');
|
if (event.data.type === 'authSuccess') {
|
||||||
|
//some kind of logic here to set user in store
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return window.open('http://localhost:3000/auth/v1/login', 'authPopup', 'width=600,height=800');
|
||||||
},
|
},
|
||||||
|
|
||||||
logout: () => {
|
logout: () => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
export interface User {
|
|
||||||
firstName: string;
|
|
||||||
lastName: string;
|
|
||||||
email: string;
|
|
||||||
role: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineRouter } from '#q-app/wrappers';
|
import { defineRouter } from '#q-app/wrappers';
|
||||||
import { createMemoryHistory, createRouter, createWebHashHistory, createWebHistory, } from 'vue-router';
|
import { createMemoryHistory, createRouter, createWebHashHistory, createWebHistory, } from 'vue-router';
|
||||||
import routes from './routes';
|
import routes from './routes';
|
||||||
import { useAuthStore } from 'src/modules/auth/auth-store';
|
import { useAuthStore } from 'src/stores/auth-store';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If not building with SSR mode, you can
|
* If not building with SSR mode, you can
|
||||||
|
|
@ -30,7 +30,7 @@ export default defineRouter(function (/* { store, ssrContext } */) {
|
||||||
Router.beforeEach((destinationPage) => {
|
Router.beforeEach((destinationPage) => {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
if (destinationPage.meta.requiresAuth && !authStore.isAuthorizedUser()) {
|
if (destinationPage.meta.requiresAuth && !authStore.isAuthorizedUser) {
|
||||||
console.log("access denied!")
|
console.log("access denied!")
|
||||||
return { name: 'login' };
|
return { name: 'login' };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
name: 'dashboard',
|
||||||
component: () => import('src/pages/test-page.vue'),
|
component: () => import('src/pages/test-page.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user