<template> <div id="feature-detail"> <div v-if="currentFeature" class="ui grid stackable" > <div class="row"> <div class="sixteen wide column"> <FeatureHeader :features-count="featuresCount" :slug-signal="slugSignal" :feature-type="featureType" @setIsCancelling="isCanceling = true" @tofeature="pushNgo" /> </div> </div> <div class="row"> <div class="eight wide column"> <FeatureTable :feature-type="featureType" @tofeature="pushNgo" /> </div> <div class="eight wide column"> <div id="map" ref="map" /> <div id="popup" class="ol-popup" > <a id="popup-closer" href="#" class="ol-popup-closer" /> <div id="popup-content" /> </div> </div> </div> <div class="row"> <div class="eight wide column"> <FeatureAttachements :attachments="attachments" /> </div> <div class="eight wide column"> <FeatureComments :events="events" @fetchEvents="getFeatureEvents" /> </div> </div> <div v-if="isCanceling" class="ui dimmer modals visible active" > <div :class="[ 'ui mini modal subscription', { 'active visible': isCanceling }, ]" > <i class="close icon" aria-hidden="true" @click="isCanceling = false" /> <div class="ui icon header"> <i class="trash alternate icon" aria-hidden="true" /> Supprimer le signalement </div> <div class="actions"> <button type="button" class="ui red compact fluid button" @click="deleteFeature" > Confirmer la suppression </button> </div> </div> </div> </div> <div v-else> Pas de signalement correspondant trouvé </div> </div> </template> <script> import { mapState, mapActions, mapMutations } from 'vuex'; import mapService from '@/services/map-service'; import axios from '@/axios-client.js'; import featureAPI from '@/services/feature-api'; import FeatureHeader from '@/components/Feature/Detail/FeatureHeader'; import FeatureTable from '@/components/Feature/Detail/FeatureTable'; import FeatureAttachements from '@/components/Feature/Detail/FeatureAttachements'; import FeatureComments from '@/components/Feature/Detail/FeatureComments'; import { buffer } from 'ol/extent'; export default { name: 'FeatureDetail', components: { FeatureHeader, FeatureTable, FeatureAttachements, FeatureComments }, data() { return { attachments: [], comment_form: { attachment_file: { errors: null, title: '', file: null, }, comment: { id_for_label: 'add-comment', html_name: 'add-comment', errors: '', value: null, }, }, events: [], featureType: {}, featuresCount: null, isCanceling: false, slugSignal: '', }; }, computed: { ...mapState('projects', [ 'project' ]), ...mapState('feature-type', [ 'feature_types' ]), ...mapState('feature', [ 'currentFeature' ]), }, created() { if (this.$route.params.slug_type_signal) { this.SET_CURRENT_FEATURE_TYPE_SLUG(this.$route.params.slug_type_signal); } }, mounted() { this.initPage(); }, beforeDestroy() { this.$store.commit('CLEAR_MESSAGES'); }, methods: { ...mapMutations([ 'DISPLAY_LOADER', 'DISCARD_LOADER' ]), ...mapMutations('feature', [ 'SET_CURRENT_FEATURE' ]), ...mapMutations('feature-type', [ 'SET_CURRENT_FEATURE_TYPE_SLUG' ]), ...mapActions('projects', [ 'GET_PROJECT', 'GET_PROJECT_INFO' ]), ...mapActions('feature', [ 'GET_PROJECT_FEATURE', 'GET_PROJECT_FEATURES' ]), async initPage() { await this.getPageInfo(); this.initMap(); }, async getPageInfo() { if (this.$route.params.slug_signal) { // if coming from the route with an id this.slugSignal = this.$route.params.slug_signal; } //* else it would be retrieve after fetchFilteredFeature with offset this.DISPLAY_LOADER('Recherche du signalement'); let promises = []; //* Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh if (!this.project) { promises.push( this.GET_PROJECT(this.$route.params.slug), this.GET_PROJECT_INFO(this.$route.params.slug), ); } //* changement de requête selon s'il y a un id ou un offset if (this.$route.query.offset >= 0) { promises.push(this.fetchFilteredFeature()); } else if (!this.currentFeature || this.currentFeature.feature_id !== this.slugSignal) { promises.push( this.GET_PROJECT_FEATURE({ project_slug: this.$route.params.slug, feature_id: this.slugSignal, }) ); } await axios.all(promises); this.getFeatureEvents(); this.getFeatureAttachments(); this.getLinkedFeatures(); this.DISCARD_LOADER(); }, async pushNgo(newEntry) { this.$router.push(newEntry); //* update the params or queries in the route/url await this.getPageInfo(); mapService.removeFeatures(); this.addFeatureToMap(); }, goBackToProject(message) { this.$router.push({ name: 'project_detail', params: { slug: this.$route.params.slug, message, }, }); }, deleteFeature() { this.$store .dispatch('feature/DELETE_FEATURE', { feature_id: this.currentFeature.feature_id }) .then(async (response) => { if (response.status === 204) { await this.GET_PROJECT_FEATURES({ project_slug: this.$route.params.slug }); this.goBackToProject(); } }); }, fetchFilteredFeature() { const queryString = new URLSearchParams(this.$route.query); const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature-paginated/?limit=1&${queryString}`; return featureAPI.getPaginatedFeatures(url) .then((data) => { if (data && data.results && data.results[0]) { this.featuresCount = data.count; this.previous = data.previous; this.next = data.next; this.SET_CURRENT_FEATURE(data.results[0]); const { feature_id, feature_type } = data.results[0]; this.slugSignal = feature_id; this.featureType = feature_type; return { feature_id }; } return; }); }, initMap() { var mapDefaultViewCenter = this.$store.state.configuration.DEFAULT_MAP_VIEW.center; var mapDefaultViewZoom = this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom; this.map = mapService.createMap(this.$refs.map, { mapDefaultViewCenter, mapDefaultViewZoom, interactions : { doubleClickZoom :false, mouseWheelZoom: false, dragPan: false } }); // Update link to feature list with map zoom and center mapService.addMapEventListener('moveend', function () { // update link to feature list with map zoom and center /*var $featureListLink = $("#feature-list-link") var baseUrl = $featureListLink.attr("href").split("?")[0] $featureListLink.attr("href", baseUrl +`?zoom=${this.map.getZoom()}&lat=${this.map.getCenter().lat}&lng=${this.map.getCenter().lng}`)*/ }); // Load the layers. // - if one basemap exists, we load the layers of the first one // - if not, load the default map and service options let layersToLoad = null; var baseMaps = this.$store.state.map.basemaps; var layers = this.$store.state.map.availableLayers; if (baseMaps && baseMaps.length > 0) { const basemapIndex = 0; layersToLoad = baseMaps[basemapIndex].layers; layersToLoad.forEach((layerToLoad) => { layers.forEach((layer) => { if (layer.id === layerToLoad.id) { layerToLoad = Object.assign(layerToLoad, layer); } }); }); layersToLoad.reverse(); } mapService.addLayers( layersToLoad, this.$store.state.configuration.DEFAULT_BASE_MAP_SERVICE, this.$store.state.configuration.DEFAULT_BASE_MAP_OPTIONS, this.$store.state.configuration.DEFAULT_BASE_MAP_SCHEMA_TYPE, ); this.addFeatureToMap(); }, addFeatureToMap() { const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/` + `?feature_id=${this.slugSignal}&output=geojson`; axios .get(url) .then((response) => { if (response.data.features.length > 0) { const featureGroup = mapService.addFeatures( response.data.features, {}, this.feature_types, true ); mapService.fitExtent(buffer(featureGroup.getExtent(),200)); } }) .catch((error) => { throw error; }); }, getFeatureEvents() { featureAPI .getFeatureEvents(this.slugSignal) .then((data) => (this.events = data)); }, getFeatureAttachments() { featureAPI .getFeatureAttachments(this.slugSignal) .then((data) => (this.attachments = data)); }, getLinkedFeatures() { featureAPI .getFeatureLinks(this.slugSignal) .then((data) => this.$store.commit('feature/SET_LINKED_FEATURES', data) ); }, }, }; </script> <style scoped> #map { width: 100%; height: 100%; min-height: 250px; max-height: 70vh; } .prewrap { white-space: pre-wrap; } </style>