<template> <div data-tab="list" class="dataTables_wrapper no-footer" > <table id="table-features" class="ui compact table" > <thead> <tr> <th class="center" /> <th class="center"> Statut <i :class="{ down: isSortedAsc('status'), up: isSortedDesc('status'), }" class="icon sort" @click="changeSort('status')" /> </th> <th class="center"> Type <i :class="{ down: isSortedAsc('feature_type'), up: isSortedDesc('feature_type'), }" class="icon sort" @click="changeSort('feature_type')" /> </th> <th class="center"> Nom <i :class="{ down: isSortedAsc('title'), up: isSortedDesc('title'), }" class="icon sort" @click="changeSort('title')" /> </th> <th class="center"> Dernière modification <i :class="{ down: isSortedAsc('updated_on'), up: isSortedDesc('updated_on'), }" class="icon sort" @click="changeSort('updated_on')" /> </th> <th v-if="user" class="center" > Auteur <i :class="{ down: isSortedAsc('display_creator'), up: isSortedDesc('display_creator'), }" class="icon sort" @click="changeSort('display_creator')" /> </th> <th v-if="user" class="center" > Dernier éditeur <i :class="{ down: isSortedAsc('display_last_editor'), up: isSortedDesc('display_last_editor'), }" class="icon sort" @click="changeSort('display_last_editor')" /> </th> </tr> </thead> <tbody> <tr v-for="(feature, index) in paginatedFeatures" :key="index" > <td class="center"> <div class="ui checkbox" :class=" feature.properties.creator.username !== user.username && !user.is_superuser && !isUserProjectAdministrator ? 'disabled' : '' " > <input :id="feature.id" v-model="checked" type="checkbox" :value="feature.id" :disabled=" feature.properties.creator.username !== user.username && !user.is_superuser && !isUserProjectAdministrator " > <label /> </div> </td> <td class="center"> <div v-if="feature.properties.status.value === 'archived'" data-tooltip="Archivé" > <i class="grey archive icon" /> </div> <div v-else-if="feature.properties.status.value === 'pending'" data-tooltip="En attente de publication" > <i class="teal hourglass outline icon" /> </div> <div v-else-if="feature.properties.status.value === 'published'" data-tooltip="Publié" > <i class="olive check icon" /> </div> <div v-else-if="feature.properties.status.value === 'draft'" data-tooltip="Brouillon" > <i class="orange pencil alternate icon" /> </div> </td> <td class="center"> <router-link :to="{ name: 'details-type-signalement', params: { feature_type_slug: feature.properties.feature_type.slug, }, }" > {{ feature.properties.feature_type.title }} </router-link> </td> <td class="center"> <router-link :to="{ name: 'details-signalement', params: { slug_type_signal: feature.properties.feature_type.slug, slug_signal: feature.properties.slug || feature.id, }, }" > {{ getFeatureDisplayName(feature) }} </router-link> </td> <td class="center"> {{ feature.properties.updated_on }} </td> <td v-if="user" class="center" > {{ getUserName(feature) }} </td> <td v-if="user" class="center" > {{ feature.properties.display_last_editor }} </td> </tr> <tr v-if="featuresCount === 0" class="odd" > <td colspan="5" class="dataTables_empty" valign="top" > Aucune donnée disponible </td> </tr> </tbody> </table> <div v-if="pageNumbers.length > 1" id="table-features_info" class="dataTables_info" role="status" aria-live="polite" > Affichage de l'élément {{ pagination.start + 1 }} à {{ displayedPageEnd }} sur {{ featuresCount }} éléments </div> <div v-if="pageNumbers.length > 1" id="table-features_paginate" class="dataTables_paginate paging_simple_numbers" > <a id="table-features_previous" :class="[ 'paginate_button previous', { disabled: pagination.currentPage === 1 }, ]" aria-controls="table-features" data-dt-idx="0" tabindex="0" @click="$emit('update:page', 'previous')" >Précédent</a> <span> <span v-if="pagination.currentPage >= 5"> <a key="page1" class="paginate_button" aria-controls="table-features" data-dt-idx="1" tabindex="0" @click="$emit('update:page', 1)" >{{ 1 }}</a> <span class="ellipsis">…</span> </span> <a v-for="pageNumber in displayedPageNumbers" :key="'page' + pageNumber" :class="[ 'paginate_button', { current: pageNumber === pagination.currentPage }, ]" aria-controls="table-features" data-dt-idx="1" tabindex="0" @click="$emit('update:page', pageNumber)" >{{ pageNumber }}</a> <span v-if="(lastPageNumber - pagination.currentPage) >= 4"> <span class="ellipsis">…</span> <a :key="'page' + lastPageNumber" class="paginate_button" aria-controls="table-features" data-dt-idx="1" tabindex="0" @click="$emit('update:page', lastPageNumber)" >{{ lastPageNumber }}</a> </span> </span> <a id="table-features_next" :class="[ 'paginate_button next', { disabled: pagination.currentPage === pageNumbers.length }, ]" aria-controls="table-features" data-dt-idx="7" tabindex="0" @click="$emit('update:page', 'next')" >Suivant</a> </div> </div> </template> <script> /* eslint-disable */ import { mapState, mapGetters } from 'vuex'; export default { name: 'FeatureListTable', props: { paginatedFeatures: { type: Array, default: null, }, checkedFeatures: { type: Array, default: null, }, featuresCount: { type: Number, default: 0, }, pagination: { type: Object, default: null, }, sort: { type: Object, default: null, }, }, computed: { ...mapState(['user']), ...mapGetters(['project', 'permissions']), isUserProjectAdministrator() { return this.permissions.is_project_administrator; }, checked: { get() { return this.checkedFeatures; }, set(newChecked) { this.$store.commit('feature/UPDATE_CHECKED_FEATURES', newChecked); }, }, displayedPageEnd() { return this.featuresCount <= this.pagination.end ? this.featuresCount : this.pagination.end; }, pageNumbers() { const totalPages = Math.ceil( this.featuresCount / this.pagination.pagesize ); return [...Array(totalPages).keys()].map((pageNumb) => { ++pageNumb; return pageNumb; }); }, lastPageNumber() { return this.pageNumbers.slice(-1)[0]; }, displayedPageNumbers() { //* si la page courante est inférieur à 5, la liste commence à l'index 0 et on retourne 5 pages let firstPageInList = 0; let pagesQuantity = 5; //* à partir de la 5ième page et jusqu'à la 4ième page avant la fin : n'afficher que 3 page entre les ellipses et la page courante doit être au milieu if (this.pagination.currentPage >= 5 && !(this.lastPageNumber - this.pagination.currentPage < 4)) { firstPageInList = this.pagination.currentPage - 2; pagesQuantity = 3; } //* a partir de 4 résultat avant la fin afficher seulement les 5 derniers résultats if (this.lastPageNumber - this.pagination.currentPage < 4) { firstPageInList = this.lastPageNumber - 5; } return this.pageNumbers.slice(firstPageInList, firstPageInList + pagesQuantity); }, }, methods: { getUserName(feature) { if (!feature.properties.creator) { return ' ---- '; } return feature.properties.creator.username || ' ---- '; }, getFeatureDisplayName(feature) { return feature.properties.title || feature.id; }, isSortedAsc(column) { return this.sort.column === column && this.sort.ascending; }, isSortedDesc(column) { return this.sort.column === column && !this.sort.ascending; }, changeSort(column) { if (this.sort.column === column) { //changer order this.$emit('update:sort', { column: this.sort.column, ascending: !this.sort.ascending, }); } else { this.sort.column = column; this.sort.ascending = true; this.$emit('update:sort', { column, ascending: true }); } }, }, }; </script> <style scoped> /* datatables */ .dataTables_wrapper { position: relative; clear: both; } .dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { color: #333; } .dataTables_wrapper .dataTables_info { clear: both; float: left; padding-top: 0.755em; } .dataTables_wrapper .dataTables_paginate { float: right; text-align: right; padding-top: 0.25em; } .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { color: #333 !important; border: 1px solid #979797; background-color: white; background: -webkit-gradient( linear, left top, left bottom, color-stop(0%, #fff), color-stop(100%, #dcdcdc) ); background: -webkit-linear-gradient(top, #fff 0%, #dcdcdc 100%); background: -moz-linear-gradient(top, #fff 0%, #dcdcdc 100%); background: -ms-linear-gradient(top, #fff 0%, #dcdcdc 100%); background: -o-linear-gradient(top, #fff 0%, #dcdcdc 100%); background: linear-gradient(to bottom, #fff 0%, #dcdcdc 100%); } .dataTables_wrapper .dataTables_paginate .paginate_button { box-sizing: border-box; display: inline-block; min-width: 1.5em; padding: 0.5em 1em; margin-left: 2px; text-align: center; text-decoration: none !important; cursor: pointer; color: #333 !important; border: 1px solid transparent; border-radius: 2px; } .dataTables_wrapper .dataTables_paginate .paginate_button:hover { color: white !important; border: 1px solid #111; background-color: #585858; background: -webkit-gradient( linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111) ); background: -webkit-linear-gradient(top, #585858 0%, #111 100%); background: -moz-linear-gradient(top, #585858 0%, #111 100%); background: -ms-linear-gradient(top, #585858 0%, #111 100%); background: -o-linear-gradient(top, #585858 0%, #111 100%); background: linear-gradient(to bottom, #585858 0%, #111 100%); } .dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active { cursor: default; color: #666 !important; border: 1px solid transparent; background: transparent; box-shadow: none; } .dataTables_wrapper .dataTables_paginate .ellipsis { padding: 0 1em; } i.icon.sort:not(.down):not(.up) { color: rgb(220, 220, 220); } /* Max width before this PARTICULAR table gets nasty This query will take effect for any screen smaller than 760px and also iPads specifically. */ @media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px) { /* Force table to not be like tables anymore */ table, thead, tbody, th, td, tr { display: block; } /* Hide table headers (but not display: none;, for accessibility) */ thead tr { position: absolute; top: -9999px; left: -9999px; } tr { border: 1px solid #ccc; } td { /* Behave like a "row" */ border: none; border-bottom: 1px solid #eee; position: relative; padding-left: 50%; } td:before { /* Now like a table header */ position: absolute; /* Top/left values mimic padding */ /* top: 6px; */ left: 6px; /* width: 45%; */ padding-right: 10px; white-space: nowrap; } /* Label the data */ td:nth-of-type(1):before { content: ""; } td:nth-of-type(2):before { content: "Statut"; } td:nth-of-type(3):before { content: "Type"; } td:nth-of-type(4):before { content: "Nom"; } td:nth-of-type(5):before { content: "Dernière modification"; } td:nth-of-type(6):before { content: "Auteur"; } .center { text-align: right !important; } #table-features { margin-left: 1em; width: calc(100% - 1em); } .ui.checkbox { position: absolute; left: -1.75em; top: 5em; } } </style>