From 78516e5f8d68c24f789f363266d39f20151ea1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poussard?= <tpoussard@neogeo.fr> Date: Mon, 26 Jul 2021 17:51:11 +0200 Subject: [PATCH] Get back previous page after login & add page project create an type list --- .env | 26 --- src/App.vue | 23 +-- src/router/index.js | 42 +++- src/store/index.js | 31 +-- src/views/Index.vue | 5 +- src/views/My_account.vue | 263 ++++++++++++++++++++++++ src/views/project/Project_create.vue | 13 +- src/views/project/Project_detail.vue | 2 +- src/views/project/Project_type_list.vue | 69 +++++++ 9 files changed, 407 insertions(+), 67 deletions(-) delete mode 100644 .env create mode 100644 src/views/My_account.vue create mode 100644 src/views/project/Project_type_list.vue diff --git a/.env b/.env deleted file mode 100644 index 446e5e7e..00000000 --- a/.env +++ /dev/null @@ -1,26 +0,0 @@ -NODE_ENV=development -VUE_APP_LOCALE=fr-FR - -DOMAIN=https://localhost:8000/api - -VUE_APP_ROOT_PATH= -VUE_APP_NEXT_DEFAULT=/ - -# API -VUE_APP_LOGIN_API=${DOMAIN}/login - -# VUE_APP_ORGANISATION_API=${DOMAIN}/organisation/ -# VUE_APP_USERGROUP_API=${DOMAIN}/usergroup/ - - -# AUTH -VUE_APP_LOGIN_API_USERNAME=admin -VUE_APP_LOGIN_API_PASSWORD=admin - - -VUE_APP_BASE_URL=http://localhost:8080/ -VUE_APP_APPLICATION_NAME=GéoContrib -VUE_APP_APPLICATION_ABSTRACT=Application de saisie d'informations géographiques contributive -VUE_APP_LOGO_PATH=@/assets/img/logo-neogeo-circle.png - -# VUE_APP_DJANGO_API_BASE=https://tim.geocontrib.dev.neogeo.fr/api/projects/ \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 25ea46cb..44f16ecb 100644 --- a/src/App.vue +++ b/src/App.vue @@ -67,16 +67,12 @@ <div class="right menu"> <!-- // todo : create my_account page + endpoint + router --> - <a - v-if="user" - class="item" - href="{% url 'geocontrib:my_account' %}" - > - {{ user.full_name || user.username - }}<!-- // ? full_name n'existe pas côté django... --> - </a> - <div v-if="project || user.is_administrator" class="item ui label"> - <span v-if="project"> {{ USER_LEVEL_PROJECT }}</span + <router-link v-if="user" to="/my_account/" class="item"> + {{ user.full_name || user.username }} + <!-- // ? full_name n'existe pas côté django... --> + </router-link> + <div v-if="project && user.is_administrator" class="item ui label"> + <span v-if="project"> {{ USER_LEVEL_PROJECTS }}</span ><br /> <span v-if="user.is_administrator"> Gestionnaire métier </span> </div> @@ -149,14 +145,17 @@ export default { LOGO_PATH: () => process.env.VUE_APP_LOGO_PATH, APPLICATION_NAME: () => process.env.VUE_APP_APPLICATION_NAME, PACKAGE_VERSION: () => process.env.PACKAGE_VERSION || "0", - USER_LEVEL_PROJECT: () => this.USER_LEVEL_PROJECTS + /* USER_LEVEL_PROJECT: function() { + return this.USER_LEVEL_PROJECTS.filter(item => item) + } */ }, created() { this.$store.dispatch("GET_COOKIE", "csrftoken"); // * ne récupère plus le cookie arès avoir vidé le cache ?! }, methods: { logout() { - this.$store.commit("SET_USER", false) + console.log("!") + this.$store.dispatch("LOGOUT"); }, }, }; diff --git a/src/router/index.js b/src/router/index.js index b285aa4e..918c21fe 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -11,23 +11,29 @@ const routes = [ component: Index }, { - path: '/mentions/', - name: 'Mentions', + path: '/connexion/', + name: 'Login', // route level code-splitting // this generates a separate chunk (login.[hash].js) for this route // which is lazy-loaded when the route is visited. - component: () => import(/* webpackChunkName: "login" */ '../views/flatpages/with_right_menu.vue') + component: () => import(/* webpackChunkName: "login" */'../views/registration/Login.vue') + }, + { + path: '/my_account/', + name: 'My_account', + component: () => import('../views/My_account.vue') + }, + { + path: '/mentions/', + name: 'Mentions', + component: () => import('../views/flatpages/with_right_menu.vue') }, { path: '/aide/', name: 'Aide', component: () => import('../views/flatpages/Default.vue') }, - { - path: '/connexion/', - name: 'Login', - component: () => import('../views/registration/Login.vue') - }, + // * PROJECTS { path: '/projet/:slug', name: 'Project_detail', @@ -40,12 +46,30 @@ const routes = [ props: true, component: () => import('../views/project/Project_create.vue') }, + { + path: '/Project_type_list/', + name: 'Project_type_list', + props: true, + component: () => import('../views/project/Project_type_list.vue') + }, ] +//let routerHistory = []; const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, - routes + routes, + routerHistory: [], + scrollBehavior(to, from, savedPosition) { + const fromHistory = Boolean(savedPosition); + + if (fromHistory && this.options.routerHistory.length > 0) { + this.options.routerHistory.splice(-1, 1); + } else { + this.options.routerHistory.push(from); + } + return savedPosition || { x: 0, y: 0 }; + }, }) export default router diff --git a/src/store/index.js b/src/store/index.js index 18c26424..52b071ce 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -22,7 +22,7 @@ const SET_STATIC_PAGES = SET_STATIC_PAGES; */ // })('csrftoken'); //} - +const DJANGO_API_BASE = process.env.VUE_APP_DJANGO_API_BASE export default new Vuex.Store({ // modules, @@ -35,7 +35,7 @@ export default new Vuex.Store({ projects: [], staticPages: null, SSO_SETTED: false, - USER_LEVEL_PROJECTS: "Administrateur projet" + USER_LEVEL_PROJECTS: null }, mutations: { @@ -75,7 +75,7 @@ export default new Vuex.Store({ return new Date(dateArr[0], dateArr[1] - 1, dateArr[2]) } await axios - .get("http://localhost:8000/api/projects/") + .get(`${DJANGO_API_BASE}projects/`) .then((response) => { const orderedProjects = response.data.sort((a, b) => parseDate(b.created_on) - parseDate(a.created_on)); commit("SET_PROJECTS", orderedProjects) @@ -86,7 +86,7 @@ export default new Vuex.Store({ }, async GET_STATIC_PAGES({ commit }) { await axios - .get("http://localhost:8000/api/aide/") + .get(`${DJANGO_API_BASE}aide/`) .then((response) => (commit("SET_STATIC_PAGES", response.data))) .catch((error) => { throw error; @@ -95,12 +95,13 @@ export default new Vuex.Store({ LOGIN({ commit, dispatch }, payload) { if (payload.username && payload.password) { axios - .post("http://localhost:8000/api/login/", { + .post(`${DJANGO_API_BASE}login/`, { username: payload.username, password: payload.password, }) .then((response) => { - commit("SET_USER", response.data.user), router.push("/"); // todo: get back to last page + const routerHistory = router.options.routerHistory // * use store previous route to go back after login + commit("SET_USER", response.data.user), router.push(routerHistory[routerHistory.length - 1] || "/"); // todo: get back to original page dispatch("GET_USER_LEVEL_PROJECTS"); }) .catch((error) => { @@ -110,17 +111,23 @@ export default new Vuex.Store({ } }, + LOGOUT({ commit }) { + commit("SET_USER", false) // ? better false or null + commit("SET_USER_LEVEL_PROJECTS", null) + }, + GET_USER_LEVEL_PROJECTS({ commit }) { - axios - .get(`http://localhost:8000/api/user_level_project/`) - .then((response) => (commit("SET_USER_LEVEL_PROJECTS", response))) + commit("SET_USER_LEVEL_PROJECTS", "Administrateur projet") // todo : use authentification) + /* axios + .get(`${DJANGO_API_BASE}user_level_project/`) + .then((response) => (commit("SET_USER_LEVEL_PROJECTS", response.data))) .catch((error) => { throw error; - }); + }); */ }, GET_PROJECT({ commit }, project_slug) { axios - .get(`http://localhost:8000/api/projet/${project_slug}/project`) + .get(`${DJANGO_API_BASE}projet/${project_slug}/project`) .then((response) => commit("SET_PROJECT", response.data)) .catch((error) => { throw error; @@ -128,7 +135,7 @@ export default new Vuex.Store({ }, GET_PROJECT_USER({ commit }, project_slug) { axios - .get(`http://localhost:8000/api/projet/${project_slug}/utilisateurs`) + .get(`${DJANGO_API_BASE}projet/${project_slug}/utilisateurs`) .then((response) => (commit("SET_PROJECT_MEMBERS", response.data.members))) .catch((error) => { throw error; diff --git a/src/views/Index.vue b/src/views/Index.vue index 52b88c43..624f034d 100644 --- a/src/views/Index.vue +++ b/src/views/Index.vue @@ -20,9 +20,10 @@ <i class="plus icon"></i> Créer un nouveau projet </router-link> <!-- //todo : get base url and add the rest --> - <a class="ui blue basic button right floated" href="#"> + <router-link to="Project_type_list" class="ui blue basic button right floated"> + <!-- <a class="ui blue basic button right floated" href="#"> --> <i class="copy icon"></i> Accéder à la liste des modèles de projets - </a> + </router-link> <!-- {% endif %} --> <div v-if="projects" class="ui divided items"> <div v-for="project in projects" class="item" :key="project.slug"> diff --git a/src/views/My_account.vue b/src/views/My_account.vue new file mode 100644 index 00000000..59e1d51b --- /dev/null +++ b/src/views/My_account.vue @@ -0,0 +1,263 @@ +<template> + <div v-frag> + <div class="fourteen wide column"> + <h1>Mon compte</h1> + </div> + + <div class="row"> + <div class="five wide column"> + <h4 class="ui horizontal divider header">PROFIL</h4> + <div class="ui divided list"> + <div class="item"> + <div class="right floated content"> + <div class="description"> + <span v-if="user.username">{{ user.username }} </span> + </div> + </div> + <div class="content">Nom d'utilisateur</div> + </div> + <div class="item"> + <div class="right floated content"> + <div class="description"> + {% if user.get_full_name %}{{ user.get_full_name }}{% endif %} + </div> + </div> + <div class="content">Nom complet</div> + </div> + <div class="item"> + <div class="right floated content"> + <div class="description"> + {% if user.email %}{{ user.email }}{% endif %} + </div> + </div> + <div class="content">Adresse e-mail</div> + </div> + <div class="item"> + <div class="right floated content"> + <div class="description"> + {% if user.is_superuser %}Oui{% else %}Non{% endif %} + </div> + </div> + <div class="content">Administrateur</div> + </div> + </div> + </div> + + <div class="nine wide column"> + <h4 class="ui horizontal divider header">MES PROJETS</h4> + + <div class="ui divided items"> + {% for project in projects %} {% if permissions|lookup:project.slug %} + <div v-for="project in projects" :key="project.slug" class="item"> + <div class="ui tiny image"> + {% if project.thumbnail %} + <img + class="ui small image" + :src=" + project.thumbnail.includes('default') + ? require('@/assets/img/default.png') + : project.thumbnail + " + height="200" + /> + {% endif %} + </div> + <div class="middle aligned content"> + <a class="header" href="'geocontrib:project' slug=project.slug"> + {{ project.title }} + </a> + <div class="description"> + <p>{{ project.description }}</p> + </div> + <div class="meta"> + <span class="right floated" + >{% if project.moderation%}Projet modéré {% else %} Projet non + modéré {% endif %}</span + > + <span + >Niveau d'autorisation requis : + {{ project.access_level_pub_feature }}</span + ><br /> + <span> + Mon niveau d'autorisation : + {{ USER_LEVEL_PROJECTS }} + <!-- |lookup:project.slug --> + {% if user.is_administrator == True %} + Gestionnaire métier{% + endif %} + </span> + </div> + <div class="meta"> + <span + class="right floated" + :data-tooltip="`Projet créé le ${project.created_on}`" + > + <i class="calendar icon"></i> {{ project.created_on }} + </span> + <span data-tooltip="Membres"> + {{ project.nb_contributors }} <i class="user icon"></i> + </span> + <span data-tooltip="Signalements"> + {{ project.nb_published_features }} <i + class="map marker icon" + ></i> + </span> + <span data-tooltip="Commentaires"> + {{ project.nb_published_features_comments }} <i + class="comment icon" + ></i> + </span> + </div> + </div> + </div> + {% endif %} {% endfor %} + </div> + </div> + </div> + + <div class="row"> + <div class="fourteen wide column"> + <div class="ui three stackable cards"> + <div class="red card"> + <div class="content"> + <div class="center aligned header"> + Mes dernières notifications reçues + </div> + <div class="center aligned description"> + <div class="ui relaxed list"> + <div v-for="item in events" :key="item.id" class="item"> + <div class="content"> + <div> + {% if item.event_type == 'create' %} {% if + item.object_type == 'feature' %} + <a :href="item.related_feature.feature_url"> + Signalement créé + </a> + {% elif item.object_type == 'comment' %} + <a :href="item.related_feature.feature_url"> + Commentaire créé + </a> + {% elif item.object_type == 'attachment' %} + <a :href="item.related_feature.feature_url"> + Pièce jointe ajoutée + </a> + {% elif item.object_type == 'project' %} + <a :href="item.project_url"> Projet créé </a> + {% endif %} {% elif item.event_type == 'update' %} {% if + item.object_type == 'feature' %} + <a :href="item.related_feature.project_url"> + Signalement mis à jour + </a> + {% elif item.object_type == 'project' %} + <a :href="item.project_url"> Projet mis à jour </a> + {% endif %} {% elif item.event_type == 'delete' %} {% if + item.object_type == 'feature' %} Signalement supprimé + ({{ item.data.feature_title }}) {% endif %} {% else %} + <i>Événement inconnu</i> + {% endif %} + </div> + <div class="description"> + <i + >[ {{ item.created_on }}{% if user.is_authenticated + %}, par {{ item.display_user }}{% endif %} ]</i + > + </div> + </div> + </div> + {% empty %} + <i>Aucune notification pour le moment.</i> + {% endfor %} + </div> + </div> + </div> + </div> + <div class="orange card"> + <div class="content"> + <div class="center aligned header">Mes derniers signalements</div> + <div class="center aligned description"> + <div class="ui relaxed list"> + <div v-for="item in features" :key="item.id" class="item"> + <div class="content"> + <div> + {% if item.related_feature %} + <a :href="item.related_feature.feature_url">{{ + item.related_feature.title + }}</a> + {% else %} + {{ item.data.feature_title }} (supprimé) {% endif %} + </div> + <div class="description"> + <i + >[ {{ item.created_on }}{% if user.is_authenticated + %}, par {{ item.display_user }}{% endif %} ]</i + > + </div> + </div> + </div> + {% empty %} + <i>Aucun signalement pour le moment.</i> + {% endfor %} + </div> + </div> + </div> + </div> + <div class="yellow card"> + <div class="content"> + <div class="center aligned header">Mes derniers commentaires</div> + <div class="center aligned description"> + <div class="ui relaxed list"> + <div v-for="item in comments" :key="item.id" class="item"> + <div class="content"> + <div> + <a :href="item.related_feature.feature_url" + >"{{ item.related_comment.comment }}"</a + > + </div> + <div class="description"> + <i + >[ {{ item.created_on }}{% if user.is_authenticated + %}, par {{ item.display_user }}{% endif %} ]</i + > + </div> + </div> + </div> + {% empty %} + <i>Aucun commentaire pour le moment.</i> + {% endfor %} + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> +</template> + +<script> +import frag from "vue-frag"; +import { mapState } from "vuex"; + +export default { + name: "My_account", + + directives: { + frag, + }, + + data() { + return { + events: [], + features: [], + comments: [], + }; + }, + + computed: { + // todo : filter projects to user + ...mapState(["user", "projects", "USER_LEVEL_PROJECTS"]), + }, + mounted() { + console.log(this.$router.history) + }, +}; +</script> \ No newline at end of file diff --git a/src/views/project/Project_create.vue b/src/views/project/Project_create.vue index 3038a1d6..7e59ef7c 100644 --- a/src/views/project/Project_create.vue +++ b/src/views/project/Project_create.vue @@ -73,9 +73,11 @@ <label :for="form.description.id_for_label">{{ form.description.label }}</label> - <textarea :name="form.description.html_name" rows="5"> -{% if form.description.value %} form.description.value {% endif %}</textarea - > + <textarea + v-model="form.description.value" + :name="form.description.html_name" + rows="5" + ></textarea> {{ form.description.errors }} </div> @@ -134,7 +136,8 @@ <div class="item" :data-value=" - x + (form.access_level_pub_feature.value === x ? selected : '') + x + + (form.access_level_pub_feature.value === x ? selected : '') " > y @@ -272,7 +275,7 @@ export default { }, }, errors: null, - x: null + x: null, }; }, }; diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue index d39f5ee1..9bcdbc0d 100644 --- a/src/views/project/Project_detail.vue +++ b/src/views/project/Project_detail.vue @@ -2,7 +2,7 @@ <div v-frag v-if="project"> <div class="row"> <div class="four wide middle aligned column"> - <img class="ui small spaced image" :src="project.thumbnail" /> + <img class="ui small spaced image" :src="project.thumbnail.includes('default') ? require('@/assets/img/default.png') : project.thumbnail" /> <div class="ui hidden divider"></div> <div class="ui basic teal label" data-tooltip="Membres"> <i class="user icon"></i>{{ project.nb_contributors }} diff --git a/src/views/project/Project_type_list.vue b/src/views/project/Project_type_list.vue new file mode 100644 index 00000000..c85d4038 --- /dev/null +++ b/src/views/project/Project_type_list.vue @@ -0,0 +1,69 @@ +<template> + <div class="row"> + <div class="seven wide column"> + <h3 class="ui header"> + Créer un projet à partir d'un modèle disponible: + </h3> + <div class="ui divided items"> + <div v-for="project in projects" :key="project.slug" class="item"> + <div class="ui tiny image"> + <img :src="project.thumbnail" /> + </div> + <div class="middle aligned content"> + <div class="description"> + <a + :href="`project_create?create_from=${project.slug}`" + >{{ project.title }}</a + > + <p>{{ project.description }}</p> + <strong v-if="project.moderation">Projet modéré</strong> + <strong v-else>Projet non modéré</strong> + </div> + <div class="meta"> + <span data-tooltip="Délai avant archivage"> + {{ project.archive_feature }} <i class="box icon"></i> + </span> + <span data-tooltip="Délai avant suppression"> + {{ project.archive_feature }} <i + class="trash alternate icon" + ></i> + </span> + <span data-tooltip="Date de création"> + {{ project.created_on }} <i class="calendar icon"></i> + </span> + </div> + <div class="meta"> + <span data-tooltip="Visibilité des signalement publiés"> + {{ project.access_level_pub_feature }} <i + class="eye icon" + ></i> + </span> + <span data-tooltip="Visibilité des signalement archivés"> + {{ project.access_level_arch_feature }} <i + class="archive icon" + ></i> + </span> + </div> + </div> + </div> + <span v-if="!projects || projects.length === 0">Aucun projet type n'est défini.</span> + </div> + </div> + </div> +</template> + +<script> +import { mapState } from "vuex" +// todo : récupérer les projets type +export default { + name: "Project_type_list", + /* data() { + return { + projects: [] + } + }, */ + computed: { + ...mapState(["projects"]) + } +} +</script> \ No newline at end of file -- GitLab