forked from verdnatura/salix-front
Added axios interceptor
This commit is contained in:
parent
4edb7de3ad
commit
f423cc2a1d
17
src/main.ts
17
src/main.ts
|
@ -7,3 +7,20 @@ import quasarUserOptions from './quasar-user-options';
|
|||
import i18n from './i18n';
|
||||
|
||||
createApp(App).use(i18n).use(Quasar, quasarUserOptions).use(store).use(router).mount('#app');
|
||||
|
||||
import axios from 'axios';
|
||||
axios.interceptors.request.use(
|
||||
function (config) {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
if (token && config.headers) {
|
||||
config.headers.Authorization = token;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -2,14 +2,31 @@ import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
|
|||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/',
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import('../views/Login/Login.vue'),
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
path: '/',
|
||||
name: 'Main',
|
||||
component: () => import('../views/Main/Main.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'Dashboard',
|
||||
component: () => import('../views/Dashboard/Dashboard.vue'),
|
||||
component: () => import('../views/Main/Dashboard.vue'),
|
||||
},
|
||||
/* {
|
||||
path: '/Client',
|
||||
name: 'Client',
|
||||
component: () => import('../views/Client/client.vue'),
|
||||
}, */
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'NotFound',
|
||||
component: () => import('../views/Main/NotFound.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -18,4 +35,14 @@ const router = createRouter({
|
|||
routes,
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const loggedIn = localStorage.getItem('token');
|
||||
|
||||
if (to.name !== 'Login' && !loggedIn) {
|
||||
next({ path: '/login', query: { redirect: to.fullPath } });
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import { Store } from '@/store'; // path to store file
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$store: Store;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,38 @@
|
|||
import { createStore } from 'vuex';
|
||||
|
||||
export default createStore({
|
||||
state: {},
|
||||
mutations: {},
|
||||
actions: {},
|
||||
state: {
|
||||
user: null,
|
||||
roles: [],
|
||||
},
|
||||
mutations: {
|
||||
setUser(state, user) {
|
||||
state.user = user;
|
||||
},
|
||||
setRoles(state, roles) {
|
||||
state.roles = roles;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
logIn({ commit }, auth) {
|
||||
localStorage.setItem('token', auth.token);
|
||||
|
||||
commit('setUser', auth);
|
||||
},
|
||||
logOut({ commit }) {
|
||||
localStorage.removeItem('token');
|
||||
|
||||
commit('setUser', null);
|
||||
},
|
||||
updateUserData({ commit }, data) {
|
||||
commit('setUser', data.user);
|
||||
commit('setRoles', data.roles);
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
hasData(state) {
|
||||
return !!state.user;
|
||||
},
|
||||
},
|
||||
modules: {},
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@ $secondary : #26A69A;
|
|||
$accent : #9C27B0;
|
||||
|
||||
$dark : #1D1D1D;
|
||||
$darker : #111111;
|
||||
|
||||
$positive : #21BA45;
|
||||
$negative : #C10015;
|
||||
|
|
|
@ -100,7 +100,11 @@ export default class Login extends Vue {
|
|||
user: this.username,
|
||||
password: this.password,
|
||||
})
|
||||
.then(() => {
|
||||
.then((response) => {
|
||||
this.$store.dispatch('logIn', {
|
||||
token: response.data.token,
|
||||
});
|
||||
|
||||
this.$q.notify({
|
||||
message: this.$t('login.loginSuccess'),
|
||||
type: 'positive',
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
<template>
|
||||
<q-layout>
|
||||
<q-header class="bg-darker" color="white" elevated>
|
||||
<q-toolbar>
|
||||
<q-btn flat round dense icon="menu" />
|
||||
<q-toolbar-title>Salix</q-toolbar-title>
|
||||
<q-space></q-space>
|
||||
|
||||
<q-btn dense flat no-wrap>
|
||||
<q-avatar size="lg" color="orange">
|
||||
<img :src="`/api/Images/user/160x160/${id}/download?access_token=${token}`" alt="" />
|
||||
</q-avatar>
|
||||
<q-tooltip>Account</q-tooltip>
|
||||
<q-icon name="arrow_drop_down" size="s" />
|
||||
|
||||
<q-menu>
|
||||
<div class="row no-wrap q-pa-md">
|
||||
<div class="column">
|
||||
<div class="text-h6 q-mb-md">Settings</div>
|
||||
<q-toggle label="Dark mode" />
|
||||
<q-toggle label="Language" class="q-mb-md" />
|
||||
|
||||
<q-btn color="orange" outline size="sm" label="Settings" icon="settings" />
|
||||
</div>
|
||||
|
||||
<q-separator vertical inset class="q-mx-lg" />
|
||||
|
||||
<div class="column items-center" style="min-width: 150px">
|
||||
<q-avatar color="orange" size="80px">
|
||||
<img
|
||||
:src="`/api/Images/user/160x160/${id}/download?access_token=${token}`"
|
||||
alt=""
|
||||
/>
|
||||
</q-avatar>
|
||||
|
||||
<div class="text-subtitle1 q-mt-md">
|
||||
<strong>{{ nickname }}</strong>
|
||||
</div>
|
||||
<div class="text-subtitle3 text-grey-7 q-mb-xs">@{{ nickname }}</div>
|
||||
|
||||
<q-btn
|
||||
color="orange"
|
||||
flat
|
||||
label="Log Out"
|
||||
size="sm"
|
||||
icon="logout"
|
||||
@click="logout()"
|
||||
v-close-popup
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</q-menu>
|
||||
|
||||
<!-- <q-menu auto-close>
|
||||
<q-list dense>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<div>
|
||||
<strong>{{ nickname }}</strong>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-separator />
|
||||
<q-item clickable>
|
||||
<q-item-section>Your profile</q-item-section>
|
||||
</q-item>
|
||||
<q-separator />
|
||||
<q-item clickable>
|
||||
<q-item-section>Settings</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable @click="logout()">
|
||||
<q-item-section>Sign out</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu> -->
|
||||
</q-btn>
|
||||
|
||||
<!-- <q-toggle
|
||||
:label="$t(`globals.lang['${language}']`)"
|
||||
icon="public"
|
||||
color="orange"
|
||||
false-value="es"
|
||||
true-value="en"
|
||||
v-model="language"
|
||||
/>
|
||||
<q-toggle v-model="mode" checked-icon="dark_mode" color="orange" unchecked-icon="light_mode" /> -->
|
||||
</q-toolbar>
|
||||
</q-header>
|
||||
<q-drawer show-if-above :mini="true" mini-to-overlay :width="200" :breakpoint="500">
|
||||
<q-scroll-area class="fit">
|
||||
<q-list padding>
|
||||
<q-item active clickable v-ripple>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="dashboard" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section> Dashboard </q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-ripple>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="people" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section> Customers </q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-ripple>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="receipt" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section> Invoice Out </q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-ripple>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="shopping_cart" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section> Catalog </q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<q-item clickable v-ripple>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="drafts" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section> Drafts </q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-scroll-area>
|
||||
</q-drawer>
|
||||
<q-page-container>
|
||||
<router-view></router-view>
|
||||
</q-page-container>
|
||||
</q-layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue } from 'vue-class-component';
|
||||
import axios from 'axios';
|
||||
|
||||
@Options({})
|
||||
export default class Main extends Vue {
|
||||
mounted(): void {
|
||||
axios.get('/api/accounts/acl').then((response) => {
|
||||
this.$store.dispatch('updateUserData', response.data);
|
||||
});
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
this.$store.dispatch('logOut');
|
||||
this.$router.push('/login');
|
||||
}
|
||||
|
||||
get nickLetter(): string {
|
||||
if (this.nickname) {
|
||||
return this.nickname.charAt(0);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
get nickname(): string {
|
||||
if (this.$store.getters.hasData) {
|
||||
return this.$store.state.user.nickname;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
if (this.$store.getters.hasData) {
|
||||
return this.$store.state.user.id;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
get token(): string {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
return token ? token : '';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bg-darker {
|
||||
background-color: $darker;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<q-page> Page not found </q-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue } from 'vue-class-component';
|
||||
|
||||
@Options({})
|
||||
export default class NotFound extends Vue {}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
Loading…
Reference in New Issue