diff --git a/src/App.vue b/src/App.vue index dccd05c731c3d81a39eb2ef7828dab392f1e9ee3..b1870d169983c1f172a4d49f6da21662faa7abe3 100644 --- a/src/App.vue +++ b/src/App.vue @@ -233,4 +233,3 @@ export default { } </style> - \ No newline at end of file diff --git a/src/assets/styles/openlayers-custom.css b/src/assets/styles/openlayers-custom.css index ef166900416817fd8d378f718ce137fae9436022..ffe44fb78c62f6d62f937928f7027a6faf998d98 100644 --- a/src/assets/styles/openlayers-custom.css +++ b/src/assets/styles/openlayers-custom.css @@ -18,7 +18,7 @@ padding: 0; } -.ol-control button{ +.ol-control button { background-color: #fff; color: #000; height: 30px; @@ -34,6 +34,34 @@ background-color: #ebebeb; } +.editionToolbar { + border: 2px solid rgba(0,0,0,.2); + background-clip: padding-box; + padding: 0; + right: 5px; +} + +.leaflet-bar { + box-shadow: none !important; +} + +.leaflet-bar a { + background-color: #fff; + color: #000; + height: 30px !important; + width: 30px !important; + font: 700 16px Lucida Console,Monaco,monospace; + margin: 0; +} +.leaflet-bar a:hover { + cursor: pointer; + background-color: #ebebeb; +} + +.leaflet-bar a > i { + margin: 0; +} + /* For geocoder search bar */ .multiselect { diff --git a/src/axios-client.js b/src/axios-client.js index 70640ddf1fb421bc193b29d99f9b30402f9aebe7..8931d1a81697ab75961be4f76934ba94f20be106 100644 --- a/src/axios-client.js +++ b/src/axios-client.js @@ -32,4 +32,4 @@ axios.interceptors.response.use(function (response) { return Promise.reject(error); }); -export default axios; \ No newline at end of file +export default axios; diff --git a/src/components/Account/UserProfile.vue b/src/components/Account/UserProfile.vue index 1b8c6aa24f6c1de1b74a8a26eb2b0b1b2369c74d..b72def753e894028f02780f9de4e7ec486f4b7d2 100644 --- a/src/components/Account/UserProfile.vue +++ b/src/components/Account/UserProfile.vue @@ -74,7 +74,3 @@ export default { }; </script> - -<style lang="less" scoped> - -</style> diff --git a/src/components/Feature/Detail/FeatureAttachements.vue b/src/components/Feature/Detail/FeatureAttachements.vue index f64f1fd904e4fd6b114653edc0b9702f23eb0158..a7eb4be122b7d58a230e6b07da9e1dcc203eeb7b 100644 --- a/src/components/Feature/Detail/FeatureAttachements.vue +++ b/src/components/Feature/Detail/FeatureAttachements.vue @@ -45,7 +45,7 @@ <script> export default { - + name: 'FeatureAttachements', props: { diff --git a/src/components/FeatureType/FeatureTypeLink.vue b/src/components/FeatureType/FeatureTypeLink.vue index 1cb2fb5ec628a352a544b741889abfdfffc1571e..d39330e1439d31d42c6e6efa2b121e04f8d7166f 100644 --- a/src/components/FeatureType/FeatureTypeLink.vue +++ b/src/components/FeatureType/FeatureTypeLink.vue @@ -35,7 +35,9 @@ export default { props: { featureType : { type: Object, - default: () => {}, + default: () => { + return {}; + }, } }, }; diff --git a/src/components/ImportTask.vue b/src/components/ImportTask.vue index 8db144cf5666e73cdaff4ba3fec6d283bbbd4b24..755a1658b414cea26d430c117d1c659a6cd11280 100644 --- a/src/components/ImportTask.vue +++ b/src/components/ImportTask.vue @@ -86,12 +86,11 @@ export default { filters: { setDate: function (value) { const date = new Date(value); - const d = date.toLocaleDateString('fr', { + return date.toLocaleDateString('fr', { year: 'numeric', month: 'long', day: 'numeric', }); - return d; }, subString: function (value) { return value.substring(0, 27) + '..'; @@ -171,7 +170,7 @@ i.icon { @-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } } @keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } } -/* +/* Max width before this PARTICULAR table gets nasty This query will take effect for any screen smaller than 760px and also iPads specifically. diff --git a/src/components/Map/EditingToolbar.vue b/src/components/Map/EditingToolbar.vue index 52a995a4258c13d4247a78982af50210a6172870..e0d7f4a975dbde278d4b83fe8fd9a2b076ff1140 100644 --- a/src/components/Map/EditingToolbar.vue +++ b/src/components/Map/EditingToolbar.vue @@ -1,9 +1,9 @@ <template> <div class="editionToolbar"> <div v-if="showDrawTool"> - <div class="leaflet-bar "> - <a - class="leaflet-draw-draw-polygon" + <div class="leaflet-bar"> + <a + class="leaflet-draw-draw-polygon" title="Dessiner un polygone" > <img @@ -30,7 +30,7 @@ <i class="edit outline icon" /> <span class="sr-only">Modifier l'objet</span></a> <a @click="deleteObj"> - <i class="trash alternate outline icon" /> + <i class="trash alternate outline icon" /> <span class="sr-only">Supprimer l'objet</span></a> </div> </div> @@ -57,39 +57,35 @@ export default { }, methods: { update(){ - console.log(this.editionService.editing_feature); editionService.activeUpdateFeature(); }, deleteObj(){ editionService.activeDeleteFeature(); }, - + } }; </script> <style scoped> -.list-image-type{ - - height: 20px; - vertical-align: middle; -} .editionToolbar{ position: absolute; top: 80px; right: 5px; } .leaflet-bar { - box-shadow: 0 1px 5px rgba(0,0,0,0.65); - border-radius: 4px; + border: 2px solid rgba(0,0,0,.2); + background-clip: padding-box; + padding: 0; + border-radius: 2px; } .leaflet-bar a:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; } .leaflet-bar a:last-child { - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; border-bottom: none; } .leaflet-bar a, .leaflet-control-layers-toggle { @@ -97,15 +93,29 @@ export default { background-repeat: no-repeat; display: block; } -.leaflet-bar a, .leaflet-bar a:hover { +.leaflet-bar a { background-color: #fff; - border-bottom: 1px solid #ccc; - width: 26px; - height: 26px; - line-height: 26px; + width: 30px; + height: 30px; display: block; text-align: center; text-decoration: none; color: black; } +.leaflet-bar a > i { + margin: 0; + vertical-align: middle; +} +.list-image-type { + height: 20px; + vertical-align: middle; + margin: 5px 0 5px 0; +} +.leaflet-bar a:hover { + cursor: pointer; + background-color: #ebebeb; +} +.leaflet-bar a:focus { + background-color: #ebebeb; +} </style> diff --git a/src/components/Map/Geocoder.vue b/src/components/Map/Geocoder.vue index aa7f4d47c6192ae670b9b86a8860401fd620df05..ca03d145b7a7af5e46d473682174e48e44be8b14 100644 --- a/src/components/Map/Geocoder.vue +++ b/src/components/Map/Geocoder.vue @@ -1,7 +1,18 @@ <template> - <div class="geocoder"> + <div + :class="{ expanded: isExpanded }" + class="geocoder-container" + > + <button + class="button-geocoder" + @click="isExpanded = !isExpanded" + > + <i class="search icon" /> + </button> <Multiselect + v-if="isExpanded" v-model="selection" + class="expanded-geocoder" :options="addresses" :options-limit="5" :allow-empty="true" @@ -78,7 +89,8 @@ export default { selectedAddress: null, addresses: [], resultats: [], - placeholder: 'Rechercher une adresse ...' + placeholder: 'Rechercher une adresse ...', + isExpanded: false }; }, mounted() { @@ -87,7 +99,6 @@ export default { }, methods: { getAddresses(query){ - // let self = this; const limit = 5; apiAdressAxios.get(`https://api-adresse.data.gouv.fr/search/?q=${query}&limit=${limit}`) .then((retour) => { @@ -106,8 +117,6 @@ export default { zoomlevel = 16; } else if (type === 'locality') { zoomlevel = 16; - } else if (type === 'municipality') { - zoomlevel = 14; } // On fait le zoom mapService.zoomTo(this.selectedAddress.geometry.coordinates, zoomlevel); @@ -131,24 +140,59 @@ export default { </script> <style scoped lang="less"> -.geocoder{ - max-width: 400px; - right: 500px; +.geocoder-container { position: absolute; - top: 0.5em; + right: 0.5em; + top: calc(1em + 60px); pointer-events: auto; z-index: 50000; border: 2px solid rgba(0,0,0,.2); background-clip: padding-box; padding: 0; border-radius: 2px; + display: flex; + + .button-geocoder { + border: none; + padding: 0; + margin: 0; + text-align: center; + background-color: #fff; + color: rgb(39, 39, 39); + width: 28px; + height: 28px; + font: 700 18px Lucida Console,Monaco,monospace; + border-radius: 2px; + line-height: 1.15; + + i { + margin: 0; + font-size: 0.9em; + } + } + .button-geocoder:hover { + cursor: pointer; + background-color: #ebebeb; + } + + .expanded-geocoder { + max-width: 400px; + } +} + +.expanded { + .button-geocoder { + height: 40px; + color: rgb(99, 99, 99); + } } + #marker { - width: 20px; - height: 20px; - border: 1px solid rgb(136, 66, 0); - border-radius: 10px; - background-color: rgb(201, 114, 15); - opacity: 0.7; + width: 20px; + height: 20px; + border: 1px solid rgb(136, 66, 0); + border-radius: 10px; + background-color: rgb(201, 114, 15); + opacity: 0.7; } </style> diff --git a/src/components/Project/Basemaps/ProjectMappingContextLayer.vue b/src/components/Project/Basemaps/ProjectMappingContextLayer.vue index 93f720837dc1663695487d211cd3658e17344b74..1ec4ccd10e5907ea40783bd6f55cf30b11fad6b5 100644 --- a/src/components/Project/Basemaps/ProjectMappingContextLayer.vue +++ b/src/components/Project/Basemaps/ProjectMappingContextLayer.vue @@ -47,7 +47,7 @@ > <input :checked="layer.queryable" - class="hidden" + class="hidden" type="checkbox" name="queryable" > diff --git a/src/components/Project/Detail/ProjectFeatureTypes.vue b/src/components/Project/Detail/ProjectFeatureTypes.vue index 8ffd93f598e4c1f5e5a6be1e5f26fffbfe84b8b3..5cce295500d533837581acdbc0c18327de1355a8 100644 --- a/src/components/Project/Detail/ProjectFeatureTypes.vue +++ b/src/components/Project/Detail/ProjectFeatureTypes.vue @@ -195,127 +195,153 @@ </div> </div> - <div id="nouveau-type-signalement"> - <router-link - v-if=" - permissions && - permissions.can_update_project && - isOnline - " - :to="{ - name: 'ajouter-type-signalement', - params: { slug }, - }" - class="ui compact basic button" - > - <i - class="ui plus icon" - aria-hidden="true" - /> - Créer un nouveau type de signalement - </router-link> - </div> - <div class="nouveau-type-signalement"> + <div class="nouveau-type-signalement-container"> <div - v-if=" - permissions && - permissions.can_update_project && - isOnline - " class=" ui - compact - basic + small button - button-align-left + circular + compact + floated + right + icon + teal " + data-tooltip="Consulter la documentation" + data-position="bottom right" + data-variation="mini" > <i - class="ui plus icon" - aria-hidden="true" + class="question icon" + @click="goToDocumentation" /> - <label - class="ui" - for="json_file" - > - <span - class="label" - >Créer un nouveau type de signalement à partir d'un - GeoJSON</span> - </label> - <input - id="json_file" - type="file" - accept="application/json, .json, .geojson" - style="display: none" - name="json_file" - @change="onGeoJSONFileChange" - > </div> - </div> - <div class="nouveau-type-signalement"> - <div - v-if=" - permissions && - permissions.can_update_project && - isOnline - " - class=" - ui - compact - basic - button - button-align-left - " - > - <i - class="ui plus icon" - aria-hidden="true" - /> - <label - class="ui" - for="csv_file" + <div id="nouveau-type-signalement"> + <router-link + v-if=" + permissions && + permissions.can_update_project && + isOnline + " + :to="{ + name: 'ajouter-type-signalement', + params: { slug }, + }" + class="ui compact basic button" > - <span - class="label" - >Créer un nouveau type de signalement à partir d'un - CSV</span> - </label> - <input - id="csv_file" - type="file" - accept="application/csv, .csv" - style="display: none" - name="csv_file" - @change="onCSVFileChange" + <i + class="ui plus icon" + aria-hidden="true" + /> + Créer un nouveau type de signalement + </router-link> + </div> + + <div class="nouveau-type-signalement"> + <div + v-if=" + permissions && + permissions.can_update_project && + isOnline + " + class=" + ui + compact + basic + button + button-align-left + " > + <i + class="ui plus icon" + aria-hidden="true" + /> + <label + class="ui" + for="json_file" + > + <span + class="label" + >Créer un nouveau type de signalement à partir d'un + GeoJSON</span> + </label> + <input + id="json_file" + type="file" + accept="application/json, .json, .geojson" + style="display: none" + name="json_file" + @change="onGeoJSONFileChange" + > + </div> </div> - </div> - <div class="nouveau-type-signalement"> - <router-link - v-if=" - IDGO && + <div class="nouveau-type-signalement"> + <div + v-if=" permissions && - permissions.can_update_project && - isOnline - " - :to="{ - name: 'catalog-import', - params: { - slug, - feature_type_slug: 'create' - }, - }" - class="ui compact basic button button-align-left" - > - <i - class="ui plus icon" - aria-hidden="true" - /> - Créer un nouveau type de signalement à partir du catalogue {{ CATALOG_NAME|| 'IDGO' }} - </router-link> + permissions.can_update_project && + isOnline + " + class=" + ui + compact + basic + button + button-align-left + " + > + <i + class="ui plus icon" + aria-hidden="true" + /> + <label + class="ui" + for="csv_file" + > + <span + class="label" + > + Créer un nouveau type de signalement à partir d'un CSV + </span> + </label> + <input + id="csv_file" + type="file" + accept="application/csv, .csv" + style="display: none" + name="csv_file" + @change="onCSVFileChange" + > + </div> + </div> + + <div class="nouveau-type-signalement"> + <router-link + v-if=" + IDGO && + permissions && + permissions.can_update_project && + isOnline + " + :to="{ + name: 'catalog-import', + params: { + slug, + feature_type_slug: 'create' + }, + }" + class="ui compact basic button button-align-left" + > + <i + class="ui plus icon" + aria-hidden="true" + /> + Créer un nouveau type de signalement à partir du catalogue {{ CATALOG_NAME|| 'IDGO' }} + </router-link> + </div> </div> <div @@ -366,7 +392,7 @@ <!-- MODALE FILESIZE --> <div :class="isFileSizeModalOpen ? 'active' : ''" - class="ui dimmer" + class="ui dimmer inverted" > <div :class="isFileSizeModalOpen ? 'active' : ''" @@ -403,7 +429,7 @@ import { fileConvertSizeToMo, csvToJson } from '@/assets/js/utils'; import FeatureTypeLink from '@/components/FeatureType/FeatureTypeLink'; export default { - + name: 'ProjectFeatureTypes', components: { @@ -417,7 +443,9 @@ export default { }, project: { type: Object, - default: () => {}, + default: () => { + return {}; + }, } }, @@ -529,6 +557,10 @@ export default { return false; }, + goToDocumentation() { + window.open('https://geocontrib.readthedocs.io/fr/latest/documentation_fonctionnelle/import_export/'); + }, + toNewGeojsonFeatureType() { this.importing = true; this.$router.push({ @@ -567,8 +599,8 @@ export default { } else if (this.geojsonFileToImport.size > 0) { const fr = new FileReader(); try { - fr.onload = (e) => { - this.geojsonImport = JSON.parse(e.target.result); + fr.onload = (ev) => { + this.geojsonImport = JSON.parse(ev.target.result); this.importing = false; }; fr.readAsText(this.geojsonFileToImport); @@ -628,7 +660,7 @@ export default { .split('\n')[1] .split(delimiter) .map(el => { - return !isNaN(el) && el.indexOf('.') != -1; + return !isNaN(el) && el.indexOf('.') !== -1; }) .filter(Boolean); if (sampleLine.length > 1 && headersLine.length === 2) { @@ -688,6 +720,21 @@ export default { width: 50%; } +.feature-type-title { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 1.5em; +} + +.nouveau-type-signalement-container { + .help { + position: absolute; + right: 0.5em; + cursor: pointer; + } +} + .nouveau-type-signalement { margin-top: 1em; } diff --git a/src/components/Project/Detail/ProjectHeader.vue b/src/components/Project/Detail/ProjectHeader.vue index 8526c9ac8c8a25ee6bf82aff880c735110a85223..c56cb750c0414bee19ffb6b72641c8d9a73d1862 100644 --- a/src/components/Project/Detail/ProjectHeader.vue +++ b/src/components/Project/Detail/ProjectHeader.vue @@ -283,7 +283,7 @@ export default { justify-content: flex-end; a.ui.button { flex-grow: 0; /* avoid stretching buttons */ - } + } } } .centered { diff --git a/src/components/Project/Detail/ProjectModal.vue b/src/components/Project/Detail/ProjectModal.vue index 8ce274e2e9249dd4dd323c701defb2ff17554e77..2a1914416a124c13601bbb2f1a0f26e2b3e1c9f4 100644 --- a/src/components/Project/Detail/ProjectModal.vue +++ b/src/components/Project/Detail/ProjectModal.vue @@ -51,7 +51,7 @@ }} </span> <span v-else> - Supprimer le + Supprimer le {{ projectModalType === 'deleteProject' ? 'projet' diff --git a/src/components/Project/FeaturesListAndMap/FeatureListTable.vue b/src/components/Project/FeaturesListAndMap/FeatureListTable.vue index 90a1fa99b665797bc58c8f4e3c507a05c1ee5d16..00cd492a07e6e848e008e403b04dd46332178a45 100644 --- a/src/components/Project/FeaturesListAndMap/FeatureListTable.vue +++ b/src/components/Project/FeaturesListAndMap/FeatureListTable.vue @@ -476,7 +476,7 @@ export default { return this.canEditFeature(feature); case 'delete': return this.canDeleteFeature(feature); - } + } }, switchMode() { @@ -614,7 +614,7 @@ i.icon.sort:not(.down):not(.up) { display: none !important; } } -/* +/* Max width before this PARTICULAR table gets nasty This query will take effect for any screen smaller than 760px and also iPads specifically. @@ -728,4 +728,4 @@ and also iPads specifically. border: none; } } -</style> \ No newline at end of file +</style> diff --git a/src/components/Project/FeaturesListAndMap/FeaturesListAndMapFilters.vue b/src/components/Project/FeaturesListAndMap/FeaturesListAndMapFilters.vue index 7efacba5638f674bb8d01784d6edee6dcb2bb811..4e624f10378ccc3b988577ab543db618af3d6ee8 100644 --- a/src/components/Project/FeaturesListAndMap/FeaturesListAndMapFilters.vue +++ b/src/components/Project/FeaturesListAndMap/FeaturesListAndMapFilters.vue @@ -331,7 +331,7 @@ export default { this.showModifyStatus = false; }, } - + }; </script> diff --git a/src/main.js b/src/main.js index 596735b966f3352948a6864b18c2897d64e91ae2..b5349516c720d93548c7d28f154d89092d7ebd3e 100644 --- a/src/main.js +++ b/src/main.js @@ -44,7 +44,7 @@ const onConfigLoaded = function(config){ }, 10000); // set title and favico - document.title= config.VUE_APP_APPLICATION_NAME+' '+config.VUE_APP_APPLICATION_ABSTRACT; + document.title = `${config.VUE_APP_APPLICATION_NAME} ${config.VUE_APP_APPLICATION_ABSTRACT}`; const link = document.createElement('link'); link.id = 'dynamic-favicon'; link.rel = 'shortcut icon'; diff --git a/src/router/index.js b/src/router/index.js index 7ace42e5e9c877a9d52cba925d3fb2521981fcb3..a1c91228b4e5218d3837b5e85256d456d20d2cfe 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -16,12 +16,12 @@ const routes = [ component: ProjectsList }, { - path: `${projectBase === 'projet' ? '': '/' + projectBase + '/:slug'}/connexion/`, + path: `${projectBase === 'projet' ? '': `/${projectBase}/:slug`}/connexion/`, name: 'login', component: () => import('../views/Login.vue') }, { - path: `${projectBase === 'projet' ? '': '/' + projectBase + '/:slug'}/my_account/`, + path: `${projectBase === 'projet' ? '': `/${projectBase}/:slug`}/my_account/`, name: 'my_account', component: () => import('../views/Account.vue') }, diff --git a/src/service-worker.js b/src/service-worker.js index ae6b3aff91d2052812dc4111ff512321d3b33870..20f36c2c81055fd5d31ab0efd946e79e03fe67dd 100644 --- a/src/service-worker.js +++ b/src/service-worker.js @@ -5,7 +5,7 @@ if (workbox) { //workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug) // apply precaching. In the built version, the precacheManifest will - // be imported using importScripts (as is workbox itself) and we can + // be imported using importScripts (as is workbox itself) and we can // precache this. This is all we need for precaching workbox.precaching.precacheAndRoute(self.__precacheManifest); diff --git a/src/services/edition-service.js b/src/services/edition-service.js index 2930278b6a4ca9960ebd12d762cfd32e8bccaeb4..dffdb9153beddf50d8da416f539b14d3f83b0c7a 100644 --- a/src/services/edition-service.js +++ b/src/services/edition-service.js @@ -90,7 +90,6 @@ const editionService = { this.draw.on('drawend', (evt) => { var feature = evt.feature; - console.log(feature); this.setEditingFeature(feature); this.draw.setActive(false); }); @@ -132,10 +131,10 @@ const editionService = { // May be corrected in a future version this.modify.handleUpEvent_old = this.modify.handleUpEvent; this.modify.handleUpEvent = function (evt) { - try { + try { this.handleUpEvent_old(evt); - } catch (ex) { - console.log(ex); + } catch (ex) { + console.log(ex); } }; @@ -199,7 +198,7 @@ const editionService = { this.selectForDeletion = new Select({ style: style }); mapService.getMap().addInteraction(this.selectForDeletion); // Lorsque de nouvelles features sont sélectionnées - let selected_features = this.selectForDeletion.getFeatures(); + const selected_features = this.selectForDeletion.getFeatures(); this.listenerKey = selected_features.on('add', (evt) => { var feature = evt.element; if (feature) { @@ -224,4 +223,4 @@ const editionService = { }; -export default editionService; \ No newline at end of file +export default editionService; diff --git a/src/services/map-service.js b/src/services/map-service.js index 968dfe430df41abbd126b9403a0180d1fe9a20bd..7a9afd5e6c7d5643bb181dec4c62aa067b78472b 100644 --- a/src/services/map-service.js +++ b/src/services/map-service.js @@ -57,7 +57,7 @@ const mapService = { return this.map; }, destroyMap() { - this.map=undefined; + this.map = undefined; }, createMap(el, options) { const { @@ -69,7 +69,11 @@ const mapService = { zoomControl = true, interactions = { doubleClickZoom: false, mouseWheelZoom: false, dragPan: true }, } = options; - console.log(options, zoomControl); + + if (el.innerHTML) { + el.innerHTML = ''; + } + this.map = new Map({ layers: [], target: el, @@ -88,7 +92,7 @@ const mapService = { zoom: !zoom ? mapDefaultViewZoom : zoom }), }); - + if (zoomControl) { this.map.addControl(new Zoom({ zoomInTipLabel: 'Zoomer', zoomOutTipLabel: 'Dézoomer' })); } @@ -107,26 +111,26 @@ const mapService = { }, }); let overlay = this.overlay; - closer.onclick = function () { - overlay.setPosition(undefined); - closer.blur(); - return false; - }; + if (closer) { + closer.onclick = function () { + overlay.setPosition(undefined); + closer.blur(); + return false; + }; + } this.map.addOverlay(this.overlay); this.map.on('click', this.onMapClick.bind(this)); return this.map; }, - + onMapClick(event) { - console.log(event); let self = this; const features = this.map.getFeaturesAtPixel(event.pixel, { layerFilter(l) { return l === self.mvtLayer; }, }); - console.log(features); if (features && features.length > 0) { const popupContent = this._createContentPopup(features[0], this.mvtLayer.featureTypes, this.mvtLayer.project_slug); @@ -134,12 +138,10 @@ const mapService = { this.overlay.setPosition(event.coordinate); } //const queryableLayerSelected = document.getElementById(`queryable-layers-selector-${this.wmsParams.basemapId}`).getElementsByClassName('selected')[0].textContent; - //console.log(queryableLayerSelected); if (this.layers) { - console.log(this.layers.find(x => x.query)); - let queryLayer = this.layers.find(x => x.query); + const queryLayer = this.layers.find(x => x.query); // pour compatibilité avec le proxy django - let proxyparams = [ + const proxyparams = [ 'request', 'service', 'srs', @@ -152,15 +154,14 @@ const mapService = { 'info_format', 'x', 'y', 'i', 'j', ]; if (queryLayer) { - console.log('get feature infos'); - let url = this.getFeatureInfoUrl(event, queryLayer); - console.log(url); - let urlInfos = url.split('?'); + const url = this.getFeatureInfoUrl(event, queryLayer); + const urlInfos = url.split('?'); const urlParams = new URLSearchParams(urlInfos[1]); - let params = {}; + const params = {}; Array.from(urlParams.keys()).forEach(param => { - if (proxyparams.indexOf(param.toLowerCase()) >= 0) + if (proxyparams.indexOf(param.toLowerCase()) >= 0) { params[param.toLowerCase()] = urlParams.get(param); + } }); params.url = urlInfos[0]; let self = this; @@ -170,7 +171,7 @@ const mapService = { params: params, } ).then(response => { - let data = response.data; + const data = response.data; var err = typeof data === 'object' ? null : data; if (data.features || err) { self.showGetFeatureInfo(err, event, data, queryLayer); @@ -199,7 +200,7 @@ const mapService = { } else { // Otherwise show the content in a popup - let contentLines = []; + const contentLines = []; let contentTitle; if (data.features.length > 0) { Object.entries(data.features[0].properties).forEach(entry => { @@ -218,18 +219,17 @@ const mapService = { } }, getFeatureInfoUrl(event, layer) { - let olLayer = dictLayersToLeaflet[layer.id]; + const olLayer = dictLayersToLeaflet[layer.id]; const source = olLayer.getSource(); const viewResolution = this.map.getView().getResolution(); let url; - let wmsOptions = { info_format: 'application/json', query_layers: layer.options.layers }; + const wmsOptions = { info_format: 'application/json', query_layers: layer.options.layers }; if (source && source.getFeatureInfoUrl) { url = source.getFeatureInfoUrl(event.coordinate, viewResolution, 'EPSG:3857', wmsOptions); } return url; }, fitBounds(bounds) { - console.log(bounds); let ext = boundingExtent([[bounds[0][1], bounds[0][0]], [bounds[1][1], bounds[1][0]]]); ext = transformExtent(ext, 'EPSG:4326', 'EPSG:3857'); this.map.getView().fit(ext, { padding: [25, 25, 25, 25] }); @@ -242,17 +242,15 @@ const mapService = { }, addLayers: function (layers, serviceMap, optionsMap, schemaType) { - console.log('addLayers'); this.layers = layers; if (layers) { //* if admin has defined basemaps for this project layers.forEach((layer) => { if (layer) { - let options = layer.options; + const options = layer.options; if (options) { options.noWrap = true; options.opacity = layer.opacity; if (layer.schema_type === 'wms') { - console.log(layer); if (layer.queryable) { options.title = layer.title; dictLayersToLeaflet[layer.id] = this.addWMSLayer(layer.service, options); @@ -340,34 +338,32 @@ const mapService = { } }, - addVectorTileLayer: function (url, project_id, project_slug, featureTypes, form_filters) { - console.log(url, project_slug, featureTypes, form_filters); + addVectorTileLayer: function (url, projectId, projectSlug, featureTypes, formFilters) { let format_cfg = {/*featureClass: Feature*/ }; - let mvt = new MVT(format_cfg); - let options = { + const mvt = new MVT(format_cfg); + const options = { urls: [], matrixSet: 'EPSG:3857' }; options.format = mvt; - let layerSource = new VectorTileSource(options); + const layerSource = new VectorTileSource(options); layerSource.setTileUrlFunction((p0) => { - return url+'/?tile=' + p0[0] + '/' + p0[1] + '/' + p0[2] + '&project_id=' + project_id; + return `${url}/?tile=${p0[0]}/${p0[1]}/${p0[2]}&project_id=${projectId}`; }); - const styleFunction = (feature) => this.getStyle(feature, featureTypes, form_filters); + const styleFunction = (feature) => this.getStyle(feature, featureTypes, formFilters); this.mvtLayer = new VectorTileLayer({ style: styleFunction, source: layerSource }); this.mvtLayer.featureTypes = featureTypes; - this.mvtLayer.project_slug = project_slug; + this.mvtLayer.project_slug = projectSlug; this.map.addLayer(this.mvtLayer); window.layerMVT = this.mvtLayer; }, - getStyle: function (feature, featureTypes, form_filters) { - //console.log(form_filters); - let properties = feature.getProperties(); + getStyle: function (feature, featureTypes, formFilters) { + const properties = feature.getProperties(); let featureType; // GeoJSON if(properties.feature_type){ @@ -376,14 +372,13 @@ const mapService = { } else { //MVT featureType = featureTypes.find((x) => x.slug.split('-')[0] === '' + properties.feature_type_id); } - //console.log(featureType); const color = this.retrieveFeatureColor(featureType, properties); const colorValue = color.value && color.value.length ? color.value : typeof color === 'string' && color.length ? color : '#000000'; - let rgbaColor = asArray(colorValue); + const rgbaColor = asArray(colorValue); rgbaColor[3] = 0.5;//opacity const hiddenStyle = new Style(); @@ -418,49 +413,48 @@ const mapService = { ); // Filtre sur le feature type - if(form_filters){ - if (form_filters.type && form_filters.type.selected) { - if (featureType.title !== form_filters.type.selected) { + if(formFilters){ + if (formFilters.type && formFilters.type.selected) { + if (featureType.title !== formFilters.type.selected) { return hiddenStyle; } } // Filtre sur le statut - if (form_filters.status && form_filters.status.selected.value) { - if (properties.status !== form_filters.status.selected.value) { + if (formFilters.status && formFilters.status.selected.value) { + if (properties.status !== formFilters.status.selected.value) { return hiddenStyle; } } // Filtre sur le titre - if (form_filters.title) { - if (!properties.title.toLowerCase().includes(form_filters.title.toLowerCase())) { + if (formFilters.title) { + if (!properties.title.toLowerCase().includes(formFilters.title.toLowerCase())) { return hiddenStyle; } } } - + return defaultStyle; }, - addFeatures: function (features, filter, addToMap = true, featureTypes) { - console.log(features, filter, addToMap, featureTypes); - let drawSource = new VectorSource(); + addFeatures: function (features, filter, featureTypes, addToMap = true) { + console.log(addToMap); + const drawSource = new VectorSource(); let retour; // TODO verifier utilité de cette boucle et remplacer par readFeatures plutot features.forEach((feature) => { - console.log(feature); retour = new GeoJSON().readFeature(feature, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }); drawSource.addFeature(retour); - const featureProperties = feature.properties ? feature.properties : feature; - 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; - const statusCheck = filter.featureStatus && featureProperties.status.value === filter.featureStatus; - const titleCheck = filter.featureTitle && featureProperties.title.includes(filter.featureTitle); - filters = [typeCheck, statusCheck, titleCheck]; - } - console.log(featureType, filters); + // const featureProperties = feature.properties ? feature.properties : feature; + // 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; + // const statusCheck = filter.featureStatus && featureProperties.status.value === filter.featureStatus; + // const titleCheck = filter.featureTitle && featureProperties.title.includes(filter.featureTitle); + // filters = [typeCheck, statusCheck, titleCheck]; + // } + // console.log(featureType, filters); }); const styleFunction = (feature) => this.getStyle(feature, featureTypes, filter); @@ -554,7 +548,6 @@ const mapService = { addOverlay(loc) { var pos = fromLonLat(loc); - console.log(loc); var marker = new Overlay({ position: pos, positioning: OverlayPositioning.CENTER_CENTER, diff --git a/src/store/modules/feature-type.store.js b/src/store/modules/feature-type.store.js index 6d15c719a6a458e9d55df5f60a9e87d9ef218f31..5eb1b790d5460376b3d24ee7785dcb29efce1f24 100644 --- a/src/store/modules/feature-type.store.js +++ b/src/store/modules/feature-type.store.js @@ -271,4 +271,4 @@ const feature_type = { } }; -export default feature_type; \ No newline at end of file +export default feature_type; diff --git a/src/store/modules/feature.store.js b/src/store/modules/feature.store.js index 18bb83f3346c11aa14db88a9a8114dd73bba68c7..b652e83445ea0ad34d018e0bdeeecf15efa0a9c0 100644 --- a/src/store/modules/feature.store.js +++ b/src/store/modules/feature.store.js @@ -124,7 +124,7 @@ const feature = { ordering, search, limit, - geojson = false + geojson = false }) { if (rootState.cancellableSearchRequest.length > 0) { const currentRequestCancelToken = @@ -241,7 +241,7 @@ const feature = { } }; } - + const geojson = createGeojson(); let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/`; if (routeName === 'editer-signalement') { @@ -301,7 +301,7 @@ const feature = { async SEND_ATTACHMENTS({ state, rootState, dispatch }, featureId) { const DJANGO_API_BASE = rootState.configuration.VUE_APP_DJANGO_API_BASE; - + function addFile(attachment, attchmtId) { const formdata = new FormData(); formdata.append('file', attachment.fileToImport, attachment.fileToImport.name); diff --git a/src/store/modules/map.store.js b/src/store/modules/map.store.js index f427678891b30ce35de3dd0477bc4a5c4f4fbf4b..1a87098abcbd86423c00101f56f2b19fcc7061c1 100644 --- a/src/store/modules/map.store.js +++ b/src/store/modules/map.store.js @@ -108,8 +108,8 @@ const map = { const mapDefaultViewCenter = [46, 2]; // defaultMapView.center; const mapDefaultViewZoom = 5; // defaultMapView.zoom; mapService.createMap(el, { - mapDefaultViewCenter, - mapDefaultViewZoom, + mapDefaultViewCenter: mapDefaultViewCenter, + mapDefaultViewZoom: mapDefaultViewZoom, }); commit('SET_MAP', mapService.getMap()); mapService.addLayers( @@ -176,4 +176,4 @@ const map = { } }, }; -export default map; \ No newline at end of file +export default map; diff --git a/src/store/modules/projects.store.js b/src/store/modules/projects.store.js index 3107a843e5ec424af0cc7740f8aedaba385345fb..4037a2cd65e0aa660162ec1e1bc8858a06240faf 100644 --- a/src/store/modules/projects.store.js +++ b/src/store/modules/projects.store.js @@ -8,7 +8,7 @@ const initialFilters = { accessible: null }; -const projects = { +const projectsStore = { namespaced: true, @@ -149,10 +149,10 @@ const projects = { rootState.cancellableSearchRequest[rootState.cancellableSearchRequest.length - 1]; currentRequestCancelToken.cancel(); } - + const cancelToken = axios.CancelToken.source(); commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true }); - + const url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/?search=${text}`; let filteredUrl; if (Object.values(state.filters).some(el => el && el.length > 0)) { @@ -163,7 +163,7 @@ const projects = { } } } - + const response = await axios.get( filteredUrl ? filteredUrl : url, { @@ -185,4 +185,4 @@ const projects = { }; -export default projects; +export default projectsStore; diff --git a/src/views/Feature/FeatureDetail.vue b/src/views/Feature/FeatureDetail.vue index 1ca1ddefb0a291ef34009b3e25b84790ab8bd31c..b8a2676c6ad7b9ecf93a87f9bb8ce6be0d73c385 100644 --- a/src/views/Feature/FeatureDetail.vue +++ b/src/views/Feature/FeatureDetail.vue @@ -303,8 +303,8 @@ export default { const featureGroup = mapService.addFeatures( response.data.features, {}, - true, - this.feature_types + this.feature_types, + true ); mapService.fitExtent(buffer(featureGroup.getExtent(),200)); } diff --git a/src/views/Feature/FeatureEdit.vue b/src/views/Feature/FeatureEdit.vue index 7c01064eef46a723dab539e1e86c7ae6849c6f53..f024fc524b7464e29341c37fc4cfe41c064e3855 100644 --- a/src/views/Feature/FeatureEdit.vue +++ b/src/views/Feature/FeatureEdit.vue @@ -220,6 +220,12 @@ class="ui tab active map-container" data-tab="map" > + <div + :class="{ active: mapLoading }" + class="ui inverted dimmer" + > + <div class="ui loader" /> + </div> <div id="map" ref="map" @@ -361,6 +367,7 @@ export default { data() { return { map: null, + mapLoading: false, baseUrl: this.$store.state.configuration.BASE_URL, file: null, showGeoRef: false, @@ -787,11 +794,9 @@ export default { onFeatureTypeLoaded() { var geomType = this.feature_type.geom_type; - console.log(geomType); editionService.addEditionControls(geomType); editionService.draw.on('drawend', (evt) => { var feature = evt.feature; - console.log('draw end'+feature); this.updateGeomField(new GeoJSON().writeGeometry(feature.getGeometry(),{ dataProjection:'EPSG:4326',featureProjection:'EPSG:3857' })); if (this.feature_type.geomType === 'point') { this.showGeoPositionBtn = false; @@ -800,7 +805,6 @@ export default { }); editionService.modify.on('modifyend', (evt) => { let feature = evt.features.getArray()[0]; - console.log(feature); this.updateGeomField(new GeoJSON().writeGeometry(feature.getGeometry(),{ dataProjection:'EPSG:4326',featureProjection:'EPSG:3857' })); }); //this.changeMobileBtnOrder(); @@ -825,7 +829,6 @@ export default { editionService.drawSource.clear(); } if (geomFeatureJSON) { - console.log('updateMap'); let retour = new GeoJSON().readFeature(geomFeatureJSON,{ dataProjection:'EPSG:4326',featureProjection:'EPSG:3857' }); editionService.startEditFeature(retour); @@ -843,6 +846,7 @@ export default { }, initMap() { + this.mapLoading = true; var mapDefaultViewCenter = this.$store.state.configuration.DEFAULT_MAP_VIEW.center; var mapDefaultViewZoom = @@ -855,17 +859,6 @@ export default { interactions : { doubleClickZoom :false, mouseWheelZoom:true, dragPan:true } }); const currentFeatureId = this.$route.params.slug_signal; - setTimeout(() => { - const project_id = this.$route.params.slug.split('-')[0]; - const mvtUrl = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features.mvt/`; - - mapService.addVectorTileLayer( - mvtUrl, - project_id, - this.$route.params.slug, - this.feature_types - ); - }, 1000); const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/?feature_type__slug=${this.$route.params.slug_type_signal}&output=geojson`; axios .get(url) @@ -878,8 +871,8 @@ export default { mapService.addFeatures( allFeaturesExceptCurrent, {}, - true, - this.feature_types + this.feature_types, + true ); if (this.currentRouteName === 'editer-signalement') { const currentFeature = features.filter( @@ -888,8 +881,10 @@ export default { this.updateMap(currentFeature); } } + this.mapLoading = false; }) .catch((error) => { + this.mapLoading = false; throw error; }); diff --git a/src/views/FeatureType/FeatureTypeDetail.vue b/src/views/FeatureType/FeatureTypeDetail.vue index 05c20fa968c90a74f906a59f368e951b30b4cbdb..6ff4e62769af70ea10197250a31e59d0db177112 100644 --- a/src/views/FeatureType/FeatureTypeDetail.vue +++ b/src/views/FeatureType/FeatureTypeDetail.vue @@ -103,7 +103,10 @@ @change="onGeojsonFileChange" > </div> - <div class="field"> + <div + v-if="structure.geom_type === 'point'" + class="field" + > <label class="ui icon button ellipsis" for="csv_file" diff --git a/src/views/FeatureType/FeatureTypeEdit.vue b/src/views/FeatureType/FeatureTypeEdit.vue index cf5af0f37dd157771c0c7cd7750bd1e34a2b5459..67d6def4ac8f5dab0ad86109b2c411d25e4f0afa 100644 --- a/src/views/FeatureType/FeatureTypeEdit.vue +++ b/src/views/FeatureType/FeatureTypeEdit.vue @@ -151,7 +151,7 @@ class="white save icon" aria-hidden="true" /> - Créer et importer le(s) signalement(s) du geojson + Créer et importer le(s) signalement(s) du {{ geojson ? 'geojson' : 'csv' }} </button> </div> </form> diff --git a/src/views/Project/FeaturesListAndMap.vue b/src/views/Project/FeaturesListAndMap.vue index 7c154a558ce81469cd7f19270bed54a89a4bd307..6b6af5454d03509df24be6f07478676b40d5138d 100644 --- a/src/views/Project/FeaturesListAndMap.vue +++ b/src/views/Project/FeaturesListAndMap.vue @@ -186,7 +186,6 @@ export default { this.currentLayer = mapService.addFeatures( this.paginatedFeatures, {}, - true, this.feature_types ); } @@ -202,7 +201,6 @@ export default { this.currentLayer = mapService.addFeatures( newValue, {}, - true, this.feature_types ); } else if (newValue && newValue.length === 0) { diff --git a/src/views/Project/ProjectDetail.vue b/src/views/Project/ProjectDetail.vue index fd98225945cffbc689776afcf9848165a631553f..452a9067c61469a8eeefc0884de1f0d0fd6eb5ea 100644 --- a/src/views/Project/ProjectDetail.vue +++ b/src/views/Project/ProjectDetail.vue @@ -61,7 +61,7 @@ /> </div> - <div class="eight wide column"> + <div class="eight wide column map-container"> <div :class="{ active: mapLoading }" class="ui inverted dimmer" @@ -70,10 +70,23 @@ Chargement de la carte... </div> </div> + <div id="map" ref="map" /> + + <div + class="ui button fluid teal" + @click="$router.push({ + name: 'liste-signalements', + params: { slug: slug }, + })" + > + <i class="ui icon arrow right" /> + Voir tous les signalements + </div> + <div id="popup" class="ol-popup" @@ -377,7 +390,7 @@ export default { .then((response) => { this.CLOSE_PROJECT_MODAL(); if (response === 'success') { - this.GET_PROJECT(); + this.GET_PROJECT(this.slug); this.retrieveProjectInfo(); this.DISPLAY_MESSAGE({ comment: `Le type de signalement ${this.featureTypeToDelete.title} a bien été supprimé.`, @@ -421,7 +434,6 @@ export default { async initMap() { if (this.project && this.permissions.can_view_project) { - console.log('initMap'); await this.INITIATE_MAP(this.$refs.map); this.checkForOfflineFeature(); let project_id = this.$route.params.slug.split('-')[0]; @@ -447,8 +459,8 @@ export default { mapService.addFeatures( [...this.features, ...featuresOffline], {}, - true, - this.feature_types + this.feature_types, + true ); }) .catch((err) => { @@ -467,10 +479,19 @@ export default { }; </script> -<style scoped> +<style lang="less" scoped> .fullwidth { width: 100%; } +.map-container { + display: flex !important; + flex-direction: column; + + .button { + margin-top: 0.5em; + } +} + </style>