From 9b6384c23e5520ab42e085474ef732913b72eea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poussard?= <tpoussard@neogeo.fr> Date: Tue, 4 Jan 2022 19:19:42 +0100 Subject: [PATCH] WIP:linting --- src/assets/js/map-util.js | 20 +- .../semantic-ui-2.4.2/semantic.min.css | 5 - src/assets/styles/base.css | 9 + src/components/Dropdown.vue | 37 +++- src/components/feature/FeatureLinkedForm.vue | 12 +- src/components/map-layers/SidebarLayers.vue | 2 + .../project/ProjectMappingContextLayer.vue | 21 +- .../project/project_mapping_basemap.vue | 21 +- src/service-worker.js | 1 + src/store/modules/feature.js | 13 +- src/store/modules/feature_type.js | 14 +- src/store/modules/map.js | 12 +- src/views/feature/Feature_detail.vue | 135 +++++------- src/views/feature/Feature_edit.vue | 30 +-- src/views/feature/Feature_list.vue | 97 ++++----- src/views/feature/Feature_offline.vue | 41 ++-- .../feature_type/Feature_type_detail.vue | 81 +++----- src/views/feature_type/Feature_type_edit.vue | 17 +- src/views/flatpages/Default.vue | 2 + src/views/flatpages/with_right_menu.vue | 3 +- src/views/project/Project_detail.vue | 195 ++++++++---------- src/views/project/Project_mapping.vue | 19 +- src/views/project/Project_members.vue | 12 +- 23 files changed, 386 insertions(+), 413 deletions(-) diff --git a/src/assets/js/map-util.js b/src/assets/js/map-util.js index a949d80a..b96a1fea 100644 --- a/src/assets/js/map-util.js +++ b/src/assets/js/map-util.js @@ -1,14 +1,8 @@ -/* eslint-disable no-mixed-spaces-and-tabs */ -/* eslint-disable no-unused-vars */ -/* eslint-disable no-undef */ import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import flip from '@turf/flip'; import axios from '@/axios-client.js'; import 'leaflet.vectorgrid'; -import store from '@/store'; - -import { FillSymbolizer, PointSymbolizer, LineSymbolizer } from '@/assets/js/vector_tile_fix.js'; let map; let dictLayersToLeaflet = {}; @@ -59,7 +53,6 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({ window.proxy_url, { params: params, - //dataType: "json", } ).then(response => { let data = response.data; @@ -70,8 +63,6 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({ }) .catch(error => { throw (error); - //xhr.status; - //xhr.responseText; } ); @@ -369,7 +360,8 @@ const mapUtil = { const featureGroup = new L.FeatureGroup(); features.forEach((feature) => { const featureProperties = feature.properties ? feature.properties : feature; - const featureType = featureTypes.find((ft) => ft.slug === (featureProperties.feature_type.slug || featureProperties.feature_type)); + const featureType = featureTypes + .find((ft) => ft.slug === (featureProperties.feature_type.slug || featureProperties.feature_type)); let filters = []; if (filter) { const typeCheck = filter.featureType && featureProperties.feature_type.slug === filter.featureType; @@ -390,8 +382,12 @@ const mapUtil = { // Look for a custom field let customField; let customFieldOption; - if (featureType.customfield_set && Object.keys(featureProperties).some(el => featureType.customfield_set.map(e => e.name).includes(el))) { - customField = Object.keys(featureProperties).filter(el => featureType.customfield_set.map(e => e.name).includes(el)); + if ( + featureType.customfield_set && + Object.keys(featureProperties).some(el => featureType.customfield_set.map(e => e.name).includes(el)) + ) { + customField = Object.keys(featureProperties) + .filter(el => featureType.customfield_set.map(e => e.name).includes(el)); customFieldOption = featureProperties[customField[0]]; } let color = this.retrieveFeatureColor(featureType, featureProperties) || featureProperties.color; diff --git a/src/assets/resources/semantic-ui-2.4.2/semantic.min.css b/src/assets/resources/semantic-ui-2.4.2/semantic.min.css index 1a81e0b5..e31f026a 100644 --- a/src/assets/resources/semantic-ui-2.4.2/semantic.min.css +++ b/src/assets/resources/semantic-ui-2.4.2/semantic.min.css @@ -26066,14 +26066,9 @@ select.ui.dropdown { .ui.modal>.actions { background: #f9fafb; padding: 1rem 1rem; - border-top: 1px solid rgba(34, 36, 38, .15); text-align: right } -.ui.modal .actions>.button { - margin-left: .75em -} - @media only screen and (max-width:767px) { .ui.modal { width: 95%; diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css index 0777e8e3..21977713 100644 --- a/src/assets/styles/base.css +++ b/src/assets/styles/base.css @@ -9,7 +9,16 @@ header { main { padding: 2em 0em; } +/* ---------------------------------- */ + /* UTILS */ +/* ---------------------------------- */ +.no-margin { + margin: 0 !important; +} +.margin-top { + margin-top: 1rem; +} /* ---------------------------------- */ /* MAIN */ /* ---------------------------------- */ diff --git a/src/components/Dropdown.vue b/src/components/Dropdown.vue index bbebbec7..d658cb72 100644 --- a/src/components/Dropdown.vue +++ b/src/components/Dropdown.vue @@ -10,10 +10,10 @@ > <input v-if="search" + ref="input" v-model="input" class="search" autocomplete="off" - ref="input" tabindex="0" :placeholder="placehold" @input="isOpen = true" @@ -24,7 +24,6 @@ v-if="!input" class="default text" > - <!-- {{ selected }} --> <div v-if="Array.isArray(selected)"> <span v-if="selected[0]"> {{ selected[0] }} - </span> <span class="italic">{{ selected[1] }}</span> @@ -66,14 +65,32 @@ export default { name: 'Dropdown', - props: [ - 'options', - 'selected', - 'disabled', - 'search', - 'placeholder', - 'clearable', - ], + props: { + clearable: { + type: Boolean, + default: null, + }, + disabled: { + type: Boolean, + default: null, + }, + options: { + type: Array, + default: null, + }, + placeholder: { + type: String, + default: null, + }, + selected: { + type: [String, Array], + default: null, + }, + search: { + type: Boolean, + default: null, + }, + }, data() { return { diff --git a/src/components/feature/FeatureLinkedForm.vue b/src/components/feature/FeatureLinkedForm.vue index cae15513..09f56863 100644 --- a/src/components/feature/FeatureLinkedForm.vue +++ b/src/components/feature/FeatureLinkedForm.vue @@ -17,8 +17,9 @@ <li v-for="error in form.errors" :key="error" - v-html="error" - /> + > + {{ error }} + </li> </ul> <div class="visible-fields"> <div class="two fields"> @@ -60,7 +61,12 @@ export default { SearchFeature }, - props: ['linkedForm', 'features'], + props: { + linkedForm: { + type: Object, + default: null, + } + }, data() { return { diff --git a/src/components/map-layers/SidebarLayers.vue b/src/components/map-layers/SidebarLayers.vue index bbe8dbaf..59c9b2ad 100644 --- a/src/components/map-layers/SidebarLayers.vue +++ b/src/components/map-layers/SidebarLayers.vue @@ -20,6 +20,7 @@ > <g> <g> + <!-- eslint-disable max-len --> <path d="M487.298,326.733l-62.304-37.128l62.304-37.128c2.421-1.443,3.904-4.054,3.904-6.872s-1.483-5.429-3.904-6.872 l-62.304-37.128l62.304-37.128c3.795-2.262,5.038-7.172,2.776-10.968c-0.68-1.142-1.635-2.096-2.776-2.776l-237.6-141.6 @@ -32,6 +33,7 @@ L245.601,377.893L23.625,245.605z M245.601,465.893L23.625,333.605l58.208-34.68l159.672,95.2c2.524,1.504,5.668,1.504,8.192,0 l159.672-95.2l58.208,34.68L245.601,465.893z" /> + <!--eslint-enable--> </g> </g> </svg> diff --git a/src/components/project/ProjectMappingContextLayer.vue b/src/components/project/ProjectMappingContextLayer.vue index 0c39a07a..eacd0d96 100644 --- a/src/components/project/ProjectMappingContextLayer.vue +++ b/src/components/project/ProjectMappingContextLayer.vue @@ -14,11 +14,6 @@ > <i class="th icon" />couche </label> - <!-- {% if is_empty %} {# TODO arranger le dropdown pour les ajout à la volée - #} {# le selecteur de couche ne s'affichant pas correctement on passe - par un field django par defaut en attendant #} --> - <!-- {{ form.layer }} --> - <!-- {% else %} --> <Dropdown :options="availableLayerOptions" :selected="selectedLayer.name" @@ -26,7 +21,6 @@ :search="true" :placeholder="placeholder" /> - <!-- {{ form.layer.errors }} --> </div> <div class="fields"> <div @@ -41,7 +35,6 @@ min="0" max="1" > - <!-- {{ form.opacity.errors }} --> </div> <div class="field three wide"> <div @@ -55,7 +48,6 @@ > <label for="queryable"> Requêtable</label> </div> - <!-- {{ form.queryable.errors }} --> </div> </div> @@ -83,7 +75,18 @@ export default { Dropdown, }, - props: ['layer', 'basemapid'], + props: { + layer: + { + type: Object, + default: null, + }, + basemapid: + { + type: Number, + default: null, + }, + }, computed: { ...mapState('map', ['availableLayers']), diff --git a/src/components/project/project_mapping_basemap.vue b/src/components/project/project_mapping_basemap.vue index c606f2f8..36684a23 100644 --- a/src/components/project/project_mapping_basemap.vue +++ b/src/components/project/project_mapping_basemap.vue @@ -21,9 +21,8 @@ <div class="nested"> <div - v-if="basemap.layers" :id="`list-${basemap.id}`" - class="ui segments layers-container" + :class="[basemap.layers.length > 0 ? 'ui segments': '', 'layers-container']" > <ProjectMappingContextLayer v-for="layer in basemap.layers" @@ -77,7 +76,12 @@ export default { ProjectMappingContextLayer, }, - props: ['basemap'], + props: { + basemap: { + type: Object, + default: null, + } + }, computed: { maxLayersCount: function () { @@ -112,19 +116,9 @@ export default { this.fillLayersWithDatakey(this.basemap.layers); } }, - // destroyed(){ - // this.errors = []; - // } mounted() { - //* not present in original this.initSortable(); - // if (!this.basemap.title) { - // this.$store.commit("map/UPDATE_BASEMAP", { - // id: this.basemap.id, - // title: newValue, - // }); - // } }, methods: { @@ -173,7 +167,6 @@ export default { }, //* drag & drop *// - onlayerMove() { //* Get the names of the current layers in order. const currentLayersNamesInOrder = Array.from( diff --git a/src/service-worker.js b/src/service-worker.js index 91c03b3a..2b50cf55 100644 --- a/src/service-worker.js +++ b/src/service-worker.js @@ -1,3 +1,4 @@ +/* global workbox */ //* allow undefined variable for 'workbox' in this file (because global variable) to avoid eslint error // custom service-worker.js if (workbox) { // adjust log level for displaying workbox logs diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js index 694e28ee..e00e2024 100644 --- a/src/store/modules/feature.js +++ b/src/store/modules/feature.js @@ -105,7 +105,14 @@ const feature = { getters: { }, actions: { - async GET_PROJECT_FEATURES({ commit, rootState }, { project_slug, feature_type__slug, ordering, search, limit, geojson = false }) { + async GET_PROJECT_FEATURES({ commit, rootState }, { + project_slug, + feature_type__slug, + ordering, + search, + limit, + geojson = false + }) { if (rootState.cancellableSearchRequest.length > 0) { const currentRequestCancelToken = rootState.cancellableSearchRequest[rootState.cancellableSearchRequest.length - 1]; @@ -233,7 +240,9 @@ const feature = { data: geojson }).then((response) => { if ((response.status === 200 || response.status === 201) && response.data) { - if (state.attachmentFormset.length > 0 || state.linkedFormset.length > 0 || state.attachmentFormset.length > 0 || state.attachmentsToDelete.length > 0) { + if (state.attachmentFormset.length > 0 || + state.linkedFormset.length > 0 || + state.attachmentsToDelete.length > 0) { handleOtherForms(response.data.id); } else { redirect(response.data.id); diff --git a/src/store/modules/feature_type.js b/src/store/modules/feature_type.js index 156f1330..31221ca5 100644 --- a/src/store/modules/feature_type.js +++ b/src/store/modules/feature_type.js @@ -1,9 +1,11 @@ import axios from '@/axios-client.js'; -const getColorsStyles = (customForms) => customForms.filter(customForm => customForm.options && customForm.options.length).map(el => { +const getColorsStyles = (customForms) => customForms + .filter(customForm => customForm.options && customForm.options.length) + .map(el => { //* in dropdown, value is the name and name is the label to be displayed, could be changed... - return { value: el.name, name: el.label, options: el.options }; -}); + return { value: el.name, name: el.label, options: el.options }; + }); const pending2draftFeatures = (features) => { let result = []; @@ -176,7 +178,11 @@ const feature_type = { const newGeojson= { type: 'FeatureCollection', features: unmoderatedFeatures }; - const newFile = new File([JSON.stringify(newGeojson)], state.fileToImport.name, { type: state.fileToImport.type }); + const newFile = new File( + [JSON.stringify(newGeojson)], + state.fileToImport.name, + { type: state.fileToImport.type } + ); formData.append('json_file', newFile); } else { formData.append('json_file', state.fileToImport); diff --git a/src/store/modules/map.js b/src/store/modules/map.js index af15ae05..cc4d836f 100644 --- a/src/store/modules/map.js +++ b/src/store/modules/map.js @@ -151,7 +151,11 @@ const map = { }); layersToLoad.reverse(); } - mapUtil.addLayers(layersToLoad, this.state.configuration.DEFAULT_BASE_MAP.SERVICE, this.state.configuration.DEFAULT_BASE_MAP.OPTIONS); + mapUtil.addLayers( + layersToLoad, + this.state.configuration.DEFAULT_BASE_MAP.SERVICE, + this.state.configuration.DEFAULT_BASE_MAP.OPTIONS + ); // Remove multiple interactions with the map //mapUtil.getMap().dragging.disable(); @@ -190,8 +194,10 @@ const map = { } const promisesResult = await Promise.all( - [...state.basemaps.map((basemap) => postOrPut(basemap)), ...state.basemapsToDelete.map((basemapId) => deleteBMap(basemapId))] - + [ + ...state.basemaps.map((basemap) => postOrPut(basemap)), + ...state.basemapsToDelete.map((basemapId) => deleteBMap(basemapId)) + ] ); state.basemapsToDelete = []; return promisesResult; diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue index 4aa684df..0e40ed7c 100644 --- a/src/views/feature/Feature_detail.vue +++ b/src/views/feature/Feature_detail.vue @@ -114,18 +114,6 @@ {{ feature.updated_on | formatDate }} </td> </tr> - <!-- <tr> - <td>Date d'archivage automatique</td> - <td v-if="feature.archived_on"> - {{ feature.archived_on }} - </td> - </tr> - <tr> - <td>Date de suppression automatique</td> - <td v-if="feature.deletion_on"> - {{ feature.deletion_on }} - </td> - </tr> --> </tbody> </table> @@ -378,23 +366,13 @@ Supprimer le signalement </div> <div class="actions"> - <form - action="{% url 'geocontrib:feature_delete' slug=feature.project.slug feature_type_slug=feature.feature_type.slug feature_id=feature.feature_id %}" - method="POST" + <button + type="button" + class="ui red compact fluid button" + @click="deleteFeature" > - <input - type="hidden" - name="_method" - value="delete" - > - <button - type="button" - class="ui red compact fluid button" - @click="deleteFeature" - > - Confirmer la suppression - </button> - </form> + Confirmer la suppression + </button> </div> </div> </div> @@ -422,6 +400,14 @@ export default { frag, }, + filters: { + formatDate(value) { + let date = new Date(value); + date = date.toLocaleString().replace(',', ''); + return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date + }, + }, + data() { return { isCanceling: false, @@ -501,12 +487,49 @@ export default { return status ? status.name : ''; }, }, - filters: { - formatDate(value) { - let date = new Date(value); - date = date.toLocaleString().replace(',', ''); - return date.substr(0, date.length - 3); //* quick & dirty way to remove seconds from date - }, + + created() { + this.$store.commit( + 'feature_type/SET_CURRENT_FEATURE_TYPE_SLUG', + this.$route.params.slug_type_signal + ); + this.getFeatureEvents(); + this.getFeatureAttachments(); + this.getLinkedFeatures(); + }, + + mounted() { + this.$store.commit('DISPLAY_LOADER', 'Recherche du signalement'); + if (!this.project) { + // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh + axios.all([ + this.$store + .dispatch('GET_PROJECT_INFO', this.$route.params.slug), + this.$store.dispatch('feature/GET_PROJECT_FEATURE', { + project_slug: this.$route.params.slug, + feature_id: this.$route.params.slug_signal + })]) + .then(() => { + this.$store.commit('DISCARD_LOADER'); + this.initMap(); + }); + } if (!this.feature || this.feature.feature_id != this.$route.params.slug_signal) { + this.$store.dispatch('feature/GET_PROJECT_FEATURE', { + project_slug: this.$route.params.slug, + feature_id: this.$route.params.slug_signal + }) + .then(() => { + this.$store.commit('DISCARD_LOADER'); + this.initMap(); + }); + } else { + this.$store.commit('DISCARD_LOADER'); + this.initMap(); + } + }, + + beforeDestroy() { + this.$store.commit('CLEAR_MESSAGES'); }, methods: { @@ -738,50 +761,6 @@ export default { ); }, }, - - created() { - this.$store.commit( - 'feature_type/SET_CURRENT_FEATURE_TYPE_SLUG', - this.$route.params.slug_type_signal - ); - this.getFeatureEvents(); - this.getFeatureAttachments(); - this.getLinkedFeatures(); - }, - - mounted() { - this.$store.commit('DISPLAY_LOADER', 'Recherche du signalement'); - if (!this.project) { - // Chargements des features et infos projet en cas d'arrivée directe sur la page ou de refresh - axios.all([ - this.$store - .dispatch('GET_PROJECT_INFO', this.$route.params.slug), - this.$store.dispatch('feature/GET_PROJECT_FEATURE', { - project_slug: this.$route.params.slug, - feature_id: this.$route.params.slug_signal - })]) - .then(() => { - this.$store.commit('DISCARD_LOADER'); - this.initMap(); - }); - } if (!this.feature || this.feature.feature_id != this.$route.params.slug_signal) { - this.$store.dispatch('feature/GET_PROJECT_FEATURE', { - project_slug: this.$route.params.slug, - feature_id: this.$route.params.slug_signal - }) - .then(() => { - this.$store.commit('DISCARD_LOADER'); - this.initMap(); - }); - } else { - this.$store.commit('DISCARD_LOADER'); - this.initMap(); - } - }, - - beforeDestroy() { - this.$store.commit('CLEAR_MESSAGES'); - }, }; </script> diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue index be4b4d72..7fc6e51a 100644 --- a/src/views/feature/Feature_edit.vue +++ b/src/views/feature/Feature_edit.vue @@ -238,10 +238,10 @@ id="formsets-attachment" > <FeatureAttachmentForm - v-for="form in attachmentFormset" - :key="form.dataKey" + v-for="attachForm in attachmentFormset" + :key="attachForm.dataKey" ref="attachementForm" - :attachment-form="form" + :attachment-form="attachForm" /> </div> @@ -262,11 +262,10 @@ </div> <div id="formsets-link"> <FeatureLinkedForm - v-for="form in linkedFormset" - :key="form.dataKey" + v-for="linkForm in linkedFormset" + :key="linkForm.dataKey" ref="linkedForm" - :linked-form="form" - :features="features" + :linked-form="linkForm" /> </div> <button @@ -308,12 +307,6 @@ import { mapUtil } from '@/assets/js/map-util.js'; import axios from '@/axios-client.js'; import flip from '@turf/flip'; -// 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: 'FeatureEdit', @@ -383,12 +376,9 @@ export default { ...mapState('map', ['basemaps']), ...mapState('feature', [ 'attachmentFormset', - 'attachmentsToDelete', - 'attachmentsToPut', 'linkedFormset', 'features', 'extra_form', - 'linked_features', 'statusChoices', ]), @@ -955,7 +945,6 @@ export default { var layers = e.layers; let self = this; layers.eachLayer(function (layer) { - //this.updateGeomField(wellknown.stringify(layer.toGeoJSON())) self.updateGeomField(layer.toGeoJSON()); }); }.bind(this) @@ -979,7 +968,7 @@ export default { if (this.drawnItems) this.drawnItems.clearLayers(); var geomType = this.feature_type.geom_type; if (geomFeatureJSON) { - var geomJSON = flip(geomFeatureJSON.geometry); //turf.flip(geomFeatureJSON) + var geomJSON = flip(geomFeatureJSON.geometry); if (geomType === 'point') { L.circleMarker(geomJSON.coordinates).addTo(this.drawnItems); } else if (geomType === 'linestring') { @@ -1062,7 +1051,6 @@ export default { this.drawControlFull.remove(this.map); this.drawControlEditOnly.addTo(this.map); //var wellknown;// TODO Remplacer par autre chose - //this.updateGeomField(wellknown.stringify(layer.toGeoJSON())) this.updateGeomField(layer.toGeoJSON()); if (this.feature_type.geomType === 'point') { this.showGeoPositionBtn = false; @@ -1120,13 +1108,13 @@ export default { height: 80vh; } } -/* // ! missing style in semantic.min.css, je ne comprends pas comment... */ +/* // ! missing style in semantic.min.css */ .ui.right.floated.button { float: right; margin-right: 0; margin-left: 0.25em; } -/* // ! margin écrasé par class last-child first-child, pas normal ... */ +/* // ! margin écrasé par class last-child first-child */ .ui.segment { margin: 1rem 0 !important; } diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue index d429df95..b50a313c 100644 --- a/src/views/feature/Feature_list.vue +++ b/src/views/feature/Feature_list.vue @@ -27,9 +27,6 @@ <div class="item"> <h4> {{ featuresCount }} signalement{{ featuresCount > 1 ? "s" : "" }} - <!-- {{ filteredFeatures.length }} signalement{{ - filteredFeatures.length > 1 ? "s" : "" - }} --> </h4> </div> @@ -199,7 +196,7 @@ <div class="actions"> <button type="button" - class="ui red compact fluid button no-margin" + class="ui red compact fluid button" @click="deleteAllFeatureSelection" > Confirmer la suppression @@ -283,6 +280,36 @@ export default { }; }, + computed: { + ...mapGetters([ + 'project', 'permissions' + ]), + ...mapState('feature', [ + 'checkedFeatures' + ]), + ...mapState('feature_type', [ + 'feature_types' + ]), + ...mapState('map', [ + 'basemaps' + ]), + + API_BASE_URL() { + return this.$store.state.configuration.VUE_APP_DJANGO_API_BASE; + }, + + statusChoices() { + //* if project is not moderate, remove pending status + return this.form.status.choices.filter((el) => + this.project && this.project.moderation ? true : el.value !== 'pending' + ); + }, + + featureTypeChoices() { + return this.feature_types.map((el) => el.title); + }, + }, + watch: { 'form.type.selected'() { this.fetchPagedFeatures(); @@ -327,34 +354,21 @@ export default { } }, - computed: { - ...mapGetters([ - 'project', 'permissions' - ]), - ...mapState('feature', [ - 'checkedFeatures' - ]), - ...mapState('feature_type', [ - 'feature_types' - ]), - ...mapState('map', [ - 'basemaps' - ]), - - API_BASE_URL() { - return this.$store.state.configuration.VUE_APP_DJANGO_API_BASE; - }, - - statusChoices() { - //* if project is not moderate, remove pending status - return this.form.status.choices.filter((el) => - this.project && this.project.moderation ? true : el.value !== 'pending' - ); - }, + mounted() { + if (!this.project) { + // 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()); + } else { + this.initMap(); + } + this.fetchPagedFeatures(); + }, - featureTypeChoices() { - return this.feature_types.map((el) => el.title); - }, + destroyed() { + //* allow user to change page if ever stuck on loader + this.$store.commit('DISCARD_LOADER'); }, methods: { @@ -569,23 +583,6 @@ export default { } }, }, - - mounted() { - if (!this.project) { - // 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()); - } else { - this.initMap(); - } - this.fetchPagedFeatures(); - }, - - destroyed() { - //* allow user to change page if ever stuck on loader - this.$store.commit('DISCARD_LOADER'); - }, }; </script> @@ -622,10 +619,6 @@ export default { margin-left: 0.25em !important; } -.no-margin { - margin: 0 !important; -} - .no-padding { padding: 0 !important; } diff --git a/src/views/feature/Feature_offline.vue b/src/views/feature/Feature_offline.vue index b75ba3c5..8bbe1718 100644 --- a/src/views/feature/Feature_offline.vue +++ b/src/views/feature/Feature_offline.vue @@ -1,42 +1,35 @@ <template> - <div v-frag> - Erreur Réseau lors de l'envoi du signalement. Votre signalement devra être envoyé au serveur quand vous aurez de nouveau accès à internet. - Veuillez à ce moment là cliquer sur Envoyer sur la page principale du projet + <div> + <div class="margin-1"> + Erreur réseau lors de l'envoi du signalement. + </div> + <div class="margin-1"> + Votre signalement devra être envoyé au serveur quand vous aurez de nouveau accès à internet. + </div> + <div class="margin-1"> + Veuillez à ce moment là , cliquer sur le bouton "Envoyer", sur la page principale du projet + </div> <router-link :to="{ name: 'project_detail', params: { slug: $route.params.slug }, }" - class="header" + class="ui positive left labeled icon button margin-1" > - Retour au projet + <i class="arrow left icon" />Retour au projet </router-link> </div> </template> <script> -import frag from 'vue-frag'; export default { name: 'FeatureOffline', - - directives: { - frag, - }, - - data() { - return { - }; - }, - - computed: { - }, - methods: { - - } }; </script> -<style> - -</style> \ No newline at end of file +<style scoped> +.margin-1 { + margin: 1rem; +} +</style> diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue index a0993450..a7852840 100644 --- a/src/views/feature_type/Feature_type_detail.vue +++ b/src/views/feature_type/Feature_type_detail.vue @@ -160,13 +160,15 @@ </div> <div v-if=" - importFeatureTypeData && importFeatureTypeData.length && importFeatureTypeData.some(el => el.status === 'pending') + 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". + Des signalements sont en cours d'import. Pour suivre le statut de + l'import, cliquez sur "Importer des Signalements". </p> </div> <div @@ -279,36 +281,26 @@ export default { }, showImport: false, featuresLoading: true, - loadingImportFile: false + loadingImportFile: false, }; }, computed: { - ...mapGetters([ - 'project', - 'permissions' - ]), - ...mapState('feature', [ - 'features', - 'features_count' - ]), - ...mapState('feature_type', [ - 'feature_types', - 'importFeatureTypeData' - ]), + ...mapGetters(['project', 'permissions']), + ...mapState('feature', ['features', 'features_count']), + ...mapState('feature_type', ['feature_types', 'importFeatureTypeData']), structure: function () { if (Object.keys(this.feature_types).length) { let st = this.feature_types.find( (el) => el.slug === this.$route.params.feature_type_slug ); - if (st) - return st; + if (st) return st; } return {}; }, feature_type_features: function () { - if(this.features.length) + if (this.features.length) return this.features.filter( (el) => el.feature_type.slug === this.$route.params.feature_type_slug ); @@ -330,14 +322,14 @@ export default { }, }, - watch:{ - structure(newValue){ - if (newValue.slug){ + watch: { + structure(newValue) { + if (newValue.slug) { this.GET_IMPORTS({ - feature_type: this.$route.params.feature_type_slug + feature_type: this.$route.params.feature_type_slug, }); } - } + }, }, created() { @@ -348,29 +340,19 @@ export default { this.getFeatures(); // .then(res => resolve(res)) // .catch(err => reject(err)); - this.SET_CURRENT_FEATURE_TYPE_SLUG( - this.$route.params.feature_type_slug - ); + this.SET_CURRENT_FEATURE_TYPE_SLUG(this.$route.params.feature_type_slug); }, methods: { - ...mapMutations('feature_type', [ - 'SET_CURRENT_FEATURE_TYPE_SLUG' - ]), - ...mapActions([ - 'GET_PROJECT_INFO' - ]), - ...mapActions('feature_type', [ - 'GET_IMPORTS' - ]), - ...mapActions('feature', [ - 'GET_PROJECT_FEATURES' - ]), + ...mapMutations('feature_type', ['SET_CURRENT_FEATURE_TYPE_SLUG']), + ...mapActions(['GET_PROJECT_INFO']), + ...mapActions('feature_type', ['GET_IMPORTS']), + ...mapActions('feature', ['GET_PROJECT_FEATURES']), toggleShowImport() { this.showImport = !this.showImport; if (this.showImport) { this.$store.dispatch('feature_type/GET_IMPORTS', { - feature_type: this.$route.params.feature_type_slug + feature_type: this.$route.params.feature_type_slug, }); } }, @@ -384,7 +366,7 @@ export default { return 'integer'; } else if ( type === 'string' && - ['/', ':', '-'].some(el => prop.includes(el)) && // check for chars found in datestring + ['/', ':', '-'].some((el) => prop.includes(el)) && // check for chars found in datestring date instanceof Date && !isNaN(date.valueOf()) ) { @@ -479,20 +461,19 @@ export default { } }); }, - async getFeatures(){ - const response = await - this.GET_PROJECT_FEATURES({ - project_slug: this.$route.params.slug, - feature_type__slug : this.$route.params.feature_type_slug, + async getFeatures() { + const response = await this.GET_PROJECT_FEATURES({ + project_slug: this.$route.params.slug, + feature_type__slug: this.$route.params.feature_type_slug, ordering: '-created_on', - limit: '5' + limit: '5', }); - if (response){ + if (response) { this.featuresLoading = false; } - } - } + }, + }, }; </script> diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue index 1a7bf5d9..f2ff4364 100644 --- a/src/views/feature_type/Feature_type_edit.vue +++ b/src/views/feature_type/Feature_type_edit.vue @@ -55,10 +55,10 @@ class="errorlist" > <li - v-for="error in form.title.errors" - :key="error" + v-for="err in form.title.errors" + :key="err" > - {{ error }} + {{ err }} </li> </ul> </div> @@ -187,7 +187,16 @@ export default { FeatureTypeCustomForm, }, - props: ['geojson', 'fileToImport'], + props: { + geojson: { + type: Object, + default: null, + }, + fileToImport: { + type: File, + default: null, + } + }, data() { return { diff --git a/src/views/flatpages/Default.vue b/src/views/flatpages/Default.vue index af25966b..e0957122 100644 --- a/src/views/flatpages/Default.vue +++ b/src/views/flatpages/Default.vue @@ -5,7 +5,9 @@ > <div class="ten wide column"> <h1>{{ flatpage.title }}</h1> + <!-- eslint-disable vue/no-v-html --> <div v-html="flatpage.content" /> + <!--eslint-enable--> </div> </div> </template> diff --git a/src/views/flatpages/with_right_menu.vue b/src/views/flatpages/with_right_menu.vue index 262c3974..46a5ff9b 100644 --- a/src/views/flatpages/with_right_menu.vue +++ b/src/views/flatpages/with_right_menu.vue @@ -2,8 +2,9 @@ <div class="row"> <div class="ten wide column"> <h1>{{ flatpage.title }}</h1> + <!-- eslint-disable vue/no-v-html --> <div v-html="flatpage.content" /> - + <!--eslint-enable--> <div class="ui right rail"> <div id="toc-container" diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue index c4ff3341..9d7adc2c 100644 --- a/src/views/project/Project_detail.vue +++ b/src/views/project/Project_detail.vue @@ -65,7 +65,9 @@ class="ui basic teal label" data-tooltip="Commentaires" > - <i class="comment icon" />{{ project.nb_published_features_comments }} + <i class="comment icon" />{{ + project.nb_published_features_comments + }} </div> </div> <div class="ten wide column"> @@ -73,7 +75,10 @@ <div class="content"> {{ project.title }} <div v-if="arraysOffline.length > 0"> - {{ arraysOffline.length }} modification<span v-if="arraysOffline.length>1">s</span> en attente + {{ arraysOffline.length }} modification<span + v-if="arraysOffline.length > 1" + >s</span> + en attente <button :disabled="isOffline()" class="ui fluid teal icon button" @@ -130,7 +135,7 @@ </h3> <div class="ui middle aligned divided list"> <div - :class="{ active : projectInfoLoading }" + :class="{ active: projectInfoLoading }" class="ui inverted dimmer" > <div class="ui text loader"> @@ -257,14 +262,14 @@ params: { slug_type_signal: type.slug }, }" class=" - ui - compact - small - icon - right - floated - button button-hover-green - " + ui + compact + small + icon + right + floated + button button-hover-green + " data-tooltip="Éditer la symbologie du type de signalement" data-position="left center" data-variation="mini" @@ -284,14 +289,14 @@ params: { slug_type_signal: type.slug }, }" class=" - ui - compact - small - icon - right - floated - button button-hover-green - " + ui + compact + small + icon + right + floated + button button-hover-green + " data-tooltip="Éditer le type de signalement" data-position="left center" data-variation="mini" @@ -377,7 +382,7 @@ </div> <div class="seven wide column"> <div - :class="{ active : mapLoading }" + :class="{ active: mapLoading }" class="ui inverted dimmer" > <div class="ui text loader"> @@ -421,7 +426,8 @@ name: 'details-signalement', params: { slug: project.slug, - slug_type_signal: item.properties.feature_type.slug, + slug_type_signal: + item.properties.feature_type.slug, slug_signal: item.id, }, }" @@ -432,13 +438,12 @@ <div class="description"> <i> [{{ item.properties.created_on }} - <span - v-if="user && item.properties.creator" - > - , par {{ - item.properties.creator.full_name ? - item.properties.creator.full_name : - item.properties.creator.username + <span v-if="user && item.properties.creator"> + , par + {{ + item.properties.creator.full_name + ? item.properties.creator.full_name + : item.properties.creator.username }} </span> ] @@ -633,8 +638,8 @@ </div> <div class="content"> <p> - Impossible de créer un type de signalement à partir d'un fichier GeoJSON - de plus de 10Mo (celui importé fait {{ fileSize }} Mo). + Impossible de créer un type de signalement à partir d'un fichier + GeoJSON de plus de 10Mo (celui importé fait {{ fileSize }} Mo). </p> </div> <div class="actions"> @@ -680,7 +685,12 @@ export default { }, }, - props: ['message'], + props: { + message: { + type: String, + default: '' + } + }, data() { return { @@ -704,25 +714,11 @@ export default { }, computed: { - ...mapGetters([ - 'project', - 'permissions' - ]), - ...mapState('feature_type', [ - 'feature_types', - 'importFeatureTypeData' - ]), - ...mapState('feature', [ - 'features' - ]), - ...mapState([ - 'last_comments', - 'user', - 'reloadIntervalId' - ]), - ...mapState('map', [ - 'map' - ]), + ...mapGetters(['project', 'permissions']), + ...mapState('feature_type', ['feature_types', 'importFeatureTypeData']), + ...mapState('feature', ['features']), + ...mapState(['last_comments', 'user', 'reloadIntervalId']), + ...mapState('map', ['map']), DJANGO_BASE_URL() { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, @@ -731,7 +727,7 @@ export default { }, fileSize() { return fileConvertSizeToMo(this.fileToImport.size); - } + }, }, watch: { @@ -740,51 +736,55 @@ export default { handler(newValue, oldValue) { if (newValue && newValue !== oldValue) { this.GET_IMPORTS({ - project_slug: this.$route.params.slug + project_slug: this.$route.params.slug, }); } - } + }, }, importFeatureTypeData: { deep: true, handler(newValue) { - if (newValue && newValue.some(el => el.status === 'pending') && !this.reloadIntervalId) { - this.SET_RELOAD_INTERVAL_ID(setInterval(() => { - this.GET_IMPORTS({ - project_slug: this.$route.params.slug - }); - }, this.$store.state.configuration.VUE_APP_RELOAD_INTERVAL)); - } else if (newValue && !newValue.some(el => el.status === 'pending') && this.reloadIntervalId) { + if ( + newValue && + newValue.some((el) => el.status === 'pending') && + !this.reloadIntervalId + ) { + this.SET_RELOAD_INTERVAL_ID( + setInterval(() => { + this.GET_IMPORTS({ + project_slug: this.$route.params.slug, + }); + }, this.$store.state.configuration.VUE_APP_RELOAD_INTERVAL) + ); + } else if ( + newValue && + !newValue.some((el) => el.status === 'pending') && + this.reloadIntervalId + ) { this.GET_PROJECT_FEATURE_TYPES(this.project.slug); this.CLEAR_RELOAD_INTERVAL_ID(); } - } + }, }, features: { deep: true, handler(newValue, oldValue) { if (newValue && newValue.length && newValue !== oldValue) { - mapUtil.addFeatures( - this.features, - {}, - true, - this.feature_types - ); + mapUtil.addFeatures(this.features, {}, true, this.feature_types); this.mapLoading = false; } - } + }, }, featuresLoading(newValue) { if (!newValue && this.features && this.features.length === 0) { this.mapLoading = false; } - } + }, }, created() { - if (this.user) { projectAPI .getProjectSubscription({ projectSlug: this.$route.params.slug }) @@ -819,25 +819,12 @@ export default { }, methods: { - ...mapMutations([ - 'SET_RELOAD_INTERVAL_ID', - 'CLEAR_RELOAD_INTERVAL_ID' - ]), - ...mapActions([ - 'GET_PROJECT_INFO' - ]), - ...mapActions('map', [ - 'INITIATE_MAP' - ]), - ...mapActions('feature_type', [ - 'GET_IMPORTS' - ]), - ...mapActions('feature', [ - 'GET_PROJECT_FEATURES' - ]), - ...mapActions('feature_type', [ - 'GET_PROJECT_FEATURE_TYPES' - ]), + ...mapMutations(['SET_RELOAD_INTERVAL_ID', 'CLEAR_RELOAD_INTERVAL_ID']), + ...mapActions(['GET_PROJECT_INFO']), + ...mapActions('map', ['INITIATE_MAP']), + ...mapActions('feature_type', ['GET_IMPORTS']), + ...mapActions('feature', ['GET_PROJECT_FEATURES']), + ...mapActions('feature_type', ['GET_PROJECT_FEATURE_TYPES']), refreshId() { return '?ver=' + Math.random(); }, @@ -849,7 +836,9 @@ export default { }, isImporting(type) { if (this.importFeatureTypeData) { - const singleImportData = this.importFeatureTypeData.find(el => el.feature_type_title === type.slug); + const singleImportData = this.importFeatureTypeData.find( + (el) => el.feature_type_title === type.slug + ); return singleImportData && singleImportData.status === 'pending'; } return false; @@ -878,8 +867,7 @@ export default { .then((response) => { if (response.status === 201 && response.data) { return 'OK'; - } - else{ + } else { self.arraysOfflineErrors.push(feature); } }) @@ -898,8 +886,7 @@ export default { .then((response) => { if (response.status === 200 && response.data) { return 'OK'; - } - else{ + } else { self.arraysOfflineErrors.push(feature); } }) @@ -926,7 +913,9 @@ export default { (x) => x.project !== this.project.slug ); this.arraysOffline = []; - arraysOffline = arraysOfflineOtherProject.concat(this.arraysOfflineErrors); + arraysOffline = arraysOfflineOtherProject.concat( + this.arraysOfflineErrors + ); localStorage.setItem('geocontrib_offline', JSON.stringify(arraysOffline)); }, @@ -1020,7 +1009,7 @@ export default { project_slug: this.slug, ordering: '-created_on', limit: null, - geojson: true + geojson: true, }) .then(() => { this.featuresLoading = false; @@ -1030,13 +1019,11 @@ export default { this.featuresLoading = false; }); - featureAPI - .getFeaturesBbox(this.project.slug) - .then((bbox) => { - if (bbox) { - mapUtil.getMap().fitBounds(bbox, { padding: [25, 25] }); - } - }); + featureAPI.getFeaturesBbox(this.project.slug).then((bbox) => { + if (bbox) { + mapUtil.getMap().fitBounds(bbox, { padding: [25, 25] }); + } + }); } }, }, @@ -1082,7 +1069,7 @@ export default { cursor: pointer; padding-top: 1em; } -.nouveau-type-signalement > a > .ui > .label{ +.nouveau-type-signalement > a > .ui > .label { cursor: pointer; } diff --git a/src/views/project/Project_mapping.vue b/src/views/project/Project_mapping.vue index 2c2bb7c1..c8b110ab 100644 --- a/src/views/project/Project_mapping.vue +++ b/src/views/project/Project_mapping.vue @@ -37,7 +37,7 @@ @click="addBasemap" > <i class="ui plus icon" /> - <span>Créer un fond cartographique</span> + <span> Créer un fond cartographique</span> </a> </div> @@ -51,14 +51,15 @@ :basemap="basemap" /> </div> - - <button - type="button" - class="ui teal icon floated button" - @click="saveChanges" - > - <i class="white save icon" /> Enregistrer les changements - </button> + <div class="margin-top"> + <button + type="button" + class="ui teal icon floated button" + @click="saveChanges" + > + <i class="white save icon" /> Enregistrer les changements + </button> + </div> </form> </div> </template> diff --git a/src/views/project/Project_members.vue b/src/views/project/Project_members.vue index 1426d182..4683a901 100644 --- a/src/views/project/Project_members.vue +++ b/src/views/project/Project_members.vue @@ -13,8 +13,6 @@ > <div class="two fields"> <div class="field"> - <!-- <label :for="">{{ form.title.label }}</label> --> - <!-- <input type="text" v-model="newMember.name" /> --> <Dropdown :options="userOptions" :selected="newMember.user.name" @@ -35,7 +33,6 @@ </ul> </div> <div class="field"> - <!-- <label for="add-member"></label> --> <Dropdown :options="levelOptions" :selected="newMember.role.name" @@ -45,16 +42,15 @@ </div> <button type="button" - class="ui teal icon button" + class="ui green icon button" + :disabled="newMember.user" @click="addMember" > - <i class="white save icon" /> + <i class="white add icon" /> <span class="padding-1">Ajouter</span> </button> </div> - <!-- <input type="text" v-model="newMember.name" /> --> - <h4>Modifier le rôle d'un membre</h4> <div id="form-members" @@ -123,7 +119,7 @@ class="ui teal icon button" @click="saveMembers" > - <i class="white save icon" /> Enregistrer les changements + <i class="white save icon" /> Enregistrer les changements </button> </div> </div> -- GitLab