...
Importante: cuando probemos nuestra aplicación en local, tendremos que usar nuestro dominio .atica.um.es, pues a través de localhost no nos dejará hacer login con el portal.
Forma nativa
Desde una terminal, nos situamos en el directorio en el que queramos generar el proyecto (nos podemos mover por los directorios con el comando cd) y ejecutamos el siguiente comando (el nombre que le demos al proyecto debe ser todo en minúsculas):
| Bloque de código |
|---|
vue create nombreproyecto |
A continuación, podremos elegir la configuración por defecto, o seleccionar los componentes y configuración manualmente. Si lo hacemos de forma manual, dispondremos de elementos como vuex o router, y se nos generarán directamente los archivos necesarios. También podremos guardar como presets las configuraciones manuales que hagamos, por si queremos reutilizarlas.
Una vez terminada la creación del proyecto, lo podremos abrir en VS Code desde File → Open Folder y seleccionando la carpeta generada.
Estructura de un proyecto Vue
...
- /src/assets: contendrá archivos que necesite nuestro proyecto, imágenes por ejemplo, y también el estilo corporativo mientras no esté disponible como un paquete de npm (guía de estilo corporativo).
- /src/components: componentes Vue propios.
- /src/locales: archivos de internacionalización (documentación de internacionalización).
- /src/mixins: mixins, archivos js para añadir funcionalidad a los componentes. Por ejemplo, aquí tendremos el mixin AuthRefresher para refrescar el token del usuario logeado.
- /src/router: contendrá un index.js con el router donde vendrán definidas las rutas de nuestra aplicación (documentación vue-router).
- /src/services: archivos js correspondientes a las llamadas a nuestros servicios REST (documentación de llamadas a servicios REST).
- /src/store: store de Vuex y sus módulos (documentación Vuex).
- /src/views: componentes que sean vistas, generalmente tendremos uno por ruta.
- /src/App.vue: componente inicial de la aplicación.
- /src/main.js: archivo js donde hacemos imports globales e inicializamos la instancia de Vue.
- /src/i18n.js: inicializa la internacionalización de nuestra aplicación.
Además, en la raíz del proyecto, tendremos:
...
Hacemos una diferenciación entre lo que serán vistas y lo que serán componentes para mantener cierta organización y que no acabemos con una carpeta poco intuitiva que contenga demasiados archivos. En ambos casos serán componentes, archivos .vue, pero las vistas serán los componentes que contengan una pantalla completa, mientras que los componentes son partes de éstas, por ejemplo una tabla, o cierta sección que queramos mostrar en nuestra pantalla, o una parte reutilizable que se utilice en diferentes vistas.
Actualizar proyectos
Si se ha creado el proyecto de cero, el contenido de los siguientes archivos estará igual, pero si tenemos proyectos antiguos, tenemos que actualizarlos para evitar conflictos y mezclas no deseadas.
package.json
En el apartado dependencies debemos poner versiones fijas. Esto es, sin ^ precediendo al número de versión. Además, debemos poner la última versión de @mncs/fwjs-components, la 0.1.56.
.env
Será así:
| Bloque de código | ||||
|---|---|---|---|---|
| ||||
# Todas las variables de nuestra aplicación deben empezar por VUE_APP_
######### i18n - Inernacionalización
VUE_APP_I18N_LOCALE=es
VUE_APP_I18N_FALLBACK_LOCALE=es
######### publicPath
VUE_APP_PUBLIC_PATH=replace1
######### Tiempo de sesión (milisegundos) y tiempo de espera del modal previo a cerrar sesión (segundos)
VUE_APP_SESSION_TIME=600000
VUE_APP_SESSION_WAIT=120
######### i18n - Inernacionalización
VUE_APP_I18N_LOCALE=es
VUE_APP_I18N_FALLBACK_LOCALE=es
######### Log
# Coincidirá con la propiedad server.servlet.context-path del backend
VUE_APP_API_URL=replace2
# Nombre de la aplicación - ui
VUE_APP_UMU_CLIENT_APP=replace3
######### Para .env.local #########
# Las siguientes variables son para pruebas en local, deberán ponerse en un archivo .env.local que será ignorado por git
# Para el proxy
#VUE_APP_API_ENVIRONMENT=https://micampusdesa.um.es
# Endpoint local
#VUE_APP_BACKEND=http://mipc.atica.um.es:8080 |
Debemos establecer estas variables:
- VUE_APP_PUBLIC_PATH: ruta de nuestra aplicación, será "/algo", siendo algo lo correspondiente a nuestra aplicación. No dejar con "/" o en blanco.
- VUE_APP_API_URL: ruta del backend, coincidirá con la propiedad server.servlet.context-path del application.properties
- VUE_APP_UMU_CLIENT_APP: nombre de la aplicación seguido de "-ui"
Archivos Login
Los archivos del login están en @mncs/fwjs-components, por lo que debemos cambiar los imports de éstos, y borrar los anteriores. En concreto, son los archivos:
- Login.vue
- AuthRefresher.js
- interceptors.js
- login.js
- user.js
Internacionalización
- También se ha incluido el archivo i18n.js en @mncs/fwjs-components, hay que importar este y borrar lo que tuviésemos.
Los archivos que contienen los mensajes antes eran archivos javascript, .js, ahora son JSON. Tendremos en la carpeta locales los archivos es.json y en.json. En ellos los mensajes se definen así:
Bloque de código title es.json { "titulo": "Mi aplicación", "hola": "Hola mundo" }
main.js
Con los cambios mencionados, el main.js queda así:
| Bloque de código | ||||||||
|---|---|---|---|---|---|---|---|---|
| ||||||||
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import i18n from "@mncs/fwjs-components/i18n";
Vue.config.productionTip = false;
// Primevue
import PrimeVue from "primevue/config";
Vue.use(PrimeVue);
// Toasts
import ToastService from "primevue/toastservice";
Vue.use(ToastService);
// Estilos Primevue
import "primevue/resources/themes/saga-blue/theme.css";
import "primevue/resources/primevue.min.css";
import "primeflex/primeflex.css";
import "primeicons/primeicons.css";
// Font Awesome
import "@fortawesome/fontawesome-free/css/all.css";
// Font Awesome
import "@fortawesome/fontawesome-free/css/all.css";
const imported = document.createElement("link");
imported.href =
process.env.NODE_ENV !== "production" ? "https://recursosdesa.um.es/forja/mncs/fontawesome/fa-5-pro/css/all.min.css" : "https://recursos.um.es/forja/mncs/fontawesome/fa-5-pro/css/all.min.css";
imported.rel = "stylesheet";
imported.type = "text/css";
document.head.appendChild(imported);
// Estilo corporativo
import "@mncs/fwjs-components/estiloUMU.css";
import mixinFixEstiloUMU from "@mncs/fwjs-components/estiloUMU/mixinFixEstiloUMU.js";
Vue.mixin(mixinFixEstiloUMU);
import VueAuthImage from "vue-auth-image";
Vue.use(VueAuthImage);
// Front logger
import log from "@mncs/fwjs-components/log";
Vue.use(log);
// Control de fin de sesion
// Idle
import IdleVue from "idle-vue";
const eventsHub = new Vue();
// idleTime es el tiempo en ms que debe pasar para que se pase a estado inactivo
var idleSeconds = 900;
// var idleSeconds = 5;
Vue.use(IdleVue, { eventEmitter: eventsHub, store, idleTime: idleSeconds * 1000, startAtIdle: false });
export const vm = new Vue({
router,
store,
i18n,
render: (h) => h(App),
});
vm.$mount("#app");
|
Vuex
Nuestro index.js de Vuex queda inicialmente así:
| Bloque de código | ||||||||
|---|---|---|---|---|---|---|---|---|
| ||||||||
import Vue from "vue";
import Vuex from "vuex";
import user from "@mncs/fwjs-components/loginPOSE/user";
import login from "@mncs/fwjs-components/loginPOSE/login";
import loadingGlobal from "@mncs/fwjs-components/loader/loadingGlobal"
import createPersistedState from "vuex-persistedstate";
Vue.use(Vuex);
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
modules: {
user,
loadingGlobal,
login,
},
// Para hacer que el estado persista tras refrescar la página
plugins: [
createPersistedState({
paths: ["login.forceRefresh", "user.language"],
}),
],
});
export default store; |
Router
El index.js de nuestro router queda inicialmente así:
| Bloque de código | ||||||
|---|---|---|---|---|---|---|
| ||||||
import Vue from "vue";
import VueRouter from "vue-router";
import store from "../store";
import Home from "../views/Home.vue";
import Login from "@mncs/fwjs-components/loginPOSE/Login.vue";
Vue.use(VueRouter);
// Comprobar autenticación
const checkAuth = (to, from, next) => {
// Si no está logeado, se navega a la página de login
if (!store.getters["login/isLogged"]) {
window.location.href = store.getters["login/urlLogin"];
}
next();
};
const routes = [
{
path: "/",
name: "Home",
component: Home,
beforeEnter: checkAuth,
},
{ path: "/login", name: "login", component: Login },
];
const router = new VueRouter({
routes,
});
// Después de cada navegación se guarda la ruta en el localStorage, excepto login.
// Para volver a la pantalla anterior tras hacer login.
router.afterEach((to) => {
if (to.name !== "login") {
localStorage.setItem("POSE_LOGIN_ROUTE_KEY", to.path);
}
});
export default router;
|
.npmrc
Debe contener:
| Bloque de código |
|---|
registry = https://verdaccio.um.es/ |
Vista inicial de la aplicación
La aplicación se inicia en main.js, donde se crea la instancia de Vue. El componente inicial, el que será el padre de todos los componentes, será App.vue. En éste, generalmente tendremos las partes fijas de la aplicación, como el header, footer, o menú. Para el contenido de la página, con <router-view> se le indica que se cargue el componente (que será una vista, es decir, un componente del directorio Views) correspondiente a la ruta en la que nos encontremos. Las diferentes rutas tendremos que definirlas en src/router/index.js. Un ejemplo de App.vue podría ser este, que incluye el header del portal de servicios y el elemento <router-view>:
| Bloque de código | ||
|---|---|---|
| ||
<template> <div id="app fwjsLoader-container"> <fwjsLoader v-if="loading" :fullScreen="true" :blurry="true" :dark="false" /> <Toast /> <fwjsSessionModal @expired="logout" style="width: 100%" /> <div style="height: 56px;"> <fwjsHeader :title="$t('titulo')" :isLoggedhasBack="true" :is-logged="isLogged" style="z-index: 9" /> </div> <div id="contenido" style="margin-top: 15px"> <div <router-view></router-view>id="vista"> <router-view /> </div> <fwjsFooter /> </div> </div> </template> <script> import fwjsHeader from "@mncs/fwjs-components/fwjsHeader"; import AuthRefresher from "@mncs/fwjs-components/loginPOSE/AuthRefresher"; import { mapGetters, mapState } from "vuex"; import Toast from "primevue/toast"; import fwjsSessionModal from "@mncs/fwjs-components/fwjsSessionModal"; import fwjsLoader from "@mncs/fwjs-components/fwjsLoader"; import fwjsFooter from "@mncs/fwjs-components/fwjsFooter"; export default { computed: { ...mapState("loadingGlobal", ["loading"]), }, methods: { logout() { this.$store.dispatch("login/revokeToken"); }, }, mixins: [AuthRefresher], components: { fwjsHeader, AuthRefresher, Toast, fwjsSessionModal, fwjsLoader, fwjsFooter, }, }; </script> |
Aquí vemos que se utiliza el header del paquete @mncs/fwjs-components, que es un paquete propio. Este se encuentra en Verdaccio, que es el repositorio propio de componentes que tenemos. Tenemos una página de documentación dedicada a cómo subir y descargar componentes: Documentación Verdaccio.
De forma resumida, para este caso, debemos tener el archivo .npmrc en la raíz del proyecto, que ya lo tendremos si hemos utilizado el script de creación, que contenga:
| Bloque de código |
|---|
registry = https://verdaccio.um.es/ |
Y ejecutar este comando en la terminal de VS Code:
| Bloque de código |
|---|
npm install --save @mncs/fwjs-components<style scoped> @media screen and (min-width: 40em) { #contenido { overflow: hidden; overflow-y: auto; padding: 24px 48px 0 48px; flex: 1; } } #vista { min-height: calc(100vh - 185px); margin-bottom: 15px; } </style> |