refs #4922 password recovery, app store, error handler, fixes
gitea/hedera-web/pipeline/head This commit looks good
Details
gitea/hedera-web/pipeline/head This commit looks good
Details
This commit is contained in:
parent
0d0be4ee5f
commit
7e26aa773c
|
@ -58,8 +58,7 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"front": "webpack serve --open",
|
"front": "webpack serve --open",
|
||||||
"back": "cd ../salix && gulp backOnly",
|
"back": "cd ../vn-database && myvc start && cd ../salix && gulp backOnly",
|
||||||
"db": "cd ../vn-database && myvc run -d",
|
|
||||||
"build": "rm -rf build/ ; webpack",
|
"build": "rm -rf build/ ; webpack",
|
||||||
"clean": "rm -rf build/",
|
"clean": "rm -rf build/",
|
||||||
"lint": "eslint --ext .js,.vue ./"
|
"lint": "eslint --ext .js,.vue ./"
|
||||||
|
|
|
@ -26,7 +26,9 @@ module.exports = configure(function (ctx) {
|
||||||
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
|
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
|
||||||
boot: [
|
boot: [
|
||||||
'i18n',
|
'i18n',
|
||||||
'axios'
|
'axios',
|
||||||
|
'error-handler',
|
||||||
|
'app'
|
||||||
],
|
],
|
||||||
|
|
||||||
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
|
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
|
||||||
|
@ -129,7 +131,9 @@ module.exports = configure(function (ctx) {
|
||||||
// directives: [],
|
// directives: [],
|
||||||
|
|
||||||
// Quasar plugins
|
// Quasar plugins
|
||||||
plugins: []
|
plugins: [
|
||||||
|
'Notify'
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
// animations: 'all', // --- includes all animations
|
// animations: 'all', // --- includes all animations
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { boot } from 'quasar/wrappers'
|
||||||
|
import { appStore } from 'stores/app'
|
||||||
|
|
||||||
|
export default boot(({ app }) => {
|
||||||
|
const myApp = appStore()
|
||||||
|
app.config.globalProperties.$app = myApp
|
||||||
|
})
|
|
@ -1,5 +1,6 @@
|
||||||
import { boot } from 'quasar/wrappers'
|
import { boot } from 'quasar/wrappers'
|
||||||
import { Connection } from '../js/db/connection'
|
import { Connection } from '../js/db/connection'
|
||||||
|
import { userStore } from 'stores/user'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
// Be careful when using SSR for cross-request state pollution
|
// Be careful when using SSR for cross-request state pollution
|
||||||
|
@ -11,17 +12,20 @@ import axios from 'axios'
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: `//${location.hostname}:${location.port}/api/`
|
baseURL: `//${location.hostname}:${location.port}/api/`
|
||||||
})
|
})
|
||||||
api.interceptors.request.use(function addToken (config) {
|
|
||||||
const token = localStorage.getItem('vnToken')
|
|
||||||
if (token) {
|
|
||||||
config.headers.Authorization = token
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
})
|
|
||||||
|
|
||||||
const jApi = new Connection()
|
const jApi = new Connection()
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
export default boot(({ app }) => {
|
||||||
|
const user = userStore()
|
||||||
|
function addToken (config) {
|
||||||
|
if (user.token) {
|
||||||
|
config.headers.Authorization = user.token
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
api.interceptors.request.use(addToken)
|
||||||
|
jApi.use(addToken)
|
||||||
|
|
||||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||||
|
|
||||||
app.config.globalProperties.$axios = axios
|
app.config.globalProperties.$axios = axios
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
export default async ({ app }) => {
|
||||||
|
/*
|
||||||
|
window.addEventListener('error',
|
||||||
|
e => onWindowError(e));
|
||||||
|
window.addEventListener('unhandledrejection',
|
||||||
|
e => onWindowRejection(e));
|
||||||
|
|
||||||
|
,onWindowError(event) {
|
||||||
|
errorHandler(event.error);
|
||||||
|
}
|
||||||
|
,onWindowRejection(event) {
|
||||||
|
errorHandler(event.reason);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
app.config.errorHandler = (err, vm, info) => {
|
||||||
|
errorHandler(err, vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorHandler (err, vm) {
|
||||||
|
let message
|
||||||
|
let tMessage
|
||||||
|
const res = err.response
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
const status = res.status
|
||||||
|
|
||||||
|
if (status >= 400 && status < 500) {
|
||||||
|
switch (status) {
|
||||||
|
case 401:
|
||||||
|
tMessage = 'loginFailed'
|
||||||
|
break
|
||||||
|
case 403:
|
||||||
|
tMessage = 'authenticationRequired'
|
||||||
|
vm.$router.push('/login')
|
||||||
|
break
|
||||||
|
case 404:
|
||||||
|
tMessage = 'notFound'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
message = res.data.error.message
|
||||||
|
}
|
||||||
|
} else if (status >= 500) {
|
||||||
|
tMessage = 'internalServerError'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tMessage = 'somethingWentWrong'
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tMessage) {
|
||||||
|
message = vm.$t(tMessage)
|
||||||
|
}
|
||||||
|
vm.$q.notify({
|
||||||
|
message,
|
||||||
|
type: 'negative'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,10 @@ import messages from 'src/i18n'
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
export default boot(({ app }) => {
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
locale: 'en-US',
|
locale: 'es-ES',
|
||||||
globalInjection: true,
|
globalInjection: true,
|
||||||
|
silentTranslationWarn: true,
|
||||||
|
silentFallbackWarn: true,
|
||||||
messages
|
messages
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,14 @@ body {
|
||||||
font-family: 'Poppins', 'Verdana', 'Sans';
|
font-family: 'Poppins', 'Verdana', 'Sans';
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
a.link {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #6a1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
.q-card {
|
.q-card {
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
box-shadow: 0 0 3px rgba(0, 0, 0, .1);
|
box-shadow: 0 0 3px rgba(0, 0, 0, .1);
|
||||||
|
|
|
@ -3,5 +3,10 @@
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
failed: 'Action failed',
|
failed: 'Action failed',
|
||||||
success: 'Action was successful'
|
success: 'Action was successful',
|
||||||
|
internalServerError: 'Internal server error',
|
||||||
|
somethingWentWrong: 'Something went wrong',
|
||||||
|
loginFailed: 'Login failed',
|
||||||
|
authenticationRequired: 'Authentication required',
|
||||||
|
notFound: 'Not found'
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// This is just an example,
|
||||||
|
// so you can safely delete all default props below
|
||||||
|
|
||||||
|
export default {
|
||||||
|
failed: 'Acción fallida',
|
||||||
|
success: 'Acción exitosa',
|
||||||
|
internalServerError: 'Error interno del servidor',
|
||||||
|
somethingWentWrong: 'Algo salió mal',
|
||||||
|
loginFailed: 'Usuario o contraseña incorrectos',
|
||||||
|
authenticationRequired: 'Autenticación requerida',
|
||||||
|
notFound: 'No encontrado'
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
import enUS from './en-US'
|
import enUS from './en-US'
|
||||||
|
import esES from './es-ES'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'en-US': enUS
|
'en-US': enUS,
|
||||||
|
'es-ES': esES
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,11 @@ export class JsonConnection extends VnObject {
|
||||||
_connected = false
|
_connected = false
|
||||||
_requestsCount = 0
|
_requestsCount = 0
|
||||||
token = null
|
token = null
|
||||||
|
interceptors = []
|
||||||
|
|
||||||
|
use (fn) {
|
||||||
|
this.interceptors.push(fn)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the specified REST service with the given params and calls
|
* Executes the specified REST service with the given params and calls
|
||||||
|
@ -70,8 +75,9 @@ export class JsonConnection extends VnObject {
|
||||||
const request = new XMLHttpRequest()
|
const request = new XMLHttpRequest()
|
||||||
request.open(config.method, config.url, true)
|
request.open(config.method, config.url, true)
|
||||||
|
|
||||||
const token = localStorage.getItem('vnToken')
|
for (const fn of this.interceptors) {
|
||||||
if (token) { request.setRequestHeader('Authorization', token) }
|
config = fn(config)
|
||||||
|
}
|
||||||
|
|
||||||
const headers = config.headers
|
const headers = config.headers
|
||||||
if (headers) {
|
if (headers) {
|
||||||
|
|
|
@ -8,26 +8,22 @@
|
||||||
round
|
round
|
||||||
icon="menu"
|
icon="menu"
|
||||||
aria-label="Menu"
|
aria-label="Menu"
|
||||||
@click="toggleLeftDrawer"
|
@click="toggleLeftDrawer"/>
|
||||||
/>
|
|
||||||
|
|
||||||
<q-toolbar-title>
|
<q-toolbar-title>
|
||||||
Home
|
Home
|
||||||
</q-toolbar-title>
|
</q-toolbar-title>
|
||||||
</q-toolbar>
|
</q-toolbar>
|
||||||
</q-header>
|
</q-header>
|
||||||
|
|
||||||
<q-drawer
|
<q-drawer
|
||||||
v-model="leftDrawerOpen"
|
v-model="leftDrawerOpen"
|
||||||
:width="250"
|
:width="250"
|
||||||
show-if-above
|
show-if-above>
|
||||||
>
|
|
||||||
<q-toolbar class="logo">
|
<q-toolbar class="logo">
|
||||||
<img src="statics/logo-dark.svg">
|
<img src="statics/logo-dark.svg">
|
||||||
</q-toolbar>
|
</q-toolbar>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div>
|
<div>
|
||||||
<span id="user-name">{{user.nickname}}</span>
|
<span id="user-name">{{(user.nickname)}}</span>
|
||||||
<q-btn flat icon="logout" alt="_Exit" @click="logout()"/>
|
<q-btn flat icon="logout" alt="_Exit" @click="logout()"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="supplant" class="supplant">
|
<div id="supplant" class="supplant">
|
||||||
|
@ -63,7 +59,6 @@
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
|
|
||||||
<q-page-container>
|
<q-page-container>
|
||||||
<router-view />
|
<router-view />
|
||||||
</q-page-container>
|
</q-page-container>
|
||||||
|
@ -156,6 +151,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
async mounted () {
|
async mounted () {
|
||||||
|
await this.user.loadData()
|
||||||
|
await this.$app.loadConfig()
|
||||||
await this.fetchData()
|
await this.fetchData()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -192,3 +189,10 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
visitor: Visitor
|
||||||
|
es-ES:
|
||||||
|
visitor: Visitante
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
v-for="myNew in news"
|
v-for="myNew in news"
|
||||||
:key="myNew.id">
|
:key="myNew.id">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-img :src="`https://verdnatura.es/vn-image-data/news/full/${myNew.image}`">
|
<q-img :src="`${$app.imageUrl}/news/full/${myNew.image}`">
|
||||||
</q-img>
|
</q-img>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="text-h5">{{ myNew.title }}</div>
|
<div class="text-h5">{{ myNew.title }}</div>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
fab
|
fab
|
||||||
icon="add_shopping_cart"
|
icon="add_shopping_cart"
|
||||||
color="accent"
|
color="accent"
|
||||||
:to="{name: 'catalog'}"
|
to="/catalog"
|
||||||
:title="$t('startOrder')"
|
:title="$t('startOrder')"
|
||||||
/>
|
/>
|
||||||
</q-page-sticky>
|
</q-page-sticky>
|
||||||
|
@ -33,27 +33,18 @@
|
||||||
.new-card {
|
.new-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@media screen and (min-width: 1000px) and (max-width: 1399px) {
|
@media screen and (min-width: 800px) and (max-width: 1400px) {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 1400px) and (max-width: 1699px) {
|
@media screen and (min-width: 1401px) and (max-width: 1920px) {
|
||||||
width: 33.33%;
|
width: 33.33%;
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 1700px) {
|
@media screen and (min-width: 19021) {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.new-body {
|
.new-body {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #6a1;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<div class="vn-pp row justify-center">
|
||||||
|
<div
|
||||||
|
v-if="orders && !orders.length"
|
||||||
|
class="text-subtitle1 text-center text-grey-7 q-pa-md">
|
||||||
|
{{$t('noOrdersFound')}}
|
||||||
|
</div>
|
||||||
|
<q-card
|
||||||
|
v-if="orders && orders.length"
|
||||||
|
class="vn-w-md">
|
||||||
|
<q-list bordered separator>
|
||||||
|
<q-item
|
||||||
|
v-for="order in orders"
|
||||||
|
:key="order.id"
|
||||||
|
:to="`/order/${order.id}/`"
|
||||||
|
clickable
|
||||||
|
v-ripple>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{order.landed}}</q-item-label>
|
||||||
|
<q-item-label caption>#{{order.id}}</q-item-label>
|
||||||
|
<q-item-label caption>{{order.address.nickname}}</q-item-label>
|
||||||
|
<q-item-label caption>{{order.address.city}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side top>
|
||||||
|
{{order.taxableBase}}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card>
|
||||||
|
<q-page-sticky position="bottom-right" :offset="[18, 18]">
|
||||||
|
<q-btn
|
||||||
|
fab
|
||||||
|
icon="add_shopping_cart"
|
||||||
|
color="accent"
|
||||||
|
to="/catalog"
|
||||||
|
:title="$t('startOrder')"/>
|
||||||
|
</q-page-sticky>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'OrdersPendingIndex',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
orders: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted () {
|
||||||
|
this.orders = await this.$jApi.query(
|
||||||
|
'CALL myTicket_list(NULL, NULL)'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
startOrder: Start order
|
||||||
|
noOrdersFound: No orders found
|
||||||
|
es-ES:
|
||||||
|
startOrder: Empezar pedido
|
||||||
|
noOrdersFound: No se encontrado pedidos
|
||||||
|
</i18n>
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
|
<div class="fullscreen bg-accent text-white text-center q-pa-md flex flex-center">
|
||||||
<div>
|
<div>
|
||||||
<div style="font-size: 30vh">
|
<div style="font-size: 30vh">
|
||||||
404
|
404
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-mt-xl"
|
class="q-mt-xl"
|
||||||
color="white"
|
color="white"
|
||||||
text-color="blue"
|
text-color="accent"
|
||||||
unelevated
|
unelevated
|
||||||
to="/"
|
to="/"
|
||||||
label="Go Home"
|
label="Go Home"
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="justify-center">
|
<div class="justify-center">
|
||||||
<q-btn
|
<q-btn
|
||||||
type="submit"
|
to="/"
|
||||||
:label="$t('logInAsGuest')"
|
:label="$t('logInAsGuest')"
|
||||||
class="full-width"
|
class="full-width"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
outline
|
outline
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p class="password-forgotten text-center">
|
<p class="password-forgotten text-center q-mt-lg">
|
||||||
<router-link to="/remember-password" class="link">
|
<router-link to="/remember-password" class="link">
|
||||||
{{$t('haveForgottenPassword')}}
|
{{$t('haveForgottenPassword')}}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
@ -67,7 +67,9 @@
|
||||||
<div class="footer text-center">
|
<div class="footer text-center">
|
||||||
<p>
|
<p>
|
||||||
{{$t('notACustomerYet')}}
|
{{$t('notACustomerYet')}}
|
||||||
<a href="//verdnatura.es/register/" target="_blank">{{$t('signUp')}}</a>
|
<a href="//verdnatura.es/register/" target="_blank" class="link">
|
||||||
|
{{$t('signUp')}}
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p class="contact">
|
<p class="contact">
|
||||||
{{$t('loginPhone')}} · {{$t('loginMail')}}
|
{{$t('loginPhone')}} · {{$t('loginMail')}}
|
||||||
|
@ -84,12 +86,7 @@ $login-margin-between: 55px;
|
||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
margin-top: $login-margin-top;
|
margin-top: $login-margin-top;
|
||||||
|
@ -110,7 +107,6 @@ a {
|
||||||
}
|
}
|
||||||
.password-forgotten {
|
.password-forgotten {
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
margin-top: 30px;
|
|
||||||
}
|
}
|
||||||
.footer {
|
.footer {
|
||||||
margin-bottom: $login-margin-top;
|
margin-bottom: $login-margin-top;
|
||||||
|
@ -159,7 +155,7 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async onLogin () {
|
async onLogin () {
|
||||||
await this.user.login(this.email, this.password)
|
await this.user.login(this.email, this.password, this.remember)
|
||||||
this.$router.push('/')
|
this.$router.push('/')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<q-card-section>
|
<div>
|
||||||
<q-icon
|
<q-icon
|
||||||
name="contact_support"
|
name="contact_support"
|
||||||
class="block q-mx-auto text-accent"
|
class="block q-mx-auto text-accent"
|
||||||
style="font-size: 120px;"
|
style="font-size: 120px;"
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</div>
|
||||||
<q-card-section>
|
<div>
|
||||||
<q-form @submit="onSend" class="q-gutter-y-md text-grey-8">
|
<q-form @submit="onSend" class="q-gutter-y-md text-grey-8">
|
||||||
<div class="text-h5">
|
<div class="text-h5">
|
||||||
<div>
|
<div>
|
||||||
|
@ -19,29 +19,31 @@
|
||||||
</div>
|
</div>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="email"
|
v-model="email"
|
||||||
:label="$t('email')"
|
:label="$t('user')"
|
||||||
:rules="[ val => !!val || $t('inputEmail')]"
|
:rules="[ val => !!val || $t('inputEmail')]"
|
||||||
autofocus
|
autofocus
|
||||||
filled
|
|
||||||
/>
|
/>
|
||||||
<div>
|
<div class="q-mt-lg">
|
||||||
{{$t('weSendEmail')}}
|
{{$t('weSendEmail')}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<q-btn
|
<q-btn
|
||||||
type="submit"
|
type="submit"
|
||||||
:label="$t('send')"
|
:label="$t('send')"
|
||||||
class="full-width"
|
class="full-width q-mt-md"
|
||||||
color="black"
|
color="primary"
|
||||||
|
rounded
|
||||||
|
no-caps
|
||||||
|
unelevated
|
||||||
/>
|
/>
|
||||||
<div class="text-center q-mt-xs">
|
<div class="text-center q-mt-md">
|
||||||
<router-link to="/login" class="link">
|
<router-link to="/login" class="link">
|
||||||
{{$t('return')}}
|
{{$t('return')}}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-form>
|
</q-form>
|
||||||
</q-card-section>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -49,6 +51,13 @@
|
||||||
#image {
|
#image {
|
||||||
height: 190px;
|
height: 190px;
|
||||||
}
|
}
|
||||||
|
.q-btn {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -64,7 +73,7 @@ export default {
|
||||||
const params = {
|
const params = {
|
||||||
email: this.email
|
email: this.email
|
||||||
}
|
}
|
||||||
await this.$axios.post('users/reset', params)
|
await this.$axios.post('Users/reset', params)
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
message: this.$t('weHaveSentEmailToRecover'),
|
message: this.$t('weHaveSentEmailToRecover'),
|
||||||
type: 'positive'
|
type: 'positive'
|
||||||
|
@ -74,3 +83,26 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<i18n lang="yaml">
|
||||||
|
en-US:
|
||||||
|
user: User
|
||||||
|
inputEmail: Input email
|
||||||
|
rememberPassword: Rememeber password
|
||||||
|
dontWorry: Don't worry!
|
||||||
|
fillData: Fill the data
|
||||||
|
weSendEmail: We will sent you an email to recover your password
|
||||||
|
weHaveSentEmailToRecover: We've sent you an email where you can recover your password
|
||||||
|
send: Send
|
||||||
|
return: Return
|
||||||
|
es-ES:
|
||||||
|
user: Usuario
|
||||||
|
inputEmail: Introduce el correo electrónico
|
||||||
|
rememberPassword: Recordar contraseña
|
||||||
|
dontWorry: ¡No te preocupes!
|
||||||
|
fillData: Rellena los datos
|
||||||
|
weSendEmail: Te enviaremos un correo para restablecer tu contraseña
|
||||||
|
weHaveSentEmailToRecover: Te hemos enviado un correo donde podrás recuperar tu contraseña
|
||||||
|
send: Enviar
|
||||||
|
return: Volver
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -25,11 +25,15 @@ const routes = [
|
||||||
{
|
{
|
||||||
name: '',
|
name: '',
|
||||||
path: '',
|
path: '',
|
||||||
component: () => import('pages/Home.vue')
|
component: () => import('src/pages/Cms/Home.vue')
|
||||||
}, {
|
}, {
|
||||||
name: 'home',
|
name: 'home',
|
||||||
path: '/cms/home',
|
path: '/cms/home',
|
||||||
component: () => import('pages/Home.vue')
|
component: () => import('src/pages/Cms/Home.vue')
|
||||||
|
}, {
|
||||||
|
name: 'orders',
|
||||||
|
path: '/ecomerce/orders',
|
||||||
|
component: () => import('pages/Ecomerce/Orders.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { jApi } from 'boot/axios'
|
||||||
|
|
||||||
|
export const appStore = defineStore('hedera', {
|
||||||
|
state: () => ({
|
||||||
|
imageUrl: ''
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
async loadConfig () {
|
||||||
|
const imageUrl = await jApi.getValue(
|
||||||
|
'SELECT url FROM imageConfig'
|
||||||
|
)
|
||||||
|
this.$patch({ imageUrl })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -1,15 +0,0 @@
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useCounterStore = defineStore('counter', {
|
|
||||||
state: () => ({
|
|
||||||
counter: 0
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
doubleCount: (state) => state.counter * 2
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
increment () {
|
|
||||||
this.counter++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -2,41 +2,58 @@ import { defineStore } from 'pinia'
|
||||||
import { api, jApi } from 'boot/axios'
|
import { api, jApi } from 'boot/axios'
|
||||||
|
|
||||||
export const userStore = defineStore('user', {
|
export const userStore = defineStore('user', {
|
||||||
state: () => ({
|
state: () => {
|
||||||
token: null,
|
const token =
|
||||||
|
localStorage.getItem('vnToken') ||
|
||||||
|
sessionStorage.getItem('vnToken')
|
||||||
|
|
||||||
|
return {
|
||||||
|
token,
|
||||||
id: null,
|
id: null,
|
||||||
name: null,
|
name: null,
|
||||||
nickname: null
|
nickname: null
|
||||||
}),
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
loggedIn: state => state.token != null
|
loggedIn: state => state.token != null
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async login (user, password) {
|
async login (user, password, remember) {
|
||||||
const params = { user, password }
|
const params = { user, password }
|
||||||
const res = await api.post('Accounts/login', params)
|
const res = await api.post('Accounts/login', params)
|
||||||
localStorage.setItem('vnToken', res.data.token)
|
|
||||||
|
|
||||||
|
if (remember) {
|
||||||
|
localStorage.setItem('vnToken', res.data.token)
|
||||||
|
} else {
|
||||||
|
sessionStorage.setItem('vnToken', res.data.token)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$patch({
|
||||||
|
token: res.data.token,
|
||||||
|
name: user
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
async logout () {
|
||||||
|
if (this.token != null) {
|
||||||
|
await api.post('Accounts/logout')
|
||||||
|
localStorage.removeItem('vnToken')
|
||||||
|
sessionStorage.removeItem('vnToken')
|
||||||
|
}
|
||||||
|
this.$reset()
|
||||||
|
},
|
||||||
|
|
||||||
|
async loadData () {
|
||||||
const userData = await jApi.getObject(
|
const userData = await jApi.getObject(
|
||||||
'SELECT id, nickname FROM account.myUser'
|
'SELECT id, nickname FROM account.myUser'
|
||||||
)
|
)
|
||||||
|
|
||||||
this.$patch({
|
this.$patch({
|
||||||
token: res.data.token,
|
|
||||||
name: user,
|
|
||||||
id: userData.id,
|
id: userData.id,
|
||||||
nickname: userData.nickname
|
nickname: userData.nickname
|
||||||
})
|
})
|
||||||
},
|
|
||||||
|
|
||||||
async logout () {
|
|
||||||
if (localStorage.getItem('vnToken') != null) {
|
|
||||||
await api.post('Accounts/logout')
|
|
||||||
}
|
|
||||||
localStorage.removeItem('vnToken')
|
|
||||||
this.$reset()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue