<template> <div> <h4 class="ui horizontal divider header"> MES PROJETS </h4> <div class="ui divided items"> <div :class="['ui inverted dimmer', { active: projectsLoading }]" > <div class="ui text loader"> Récupération des projets en cours... </div> </div> <div v-for="project in projectsArray" :key="project.slug" class="item" > <div v-if="user_permissions[project.slug].can_view_project" class="item-content-wrapper" > <div class="ui tiny image"> <img v-if="project.thumbnail" class="ui small image" alt="Thumbnail projet" :src=" project.thumbnail.includes('default') ? require('@/assets/img/default.png') : DJANGO_BASE_URL + project.thumbnail + refreshId() " height="200" > </div> <div class="middle aligned content"> <router-link :to="{ name: 'project_detail', params: { slug: project.slug }, }" class="header" > {{ project.title }} </router-link> <div class="description"> <p>{{ project.description }}</p> </div> <div class="meta"> <span class="right floated" > Projet {{ project.moderation ? "" : "non" }} modéré </span> <span> Niveau d'autorisation requis : {{ project.access_level_pub_feature }} </span><br> <span> Mon niveau d'autorisation : <span v-if="USER_LEVEL_PROJECTS && project"> {{ USER_LEVEL_PROJECTS[project.slug] }} </span> <span v-if="user && user.is_administrator"> {{ "+ Gestionnaire métier" }} </span> </span> </div> <div class="meta"> <span class="right floated" :data-tooltip="`Projet créé le ${project.created_on}`" > <i class="calendar icon" aria-hidden="true" /> {{ project.created_on }} </span> <span data-tooltip="Membres"> {{ project.nb_contributors }} <i class="user icon" aria-hidden="true" /> </span> <span data-tooltip="Signalements publiés"> {{ project.nb_published_features }} <i class="map marker icon" aria-hidden="true" /> </span> <span data-tooltip="Commentaires"> {{ project.nb_published_features_comments }} <i class="comment icon" aria-hidden="true" /> </span> </div> </div> </div> </div> <!-- PAGINATION --> <Pagination v-if="count" :nb-pages="Math.ceil(count/10)" :on-page-change="SET_CURRENT_PAGE" @change-page="changePage" /> </div> </div> </template> <script> import { mapState, mapMutations, mapActions } from 'vuex'; import Pagination from '@/components/Pagination.vue'; export default { name: 'UserProjectList', components: { Pagination, }, data() { return { projectsLoading: true, }; }, computed: { ...mapState([ 'user', 'USER_LEVEL_PROJECTS', 'user_permissions', ]), // todo : filter projects to user ...mapState('projects', [ 'projects', 'count', ]), DJANGO_BASE_URL() { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, isSharedProject() { return this.$route.path.includes('projet-partage'); }, availableProjects() { if (this.isSharedProject) { return this.projects.filter((el) => el.slug === this.$route.params.slug); } return this.projects; }, projectsArray() { //* if only one project, only project object is returned return Array.isArray(this.projects) ? this.projects : [this.projects]; } }, created(){ this.SET_PROJECTS([]); //* empty previous project to avoid undefined user_permissions[project.slug] this.getData(); }, methods: { ...mapMutations('projects', [ 'SET_CURRENT_PAGE', 'SET_PROJECTS', ]), ...mapActions('projects', [ 'GET_PROJECTS', ]), refreshId() { const crypto = window.crypto || window.msCrypto; var array = new Uint32Array(1); return '?ver=' + crypto.getRandomValues(array); // Compliant for security-sensitive use cases }, getData(page) { this.loading = true; this.GET_PROJECTS({ ismyaccount: true, projectSlug: this.$route.params.slug, page }) .then(() => this.projectsLoading = false) .catch(() => this.projectsLoading = false); }, changePage(e) { this.getData(e); }, } }; </script> <style lang="less" scoped> .ui.divided.items { .item { .item-content-wrapper { width: 100%; margin: 0; padding: 1em 0; display: flex; .middle.aligned.content { .header { font-size: 1.28571429em; font-weight: 600; color: rgb(31, 31, 31) } } } } > .item:nth-child(2) { border: none !important; } } @media only screen and (min-width: 767px) { .item-content-wrapper { align-items: flex-start; .middle.aligned.content { width: 100%; padding: 0 0 0 1.5em; } } } @media only screen and (max-width: 767px) { .item-content-wrapper { flex-direction: column; align-items: center; .middle.aligned.content { width: 70%; padding: 1.5em 0 0; } } } </style>