Router navigation
This commit is contained in:
parent
cee5605c63
commit
51015c72f6
File diff suppressed because it is too large
Load Diff
|
@ -28,16 +28,17 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/eslint-parser": "^7.13.14",
|
"@babel/eslint-parser": "^7.13.14",
|
||||||
|
"@intlify/vue-i18n-loader": "^4.1.0",
|
||||||
"@quasar/app-webpack": "^3.0.0",
|
"@quasar/app-webpack": "^3.0.0",
|
||||||
"@quasar/quasar-app-extension-testing-e2e-cypress": "^4.0.1",
|
"@quasar/quasar-app-extension-testing-e2e-cypress": "^4.0.1",
|
||||||
"@quasar/quasar-app-extension-testing-unit-jest": "^3.0.0-alpha.9",
|
"@quasar/quasar-app-extension-testing-unit-jest": "^3.0.0-alpha.9",
|
||||||
"eslint": "^8.10.0",
|
"eslint": "^8.10.0",
|
||||||
"eslint-config-prettier": "^8.1.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
|
"eslint-plugin-cypress": "^2.11.3",
|
||||||
"eslint-plugin-jest": "^25.2.2",
|
"eslint-plugin-jest": "^25.2.2",
|
||||||
"eslint-plugin-vue": "^8.5.0",
|
"eslint-plugin-vue": "^8.5.0",
|
||||||
"eslint-webpack-plugin": "^3.1.1",
|
"eslint-webpack-plugin": "^3.1.1",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1"
|
||||||
"eslint-plugin-cypress": "^2.11.3"
|
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 10 Chrome versions",
|
"last 10 Chrome versions",
|
||||||
|
|
|
@ -67,7 +67,16 @@ module.exports = configure(function (ctx) {
|
||||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
||||||
|
|
||||||
chainWebpack(chain) {
|
chainWebpack(chain) {
|
||||||
chain.plugin('eslint-webpack-plugin').use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
chain.module
|
||||||
|
.rule("i18n")
|
||||||
|
.resourceQuery(/blockType=i18n/)
|
||||||
|
.type('javascript/auto')
|
||||||
|
.use("i18n")
|
||||||
|
.loader("@intlify/vue-i18n-loader")
|
||||||
|
.end();
|
||||||
|
|
||||||
|
chain.plugin('eslint-webpack-plugin')
|
||||||
|
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import messages from 'src/i18n';
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
messages,
|
messages,
|
||||||
|
legacy: false
|
||||||
});
|
});
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
export default boot(({ app }) => {
|
||||||
|
|
|
@ -8,41 +8,38 @@ const { t } = useI18n();
|
||||||
const { hasAny } = useRole();
|
const { hasAny } = useRole();
|
||||||
|
|
||||||
const mainRoute = routes.find(route => route.path === '/');
|
const mainRoute = routes.find(route => route.path === '/');
|
||||||
const modules = mainRoute && mainRoute.children || []
|
const moduleRoutes = mainRoute && mainRoute.children || []
|
||||||
|
|
||||||
const items = ref([]);
|
const modules = ref([]);
|
||||||
for (const module of modules) {
|
for (const route of moduleRoutes) {
|
||||||
const item = {
|
const module = {
|
||||||
path: module.path,
|
path: route.path,
|
||||||
|
name: route.name.toLowerCase(),
|
||||||
roles: []
|
roles: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (module.meta) {
|
if (route.meta) {
|
||||||
const meta = module.meta;
|
Object.assign(module, route.meta);
|
||||||
item.title = meta.title;
|
|
||||||
item.icon = meta.icon;
|
|
||||||
item.roles = meta.roles || [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
items.value.push(item);
|
modules.value.push(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-list padding>
|
<q-list padding>
|
||||||
<template v-for="route in items" :key="route.title">
|
<template v-for="module in modules" :key="module.title">
|
||||||
<q-item
|
<q-item
|
||||||
clickable
|
clickable
|
||||||
v-ripple
|
v-ripple
|
||||||
:to="{ path: route.path }"
|
:to="{ path: module.path }"
|
||||||
v-if="!route.roles.length || hasAny(route.roles)"
|
v-if="!module.roles.length || hasAny(module.roles)"
|
||||||
active-class="text-orange"
|
active-class="text-orange"
|
||||||
>
|
>
|
||||||
<q-item-section avatar :if="route.icon">
|
<q-item-section avatar :if="module.icon">
|
||||||
<q-icon :name="route.icon" />
|
<q-icon :name="module.icon" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>{{ t(`pages.${route.title}`) }}</q-item-section>
|
<q-item-section>{{ t(`${module.name}.pageTitles.${module.title}`) }}</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
</q-list>
|
</q-list>
|
||||||
|
|
|
@ -16,9 +16,25 @@ export default {
|
||||||
submit: 'Log in',
|
submit: 'Log in',
|
||||||
keepLogin: 'Keep me logged in',
|
keepLogin: 'Keep me logged in',
|
||||||
loginSuccess: 'You have successfully logged in',
|
loginSuccess: 'You have successfully logged in',
|
||||||
loginError: 'Invalid username or password',
|
loginError: 'Invalid username or password'
|
||||||
|
},
|
||||||
|
dashboard: {
|
||||||
|
pageTitles: {
|
||||||
|
dashboard: 'Dashboard',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
pageTitles: {
|
||||||
|
customers: 'Customers',
|
||||||
|
list: 'List',
|
||||||
|
basicData: 'Basic Data'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ticket: {
|
||||||
|
pageTitles: {
|
||||||
|
tickets: 'Tickets'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
customer: {},
|
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
@ -26,12 +42,4 @@ export default {
|
||||||
logOut: 'Log Out',
|
logOut: 'Log Out',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pages: {
|
|
||||||
logIn: 'Log In',
|
|
||||||
dashboard: 'Dashboard',
|
|
||||||
customers: 'Customers',
|
|
||||||
list: 'List',
|
|
||||||
basicData: 'Basic Data',
|
|
||||||
tickets: 'Tickets',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
statusInternalServerError: 'Ha ocurrido un error interno del servidor',
|
statusInternalServerError: 'Ha ocurrido un error interno del servidor',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
title: 'Iniciar sesión',
|
title: 'Inicio de sesión',
|
||||||
username: 'Nombre de usuario',
|
username: 'Nombre de usuario',
|
||||||
password: 'Contraseña',
|
password: 'Contraseña',
|
||||||
submit: 'Iniciar sesión',
|
submit: 'Iniciar sesión',
|
||||||
|
@ -18,7 +18,23 @@ export default {
|
||||||
loginSuccess: 'Inicio de sesión correcto',
|
loginSuccess: 'Inicio de sesión correcto',
|
||||||
loginError: 'Nombre de usuario o contraseña incorrectos',
|
loginError: 'Nombre de usuario o contraseña incorrectos',
|
||||||
},
|
},
|
||||||
customer: {},
|
dashboard: {
|
||||||
|
pageTitles: {
|
||||||
|
dashboard: 'Tablón',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
pageTitles: {
|
||||||
|
customers: 'Clientes',
|
||||||
|
list: 'Listado',
|
||||||
|
basicData: 'Datos básicos'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ticket: {
|
||||||
|
pageTitles: {
|
||||||
|
tickets: 'Tickets'
|
||||||
|
}
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
topbar: {},
|
topbar: {},
|
||||||
userPanel: {
|
userPanel: {
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
<script setup>
|
||||||
|
import { reactive, watch } from 'vue'
|
||||||
|
|
||||||
|
const customer = reactive({
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => customer.name, () => {
|
||||||
|
console.log('customer.name changed');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-page class="q-pa-md">
|
||||||
|
<q-card class="q-pa-md">
|
||||||
|
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-md">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
v-model="customer.name"
|
||||||
|
label="Your name *"
|
||||||
|
hint="Name and surname"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[val => val && val.length > 0 || 'Please type something']"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
type="number"
|
||||||
|
v-model="age"
|
||||||
|
label="Your age *"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[
|
||||||
|
val => val !== null && val !== '' || 'Please type your age',
|
||||||
|
val => val > 0 && val < 100 || 'Please type a real age'
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<q-btn label="Submit" type="submit" color="primary" />
|
||||||
|
<q-btn label="Reset" type="reset" color="primary" flat class="q-ml-sm" />
|
||||||
|
</div>
|
||||||
|
</q-form>
|
||||||
|
</q-card>
|
||||||
|
</q-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 60em;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -12,9 +12,9 @@ const session = useSession();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
|
|
||||||
let username = ref('');
|
const username = ref('');
|
||||||
let password = ref('');
|
const password = ref('');
|
||||||
let keepLogin = ref(true);
|
const keepLogin = ref(true);
|
||||||
|
|
||||||
const darkMode = computed({
|
const darkMode = computed({
|
||||||
get() {
|
get() {
|
||||||
|
|
|
@ -39,7 +39,6 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
if (!isLoggedIn && to.name !== 'Login') {
|
if (!isLoggedIn && to.name !== 'Login') {
|
||||||
next({ path: '/login', query: { redirect: to.fullPath } });
|
next({ path: '/login', query: { redirect: to.fullPath } });
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const pathRoutes = to.matched;
|
const pathRoutes = to.matched;
|
||||||
const droles = pathRoutes.every(route => {
|
const droles = pathRoutes.every(route => {
|
||||||
const meta = route.meta;
|
const meta = route.meta;
|
||||||
|
@ -58,33 +57,30 @@ export default route(function (/* { store, ssrContext } */) {
|
||||||
|
|
||||||
Router.afterEach((to) => {
|
Router.afterEach((to) => {
|
||||||
const { t } = i18n.global;
|
const { t } = i18n.global;
|
||||||
let title = '';
|
let title = t(`login.title`);
|
||||||
|
|
||||||
if (to.matched && to.matched.length > 2) {
|
const matches = to.matched;
|
||||||
|
let moduleName;
|
||||||
const parent = to.matched[1];
|
if (matches && matches.length > 1) {
|
||||||
const parentMeta = parent.meta;
|
const module = matches[1];
|
||||||
if (parentMeta && parentMeta.title) {
|
const moduleTitle = module.meta && module.meta.title;
|
||||||
title += t(`pages.${parentMeta.title}`);
|
moduleName = module.name.toLowerCase();
|
||||||
|
if (moduleTitle) {
|
||||||
|
title = t(`${moduleName}.pageTitles.${moduleTitle}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const childMeta = to.meta;
|
const childPage = to.meta;
|
||||||
if (childMeta && childMeta.title) {
|
const childPageTitle = childPage && childPage.title;
|
||||||
|
if (childPageTitle && matches.length > 2) {
|
||||||
if (title != '') title += ': ';
|
if (title != '') title += ': ';
|
||||||
|
|
||||||
const childTitle = t(`pages.${childMeta.title}`);
|
const pageTitle = t(`${moduleName}.pageTitles.${childPageTitle}`);
|
||||||
|
const idParam = to.params && to.params.id;
|
||||||
|
const idPageTitle = `${idParam} - ${pageTitle}`;
|
||||||
|
const builtTitle = idParam ? idPageTitle : pageTitle;
|
||||||
|
|
||||||
if (to.params && to.params.id) {
|
title += builtTitle;
|
||||||
const idParam = to.params.id;
|
|
||||||
if (idParam instanceof Array) {
|
|
||||||
title += `${idParam[0]} - ${childTitle}`
|
|
||||||
} else {
|
|
||||||
title += `${idParam} - ${childTitle}`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
title += t(`pages.${childMeta.title}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.title = title;
|
document.title = title;
|
||||||
|
|
|
@ -17,6 +17,14 @@ export default {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Customer/CustomerList.vue'),
|
component: () => import('src/pages/Customer/CustomerList.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
name: 'CustomerCreate',
|
||||||
|
meta: {
|
||||||
|
title: 'create'
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Customer/CustomerCreate.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: ':id',
|
path: ':id',
|
||||||
component: () => import('src/pages/Customer/Card/CustomerCard.vue'),
|
component: () => import('src/pages/Customer/Card/CustomerCard.vue'),
|
||||||
|
|
Loading…
Reference in New Issue