UPDATE: Simplificación de funsionamiento
- ADD: Función creación de URL a backend fuera de VUEJS. - UPDATE: Ahora las plantillas se definen en el grupo de rutas, y se heredan en las rutas hijas. - UPDATE: Traducciones modulares faltantes. - UPDATE: Simplificación de las rutas de autenticación. - FIX: Títulos de modal de eliminación ahora son editables. - FIX: Obtención de recursos de backend mediante `api.resource`.
This commit is contained in:
parent
28c5ba153b
commit
6b7bccc500
14
auth.html
14
auth.html
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html id="main-page" lang="es">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Login</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/auth.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "notsoweb.frontend",
|
"name": "notsoweb.frontend",
|
||||||
"copyright": "Notsoweb Software Inc.",
|
"copyright": "Notsoweb Software Inc.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.9.8",
|
"version": "0.9.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
50
src/auth.js
50
src/auth.js
@ -1,50 +0,0 @@
|
|||||||
import './css/base.css'
|
|
||||||
|
|
||||||
import axios from 'axios';
|
|
||||||
import { createPinia } from 'pinia'
|
|
||||||
import { createApp } from 'vue'
|
|
||||||
import { useRoute, ZiggyVue } from 'ziggy-js';
|
|
||||||
import { i18n, lang } from '@/lang/i18n.js';
|
|
||||||
import router from '@Router/Auth'
|
|
||||||
import Notify from '@Plugins/Notify'
|
|
||||||
import TailwindScreen from '@Plugins/TailwindScreen'
|
|
||||||
import { defineApp, pagePlugin, reloadApp } from '@Services/Page';
|
|
||||||
|
|
||||||
import Auth from '@Holos/Layout/Auth.vue'
|
|
||||||
|
|
||||||
// Configurar axios
|
|
||||||
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
|
||||||
|
|
||||||
// Crear instancias globales
|
|
||||||
window.Lang = lang;
|
|
||||||
window.Notify = new Notify();
|
|
||||||
window.TwScreen = new TailwindScreen();
|
|
||||||
|
|
||||||
async function boot() {
|
|
||||||
try {
|
|
||||||
const routes = await axios.get(import.meta.env.VITE_API_URL + '/api/resources/routes');
|
|
||||||
const app = await axios.get(import.meta.env.VITE_API_URL + '/api/resources/app');
|
|
||||||
|
|
||||||
// Iniciar rutas
|
|
||||||
window.Ziggy = routes.data;
|
|
||||||
window.route = useRoute();
|
|
||||||
|
|
||||||
defineApp(app.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
alert('Failed to load routes');
|
|
||||||
}
|
|
||||||
|
|
||||||
reloadApp();
|
|
||||||
|
|
||||||
createApp(Auth)
|
|
||||||
.use(createPinia())
|
|
||||||
.use(i18n)
|
|
||||||
.use(pagePlugin)
|
|
||||||
.use(router)
|
|
||||||
.use(ZiggyVue)
|
|
||||||
.mount('#app');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iniciar aplicación
|
|
||||||
boot();
|
|
||||||
23
src/components/App.vue
Normal file
23
src/components/App.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import useLoader from '@Stores/Loader';
|
||||||
|
import { hasToken } from '@Services/Api';
|
||||||
|
|
||||||
|
/** Definidores */
|
||||||
|
const router = useRouter();
|
||||||
|
const loader = useLoader();
|
||||||
|
|
||||||
|
/** Ciclos */
|
||||||
|
onMounted(() => {
|
||||||
|
if(!hasToken()) {
|
||||||
|
return router.push({ name: 'auth.index' })
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.boot()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<router-view />
|
||||||
|
</template>
|
||||||
@ -6,7 +6,7 @@ defineProps({
|
|||||||
to: String
|
to: String
|
||||||
});
|
});
|
||||||
|
|
||||||
const style = 'block px-4 py-2 text-sm leading-5 hover:bg-secondary/80 dark:hover:bg-secondary-d/80 focus:outline-hidden focus:bg-gray-100 transition';
|
const style = 'block px-4 py-2 text-sm leading-5 hover:bg-secondary/80 dark:hover:bg-secondary-d/80 focus:outline-hidden focus:bg-gray-100 cursor-pointer transition';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { hasToken } from '@Services/Api';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
/** Definidores */
|
/** Definidores */
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
/** Métodos */
|
/** Métodos */
|
||||||
const home = () => router.push(view({ name: 'index' }));
|
const home = () => {
|
||||||
|
if(hasToken()) {
|
||||||
|
router.push({ name: 'dashboard.index' });
|
||||||
|
} else {
|
||||||
|
location.replace('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -15,6 +15,14 @@ const props = defineProps({
|
|||||||
model: Object,
|
model: Object,
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
to: Function,
|
to: Function,
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: 'name'
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
type: String,
|
||||||
|
default: 'description'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Métodos */
|
/** Métodos */
|
||||||
@ -38,8 +46,8 @@ const destroy = (id) => api.delete(props.to(id), {
|
|||||||
@destroy="destroy(model.id)"
|
@destroy="destroy(model.id)"
|
||||||
>
|
>
|
||||||
<Header
|
<Header
|
||||||
:subtitle="model.full_last_name"
|
:title="model[title]"
|
||||||
:title="model.name"
|
:subtitle="model[subtitle]"
|
||||||
/>
|
/>
|
||||||
</DestroyModal>
|
</DestroyModal>
|
||||||
</template>
|
</template>
|
||||||
20
src/index.js
20
src/index.js
@ -11,9 +11,11 @@ import { bootPermissions, bootRoles } from '@Plugins/RolePermission';
|
|||||||
import TailwindScreen from '@Plugins/TailwindScreen'
|
import TailwindScreen from '@Plugins/TailwindScreen'
|
||||||
import { pagePlugin } from '@Services/Page';
|
import { pagePlugin } from '@Services/Page';
|
||||||
import { reloadApp, view } from '@Services/Page';
|
import { reloadApp, view } from '@Services/Page';
|
||||||
|
import { apiURL } from '@Services/Api';
|
||||||
|
|
||||||
import App from '@Layouts/AppLayout.vue'
|
import App from '@Components/App.vue'
|
||||||
import Error503 from '@Pages/Errors/503.vue'
|
import Error503 from '@Pages/Errors/503.vue'
|
||||||
|
import { hasToken } from './services/Api';
|
||||||
|
|
||||||
// Configurar axios
|
// Configurar axios
|
||||||
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
@ -29,7 +31,7 @@ async function boot() {
|
|||||||
|
|
||||||
// Iniciar rutas
|
// Iniciar rutas
|
||||||
try {
|
try {
|
||||||
const routes = await axios.get(import.meta.env.VITE_API_URL + '/api/resources/routes');
|
const routes = await axios.get(apiURL('resources/routes'));
|
||||||
|
|
||||||
window.Ziggy = routes.data;
|
window.Ziggy = routes.data;
|
||||||
window.route = useRoute();
|
window.route = useRoute();
|
||||||
@ -41,12 +43,14 @@ async function boot() {
|
|||||||
|
|
||||||
if(initRoutes) {
|
if(initRoutes) {
|
||||||
// Iniciar permisos
|
// Iniciar permisos
|
||||||
await bootPermissions();
|
if(hasToken()) {
|
||||||
await bootRoles();
|
await bootPermissions();
|
||||||
|
await bootRoles();
|
||||||
// Iniciar broadcast
|
|
||||||
if(import.meta.env.VITE_REVERB_ACTIVE === 'true') {
|
// Iniciar broadcast
|
||||||
await import('@Services/Broadcast')
|
if(import.meta.env.VITE_REVERB_ACTIVE === 'true') {
|
||||||
|
await import('@Services/Broadcast')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadApp();
|
reloadApp();
|
||||||
|
|||||||
@ -298,7 +298,7 @@ export default {
|
|||||||
roles:{
|
roles:{
|
||||||
create: {
|
create: {
|
||||||
title: 'Crear rol',
|
title: 'Crear rol',
|
||||||
description: 'Estos roles serán usados para dar permisos en el sistema.',
|
description: 'Este nombre sera necesario para identificar el rol en el sistema. Procura que sea algo simple.',
|
||||||
onSuccess: 'Rol creado exitosamente',
|
onSuccess: 'Rol creado exitosamente',
|
||||||
onError: 'Error al crear el role',
|
onError: 'Error al crear el role',
|
||||||
},
|
},
|
||||||
@ -309,9 +309,10 @@ export default {
|
|||||||
onError: 'Error al actualizar el role',
|
onError: 'Error al actualizar el role',
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
description: 'Actualiza los permisos del rol.',
|
description: 'Si crees necesario, puedes actualizar el nombre del rol. No afecta a los permisos.',
|
||||||
},
|
},
|
||||||
title: 'Roles',
|
title: 'Roles',
|
||||||
|
description: 'Gestión de roles del sistema. Puedes crear los roles con los permisos que necesites.',
|
||||||
permissions: {
|
permissions: {
|
||||||
title: 'Permisos',
|
title: 'Permisos',
|
||||||
description: 'Permisos del rol.',
|
description: 'Permisos del rol.',
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { onMounted, reactive, ref } from 'vue';
|
|||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { hasPermission } from '@Plugins/RolePermission';
|
import { hasPermission } from '@Plugins/RolePermission';
|
||||||
import { useSearcher } from '@Services/Api';
|
import { useSearcher } from '@Services/Api';
|
||||||
import { apiTo } from './Module';
|
import { apiTo, transl } from './Module';
|
||||||
|
|
||||||
import ModalController from '@Controllers/ModalController.js';
|
import ModalController from '@Controllers/ModalController.js';
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Header :title="$t('admin.activity.title')">
|
<Header :title="transl('title')">
|
||||||
<RouterLink v-if="filters.user && hasPermission('users.index')" :to="$view({ name: 'admin.users.index' })">
|
<RouterLink v-if="filters.user && hasPermission('users.index')" :to="$view({ name: 'admin.users.index' })">
|
||||||
<IconButton
|
<IconButton
|
||||||
class="text-white"
|
class="text-white"
|
||||||
@ -81,7 +81,7 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</Header>
|
</Header>
|
||||||
<p class="mt-2 text-sm">{{ $t('admin.activity.description') }}</p>
|
<p class="mt-2 text-sm">{{ transl('description') }}</p>
|
||||||
|
|
||||||
<div id="filters" class="grid gap-2 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mt-4">
|
<div id="filters" class="grid gap-2 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mt-4">
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@ -22,8 +22,7 @@ defineProps({
|
|||||||
@close="$emit('close')"
|
@close="$emit('close')"
|
||||||
>
|
>
|
||||||
<Header
|
<Header
|
||||||
:title="model.name"
|
:title="model.event"
|
||||||
:subtitle="model.last_name"
|
|
||||||
/>
|
/>
|
||||||
<div class="flex w-full p-4">
|
<div class="flex w-full p-4">
|
||||||
<GoogleIcon
|
<GoogleIcon
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const apiTo = (name, params = {}) => route(`admin.activities.${name}`, params)
|
|||||||
const viewTo = ({ name = '', params = {}, query = {} }) => view({ name: `admin.activities.${name}`, params, query })
|
const viewTo = ({ name = '', params = {}, query = {} }) => view({ name: `admin.activities.${name}`, params, query })
|
||||||
|
|
||||||
// Obtener traducción del componente
|
// Obtener traducción del componente
|
||||||
const transl = (str) => lang(`activities.${str}`)
|
const transl = (str) => lang(`admin.activity.${str}`)
|
||||||
|
|
||||||
// Determina si un usuario puede hacer algo no en base a los permisos
|
// Determina si un usuario puede hacer algo no en base a los permisos
|
||||||
const can = (permission) => hasPermission(`activities.${permission}`)
|
const can = (permission) => hasPermission(`activities.${permission}`)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { can, apiTo, viewTo } from './Module'
|
import { can, apiTo, viewTo, transl } from './Module'
|
||||||
import { useSearcher } from '@Services/Api';
|
import { useSearcher } from '@Services/Api';
|
||||||
|
|
||||||
import ModalController from '@Controllers/ModalController.js';
|
import ModalController from '@Controllers/ModalController.js';
|
||||||
@ -36,7 +36,7 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SearcherHead
|
<SearcherHead
|
||||||
:title="$t('roles.title')"
|
:title="transl('title')"
|
||||||
@search="(x) => searcher.search(x)"
|
@search="(x) => searcher.search(x)"
|
||||||
>
|
>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
@ -56,7 +56,10 @@ onMounted(() => {
|
|||||||
@click="searcher.search()"
|
@click="searcher.search()"
|
||||||
/>
|
/>
|
||||||
</SearcherHead>
|
</SearcherHead>
|
||||||
<div class="pt-2 w-full">
|
<div class="pt-2 space-y-2 w-full">
|
||||||
|
<p class="text-sm">
|
||||||
|
{{ transl('description') }}
|
||||||
|
</p>
|
||||||
<Table
|
<Table
|
||||||
:items="models"
|
:items="models"
|
||||||
@send-pagination="(page) => searcher.pagination(page)"
|
@send-pagination="(page) => searcher.pagination(page)"
|
||||||
@ -79,7 +82,7 @@ onMounted(() => {
|
|||||||
<IconButton
|
<IconButton
|
||||||
v-if="can('edit') && ![1,2].includes(model.id)"
|
v-if="can('edit') && ![1,2].includes(model.id)"
|
||||||
icon="license"
|
icon="license"
|
||||||
:title="$t('roles.permissions.title')"
|
:title="transl('permissions.title')"
|
||||||
@click="Modal.switchEditModal(model)"
|
@click="Modal.switchEditModal(model)"
|
||||||
outline
|
outline
|
||||||
/>
|
/>
|
||||||
@ -116,6 +119,8 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
<DestroyView
|
<DestroyView
|
||||||
v-if="can('destroy')"
|
v-if="can('destroy')"
|
||||||
|
title="description"
|
||||||
|
subtitle=""
|
||||||
:model="modelModal"
|
:model="modelModal"
|
||||||
:show="destroyModal"
|
:show="destroyModal"
|
||||||
:to="(role) => apiTo('destroy', { role })"
|
:to="(role) => apiTo('destroy', { role })"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { can, apiTo, viewTo } from './Module'
|
import { can, apiTo, viewTo, transl } from './Module'
|
||||||
import { useSearcher } from '@Services/Api';
|
import { useSearcher } from '@Services/Api';
|
||||||
import { hasPermission } from '@Plugins/RolePermission';
|
import { hasPermission } from '@Plugins/RolePermission';
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SearcherHead
|
<SearcherHead
|
||||||
:title="$t('users.title')"
|
:title="transl('title')"
|
||||||
@search="(x) => searcher.search(x)"
|
@search="(x) => searcher.search(x)"
|
||||||
>
|
>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
@ -173,6 +173,7 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
<DestroyView
|
<DestroyView
|
||||||
v-if="can('destroy')"
|
v-if="can('destroy')"
|
||||||
|
subtitle="last_name"
|
||||||
:model="modelModal"
|
:model="modelModal"
|
||||||
:show="destroyModal"
|
:show="destroyModal"
|
||||||
:to="(user) => apiTo('destroy', { user })"
|
:to="(user) => apiTo('destroy', { user })"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { can, apiTo, viewTo } from './Module'
|
import { can, apiTo, viewTo, transl } from './Module'
|
||||||
import { users } from '@Plugins/AuthUsers'
|
import { users } from '@Plugins/AuthUsers'
|
||||||
|
|
||||||
import ModalController from '@Controllers/ModalController.js';
|
import ModalController from '@Controllers/ModalController.js';
|
||||||
@ -24,7 +24,7 @@ const modelModal = ref(Modal.modelModal);
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Header
|
<Header
|
||||||
:title="$t('users.online.title')"
|
:title="transl('online.title')"
|
||||||
>
|
>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
v-if="can('create')"
|
v-if="can('create')"
|
||||||
@ -38,7 +38,7 @@ const modelModal = ref(Modal.modelModal);
|
|||||||
/>
|
/>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</Header>
|
</Header>
|
||||||
<p class="mt-2">{{ $t('users.online.description') }} {{ users.length - 1 }} {{ $t('users.online.count') }}</p>
|
<p class="mt-2">{{ transl('online.description') }} {{ users.length - 1 }} {{ transl('online.count') }}</p>
|
||||||
<div class="w-full -mt-2">
|
<div class="w-full -mt-2">
|
||||||
<Table
|
<Table
|
||||||
:items="users"
|
:items="users"
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useForm } from '@Services/Api';
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useForm } from '@Services/Api';
|
||||||
|
import { viewTo } from './Module';
|
||||||
|
|
||||||
import Input from '@Holos/Form/InputWithIcon.vue'
|
import Input from '@Holos/Form/InputWithIcon.vue'
|
||||||
import PrimaryButton from '@Holos/Button/Primary.vue'
|
import PrimaryButton from '@Holos/Button/Primary.vue'
|
||||||
|
|
||||||
@ -21,11 +23,11 @@ const submit = () => {
|
|||||||
form.post(route('auth.forgot-password'), {
|
form.post(route('auth.forgot-password'), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Notify.success(Lang('auth.forgotPassword.success'));
|
Notify.success(Lang('auth.forgotPassword.success'));
|
||||||
router.push({ name: 'index' });
|
router.push(viewTo({ name: 'index' }));
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Notify.error(Lang('auth.forgotPassword.error'));
|
Notify.error(Lang('auth.forgotPassword.error'));
|
||||||
router.push({ name: 'index' });
|
router.push(viewTo({ name: 'index' }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
import { defineApiToken, defineCsrfToken, hasToken, useForm } from '@Services/Api.js'
|
import { defineApiToken, defineCsrfToken, hasToken, useForm } from '@Services/Api.js'
|
||||||
import { defineUser } from '@Services/Page';
|
import { defineUser } from '@Services/Page';
|
||||||
|
import { viewTo } from './Module.js';
|
||||||
|
|
||||||
import PrimaryButton from '@Holos/Button/Primary.vue'
|
import PrimaryButton from '@Holos/Button/Primary.vue'
|
||||||
import Input from '@Holos/Form/InputWithIcon.vue'
|
import Input from '@Holos/Form/InputWithIcon.vue'
|
||||||
|
|
||||||
|
/** Definidores */
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
/** Propiedades */
|
/** Propiedades */
|
||||||
defineProps({
|
defineProps({
|
||||||
canResetPassword: Boolean,
|
canResetPassword: Boolean,
|
||||||
@ -33,7 +38,7 @@ const login = () => {
|
|||||||
/** Ciclos */
|
/** Ciclos */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (hasToken()) {
|
if (hasToken()) {
|
||||||
location.replace('/')
|
router.push({ name: 'dashboard.index' });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -62,7 +67,7 @@ onMounted(() => {
|
|||||||
<div class="flex justify-end mt-4">
|
<div class="flex justify-end mt-4">
|
||||||
<RouterLink
|
<RouterLink
|
||||||
class="text-sm ml-2 hover:text-blue-200 cursor-pointer hover:-translate-y-1 duration-500 transition-all"
|
class="text-sm ml-2 hover:text-blue-200 cursor-pointer hover:-translate-y-1 duration-500 transition-all"
|
||||||
:to="$view({ name: 'forgot-password' })"
|
:to="viewTo({ name: 'forgot-password' })"
|
||||||
>
|
>
|
||||||
{{ $t('auth.forgotPassword.ask') }}
|
{{ $t('auth.forgotPassword.ask') }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|||||||
17
src/pages/Auth/Module.js
Normal file
17
src/pages/Auth/Module.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
import { lang } from '@Lang/i18n';
|
||||||
|
|
||||||
|
// Ruta API
|
||||||
|
const apiTo = (name, params = {}) => route(`auth.${name}`, params)
|
||||||
|
|
||||||
|
// Ruta visual
|
||||||
|
const viewTo = ({ name = '', params = {}, query = {} }) => view({ name: `auth.${name}`, params, query })
|
||||||
|
|
||||||
|
// Obtener traducción del componente
|
||||||
|
const transl = (str) => lang(`auth.${str}`)
|
||||||
|
|
||||||
|
export {
|
||||||
|
viewTo,
|
||||||
|
apiTo,
|
||||||
|
transl
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useForm } from '@Services/Api.js'
|
import { useForm } from '@Services/Api.js'
|
||||||
|
import { viewTo } from './Module';
|
||||||
import PrimaryButton from '@Holos/Button/Primary.vue';
|
import PrimaryButton from '@Holos/Button/Primary.vue';
|
||||||
import Input from '@Holos/Form/InputWithIcon.vue'
|
import Input from '@Holos/Form/InputWithIcon.vue'
|
||||||
|
|
||||||
@ -24,21 +24,17 @@ const submit = () => {
|
|||||||
form.post(route('auth.reset-password'), {
|
form.post(route('auth.reset-password'), {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Notify.success(Lang('auth.reset.success'));
|
Notify.success(Lang('auth.reset.success'));
|
||||||
router.push({ name: 'index' })
|
router.push(viewTo({ name: 'index' }));
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
router.push({ name: 'index' });
|
router.push(viewTo({ name: 'index' }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log('mount')
|
|
||||||
|
|
||||||
form.token = vroute.query.token;
|
form.token = vroute.query.token;
|
||||||
email.value = vroute.query.email;
|
email.value = vroute.query.email;
|
||||||
|
|
||||||
// router.replace({ query: {} });
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,28 @@ const changelogs = [
|
|||||||
'ADD: Visualización de historial de cambios del backend.',
|
'ADD: Visualización de historial de cambios del backend.',
|
||||||
],
|
],
|
||||||
date: '2025-01-17'
|
date: '2025-01-17'
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
version: '0.9.8',
|
||||||
|
details: [
|
||||||
|
'UPDATE: Actualización de dependencias.',
|
||||||
|
'UPDATE: TailwindCSS 3 => 4.',
|
||||||
|
'UPDATE: Actualización de Diseño, mejoras visuales.',
|
||||||
|
],
|
||||||
|
date: '2025-03-04'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: '0.9.9',
|
||||||
|
details: [
|
||||||
|
'FIX: Obtención de recursos de backend mediante `api.resource`.',
|
||||||
|
'FIX: Títulos de modal de eliminación ahora son editables.',
|
||||||
|
'UPDATE: Simplificación de las rutas de autenticación.',
|
||||||
|
'UPDATE: Traducciones modulares faltantes.',
|
||||||
|
'UPDATE: Ahora las plantillas se definen en el grupo de rutas, y se heredan en las rutas hijas.',
|
||||||
|
'ADD: Función creación de URL a backend fuera de VUEJS.',
|
||||||
|
],
|
||||||
|
date: '2025-03-13'
|
||||||
|
},
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
|
||||||
|
|
||||||
const router = createRouter({
|
|
||||||
history: createWebHashHistory(import.meta.env.BASE_URL),
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
name: 'index',
|
|
||||||
component: () => import('@Pages/Auth/Login.vue')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/forgot-password',
|
|
||||||
name: 'forgot-password',
|
|
||||||
component: () => import('@Pages/Auth/ForgotPassword.vue')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/reset-password',
|
|
||||||
name: 'reset-password',
|
|
||||||
component: () => import('@Pages/Auth/ResetPassword.vue')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
export default router
|
|
||||||
@ -16,6 +16,7 @@ const router = createRouter({
|
|||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
component: () => import('@Layouts/AppLayout.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@ -51,6 +52,7 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
|
component: () => import('@Layouts/AppLayout.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'users',
|
path: 'users',
|
||||||
@ -119,7 +121,7 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/changelogs',
|
path: '/changelogs',
|
||||||
name: 'changelogs',
|
component: () => import('@Layouts/AppLayout.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@ -133,6 +135,27 @@ const router = createRouter({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/auth',
|
||||||
|
component: () => import('@Holos/Layout/Auth.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'auth.index',
|
||||||
|
component: () => import('@Pages/Auth/Login.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'forgot-password',
|
||||||
|
name: 'auth.forgot-password',
|
||||||
|
component: () => import('@Pages/Auth/ForgotPassword.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'reset-password',
|
||||||
|
name: 'auth.reset-password',
|
||||||
|
component: () => import('@Pages/Auth/ResetPassword.vue')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
name: '404',
|
name: '404',
|
||||||
|
|||||||
@ -73,8 +73,6 @@ const closeSession = () => {
|
|||||||
resetCsrfToken()
|
resetCsrfToken()
|
||||||
|
|
||||||
Notify.info(Lang('session.closed'))
|
Notify.info(Lang('session.closed'))
|
||||||
|
|
||||||
location.replace('auth.html')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +84,13 @@ function composeKey(parent, key) {
|
|||||||
return parent ? parent + '[' + key + ']' : key
|
return parent ? parent + '[' + key + ']' : key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL API
|
||||||
|
*/
|
||||||
|
const apiURL = (path) => {
|
||||||
|
return import.meta.env.VITE_API_URL + '/api/' + path
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instancia de la API de uso directo
|
* Instancia de la API de uso directo
|
||||||
*/
|
*/
|
||||||
@ -135,8 +140,6 @@ const api = {
|
|||||||
if(options.hasOwnProperty('onFail')) {
|
if(options.hasOwnProperty('onFail')) {
|
||||||
options.onFail(data.data);
|
options.onFail(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(data.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options.hasOwnProperty('onFinish')) {
|
if(options.hasOwnProperty('onFinish')) {
|
||||||
@ -214,7 +217,7 @@ const api = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
resource(resources, options) {
|
resource(resources, options) {
|
||||||
this.post('resources/get', {
|
this.post(apiURL('resources/get'), {
|
||||||
...options,
|
...options,
|
||||||
data: resources
|
data: resources
|
||||||
})
|
})
|
||||||
@ -569,6 +572,7 @@ const useSearcher = (options = {
|
|||||||
export {
|
export {
|
||||||
api,
|
api,
|
||||||
token,
|
token,
|
||||||
|
apiURL,
|
||||||
closeSession,
|
closeSession,
|
||||||
defineCsrfToken,
|
defineCsrfToken,
|
||||||
defineApiToken,
|
defineApiToken,
|
||||||
|
|||||||
@ -110,6 +110,8 @@ const logout = () => {
|
|||||||
onSuccess: (r) => {
|
onSuccess: (r) => {
|
||||||
if(r.is_revoked === true) {
|
if(r.is_revoked === true) {
|
||||||
closeSession()
|
closeSession()
|
||||||
|
|
||||||
|
location.replace('/')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,14 +7,6 @@ import vue from '@vitejs/plugin-vue'
|
|||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue(), tailwindcss()],
|
plugins: [vue(), tailwindcss()],
|
||||||
build: {
|
|
||||||
rollupOptions: {
|
|
||||||
input: {
|
|
||||||
main: './index.html', // Ruta al archivo index.html
|
|
||||||
auth: './auth.html', // Ruta al archivo auth.html
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
server: {
|
server: {
|
||||||
allowedHosts: true,
|
allowedHosts: true,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user