diff --git a/src/components/feature/FeatureAttachmentForm.vue b/src/components/feature/FeatureAttachmentForm.vue index 7e9ef3a1d2aa912bb6292cd6e6c8c7c82ddec024..89d15280418ab341e4bbd3056ac461e6d4ab7398 100644 --- a/src/components/feature/FeatureAttachmentForm.vue +++ b/src/components/feature/FeatureAttachmentForm.vue @@ -27,7 +27,7 @@ :name="form.title.html_name" :id="form.title.id_for_label" v-model="form.title.value" - @blur="updateStore" + @change="updateStore" /> {{ form.title.errors }} </div> @@ -53,7 +53,7 @@ :name="form.attachment_file.html_name" class="image_file" :id="form.attachment_file.id_for_label" - @blur="updateStore" + @change="updateStore" /> {{ form.attachment_file.errors }} </div> @@ -64,7 +64,7 @@ name="form.info.html_name" rows="5" v-model="form.info.value" - @blur="updateStore" + @change="updateStore" ></textarea> {{ form.info.errors }} </div> @@ -107,7 +107,21 @@ export default { }, }; }, + + watch: { + attachmentForm(newValue) { + this.initForm(newValue); + }, + }, + methods: { + initForm(attachmentForm) { + for (let el in attachmentForm) { + if (el && this.form[el]) { + this.form[el].value = attachmentForm[el]; + } + } + }, remove_attachment_formset() { this.$store.commit( "feature/REMOVE_ATTACHMENT_FORM", @@ -124,5 +138,9 @@ export default { }); }, }, + + mounted() { + this.initForm(this.attachmentForm); + }, }; </script> \ No newline at end of file diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js index 07c33eef2583583f5aa911af5b58dc63bef7d752..10858ac1dab559f3a902f072d89a0e4b6cf367ee 100644 --- a/src/store/modules/feature.js +++ b/src/store/modules/feature.js @@ -27,8 +27,8 @@ const feature = { SET_EXTRA_FORM(state, extra_form) { state.extra_form = extra_form; }, - ADD_ATTACHMENT_FORM(state, dataKey) { - state.attachmentFormset = [...state.attachmentFormset, { dataKey }]; + ADD_ATTACHMENT_FORM(state, attachmentFormset) { + state.attachmentFormset = [...state.attachmentFormset, attachmentFormset]; }, UPDATE_ATTACHMENT_FORM(state, payload) { const index = state.attachmentFormset.findIndex((el) => el.dataKey === payload.dataKey); @@ -37,6 +37,9 @@ const feature = { REMOVE_ATTACHMENT_FORM(state, payload) { state.attachmentFormset = state.attachmentFormset.filter(form => form.dataKey !== payload); }, + CLEAR_ATTACHMENT_FORM(state) { + state.attachmentFormset = []; + }, ADD_LINKED_FORM(state, dataKey) { state.linkedFormset = [...state.linkedFormset, { dataKey }]; }, @@ -64,10 +67,10 @@ const feature = { }); }, - POST_FEATURE({ state, rootState }, routeName) { - let extraFormOject = {}; + SEND_FEATURE({ state, rootState, dispatch }, routeName) { + let extraFormObject = {}; //* prepare an object to be flatten in properties of geojson for (const field of state.extra_form) { - extraFormOject[field.name] = field.value; + extraFormObject[field.name] = field.value; } const geojson = { "id": state.form.feature_id, @@ -79,7 +82,7 @@ const feature = { "status": state.form.status.value, "project": rootState.project_slug, "feature_type": rootState.feature_type.current_feature_type_slug, - ...extraFormOject + ...extraFormObject } } @@ -97,12 +100,26 @@ const feature = { .post(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}features/`, geojson) .then((response) => { console.log(response, response.data) + dispatch("SEND_ATTACHMENTS", response.data.id) }) .catch((error) => { throw error; }); } }, + + SEND_ATTACHMENTS({ state }, featureId) { + for (let attachment of state.attachmentFormset) { + axios + .post(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}features/${featureId}/attachments/`, attachment) + .then((response) => { + console.log(response, response.data) + }) + .catch((error) => { + throw error; + }); + } + } //DELETE_FEATURE({ state }, feature_slug) { //console.log("Deleting feature:", feature_slug, state) diff --git a/src/store/modules/feature_type.js b/src/store/modules/feature_type.js index b1c65d094d405450babbad5a0a782fca292f318f..1f0ced836f3359f7db4a331bba40fe3bc1c202b7 100644 --- a/src/store/modules/feature_type.js +++ b/src/store/modules/feature_type.js @@ -122,7 +122,7 @@ const feature_type = { } }, - POST_FEATURES_FROM_GEOJSON({ state, dispatch }, payload) { + SEND_FEATURES_FROM_GEOJSON({ state, dispatch }, payload) { const { feature_type_slug } = payload if (state.fileToImport.size > 0) { diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue index aa803f96591f2cdddc4758b2485a18985b6652c1..0ef149bec65dde7066ed12658feec198ed81e2d3 100644 --- a/src/views/feature/Feature_edit.vue +++ b/src/views/feature/Feature_edit.vue @@ -65,7 +65,8 @@ <!-- Import GeoImage --> <div v-frag v-if="feature_type && feature_type.geom_type === 'point'"> <p> - <button @click="showGeoRef=true;" + <button + @click="showGeoRef = true" id="add-geo-image" type="button" class="ui compact button" @@ -75,25 +76,44 @@ Vous pouvez utiliser une image géoréférencée pour localiser le signalement. </p> - <div v-if="showGeoRef"> - <p>Attention, si vous avez déjà saisi une géométrie, celle issue de l'image importée l'écrasera.</p> - <div class="field"> - <label>Image (png ou jpeg)</label> - <label class="ui icon button" for="image_file"> - <i class="file icon"></i> - <span class="label">Sélectionner une image ...</span> - </label> - <input type="file" accept="image/jpeg, image/png" style="display:none;" ref="file" v-on:change="handleFileUpload()" - name="image_file" class="image_file" id="image_file" > - <p class="error-message" style="color:red;">{{ erreurUploadMessage }}</p> - </div> - <button @click="georeferencement()" id="get-geom-from-image-file" type='button' class="ui positive right labeled icon button"> - Importer - <i class="checkmark icon"></i> - </button> + <div v-if="showGeoRef"> + <p> + Attention, si vous avez déjà saisi une géométrie, celle issue de + l'image importée l'écrasera. + </p> + <div class="field"> + <label>Image (png ou jpeg)</label> + <label class="ui icon button" for="image_file"> + <i class="file icon"></i> + <span class="label">Sélectionner une image ...</span> + </label> + <input + type="file" + accept="image/jpeg, image/png" + style="display: none" + ref="file" + v-on:change="handleFileUpload()" + name="image_file" + class="image_file" + id="image_file" + /> + <p class="error-message" style="color: red"> + {{ erreurUploadMessage }} + </p> + </div> + <button + @click="georeferencement()" + id="get-geom-from-image-file" + type="button" + class="ui positive right labeled icon button" + > + Importer + <i class="checkmark icon"></i> + </button> </div> <p v-if="showGeoPositionBtn"> - <button @click="create_point_geoposition()" + <button + @click="create_point_geoposition()" id="create-point-geoposition" type="button" class="ui compact button" @@ -102,13 +122,18 @@ signalement à partir de votre géolocalisation </button> </p> - <span id="erreur-geolocalisation" v-if="erreurGeolocalisationMessage"> + <span + id="erreur-geolocalisation" + v-if="erreurGeolocalisationMessage" + > <div class="ui negative message"> <div class="header"> Une erreur est survenue avec la fonctionnalité de géolocalisation </div> - <p id="erreur-geolocalisation-message">{{ erreurGeolocalisationMessage }}</p> + <p id="erreur-geolocalisation-message"> + {{ erreurGeolocalisationMessage }} + </p> </div> <br /> </span> @@ -130,7 +155,7 @@ "geocontrib/map-layers/sidebar-layers.html" with basemaps=serialized_base_maps layers=serialized_layers project=project.slug%} {% endif %} --> - <SidebarLayers v-if="baseMaps && map" /> + <SidebarLayers v-if="basemaps && map" /> </div> </div> @@ -207,6 +232,7 @@ import FeatureLinkedForm from "@/components/feature/FeatureLinkedForm"; import FeatureExtraForm from "@/components/feature/FeatureExtraForm"; import Dropdown from "@/components/Dropdown.vue"; import SidebarLayers from "@/components/map-layers/SidebarLayers"; +import featureAPI from "@/services/feature-api"; import L from "leaflet"; import "leaflet-draw"; @@ -231,12 +257,12 @@ export default { data() { return { - map:null, - file:null, - showGeoRef:false, - showGeoPositionBtn:true, - erreurGeolocalisationMessage:null, - erreurUploadMessage:null, + map: null, + file: null, + showGeoRef: false, + showGeoPositionBtn: true, + erreurGeolocalisationMessage: null, + erreurUploadMessage: null, attachmentDataKey: 0, linkedDataKey: 0, statusChoices: [ @@ -282,6 +308,7 @@ export default { computed: { ...mapState(["project"]), + ...mapState("map", ["basemaps"]), ...mapState("feature", [ "attachmentFormset", "linkedFormset", @@ -344,51 +371,52 @@ export default { } }, create_point_geoposition() { - function success(position) { - const latitude = position.coords.latitude - const longitude = position.coords.longitude + const latitude = position.coords.latitude; + const longitude = position.coords.longitude; - var layer = L.circleMarker([latitude, longitude]) - this.add_layer_call_back(layer) + var layer = L.circleMarker([latitude, longitude]); + this.add_layer_call_back(layer); this.map.setView([latitude, longitude]); } function error(err) { - this.erreurGeolocalisationMessage=err.message; - + this.erreurGeolocalisationMessage = err.message; } - this.erreurGeolocalisationMessage=null; + this.erreurGeolocalisationMessage = null; if (!navigator.geolocation) { - this.erreurGeolocalisationMessage="La géolocalisation n'est pas supportée par votre navigateur."; + this.erreurGeolocalisationMessage = + "La géolocalisation n'est pas supportée par votre navigateur."; } else { - navigator.geolocation.getCurrentPosition(success.bind(this), error.bind(this)); + navigator.geolocation.getCurrentPosition( + success.bind(this), + error.bind(this) + ); } - }, handleFileUpload() { this.file = this.$refs.file.files[0]; - console.log('>>>> 1st element in files array >>>> ', this.file); + console.log(">>>> 1st element in files array >>>> ", this.file); }, - georeferencement(){ + georeferencement() { console.log("georeferencement"); const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}exif-geom-reader/`; let formData = new FormData(); - formData.append('file', this.file); - console.log('>> formData >> ', formData); - let self=this; - axios.post(url, - formData, { - headers: { - 'Content-Type': 'multipart/form-data' - } - } - ).then(function () { - console.log('SUCCESS!!'); + formData.append("file", this.file); + console.log(">> formData >> ", formData); + let self = this; + axios + .post(url, formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + }) + .then(function () { + console.log("SUCCESS!!"); }) .catch(function () { - console.log('FAILURE!!'); - self.erreurUploadMessage='FAILURE!!'; + console.log("FAILURE!!"); + self.erreurUploadMessage = "FAILURE!!"; }); }, @@ -409,10 +437,26 @@ export default { }, add_attachement_formset() { - this.$store.commit("feature/ADD_ATTACHMENT_FORM", this.attachmentDataKey); // * create an object with the counter in store + this.$store.commit("feature/ADD_ATTACHMENT_FORM", { + dataKey: this.attachmentDataKey, + }); // * create an object with the counter in store this.attachmentDataKey += 1; // * increment counter for key in v-for }, + addExistingAttachementFormset(attachementFormset) { + for (const attachment of attachementFormset) { + console.log("attachment", attachment); + this.$store.commit("feature/ADD_ATTACHMENT_FORM", { + dataKey: this.attachmentDataKey, + title: attachment.title, + attachment_file: attachment.attachment_file, + info: attachment.info, + id: attachment.id, + }); + this.attachmentDataKey += 1; + } + }, + add_linked_formset() { this.$store.commit("feature/ADD_LINKED_FORM", this.linkedDataKey); // * create an object with the counter in store this.linkedDataKey += 1; // * increment counter for key in v-for @@ -431,7 +475,7 @@ export default { postForm() { if (this.form.title.value) { this.form.title.errors = null; - this.$store.dispatch("feature/POST_FEATURE", this.currentRouteName); + this.$store.dispatch("feature/SEND_FEATURE", this.currentRouteName); } else { this.form.title.errors = "Veuillez compléter ce champ."; } @@ -614,8 +658,8 @@ export default { this.drawControlFull.addTo(this.map); this.updateGeomField(""); if (geomType === "point") { - this.showGeoPositionBtn=true; - this.erreurGeolocalisationMessage=""; + this.showGeoPositionBtn = true; + this.erreurGeolocalisationMessage = ""; } }.bind(this) ); @@ -687,15 +731,11 @@ export default { throw error; }); - - - document.addEventListener("change-layers-order", (event) => { // Reverse is done because the first layer in order has to be added in the map in last. // Slice is done because reverse() changes the original array, so we make a copy first mapUtil.updateOrder(event.detail.layers.slice().reverse()); }); - }, add_layer_call_back(layer) { @@ -706,8 +746,8 @@ export default { //this.updateGeomField(wellknown.stringify(layer.toGeoJSON())) this.updateGeomField(layer.toGeoJSON()); if (this.feature_type.geomType === "point") { - this.showGeoPositionBtn=false; - this.erreurGeolocalisationMessage=""; + this.showGeoPositionBtn = false; + this.erreurGeolocalisationMessage = ""; } }, }, @@ -720,6 +760,15 @@ export default { "feature_type/SET_CURRENT_FEATURE_TYPE_SLUG", this.$route.params.slug_type_signal ); + // todo : mutualize in store with feature_detail.vue + + if (this.$route.params.slug_signal) { + featureAPI + .getFeatureAttachments(this.$route.params.slug_signal) + .then((data) => this.addExistingAttachementFormset(data)); + } else { //* be sure that previous attachemntFormset has been cleared for creation + this.$store.commit("feature/CLEAR_ATTACHMENT_FORM"); + } }, mounted() { diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue index a595e6ea9760b71202e6fd9ad3ad5227858cc54f..cd18f5ec2fa0f784d0cf5452bbaef8081649ba32 100644 --- a/src/views/feature_type/Feature_type_detail.vue +++ b/src/views/feature_type/Feature_type_detail.vue @@ -242,7 +242,7 @@ export default { }, importGeoJson() { - this.$store.dispatch("feature_type/POST_FEATURES_FROM_GEOJSON", { + this.$store.dispatch("feature_type/SEND_FEATURES_FROM_GEOJSON", { slug: this.$route.params.slug, feature_type_slug: this.$route.params.feature_type_slug, fileToImport: this.fileToImport, diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue index 7b198c7f03a260048a4fbe23e2d451ec315cc14b..8b81dd4148a43bd90cb330e00373e11d8654a387 100644 --- a/src/views/feature_type/Feature_type_edit.vue +++ b/src/views/feature_type/Feature_type_edit.vue @@ -371,7 +371,7 @@ export default { postFeatures(feature_type_slug) { this.$store - .dispatch("feature_type/POST_FEATURES_FROM_GEOJSON", { + .dispatch("feature_type/SEND_FEATURES_FROM_GEOJSON", { slug: this.$route.params.slug, feature_type_slug, })