diff --git a/package.json b/package.json index 9ebf5068..2d7bd877 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,7 @@ }, "scripts": { "front": "webpack serve --open", - "back": "cd ../salix && gulp backOnly", - "db": "cd ../vn-database && myvc run -d", + "back": "cd ../vn-database && myvc start && cd ../salix && gulp backOnly", "build": "rm -rf build/ ; webpack", "clean": "rm -rf build/", "lint": "eslint --ext .js,.vue ./" diff --git a/quasar.config.js b/quasar.config.js index d0fd8d6b..08fc8ee3 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -26,7 +26,9 @@ module.exports = configure(function (ctx) { // https://v2.quasar.dev/quasar-cli-webpack/boot-files boot: [ 'i18n', - 'axios' + 'axios', + 'error-handler', + 'app' ], // https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css @@ -129,7 +131,9 @@ module.exports = configure(function (ctx) { // directives: [], // Quasar plugins - plugins: [] + plugins: [ + 'Notify' + ] }, // animations: 'all', // --- includes all animations diff --git a/src/boot/app.js b/src/boot/app.js new file mode 100644 index 00000000..08b64067 --- /dev/null +++ b/src/boot/app.js @@ -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 +}) diff --git a/src/boot/axios.js b/src/boot/axios.js index 079f1bed..150a8d8d 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -1,5 +1,6 @@ import { boot } from 'quasar/wrappers' import { Connection } from '../js/db/connection' +import { userStore } from 'stores/user' import axios from 'axios' // Be careful when using SSR for cross-request state pollution @@ -11,17 +12,20 @@ import axios from 'axios' const api = axios.create({ 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() 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 app.config.globalProperties.$axios = axios diff --git a/src/boot/error-handler.js b/src/boot/error-handler.js new file mode 100644 index 00000000..cbf541d2 --- /dev/null +++ b/src/boot/error-handler.js @@ -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' + }) + } +} diff --git a/src/boot/i18n.js b/src/boot/i18n.js index e36a6ba2..3b264658 100644 --- a/src/boot/i18n.js +++ b/src/boot/i18n.js @@ -4,8 +4,10 @@ import messages from 'src/i18n' export default boot(({ app }) => { const i18n = createI18n({ - locale: 'en-US', + locale: 'es-ES', globalInjection: true, + silentTranslationWarn: true, + silentFallbackWarn: true, messages }) diff --git a/src/css/app.scss b/src/css/app.scss index e0d7afb3..5e320667 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -13,6 +13,14 @@ body { font-family: 'Poppins', 'Verdana', 'Sans'; background-color: #fafafa; } +a.link { + text-decoration: none; + color: #6a1; + + &:hover { + text-decoration: underline; + } +} .q-card { border-radius: 7px; box-shadow: 0 0 3px rgba(0, 0, 0, .1); diff --git a/src/i18n/en-US/index.js b/src/i18n/en-US/index.js index b70b80f0..0eaf5814 100644 --- a/src/i18n/en-US/index.js +++ b/src/i18n/en-US/index.js @@ -3,5 +3,10 @@ export default { 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' } diff --git a/src/i18n/es-ES/index.js b/src/i18n/es-ES/index.js new file mode 100644 index 00000000..174bb108 --- /dev/null +++ b/src/i18n/es-ES/index.js @@ -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' +} diff --git a/src/i18n/index.js b/src/i18n/index.js index 81e1ad08..136539a4 100644 --- a/src/i18n/index.js +++ b/src/i18n/index.js @@ -1,5 +1,7 @@ import enUS from './en-US' +import esES from './es-ES' export default { - 'en-US': enUS + 'en-US': enUS, + 'es-ES': esES } diff --git a/src/js/vn/json-connection.js b/src/js/vn/json-connection.js index de9cd0f6..9a3e4cb9 100644 --- a/src/js/vn/json-connection.js +++ b/src/js/vn/json-connection.js @@ -9,6 +9,11 @@ export class JsonConnection extends VnObject { _connected = false _requestsCount = 0 token = null + interceptors = [] + + use (fn) { + this.interceptors.push(fn) + } /** * Executes the specified REST service with the given params and calls @@ -70,8 +75,9 @@ export class JsonConnection extends VnObject { const request = new XMLHttpRequest() request.open(config.method, config.url, true) - const token = localStorage.getItem('vnToken') - if (token) { request.setRequestHeader('Authorization', token) } + for (const fn of this.interceptors) { + config = fn(config) + } const headers = config.headers if (headers) { diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index d8fa8510..061e9a9d 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -8,26 +8,22 @@ round icon="menu" aria-label="Menu" - @click="toggleLeftDrawer" - /> - + @click="toggleLeftDrawer"/> Home - + show-if-above>
- {{user.nickname}} + {{(user.nickname)}}
@@ -63,7 +59,6 @@ - @@ -156,6 +151,8 @@ export default defineComponent({ }, async mounted () { + await this.user.loadData() + await this.$app.loadConfig() await this.fetchData() }, @@ -192,3 +189,10 @@ export default defineComponent({ } }) + + + en-US: + visitor: Visitor + es-ES: + visitor: Visitante + diff --git a/src/pages/Home.vue b/src/pages/Cms/Home.vue similarity index 75% rename from src/pages/Home.vue rename to src/pages/Cms/Home.vue index 92f12284..8fecd8ea 100644 --- a/src/pages/Home.vue +++ b/src/pages/Cms/Home.vue @@ -6,7 +6,7 @@ v-for="myNew in news" :key="myNew.id"> - +
{{ myNew.title }}
@@ -22,7 +22,7 @@ fab icon="add_shopping_cart" color="accent" - :to="{name: 'catalog'}" + to="/catalog" :title="$t('startOrder')" /> @@ -33,27 +33,18 @@ .new-card { width: 100%; - @media screen and (min-width: 1000px) and (max-width: 1399px) { + @media screen and (min-width: 800px) and (max-width: 1400px) { 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%; } - @media screen and (min-width: 1700px) { + @media screen and (min-width: 19021) { width: 25%; } } .new-body { font-family: 'Open Sans'; - - a { - text-decoration: none; - color: #6a1; - - &:hover { - text-decoration: underline; - } - } } diff --git a/src/pages/Ecomerce/Orders.vue b/src/pages/Ecomerce/Orders.vue new file mode 100644 index 00000000..1a103f77 --- /dev/null +++ b/src/pages/Ecomerce/Orders.vue @@ -0,0 +1,64 @@ + + + + + + en-US: + startOrder: Start order + noOrdersFound: No orders found + es-ES: + startOrder: Empezar pedido + noOrdersFound: No se encontrado pedidos + diff --git a/src/pages/ErrorNotFound.vue b/src/pages/ErrorNotFound.vue index c1c178b3..f84a4868 100644 --- a/src/pages/ErrorNotFound.vue +++ b/src/pages/ErrorNotFound.vue @@ -1,5 +1,5 @@