Newer
Older
Sébastien DA ROCHA
committed
<template>

Timothee P
committed
<div id="feature-detail">
<div class="row">

Timothee P
committed
:features-count="featuresCount"
:slug-signal="slugSignal"
:feature-type="featureType"

Timothee P
committed
:display-to-list-button="displayToListButton"
@setIsCancelling="isCanceling = true"

Timothee P
committed
@tofeature="pushNgo"
</div>
Sébastien DA ROCHA
committed
</div>
<div class="row">

Timothee P
committed
:feature-type="featureType"
@tofeature="pushNgo"
</div>
</div>
Sébastien DA ROCHA
committed
</div>
<div class="row">
<div class="eight wide column">
<FeatureAttachements
:attachments="attachments"
/>
Sébastien DA ROCHA
committed
</div>
<div class="eight wide column">
<FeatureComments
:events="events"
@fetchEvents="getFeatureEvents"
Sébastien DA ROCHA
committed
</div>
</div>
<div
v-if="isCanceling"

Timothee P
committed
class="ui dimmer modals visible active"
Sébastien DA ROCHA
committed
>
<div
:class="[
'ui mini modal subscription',
{ 'active visible': isCanceling },
]"
>
<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"
Sébastien DA ROCHA
committed
>
</div>
Sébastien DA ROCHA
committed
</div>
</div>
</div>
Pas de signalement correspondant trouvé
</div>
Sébastien DA ROCHA
committed
</div>
</template>
<script>
import { mapState, mapActions, mapMutations } from 'vuex';
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';
Sébastien DA ROCHA
committed
export default {
Sébastien DA ROCHA
committed
components: {
FeatureHeader,
FeatureTable,
FeatureAttachements,
FeatureComments

Timothee P
committed
beforeRouteEnter (to, from, next) {
// if the user edited the feature, coming from filtered features details browsing,
// display a button to turn back to the list view, in order to start again from the list
// because order changes after edition, depending the sort criteria
// in beforeRouteEnter, the component is not mounted and this doesn't exist yet, thus we store the value in window object
window.displayToListButton = false; // reinitialisation of the value
if (from.query.offset !== undefined) { // if a queryset for filtered features is stored in the route from
window.displayToListButton = true; // toggle the value to display the button
}
next(); // continue page loading
},
beforeRouteLeave (to, from, next) {
if (// In case of filtered listed featuers, if the user wants to edit a feature,
from.query.offset >= 0 &&
to.name === 'editer-signalement' &&
!this.confirmLeave() // warn the user that features order might change
){
next(false);
} else {// Navigate to next view
next();
}
},
Sébastien DA ROCHA
committed
data() {
return {
Sébastien DA ROCHA
committed
comment_form: {
attachment_file: {
errors: null,
Sébastien DA ROCHA
committed
},
comment: {
id_for_label: 'add-comment',
html_name: 'add-comment',
errors: '',
Sébastien DA ROCHA
committed
value: null,
},
},
events: [],

Timothee P
committed
featureType: {},
featuresCount: null,
isCanceling: false,

Timothee P
committed
slugSignal: '',

Timothee P
committed
displayToListButton: false,
Sébastien DA ROCHA
committed
};
},
computed: {
Sébastien DA ROCHA
committed
},
watch: {
'$route.query'(newValue, oldValue) {
if (newValue !== oldValue) { //* Navigate back or forward to the previous or next URL
this.initPage(); //* doesn't update the page at query changes, thus it is done manually here
}
},
},

Timothee P
committed
if (this.$route.params.slug_type_signal) {
this.SET_CURRENT_FEATURE_TYPE_SLUG(this.$route.params.slug_type_signal);
}

Timothee P
committed
this.initPage();

Timothee P
committed
// when this is available, set the value with previously stored value in windows to pass it as a prop
this.displayToListButton = window.displayToListButton;
},
beforeDestroy() {
this.$store.commit('CLEAR_MESSAGES');
Sébastien DA ROCHA
committed
methods: {
...mapMutations([
'DISPLAY_LOADER',
'DISCARD_LOADER'
]),

Timothee P
committed
...mapMutations('feature', [
'SET_CURRENT_FEATURE'
]),
...mapMutations('feature-type', [
'SET_CURRENT_FEATURE_TYPE_SLUG'
]),
...mapActions('projects', [
'GET_PROJECT',
'GET_PROJECT_INFO'
]),

Timothee P
committed

Timothee P
committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
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();

Timothee P
committed
this.DISCARD_LOADER();
},

Timothee P
committed
confirmLeave() {
return window.confirm('Vous allez quittez la vue signalement filtré, l\'ordre des signalements pourrait changer après édition d\'un signalement.');
},

Timothee P
committed
async pushNgo(newEntry) {
this.$router.push(newEntry); //* update the params or queries in the route/url
await this.getPageInfo();
mapService.removeFeatures();
this.addFeatureToMap();
},
slug: this.$route.params.slug,
Sébastien DA ROCHA
committed
deleteFeature() {
this.$store
.dispatch('feature/DELETE_FEATURE', { feature_id: this.currentFeature.feature_id })
if (response.status === 204) {
this.goBackToProject();
}
});
Sébastien DA ROCHA
committed
},

Timothee P
committed
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;
});
},
Sébastien DA ROCHA
committed
initMap() {
var mapDefaultViewCenter =
this.$store.state.configuration.DEFAULT_MAP_VIEW.center;
var mapDefaultViewZoom =
this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom;
Sébastien DA ROCHA
committed
mapDefaultViewCenter,
mapDefaultViewZoom,
interactions : {
doubleClickZoom :false,
mouseWheelZoom: false,
dragPan: false
}
Sébastien DA ROCHA
committed
});
// Update link to feature list with map zoom and center
mapService.addMapEventListener('moveend', function () {
Sébastien DA ROCHA
committed
// 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;

Timothee P
committed
var layers = this.$store.state.map.availableLayers;
Sébastien DA ROCHA
committed
if (baseMaps && baseMaps.length > 0) {
Sébastien DA ROCHA
committed
layersToLoad = baseMaps[basemapIndex].layers;
layersToLoad.forEach((layerToLoad) => {
layers.forEach((layer) => {
if (layer.id === layerToLoad.id) {
layerToLoad = Object.assign(layerToLoad, layer);
}
});
});
layersToLoad.reverse();
}
Sébastien DA ROCHA
committed
layersToLoad,
this.$store.state.configuration.DEFAULT_BASE_MAP_SERVICE,

Timothee P
committed
this.$store.state.configuration.DEFAULT_BASE_MAP_OPTIONS,
this.$store.state.configuration.DEFAULT_BASE_MAP_SCHEMA_TYPE,
Sébastien DA ROCHA
committed
);
this.addFeatureToMap();
},
addFeatureToMap() {
const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/` +

Timothee P
committed
`?feature_id=${this.slugSignal}&output=geojson`;
axios
.get(url)
Sébastien DA ROCHA
committed
.then((response) => {
if (response.data.features.length > 0) {
response.data.features,
mapService.fitExtent(buffer(featureGroup.getExtent(),200));
Sébastien DA ROCHA
committed
}
})
.catch((error) => {
throw error;
});
getFeatureEvents() {
featureAPI

Timothee P
committed
.getFeatureEvents(this.slugSignal)
.then((data) => (this.events = data));
},
getFeatureAttachments() {
featureAPI

Timothee P
committed
.getFeatureAttachments(this.slugSignal)
.then((data) => (this.attachments = data));
},
getLinkedFeatures() {
featureAPI

Timothee P
committed
.getFeatureLinks(this.slugSignal)
this.$store.commit('feature/SET_LINKED_FEATURES', data)
Sébastien DA ROCHA
committed
},
};
</script>
Sébastien DA ROCHA
committed
#map {
width: 100%;
height: 100%;
min-height: 250px;
max-height: 70vh;
}

Timothee P
committed
.prewrap {
white-space: pre-wrap;
}