diff --git a/src/components/feature/FeatureListTable.vue b/src/components/feature/FeatureListTable.vue index 1679fadcd49bcf4bf4699cb958107c9505fc1df9..524b23f5bba1b3a8e84a9517ac8820539f1ee7a0 100644 --- a/src/components/feature/FeatureListTable.vue +++ b/src/components/feature/FeatureListTable.vue @@ -236,7 +236,7 @@ export default { name: "FeatureListTable", props: [ - "geojsonFeatures", + "paginatedFeatures", "checkedFeatures", "featuresCount", "pagination", @@ -261,7 +261,7 @@ export default { }, sortedFeatures() { - let sortedFeatures = [...this.geojsonFeatures]; + let sortedFeatures = [...this.paginatedFeatures]; // Ajout du tri if (this.sort.column !== "") { sortedFeatures = sortedFeatures.sort((a, b) => { diff --git a/src/main.js b/src/main.js index 56bc1b0585e4d9d65e0712b9b6438479597db717..87be60e859f1e0bd80fc3ea91ea87260740da337 100644 --- a/src/main.js +++ b/src/main.js @@ -54,6 +54,7 @@ let onConfigLoaded = function(config){ store.dispatch("GET_USER_LEVEL_PROJECTS"), store.dispatch("map/GET_AVAILABLE_LAYERS"), store.dispatch("GET_USER_LEVEL_PERMISSIONS"), + store.dispatch("GET_LEVELS_PERMISSIONS"), ]).then(axios.spread(function () { new Vue({ router, diff --git a/src/services/feature-api.js b/src/services/feature-api.js index e9a02215c3a9f855c376e8ccf357d722fd63355d..3618c8687cd360acd707e991b6f8bd050e5768c7 100644 --- a/src/services/feature-api.js +++ b/src/services/feature-api.js @@ -1,9 +1,39 @@ -import axios from 'axios'; +import axios from "@/axios-client.js"; import store from '../store' const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE; const featureAPI = { + async getFeaturesBbox(project_slug, queryParams) { + const response = await axios.get( + `${baseUrl}projects/${project_slug}/feature-bbox/${queryParams ? '?' + queryParams : ""}` + ); + if ( + response.status === 200 && + response.data + ) { + const bbox = response.data; + return [ + [bbox[2], bbox[3]], + [bbox[0], bbox[1]], + ]; + } else { + return null; + } + }, + + async getPaginatedFeatures(url) { + const response = await axios.get(url); + if ( + response.status === 200 && + response.data + ) { + return response.data; + } else { + return null; + } + }, + async getFeatureEvents(featureId) { const response = await axios.get( `${baseUrl}features/${featureId}/events/` diff --git a/src/store/index.js b/src/store/index.js index 8ca73167c4c0afe944e3b551f99d243c47b79ab4..bc5b7567f9f6994e4b2bd439d54daea9537e2989 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -46,6 +46,7 @@ export default new Vuex.Store({ SSO_SETTED: false, USER_LEVEL_PROJECTS: null, user_permissions: null, + levelsPermissions: [], messages: [], events: null, loader: { @@ -95,6 +96,9 @@ export default new Vuex.Store({ SET_USER_PERMISSIONS(state, userPermissions) { state.user_permissions = userPermissions; }, + SET_LEVELS_PERMISSIONS(state, levelsPermissions) { + state.levelsPermissions = levelsPermissions; + }, SET_EVENTS(state, events) { state.events = events; }, @@ -280,6 +284,18 @@ export default new Vuex.Store({ throw error; }); }, + GET_LEVELS_PERMISSIONS({ commit }) { + return axios + .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}levels-permissions/`) + .then((response) => { + if (response && response.status === 200) { + commit("SET_LEVELS_PERMISSIONS", response.data); + } + }) + .catch((error) => { + throw error; + }); + }, async GET_PROJECT_INFO({ state, commit, dispatch }, slug) { commit("SET_PROJECT_SLUG", slug); diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js index 8d8bd2f237608f89ae580b6ad6af716854d1c795..d4aad9d8d650e87945344403d291a1608648340b 100644 --- a/src/store/modules/feature.js +++ b/src/store/modules/feature.js @@ -16,6 +16,7 @@ const feature = { checkedFeatures: [], extra_form: [], features: [], + features_count: 0, current_feature: [], form: null, linkedFormset: [], @@ -43,6 +44,9 @@ const feature = { SET_FEATURES(state, features) { state.features = features; }, + SET_FEATURES_COUNT(state, features_count) { + state.features_count = features_count; + }, SET_CURRENT_FEATURE(state, feature) { state.current_feature = feature; }, @@ -116,6 +120,7 @@ const feature = { const cancelToken = axios.CancelToken.source(); commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true }); commit("SET_FEATURES", []); + commit("SET_FEATURES_COUNT", 0); let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/${project_slug}/feature/`; if (feature_type__slug) { url = url.concat('', `${url.includes('?') ? '&' : '?'}feature_type__slug=${feature_type__slug}`); @@ -132,6 +137,8 @@ const feature = { if (response.status === 200 && response.data) { const features = response.data.features; commit("SET_FEATURES", features); + const features_count = response.data.count; + commit("SET_FEATURES_COUNT", features_count); //dispatch("map/ADD_FEATURES", null, { root: true }); //todo: should check if map was initiated } return response; @@ -187,6 +194,7 @@ const feature = { message, }, }); + dispatch("GET_ALL_PROJECTS", null, {root:true}) //* & refresh project list }); } @@ -303,6 +311,7 @@ const feature = { }); } + // this.$store.dispatch("GET_ALL_PROJECTS"), //* & refresh project list }, async SEND_ATTACHMENTS({ state, rootState, dispatch }, featureId) { diff --git a/src/views/Index.vue b/src/views/Index.vue index b751999169c005a0a90fc93e2df3ffc4156c7912..33ced862f9a5074b1d1184ce1d75dbb4877b4ecd 100644 --- a/src/views/Index.vue +++ b/src/views/Index.vue @@ -79,7 +79,7 @@ <span data-tooltip="Membres"> {{ project.nb_contributors }} <i class="user icon"></i> </span> - <span data-tooltip="Signalements"> + <span data-tooltip="Signalements publiés"> {{ project.nb_published_features }} <i class="map marker icon" ></i> diff --git a/src/views/My_account.vue b/src/views/My_account.vue index 8967257b25442a46f9958b202ce1d76486e78d01..162eedc20f53ad512982c19a8ff700730f82791a 100644 --- a/src/views/My_account.vue +++ b/src/views/My_account.vue @@ -102,7 +102,7 @@ <span data-tooltip="Membres"> {{ project.nb_contributors }} <i class="user icon"></i> </span> - <span data-tooltip="Signalements"> + <span data-tooltip="Signalements publiés"> {{ project.nb_published_features }} <i class="map marker icon" ></i> diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue index 6c3d8f37a2e81a4226c1f0b3350355fd25a7bcd4..533d6b0d25a5f5f332644fad94973a11142850a9 100644 --- a/src/views/feature/Feature_list.vue +++ b/src/views/feature/Feature_list.vue @@ -1,6 +1,5 @@ <template> <div class="fourteen wide column"> - <div id="feature-list-container" class="ui grid mobile-column"> <div class="four wide column mobile-fullwidth"> <h1>Signalements</h1> @@ -16,7 +15,7 @@ ><i class="map fitted icon"></i ></a> <a - @click="showTable" + @click="showMap = false" :class="['item no-margin', { active: !showMap }]" data-tab="list" data-tooltip="Liste" @@ -24,10 +23,10 @@ ></a> <div class="item"> <h4> - <!-- {{ featuresCount }} signalement{{ featuresCount > 1 ? "s" : "" }} --> - {{ filteredFeatures.length }} signalement{{ + {{ featuresCount }} signalement{{ featuresCount > 1 ? "s" : "" }} + <!-- {{ filteredFeatures.length }} signalement{{ filteredFeatures.length > 1 ? "s" : "" - }} + }} --> </h4> </div> @@ -83,12 +82,12 @@ </div> </div> - <form id="form-filters" class="ui form grid" action="" method="get"> + <section id="form-filters" class="ui form grid"> <div class="field wide four column no-margin-mobile"> <label>Type</label> <Dropdown v-on:update:selection="updateTypeFeatures" - :options="form.type.choices" + :options="featureTypeChoices" :selected="form.type.selected" :selection.sync="form.type.selected" :search="true" @@ -116,12 +115,12 @@ type="text" name="title" v-model="form.title" - @input="fetchPagedFeatures" + v-on:keyup.enter="fetchPagedFeatures" /> <button - type="button" - class="ui teal icon button" + @click="fetchPagedFeatures" id="submit-search" + class="ui teal icon button" > <i class="search icon"></i> </button> @@ -132,7 +131,7 @@ <input type="hidden" name="zoom" v-model="zoom" /> <input type="hidden" name="lat" v-model="lat" /> <input type="hidden" name="lng" v-model="lng" /> - </form> + </section> <div v-show="showMap" class="ui tab active map-container" data-tab="map"> <div id="map" ref="map"></div> @@ -143,7 +142,7 @@ v-show="!showMap" v-on:update:page="handlePageChange" v-on:update:sort="handleSortChange" - :geojsonFeatures="geojsonFeaturesPaginated" + :paginatedFeatures="paginatedFeatures" :checkedFeatures.sync="checkedFeatures" :featuresCount="featuresCount" :pagination="pagination" @@ -186,17 +185,12 @@ <script> import { mapGetters, mapState } from "vuex"; import { mapUtil } from "@/assets/js/map-util.js"; +import featureAPI from "@/services/feature-api"; import SidebarLayers from "@/components/map-layers/SidebarLayers"; import FeatureListTable from "@/components/feature/FeatureListTable"; import Dropdown from "@/components/Dropdown.vue"; import axios from "@/axios-client.js"; -// axios.defaults.headers.common['X-CSRFToken'] = (name => { -// var re = new RegExp(name + "=([^;]+)"); -// var value = re.exec(document.cookie); -// return (value !== null) ? unescape(value[1]) : null; -// })('csrftoken'); - export default { name: "Feature_list", @@ -240,30 +234,23 @@ export default { }, title: null, }, - - geojsonFeatures: [], - geojsonFeaturesPaginated: [], + paginatedFeatures: [], baseUrl: this.$store.state.configuration.BASE_URL, map: null, zoom: null, lat: null, lng: null, - //limit: 15, - //offset: 0, featuresCount: 0, - filterType: null, - filterStatus: null, + next: null, + previous: null, pagination: { currentPage: 1, pagesize: 15, start: 0, end: 15, }, - previous: null, - next: null, showMap: true, showAddFeature: false, - paginatedFeaturesDone: true, }; }, @@ -284,6 +271,10 @@ export default { ); }, + featureTypeChoices() { + return this.feature_types.map((el) => el.title); + }, + pageNumbers() { const totalPages = Math.ceil( this.featuresCount / this.pagination.pagesize @@ -293,51 +284,9 @@ export default { return pageNumb; }); }, - - filteredFeatures() { - let results = this.geojsonFeatures; - if (this.form.type.selected) { - results = results.filter( - (el) => el.properties.feature_type.title === this.form.type.selected - ); - } - if (this.form.status.selected.value) { - console.log("filter by" + this.form.status.selected.value); - results = results.filter( - (el) => el.properties.status.value === this.form.status.selected.value - ); - } - if (this.form.title) { - results = results.filter((el) => { - if (el.properties.title) { - return el.properties.title - .toLowerCase() - .includes(this.form.title.toLowerCase()); - } else - return el.id.toLowerCase().includes(this.form.title.toLowerCase()); - }); - } - return results; - }, - }, - - watch: { - filteredFeatures(newValue, oldValue) { - if (newValue && newValue !== oldValue) { - this.onFilterChange(); - } - }, }, methods: { - showTable() { - if (this.paginatedFeaturesDone) { - this.fetchPagedFeatures(); - this.paginatedFeaturesDone = false; - } - this.showMap = false; - }, - modalAllDelete() { this.modalAllDeleteOpen = !this.modalAllDeleteOpen; }, @@ -374,28 +323,12 @@ export default { }, onFilterChange() { - if (this.featureGroup) { - const features = this.filteredFeatures; - this.featureGroup.clearLayers(); - this.featureGroup = mapUtil.addFeatures( - features, - {}, - true, - this.feature_types - ); + if (mapUtil.getMap()) { mapUtil.getMap().invalidateSize(); mapUtil.getMap()._onResize(); // force refresh for vector tiles - if(window.layerMVT) { + if (window.layerMVT) { window.layerMVT.redraw(); } - - if (this.featureGroup.getLayers().length > 0) { - mapUtil - .getMap() - .fitBounds(this.featureGroup.getBounds(), { padding: [25, 25] }); - } else { - mapUtil.getMap().zoomOut(1); - } } }, @@ -417,6 +350,8 @@ export default { mapDefaultViewZoom, }); + this.getBbox2FIt(); + 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 @@ -424,8 +359,6 @@ export default { }); // --------- End sidebar events ---------- - //this.fetchPagedFeatures(); - this.getNloadGeojsonFeatures(); setTimeout(() => { const project_id = this.$route.params.slug.split("-")[0]; @@ -440,59 +373,16 @@ export default { }, 1000); }, - getNloadGeojsonFeatures() { - const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/?output=geojson`; - this.$store.commit( - "DISPLAY_LOADER", - "Récupération des signalements en cours..." - ); - axios - .get(url) - .then((response) => { - if (response.status === 200 && response.data.features.length > 0) { - this.geojsonFeatures = response.data.features; - this.loadFeatures(); + getBbox2FIt(queryParams) { + featureAPI + .getFeaturesBbox(this.project.slug, queryParams) + .then((bbox) => { + if (bbox) { + mapUtil.getMap().fitBounds(bbox, { padding: [25, 25] }); } - this.$store.commit("DISCARD_LOADER"); - }) - .catch((error) => { - this.$store.commit("DISCARD_LOADER"); - throw error; }); }, - loadFeatures() { - const urlParams = new URLSearchParams(window.location.search); - const featureType = urlParams.get("feature_type"); - const featureStatus = urlParams.get("status"); - const featureTitle = urlParams.get("title"); - this.featureGroup = mapUtil.addFeatures( - this.geojsonFeatures, - { - featureType, - featureStatus, - featureTitle, - }, - true, - this.feature_types - ); - // Fit the map to bound only if no initial zoom and center are defined - if ( - (this.lat === "" || this.lng === "" || this.zoom === "") && - this.geojsonFeatures.length > 0 - ) { - mapUtil - .getMap() - .fitBounds(this.featureGroup.getBounds(), { padding: [25, 25] }); - } - this.form.type.choices = [ - //* converting Set to an Array with spread "..." - ...new Set( - this.geojsonFeatures.map((el) => el.properties.feature_type.title) - ), //* use Set to eliminate duplicate values - ]; - }, - //* Paginated Features for table *// getFeatureTypeSlug(title) { const featureType = this.feature_types.find((el) => el.title === title); @@ -550,7 +440,7 @@ export default { if (this.form.title) { params += `&title=${this.form.title}`; } - + this.getBbox2FIt(params); return params; }, @@ -565,8 +455,7 @@ export default { }, fetchPagedFeatures(params) { - // this.onFilterChange(); //* temporary, use paginated event to watch change in filters, to modify geojson on map - //* replace function calls in watcher and on input + this.onFilterChange(); //* temporary, use paginated event to watch change in filters, to modify geojson on map let url = `${this.API_BASE_URL}projects/${this.$route.params.slug}/feature-paginated/?output=geojson&limit=${this.pagination.pagesize}&offset=${this.pagination.start}`; if (params) { @@ -576,8 +465,7 @@ export default { url += filterParams; } else { //console.error("ONLY FOR DEV !!!!!!!!!!!!!"); - //params = params.replace("8000", "8010"); - //console.log(url); + //params = params.replace("8000", "8010"); //* for dev uncomment to use proxy link url = params; } } @@ -586,25 +474,15 @@ export default { "DISPLAY_LOADER", "Récupération des signalements en cours..." ); - axios - .get(url) - .then((response) => { - if (response.status === 200) { - this.featuresCount = response.data.count; - this.previous = response.data.previous; - this.next = response.data.next; - this.geojsonFeaturesPaginated = response.data.results.features; - //if (response.data.results.features.length > 0) { - //this.loadFeatures(); - //this.onFilterChange(); - //} - } - this.$store.commit("DISCARD_LOADER"); - }) - .catch((error) => { - this.$store.commit("DISCARD_LOADER"); - throw error; - }); + featureAPI.getPaginatedFeatures(url).then((data) => { + if (data) { + this.featuresCount = data.count; + this.previous = data.previous; + this.next = data.next; + this.paginatedFeatures = data.results.features; + } + this.$store.commit("DISCARD_LOADER"); + }); }, //* Pagination for table *// @@ -661,12 +539,11 @@ export default { // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh this.$store .dispatch("GET_PROJECT_INFO", this.$route.params.slug) - .then(() => { - this.initMap(); - }); + .then(() => this.initMap()); } else { this.initMap(); } + this.fetchPagedFeatures(); }, destroyed() { diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue index b541bb17995c3a95c1a00ea0290832b00a8f0b8b..d96d84f28f8c36b02a0832de6f96ab43a241bede 100644 --- a/src/views/feature_type/Feature_type_detail.vue +++ b/src/views/feature_type/Feature_type_detail.vue @@ -33,7 +33,7 @@ </div> </div> <div class="value"> - {{ feature_type_features.length }} + {{ features_count }} </div> <div class="label"> Signalement{{ features.length > 1 ? "s" : "" }} @@ -126,14 +126,25 @@ </div> <div class="nine wide column"> <h3 class="ui header">Derniers signalements</h3> - <div - :class="{ active: featuresLoading }" - class="ui inverted dimmer" - > - <div class="ui text loader"> - Récupération des signalements en cours... - </div> + <div + :class="{ active: featuresLoading }" + class="ui inverted dimmer" + > + <div class="ui text loader"> + Récupération des signalements en cours... </div> + </div> + <div + v-if=" + importFeatureTypeData && importFeatureTypeData.length && importFeatureTypeData.some(el => el.status === 'pending') + " + class="ui message info" + > + <p> + Des signalements sont en cours d'import. + Pour suivre le statut de l'import, cliquez sur "Importer des Signalements". + </p> + </div> <div v-for="(feature, index) in lastFeatures" :key="feature.feature_id + index" @@ -239,7 +250,7 @@ export default { computed: { ...mapGetters(["project", "permissions"]), - ...mapState("feature", ["features"]), + ...mapState("feature", ["features", "features_count"]), ...mapState("feature_type", ["feature_types", "importFeatureTypeData"]), structure: function () { if (this.feature_types) { @@ -369,7 +380,8 @@ export default { async setCurrentFeatureTypeSlug(){ const response = await this.$store.dispatch('feature/GET_PROJECT_FEATURES', { - project_slug: this.$route.params.slug + project_slug: this.$route.params.slug, + limit: '5' }) console.log(response) @@ -390,7 +402,8 @@ export default { if (!this.project) { this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug); } - this.setCurrentFeatureTypeSlug(); + this.$store.dispatch("feature_type/GET_IMPORTS", this.structure.slug); + this.setCurrentFeatureTypeSlug(); // .then(res => resolve(res)) // .catch(err => reject(err)); this.$store.commit( diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue index bb69a28bbc5351239cb9382aa181bfb36fe91ff4..8cbda5cfbed20f39a08a0e54273f14bf57c79e1f 100644 --- a/src/views/feature_type/Feature_type_edit.vue +++ b/src/views/feature_type/Feature_type_edit.vue @@ -6,6 +6,12 @@ </div> </div> <div class="fourteen wide column"> + <div + :class="{ active: loading }" + class="ui inverted dimmer" + > + <div class="ui loader" /> + </div> <form id="form-type-edit" action="" @@ -183,6 +189,7 @@ export default { data() { return { + loading: false, action: "create", dataKey: 0, error: null, @@ -482,19 +489,29 @@ export default { response.data.detail ); } + this.loading = false; + }) + .catch(() => { + this.loading = false; }); }, async postFeatureTypeThenFeatures() { + this.loading = true; const requestType = this.action === "edit" ? "put" : "post"; if (this.checkForms()) { await this.$store .dispatch("feature_type/SEND_FEATURE_TYPE", requestType) - .then(({ feature_type_slug }) => { - if (feature_type_slug) { - this.postFeatures(feature_type_slug); - } - }); + .then(({ feature_type_slug }) => { + if (feature_type_slug) { + this.postFeatures(feature_type_slug); + } else { + this.loading = false; + } + }) + .catch(() => { + this.loading = false; + }); } }, diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue index 2e7066dd2d7090c0176df277e063a6f34fb0cc60..a521510dafccaec62c0d38b68930b86e4f4d8773 100644 --- a/src/views/project/Project_detail.vue +++ b/src/views/project/Project_detail.vue @@ -40,7 +40,7 @@ <div class="ui basic teal label" data-tooltip="Membres"> <i class="user icon"></i>{{ project.nb_contributors }} </div> - <div class="ui basic teal label" data-tooltip="Signalements"> + <div class="ui basic teal label" data-tooltip="Signalements publiés"> <i class="map marker icon"></i>{{ project.nb_published_features }} </div> <div class="ui basic teal label" data-tooltip="Commentaires"> @@ -115,17 +115,26 @@ Récupération des types de signalements en cours... </div> </div> + <div + :class="{ active: featureTypeImporting }" + class="ui inverted dimmer" + > + <div class="ui text loader"> + Traitement du fichier en cours ... + </div> + </div> <div v-for="(type, index) in feature_types" :key="type.title + '-' + index" class="item" > - <div class="middle aligned content"> + <div class="feature-type-container"> <router-link :to="{ name: 'details-type-signalement', params: { feature_type_slug: type.slug }, }" + class="feature-type-title" > <img v-if="type.geom_type === 'point'" @@ -152,6 +161,7 @@ permissions.can_create_feature && type.is_editable " --> + <div class="middle aligned content"> <router-link v-if=" project && permissions && permissions.can_create_feature @@ -256,6 +266,7 @@ > <i class="inverted grey paint brush alternate icon"></i> </router-link> + </div> </div> </div> <div v-if="feature_types.length === 0"> @@ -395,7 +406,8 @@ > <div class="content"> <div> - <router-link :to="getRouteUrl(item.related_feature.feature_url)" + <router-link + :to="getRouteUrl(item.related_feature.feature_url)" >"{{ item.comment }}"</router-link > </div> @@ -539,14 +551,9 @@ import frag from "vue-frag"; import { mapUtil } from "@/assets/js/map-util.js"; import { mapGetters, mapState } from "vuex"; import projectAPI from "@/services/project-api"; +import featureAPI from "@/services/feature-api"; -import axios from '@/axios-client.js'; - -// axios.defaults.headers.common['X-CSRFToken'] = (name => { -// var re = new RegExp(name + "=([^;]+)"); -// var value = re.exec(document.cookie); -// return (value !== null) ? unescape(value[1]) : null; -// })('csrftoken'); +import axios from "@/axios-client.js"; export default { name: "Project_details", @@ -580,6 +587,7 @@ export default { is_suscriber: false, tempMessage: null, featureTypeLoading: true, + featureTypeImporting: false, featuresLoading: true }; }, @@ -605,8 +613,8 @@ export default { refreshId() { return "?ver=" + Math.random(); }, - getRouteUrl(url){ - return '/'+url.replace(this.$store.state.configuration.BASE_URL,''); // remove duplicate /geocontrib + getRouteUrl(url) { + return "/" + url.replace(this.$store.state.configuration.BASE_URL, ""); // remove duplicate /geocontrib }, isOffline() { return navigator.onLine === false; @@ -680,6 +688,8 @@ export default { }, toNewFeatureType() { + console.log('prout'); + this.featureTypeImporting = true; this.$router.push({ name: "ajouter-type-signalement", params: { @@ -687,25 +697,36 @@ export default { fileToImport: this.fileToImport, }, }); + this.featureTypeImporting = false; }, onFileChange(e) { + this.featureTypeImporting = true; var files = e.target.files || e.dataTransfer.files; + console.log(files); if (!files.length) return; this.fileToImport = files[0]; // TODO : VALIDATION IF FILE IS JSON if (this.fileToImport.size > 0) { const fr = new FileReader(); - fr.onload = (e) => { - this.geojsonImport = JSON.parse(e.target.result); - }; - fr.readAsText(this.fileToImport); - //* stock filename to import features afterward - this.$store.commit( - "feature_type/SET_FILE_TO_IMPORT", - this.fileToImport - ); + try { + fr.onload = (e) => { + this.geojsonImport = JSON.parse(e.target.result); + this.featureTypeImporting = false; + }; + fr.readAsText(this.fileToImport); + //* stock filename to import features afterward + this.$store.commit( + "feature_type/SET_FILE_TO_IMPORT", + this.fileToImport + ); + } catch (err) { + console.error(err); + this.featureTypeImporting = false + } + } else { + this.featureTypeImporting = false; } }, @@ -730,7 +751,6 @@ export default { initMap() { if (this.project && this.permissions.can_view_project) { this.$store.dispatch("map/INITIATE_MAP", this.$refs.map); - const url = `${this.API_BASE_URL}projects/${this.$route.params.slug}/feature/?output=geojson`; this.checkForOfflineFeature(); let project_id = this.$route.params.slug.split("-")[0]; const mvtUrl = `${this.API_BASE_URL}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`; @@ -739,34 +759,22 @@ export default { this.$route.params.slug, this.$store.state.feature_type.feature_types ); - axios - .get(url) - .then((response) => { - let features = response.data.features; - this.arraysOffline.forEach( - (x) => (x.geojson.properties.color = "red") - ); - features = response.data.features.concat( - this.arraysOffline.map((x) => x.geojson) - ); - const featureGroup = mapUtil.addFeatures( - features, - {}, - true, - this.$store.state.feature_type.feature_types - ); - - if (featureGroup && featureGroup.getLayers().length > 0) { - mapUtil - .getMap() - .fitBounds(featureGroup.getBounds(), { padding: [25, 25] }); - this.$store.commit("map/SET_GEOJSON_FEATURES", features); - } else { - this.$store.commit("map/SET_GEOJSON_FEATURES", []); + + this.arraysOffline.forEach((x) => (x.geojson.properties.color = "red")); + const features = this.arraysOffline.map((x) => x.geojson); + mapUtil.addFeatures( + features, + {}, + true, + this.$store.state.feature_type.feature_types + ); + + featureAPI + .getFeaturesBbox(this.project.slug) + .then((bbox) => { + if (bbox) { + mapUtil.getMap().fitBounds(bbox, { padding: [25, 25] }); } - }) - .catch((error) => { - throw error; }); } }, @@ -782,14 +790,14 @@ export default { }, mounted() { - this.$store.dispatch('GET_PROJECT_INFO', this.slug) - .then(() => { - this.featureTypeLoading = false; - setTimeout(this.initMap, 1000); - }); - this.$store.dispatch('feature/GET_PROJECT_FEATURES', { - project_slug: this.slug - }) + this.$store.dispatch("GET_PROJECT_INFO", this.slug).then(() => { + this.featureTypeLoading = false; + setTimeout(this.initMap, 1000); + }); + this.$store + .dispatch("feature/GET_PROJECT_FEATURES", { + project_slug: this.slug, + }) .then(() => { this.featuresLoading = false; }); @@ -822,9 +830,31 @@ export default { float: right; margin: 0 0 0 1em; } + +.feature-type-container { + display: flex; + justify-content: space-between; + align-items: center; +} + +.feature-type-container > .middle.aligned.content { + width: 50%; +} + +.feature-type-title { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 1.5em; +} + .nouveau-type-signalement { + cursor: pointer; padding-top: 1em; } +.nouveau-type-signalement > a > .ui > .label{ + cursor: pointer; +} #button-import { padding-top: 0.5em; @@ -841,4 +871,4 @@ export default { .text-left { text-align: left !important; } -</style> \ No newline at end of file +</style> diff --git a/src/views/project/Project_edit.vue b/src/views/project/Project_edit.vue index f9784c6a4e5a064f2201ae0b7cc50c30a14cb556..411d78cc48f9f579ce99d9e8c3d42802a23a7bb2 100644 --- a/src/views/project/Project_edit.vue +++ b/src/views/project/Project_edit.vue @@ -194,7 +194,7 @@ import axios from '@/axios-client.js'; import Dropdown from "@/components/Dropdown.vue"; -import { mapGetters } from "vuex"; +import { mapState, mapGetters } from "vuex"; // axios.defaults.headers.common["X-CSRFToken"] = ((name) => { // var re = new RegExp(name + "=([^;]+)"); @@ -213,11 +213,6 @@ export default { return { loading: false, action: "create", - levelPermissions: [ - { name: "Utilisateur anonyme", value: "anonymous" }, - { name: "Utilisateur connecté", value: "logged_user" }, - { name: "Contributeur", value: "contributor" }, - ], fileToImport: { name: "Sélectionner une image ...", size: 0, @@ -255,10 +250,25 @@ export default { }, computed: { + ...mapState([ + "levelsPermissions", + ]), ...mapGetters(["project"]), DJANGO_BASE_URL: function () { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, + levelPermissions(){ + let self = this; + let levels = [] + this.levelsPermissions.map(function(item) { + if (item.user_type_id != "super_contributor") + levels.push({ + 'name': self.traslateRoleToFrench(item.user_type_id), + 'value': item.user_type_id, + }) + }); + return levels + } }, methods: { @@ -271,6 +281,14 @@ export default { this.action = "create_from"; } }, + + traslateRoleToFrench(role){ + if (role == "admin") return "Administrateur de projet"; + if (role == "moderator") return "Modérateur"; + if (role == "contributor") return "Contributeur"; + if (role == "logged_user") return "Utilisateur connecté"; + if (role == "anonymous") return "Utilisateur anonyme"; + }, truncate(n, len) { let ext = n.substring(n.lastIndexOf(".") + 1, n.length).toLowerCase();