diff --git a/package-lock.json b/package-lock.json index 5c65244599ec38ec18636b5cfef2ee74c1468351..a0b0d016fa8a592eee3720a160f8ce89058d0278 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "geocontrib-frontend", - "version": "2.2.0", + "version": "2.3.2-rc2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1795,6 +1795,87 @@ "webpack-chain": "^6.4.0", "webpack-dev-server": "^3.11.0", "webpack-merge": "^4.2.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "optional": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.8.3", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", + "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + } + } } }, "@vue/cli-shared-utils": { @@ -7179,8 +7260,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -11511,87 +11591,6 @@ } } }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.8.1", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.1.tgz", - "integrity": "sha512-V53TJbHmzjBhCG5OYI2JWy/aYDspz4oVHKxS43Iy212GjGIG1T3EsB3+GWXFm/1z5VwjdjLmdZUFYM70y77vtQ==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "optional": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "vue-multiselect": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.6.tgz", diff --git a/package.json b/package.json index 9c54f9e0edfd6ca848a1c84a8bcde9746b2e0b28..8f55afdbe57b2ad2089383f64f4e017bdb6981cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "geocontrib-frontend", - "version": "2.3.1", + "version": "2.3.2-rc2", "private": true, "scripts": { "serve": "npm run init-proxy & npm run init-serve", @@ -22,6 +22,7 @@ "leaflet": "^1.5.1", "leaflet-draw": "^1.0.4", "leaflet.vectorgrid": "^1.3.0", + "lodash": "^4.17.21", "pbf": "^3.2.1", "register-service-worker": "^1.7.1", "sortablejs": "^1.14.0", diff --git a/src/assets/icons/fa-icons.js b/src/assets/icons/fa-icons.js index 5e9fff5abcbe8853af77ce58452a4b98f77eb614..6ee50a04c0bdcf03d8af346aa3f45b5ae8277a61 100644 --- a/src/assets/icons/fa-icons.js +++ b/src/assets/icons/fa-icons.js @@ -1,16 +1,8 @@ const faIcons = [ - 'ad', 'address-book', 'address-card', 'adjust', - 'air-freshener', - 'align-center', - 'align-justify', - 'align-left', - 'align-right', - 'allergies', 'ambulance', - 'american-sign-language-interpreting', 'anchor', 'angle-double-down', 'angle-double-left', @@ -20,8 +12,6 @@ const faIcons = [ 'angle-left', 'angle-right', 'angle-up', - 'angry', - 'ankh', 'apple-alt', 'archive', 'archway', @@ -44,101 +34,41 @@ const faIcons = [ 'asterisk', 'at', 'atlas', - 'atom', - 'audio-description', 'award', 'baby', 'baby-carriage', 'backspace', 'backward', - 'bacon', - 'bacteria', - 'bacterium', 'bahai', 'balance-scale', - 'balance-scale-left', - 'balance-scale-right', 'ban', 'band-aid', - 'barcode', - 'bars', 'baseball-ball', 'basketball-ball', - 'bath', - 'battery-empty', - 'battery-full', - 'battery-half', - 'battery-quarter', - 'battery-three-quarters', 'bed', 'beer', - 'bell', - 'bell-slash', - 'bezier-curve', - 'bible', 'bicycle', 'biking', 'binoculars', - 'biohazard', - 'birthday-cake', - 'blender', - 'blender-phone', 'blind', - 'blog', - 'bold', 'bolt', - 'bomb', - 'bone', 'bong', 'book', - 'book-dead', 'book-medical', 'book-open', 'book-reader', - 'bookmark', - 'border-all', - 'border-none', - 'border-style', - 'bowling-ball', - 'box', 'box-open', - 'box-tissue', - 'boxes', - 'braille', - 'brain', - 'bread-slice', 'briefcase', 'briefcase-medical', 'broadcast-tower', - 'broom', - 'brush', - 'bug', 'building', - 'bullhorn', - 'bullseye', - 'burn', 'bus', 'bus-alt', - 'business-time', - 'calculator', - 'calendar', - 'calendar-alt', - 'calendar-check', - 'calendar-day', - 'calendar-minus', - 'calendar-plus', - 'calendar-times', - 'calendar-week', 'camera', 'camera-retro', 'campground', - 'candy-cane', - 'cannabis', - 'capsules', 'car', 'car-alt', - 'car-battery', - 'car-crash', 'car-side', 'caravan', 'caret-down', @@ -153,29 +83,9 @@ const faIcons = [ 'cart-arrow-down', 'cart-plus', 'cash-register', - 'cat', - 'certificate', - 'chair', - 'chalkboard', - 'chalkboard-teacher', - 'charging-station', - 'chart-area', - 'chart-bar', - 'chart-line', - 'chart-pie', 'check', 'check-circle', - 'check-double', 'check-square', - 'cheese', - 'chess', - 'chess-bishop', - 'chess-board', - 'chess-king', - 'chess-knight', - 'chess-pawn', - 'chess-queen', - 'chess-rook', 'chevron-circle-down', 'chevron-circle-left', 'chevron-circle-right', @@ -184,371 +94,72 @@ const faIcons = [ 'chevron-left', 'chevron-right', 'chevron-up', - 'child', - 'church', - 'circle', - 'circle-notch', 'city', 'clinic-medical', - 'clipboard', - 'clipboard-check', - 'clipboard-list', 'clock', - 'clone', - 'closed-captioning', - 'cloud', - 'cloud-download-alt', - 'cloud-meatball', - 'cloud-moon', - 'cloud-moon-rain', - 'cloud-rain', - 'cloud-showers-heavy', - 'cloud-sun', - 'cloud-sun-rain', - 'cloud-upload-alt', 'cocktail', - 'code', 'code-branch', 'coffee', 'cog', 'cogs', - 'coins', - 'columns', 'comment', 'comment-alt', - 'comment-dollar', - 'comment-dots', - 'comment-medical', - 'comment-slash', - 'comments', - 'comments-dollar', - 'compact-disc', 'compass', 'compress', 'compress-alt', 'compress-arrows-alt', 'concierge-bell', - 'cookie', - 'cookie-bite', - 'copy', - 'copyright', - 'couch', 'credit-card', - 'crop', - 'crop-alt', 'cross', 'crosshairs', 'crow', - 'crown', - 'crutch', - 'cube', - 'cubes', - 'cut', - 'database', 'deaf', - 'democrat', - 'desktop', - 'dharmachakra', - 'diagnoses', - 'dice', - 'dice-d20', - 'dice-d6', - 'dice-five', - 'dice-four', - 'dice-one', - 'dice-six', - 'dice-three', - 'dice-two', - 'digital-tachograph', 'directions', - 'disease', - 'divide', - 'dizzy', - 'dna', 'dog', - 'dollar-sign', - 'dolly', - 'dolly-flatbed', - 'donate', - 'door-closed', - 'door-open', - 'dot-circle', - 'dove', - 'download', - 'drafting-compass', - 'dragon', - 'draw-polygon', - 'drum', - 'drum-steelpan', - 'drumstick-bite', - 'dumbbell', - 'dumpster', - 'dumpster-fire', - 'dungeon', 'edit', - 'egg', - 'eject', - 'ellipsis-h', - 'ellipsis-v', 'envelope', - 'envelope-open', - 'envelope-open-text', - 'envelope-square', - 'equals', - 'eraser', - 'ethernet', 'euro-sign', - 'exchange-alt', 'exclamation', 'exclamation-circle', 'exclamation-triangle', 'expand', - 'expand-alt', - 'expand-arrows-alt', - 'external-link-alt', - 'external-link-square-alt', 'eye', - 'eye-dropper', 'eye-slash', - 'fan', - 'fast-backward', - 'fast-forward', 'faucet', - 'fax', - 'feather', - 'feather-alt', 'female', - 'fighter-jet', 'file', - 'file-alt', - 'file-archive', - 'file-audio', - 'file-code', - 'file-contract', - 'file-csv', - 'file-download', - 'file-excel', - 'file-export', - 'file-image', - 'file-import', - 'file-invoice', - 'file-invoice-dollar', - 'file-medical', - 'file-medical-alt', - 'file-pdf', - 'file-powerpoint', - 'file-prescription', - 'file-signature', - 'file-upload', - 'file-video', - 'file-word', - 'fill', - 'fill-drip', - 'film', - 'filter', - 'fingerprint', - 'fire', 'fire-alt', - 'fire-extinguisher', - 'first-aid', 'fish', - 'fist-raised', 'flag', - 'flag-checkered', - 'flag-usa', 'flask', - 'flushed', - 'folder', - 'folder-minus', - 'folder-open', - 'folder-plus', - 'font', - 'football-ball', - 'forward', - 'frog', - 'frown', - 'frown-open', - 'funnel-dollar', - 'futbol', - 'gamepad', 'gas-pump', 'gavel', - 'gem', - 'genderless', - 'ghost', - 'gift', - 'gifts', - 'glass-cheers', - 'glass-martini', - 'glass-martini-alt', - 'glass-whiskey', - 'glasses', - 'globe', - 'globe-africa', - 'globe-americas', - 'globe-asia', - 'globe-europe', - 'golf-ball', - 'gopuram', 'graduation-cap', - 'greater-than', - 'greater-than-equal', - 'grimace', - 'grin', - 'grin-alt', - 'grin-beam', - 'grin-beam-sweat', - 'grin-hearts', - 'grin-squint', - 'grin-squint-tears', - 'grin-stars', - 'grin-tears', - 'grin-tongue', - 'grin-tongue-squint', - 'grin-tongue-wink', - 'grin-wink', - 'grip-horizontal', - 'grip-lines', - 'grip-lines-vertical', - 'grip-vertical', - 'guitar', 'h-square', - 'hamburger', 'hammer', - 'hamsa', - 'hand-holding', - 'hand-holding-heart', - 'hand-holding-medical', - 'hand-holding-usd', - 'hand-holding-water', - 'hand-lizard', - 'hand-middle-finger', - 'hand-paper', - 'hand-peace', - 'hand-point-down', - 'hand-point-left', - 'hand-point-right', - 'hand-point-up', - 'hand-pointer', - 'hand-rock', - 'hand-scissors', - 'hand-sparkles', - 'hand-spock', - 'hands', - 'hands-helping', - 'hands-wash', - 'handshake', - 'handshake-alt-slash', - 'handshake-slash', - 'hanukiah', - 'hard-hat', - 'hashtag', - 'hat-cowboy', - 'hat-cowboy-side', - 'hat-wizard', - 'hdd', - 'head-side-cough', - 'head-side-cough-slash', - 'head-side-mask', - 'head-side-virus', - 'heading', - 'headphones', - 'headphones-alt', - 'headset', - 'heart', - 'heart-broken', - 'heartbeat', - 'helicopter', - 'highlighter', 'hiking', - 'hippo', - 'history', - 'hockey-puck', - 'holly-berry', 'home', - 'horse', - 'horse-head', 'hospital', - 'hospital-alt', 'hospital-symbol', - 'hospital-user', - 'hot-tub', - 'hotdog', 'hotel', - 'hourglass', - 'hourglass-end', 'hourglass-half', - 'hourglass-start', 'house-damage', 'house-user', - 'hryvnia', - 'i-cursor', - 'ice-cream', - 'icicles', - 'icons', - 'id-badge', - 'id-card', - 'id-card-alt', - 'igloo', 'image', - 'images', - 'inbox', - 'indent', 'industry', - 'infinity', 'info', 'info-circle', - 'italic', - 'jedi', - 'joint', - 'journal-whills', - 'kaaba', - 'key', - 'keyboard', - 'khanda', - 'kiss', - 'kiss-beam', - 'kiss-wink-heart', - 'kiwi-bird', 'landmark', - 'language', - 'laptop', - 'laptop-code', 'laptop-house', - 'laptop-medical', - 'laugh', - 'laugh-beam', - 'laugh-squint', - 'laugh-wink', - 'layer-group', 'leaf', - 'lemon', - 'less-than', - 'less-than-equal', - 'level-down-alt', - 'level-up-alt', 'life-ring', 'lightbulb', - 'link', - 'lira-sign', - 'list', - 'list-alt', - 'list-ol', - 'list-ul', 'location-arrow', 'lock', - 'lock-open', 'long-arrow-alt-down', 'long-arrow-alt-left', 'long-arrow-alt-right', 'long-arrow-alt-up', - 'low-vision', - 'luggage-cart', - 'lungs', - 'lungs-virus', - 'magic', - 'magnet', - 'mail-bulk', 'male', 'map', 'map-marked', @@ -558,448 +169,105 @@ const faIcons = [ 'map-pin', 'map-signs', 'marker', - 'mars', - 'mars-double', - 'mars-stroke', - 'mars-stroke-h', - 'mars-stroke-v', - 'mask', 'medal', 'medkit', - 'meh', - 'meh-blank', - 'meh-rolling-eyes', - 'memory', - 'menorah', - 'mercury', - 'meteor', - 'microchip', 'microphone', - 'microphone-alt', - 'microphone-alt-slash', - 'microphone-slash', 'microscope', - 'minus', - 'minus-circle', - 'minus-square', - 'mitten', - 'mobile', 'mobile-alt', 'money-bill', - 'money-bill-alt', - 'money-bill-wave', - 'money-bill-wave-alt', - 'money-check', - 'money-check-alt', - 'monument', - 'moon', - 'mortar-pestle', - 'mosque', 'motorcycle', 'mountain', - 'mouse', 'mouse-pointer', 'mug-hot', 'music', - 'network-wired', - 'neuter', - 'newspaper', - 'not-equal', - 'notes-medical', - 'object-group', - 'object-ungroup', - 'oil-can', - 'om', - 'otter', - 'outdent', - 'pager', 'paint-brush', - 'paint-roller', 'palette', - 'pallet', 'paper-plane', - 'paperclip', - 'parachute-box', - 'paragraph', 'parking', - 'passport', - 'pastafarianism', - 'paste', - 'pause', - 'pause-circle', 'paw', - 'peace', 'pen', - 'pen-alt', - 'pen-fancy', - 'pen-nib', - 'pen-square', - 'pencil-alt', - 'pencil-ruler', - 'people-arrows', - 'people-carry', - 'pepper-hot', - 'percent', - 'percentage', - 'person-booth', - 'phone', 'phone-alt', - 'phone-slash', - 'phone-square', - 'phone-square-alt', - 'phone-volume', - 'photo-video', - 'piggy-bank', - 'pills', - 'pizza-slice', - 'place-of-worship', 'plane', - 'plane-arrival', - 'plane-departure', - 'plane-slash', - 'play', - 'play-circle', 'plug', 'plus', 'plus-circle', 'plus-square', 'podcast', - 'poll', - 'poll-h', - 'poo', - 'poo-storm', - 'poop', - 'portrait', - 'pound-sign', - 'power-off', - 'pray', - 'praying-hands', - 'prescription', - 'prescription-bottle', - 'prescription-bottle-alt', - 'print', - 'procedures', - 'project-diagram', - 'pump-medical', - 'pump-soap', - 'puzzle-piece', - 'qrcode', 'question', 'question-circle', - 'quidditch', - 'quote-left', - 'quote-right', - 'quran', 'radiation', - 'radiation-alt', - 'rainbow', - 'random', - 'receipt', - 'record-vinyl', 'recycle', - 'redo', - 'redo-alt', - 'registered', - 'remove-format', - 'reply', - 'reply-all', - 'republican', - 'restroom', - 'retweet', - 'ribbon', - 'ring', 'road', - 'robot', - 'rocket', - 'route', - 'rss', - 'rss-square', - 'ruble-sign', - 'ruler', - 'ruler-combined', - 'ruler-horizontal', - 'ruler-vertical', 'running', - 'rupee-sign', - 'sad-cry', - 'sad-tear', - 'satellite', 'satellite-dish', - 'save', - 'school', - 'screwdriver', - 'scroll', - 'sd-card', 'search', - 'search-dollar', 'search-location', - 'search-minus', - 'search-plus', 'seedling', - 'server', - 'shapes', - 'share', 'share-alt', - 'share-alt-square', - 'share-square', - 'shekel-sign', - 'shield-alt', - 'shield-virus', 'ship', - 'shipping-fast', - 'shoe-prints', - 'shopping-bag', 'shopping-basket', 'shopping-cart', - 'shower', 'shuttle-van', - 'sign', - 'sign-in-alt', - 'sign-language', - 'sign-out-alt', - 'signal', - 'signature', - 'sim-card', - 'sink', - 'sitemap', - 'skating', 'skiing', - 'skiing-nordic', - 'skull', - 'skull-crossbones', - 'slash', - 'sleigh', - 'sliders-h', - 'smile', - 'smile-beam', - 'smile-wink', - 'smog', - 'smoking', - 'smoking-ban', - 'sms', - 'snowboarding', 'snowflake', - 'snowman', - 'snowplow', - 'soap', - 'socks', - 'solar-panel', - 'sort', - 'sort-alpha-down', - 'sort-alpha-down-alt', - 'sort-alpha-up', - 'sort-alpha-up-alt', - 'sort-amount-down', - 'sort-amount-down-alt', - 'sort-amount-up', - 'sort-amount-up-alt', 'sort-down', - 'sort-numeric-down', - 'sort-numeric-down-alt', - 'sort-numeric-up', - 'sort-numeric-up-alt', - 'sort-up', - 'spa', - 'space-shuttle', - 'spell-check', - 'spider', - 'spinner', - 'splotch', - 'spray-can', 'square', 'square-full', - 'square-root-alt', - 'stamp', 'star', 'star-and-crescent', - 'star-half', - 'star-half-alt', 'star-of-david', 'star-of-life', - 'step-backward', - 'step-forward', 'stethoscope', 'sticky-note', - 'stop', - 'stop-circle', - 'stopwatch', - 'stopwatch-20', 'store', 'store-alt', - 'store-alt-slash', - 'store-slash', - 'stream', 'street-view', - 'strikethrough', - 'stroopwafel', - 'subscript', 'subway', 'suitcase', 'suitcase-rolling', 'sun', - 'superscript', - 'surprise', - 'swatchbook', 'swimmer', - 'swimming-pool', - 'synagogue', - 'sync', - 'sync-alt', 'syringe', - 'table', - 'table-tennis', - 'tablet', - 'tablet-alt', - 'tablets', - 'tachometer-alt', 'tag', - 'tags', - 'tape', - 'tasks', 'taxi', - 'teeth', - 'teeth-open', 'temperature-high', 'temperature-low', - 'tenge', - 'terminal', - 'text-height', - 'text-width', - 'th', - 'th-large', - 'th-list', - 'theater-masks', - 'thermometer', - 'thermometer-empty', - 'thermometer-full', - 'thermometer-half', - 'thermometer-quarter', - 'thermometer-three-quarters', 'thumbs-down', 'thumbs-up', 'thumbtack', - 'ticket-alt', 'times', 'times-circle', 'tint', 'tint-slash', - 'tired', - 'toggle-off', - 'toggle-on', - 'toilet', - 'toilet-paper', - 'toilet-paper-slash', 'toolbox', 'tools', - 'tooth', - 'torah', - 'torii-gate', 'tractor', - 'trademark', - 'traffic-light', - 'trailer', 'train', 'tram', - 'transgender', - 'transgender-alt', - 'trash', 'trash-alt', - 'trash-restore', - 'trash-restore-alt', 'tree', 'trophy', 'truck', - 'truck-loading', - 'truck-monster', 'truck-moving', - 'truck-pickup', 'tshirt', - 'tty', 'tv', 'umbrella', 'umbrella-beach', - 'underline', - 'undo', - 'undo-alt', - 'universal-access', 'university', - 'unlink', - 'unlock', - 'unlock-alt', - 'upload', - 'user', - 'user-alt', - 'user-alt-slash', - 'user-astronaut', - 'user-check', 'user-circle', - 'user-clock', - 'user-cog', - 'user-edit', 'user-friends', 'user-graduate', - 'user-injured', - 'user-lock', 'user-md', - 'user-minus', - 'user-ninja', - 'user-nurse', - 'user-plus', - 'user-secret', - 'user-shield', - 'user-slash', - 'user-tag', - 'user-tie', - 'user-times', - 'users', - 'users-cog', - 'users-slash', - 'utensil-spoon', 'utensils', - 'vector-square', - 'venus', - 'venus-double', - 'venus-mars', - 'vest', - 'vest-patches', 'vial', - 'vials', 'video', - 'video-slash', - 'vihara', - 'virus', - 'virus-slash', - 'viruses', - 'voicemail', - 'volleyball-ball', - 'volume-down', - 'volume-mute', - 'volume-off', - 'volume-up', - 'vote-yea', - 'vr-cardboard', 'walking', - 'wallet', - 'warehouse', 'water', - 'wave-square', - 'weight', 'weight-hanging', 'wheelchair', 'wifi', - 'wind', - 'window-close', - 'window-maximize', - 'window-minimize', - 'window-restore', - 'wine-bottle', - 'wine-glass', 'wine-glass-alt', - 'won-sign', - 'wrench', - 'x-ray', - 'yen-sign', - 'yin-yang' + 'wrench' ]; export default faIcons; diff --git a/src/assets/js/map-util.js b/src/assets/js/map-util.js index 10535ded16b11cdcfff46c84a9313c101265f0d2..56d127c116f392e1afdb8254a704bff09895c397 100644 --- a/src/assets/js/map-util.js +++ b/src/assets/js/map-util.js @@ -72,7 +72,6 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({ throw (error) //xhr.status; //xhr.responseText; - //console.log(status) } ) @@ -114,7 +113,6 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({ let content; if (err) { - //console.log(err); content = ` <h4>${this.options.title}</h4> <p>Données de la couche inaccessibles</p> @@ -143,9 +141,7 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({ .setLatLng(latlng) .setContent(content) .openOn(this._map); - } /* else { - console.log('Pas de features trouvées pour cette couche'); - } */ + } } } @@ -297,9 +293,10 @@ const mapUtil = { }, retrieveFeatureColor: function (featureType, properties) { - if (featureType && featureType.colors_style && featureType.colors_style.custom_field_name) { - const currentValue = properties[featureType.colors_style.custom_field_name]; - const colorStyle = featureType.colors_style.colors[currentValue]; + const colorsStyle = featureType.colors_style && featureType.colors_style.value ? featureType.colors_style.value : featureType.colors_style; + if (featureType && colorsStyle && colorsStyle.custom_field_name) { + const currentValue = properties[colorsStyle.custom_field_name]; + const colorStyle = colorsStyle.colors[currentValue]; return colorStyle ? colorStyle : featureType.color } else{ @@ -358,7 +355,6 @@ const mapUtil = { } }); layerMVT.on('click', (e) => { // The .on method attaches an event handler - console.log("e", e); const popupContent = this._createContentPopup(e.layer, featureTypes, project_slug); L.popup() .setContent(popupContent) @@ -372,83 +368,109 @@ const mapUtil = { addFeatures: function (features, filter, addToMap = true, featureTypes) { const featureGroup = new L.FeatureGroup(); features.forEach((feature) => { - - const featureType = featureTypes.find((ft) => ft.slug === (feature.properties.feature_type.slug || feature.properties.feature_type)); - + 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 && feature.properties.feature_type.slug === filter.featureType; - const statusCheck = filter.featureStatus && feature.properties.status.value === filter.featureStatus; - const titleCheck = filter.featureTitle && feature.properties.title.includes(filter.featureTitle); + 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]; } - if (!filter || !Object.values(filter).some(val => val) || Object.values(filter).some(val => val) && filters.length && filters.every(val => val !== false)) { - const geomJSON = flip(feature.geometry); + if ( + !filter || + !Object.values(filter).some(val => val) || + Object.values(filter).some(val => val) && + filters.length && filters.every(val => val !== false) + ) { + const geomJSON = flip(feature.geometry || feature.geom); const popupContent = this._createContentPopup(feature); // Look for a custom field let customField; let customFieldOption; - if (featureType.customfield_set && Object.keys(feature.properties).some(el => featureType.customfield_set.map(e => e.name).includes(el))) { - customField = Object.keys(feature.properties).filter(el => featureType.customfield_set.map(e => e.name).includes(el)); - customFieldOption = feature.properties[customField[0]]; + 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, feature.properties) || feature.properties.color; - - // if (!color && customFieldOption && featureType.colors_style) { - // color = - // featureType.colors_style.value ? - // featureType.colors_style.value.colors[customFieldOption].value ? - // featureType.colors_style.value.colors[customFieldOption].value : - // featureType.colors_style.value.colors[customFieldOption] : - // featureType.colors_style.colors[customFieldOption] - // } else { - // color = feature.properties.color; - // } + let color = this.retrieveFeatureColor(featureType, featureProperties) || featureProperties.color; if (color == undefined){ color = featureType.color; } + const colorValue = color.value ? color.value : color; if (geomJSON.type === 'Point') { if (customFieldOption && featureType.colors_style && featureType.colors_style.value && featureType.colors_style.value.icons) { - const iconHTML = ` - <i - class="fas fa-${featureType.colors_style.value.icons[customFieldOption]} fa-2x" - style="color: ${color}" - ></i> - `; - const customMapIcon = L.divIcon({ - html: iconHTML, - iconSize: [20, 20], - className: 'myDivIcon', - }); - L.marker(geomJSON.coordinates, { - icon: customMapIcon, - color: color, - zIndexOffset: 100 - }) + if (featureType.colors_style.value.icons[customFieldOption]) { + const iconHTML = ` + <i + class="fas fa-${featureType.colors_style.value.icons[customFieldOption]} fa-lg" + style="color: ${colorValue}" + ></i> + `; + const customMapIcon = L.divIcon({ + html: iconHTML, + iconSize: [20, 20], + className: 'myDivIcon', + }); + L.marker(geomJSON.coordinates, { + icon: customMapIcon, + color: colorValue, + zIndexOffset: 100 + }) + .bindPopup(popupContent) + .addTo(featureGroup); + } else { + L.circleMarker(geomJSON.coordinates, { + color: color, + radius: 4, + fillOpacity: 0.5, + weight: 3, + }) .bindPopup(popupContent) .addTo(featureGroup); + } } else { - L.circleMarker(geomJSON.coordinates, { - color: color, - radius: 4, - fillOpacity: 0.5, - weight: 3, - }) - .bindPopup(popupContent) - .addTo(featureGroup); + if (featureType.icon) { + const iconHTML = ` + <i + class="fas fa-${featureType.icon} fa-lg" + style="color: ${colorValue}" + ></i> + `; + const customMapIcon = L.divIcon({ + html: iconHTML, + iconSize: [20, 20], + className: 'myDivIcon', + }); + L.marker(geomJSON.coordinates, { + icon: customMapIcon, + color: colorValue, + zIndexOffset: 100 + }) + .bindPopup(popupContent) + .addTo(featureGroup); + } else { + L.circleMarker(geomJSON.coordinates, { + color: color, + radius: 4, + fillOpacity: 0.5, + weight: 3, + }) + .bindPopup(popupContent) + .addTo(featureGroup); + } } } else if (geomJSON.type === 'LineString') { L.polyline(geomJSON.coordinates, { - color: color, + color: colorValue, weight: 3, }) .bindPopup(popupContent) .addTo(featureGroup); } else if (geomJSON.type === 'Polygon') { L.polygon(geomJSON.coordinates, { - color: color, + color: colorValue, weight: 3, fillOpacity: 0.5, }) @@ -457,7 +479,7 @@ const mapUtil = { } } }); - if (addToMap) { + if (map && addToMap) { map.addLayer(featureGroup); } @@ -474,10 +496,23 @@ const mapUtil = { return formatted_date; } let feature_type; - let status = feature.properties.status; - let date_maj = feature.properties.updated_on; - let feature_type_url = feature.properties.feature_type_url; - let feature_url = feature.properties.feature_url; + let status; + let date_maj; + let feature_type_url; + let feature_url; + + if (feature.properties) { + status = feature.properties.status; + date_maj = feature.properties.updated_on; + feature_type_url = feature.properties.feature_type_url; + feature_url = feature.properties.feature_url; + } else { + status = feature.status; + date_maj = feature.updated_on; + feature_type_url =feature.feature_type_url; + feature_url = feature.feature_url; + } + if (featureTypes) { // => VectorTile feature_type = featureTypes.find((x) => x.slug.split('-')[0] === '' + feature.properties.feature_type_id); status = statusList.find((x) => x.value === feature.properties.status).name; @@ -486,22 +521,24 @@ const mapUtil = { feature_url = feature_type_url + 'signalement/' + feature.properties.feature_id + '/'; //status=feature.properties.status; } else { - feature_type = feature.properties.feature_type; - status = feature.properties.status.label; + feature_type = feature.properties ? feature.properties.feature_type : feature.feature_type; + status = feature.properties ? feature.properties.status.label : feature.status.label; } - let author = ""; - if (feature.properties.creator) { - author = feature.properties.creator.full_name + let author = ''; + const creator = feature.properties ? feature.properties.creator : feature.creator + if (creator) { + author = creator.full_name ? `<div> - Auteur : ${feature.properties.creator.first_name} ${feature.properties.creator.last_name} + Auteur : ${creator.first_name} ${creator.last_name} </div>` - : feature.properties.creator.username ? `<div>Auteur: ${feature.properties.creator.username}</div>` : ''; + : creator.username ? `<div>Auteur: ${creator.username}</div>` : ''; } + const title = feature.properties ? feature.properties.title : feature.title; return ` <h4> - <a href="${feature_url}">${feature.properties.title}</a> + <a href="${feature_url}">${title}</a> </h4> <div> Statut : ${status} diff --git a/src/components/feature_type/SymbologySelector.vue b/src/components/feature_type/SymbologySelector.vue index 7e730930a5b193d63e737131ce32735c825e764c..cd3c2409e6c8a375c139fd075818b7c58b25aa56 100644 --- a/src/components/feature_type/SymbologySelector.vue +++ b/src/components/feature_type/SymbologySelector.vue @@ -23,7 +23,7 @@ > <font-awesome-icon :icon="['fas', form.icon]" - :style="{ color: form.color.value }" + :style="{ color: form.color.value || '#000000' }" class="icon alt" /> </button> @@ -161,7 +161,6 @@ export default { border-radius: 3px; box-shadow: 0 0 2px 1px rgb(131, 131, 131); .icon.alt { - color: rgb(75, 75, 75); width: 30px; height: 30px; } diff --git a/src/components/project/project_mapping_basemap.vue b/src/components/project/project_mapping_basemap.vue index 99fb2a408625294a27b56e5e1c3a3524b0ae66e4..34399ea8a969706a4f84714d76b0ceb67bc6e3ef 100644 --- a/src/components/project/project_mapping_basemap.vue +++ b/src/components/project/project_mapping_basemap.vue @@ -135,8 +135,7 @@ export default { //* drag & drop *// - onlayerMove(event) { - console.log(event); + onlayerMove() { //* Get the names of the current layers in order. const currentLayersNamesInOrder = Array.from( document.getElementsByClassName("layer-item") diff --git a/src/main.js b/src/main.js index 87be60e859f1e0bd80fc3ea91ea87260740da337..3ff59325ded1f4dff75020ca8abb256e0edcdd0b 100644 --- a/src/main.js +++ b/src/main.js @@ -67,7 +67,7 @@ let onConfigLoaded = function(config){ axios.get("./config/config.json") .catch((error)=>{ - console.log(error); + console.error(error); console.log("try to get From Localstorage"); let conf=localStorage.getItem("geontrib_conf"); if(conf){ diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js index 30735fef4da3ee7b0715a189b148848cbe7284aa..7c08380c4cebf1749266601ca7b2825a002f1a8b 100644 --- a/src/store/modules/feature.js +++ b/src/store/modules/feature.js @@ -1,12 +1,6 @@ import axios from '@/axios-client.js'; import router from '../../router' -// 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'); - const feature = { namespaced: true, @@ -98,7 +92,6 @@ const feature = { }, ADD_ATTACHMENT_TO_DELETE(state, attachementId) { - // state.attachmentFormset = state.attachmentFormset.filter(el => el.id !== attachementId); state.attachmentsToDelete.push(attachementId); }, @@ -112,7 +105,7 @@ const feature = { getters: { }, actions: { - GET_PROJECT_FEATURES({ commit, rootState }, { project_slug, feature_type__slug, ordering, search, limit }) { + 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]; @@ -131,26 +124,24 @@ const feature = { url = url.concat('', `${url.includes('?') ? '&' : '?'}ordering=${ordering}`); } if (search) { - url = url.concat('', `${url.includes('?') ? '&' : '?'}title__contains=${search}`); + url = url.concat('', `${url.includes('?') ? '&' : '?'}title__icontains=${search}`); } if (limit) { url = url.concat('', `${url.includes('?') ? '&' : '?'}limit=${limit}`); } - return axios - .get(url, { cancelToken: cancelToken.token }) - .then((response) => { - 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; - }) - .catch((error) => { - throw error; - }); + if (geojson) url = url.concat('', '&output=geojson'); + + try { + const response = await axios.get(url, { cancelToken: cancelToken.token }); + 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); + } + } catch (error) { + console.error(error); + } }, GET_PROJECT_FEATURE({ commit, rootState }, { project_slug, feature_id }) { if (rootState.cancellableSearchRequest.length > 0) { @@ -180,7 +171,6 @@ const feature = { SEND_FEATURE({ state, rootState, commit, dispatch }, routeName) { commit("DISPLAY_LOADER", "Le signalement est en cours de création", { root: true }) const message = routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée"; - function redirect(featureId) { dispatch( 'GET_PROJECT_FEATURE', @@ -228,110 +218,66 @@ const feature = { } } + let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/` if (routeName === "editer-signalement") { - return axios - .put(`${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/${state.form.feature_id}/?` + - `feature_type__slug=${rootState.feature_type.current_feature_type_slug}` + - `&project__slug=${rootState.project_slug}` - , geojson) - .then((response) => { - if (response.status === 200 && response.data) { - if (state.attachmentFormset.length > 0 || state.linkedFormset.length > 0) { - handleOtherForms(response.data.id) - } else { - redirect(response.data.id) - } - } - }) - .catch((error) => { - commit("DISCARD_LOADER", null, { root: true }) - if (error.message === "Network Error" || window.navigator.onLine === false) { - let arraysOffline = []; - let localStorageArray = localStorage.getItem("geocontrib_offline"); - if (localStorageArray) { - arraysOffline = JSON.parse(localStorageArray); - } - let updateMsg = { - project: rootState.project_slug, - type: 'put', - featureId: state.form.feature_id, - geojson: geojson - }; - arraysOffline.push(updateMsg); - localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline)); - router.push({ - name: "offline-signalement", - params: { - slug_type_signal: rootState.feature_type.current_feature_type_slug - }, - }); + url += `${state.form.feature_id}/?` + + `feature_type__slug=${rootState.feature_type.current_feature_type_slug}` + + `&project__slug=${rootState.project_slug}` + } + return axios({ + url, + method: routeName === "editer-signalement" ? "PUT" : "POST", + 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) { + handleOtherForms(response.data.id) + } else { + redirect(response.data.id) } - else { - console.log(error) - throw error; + } + }) + .catch((error) => { + commit("DISCARD_LOADER", null, { root: true }) + if (error.message === "Network Error" || window.navigator.onLine === false) { + let arraysOffline = []; + let localStorageArray = localStorage.getItem("geocontrib_offline"); + if (localStorageArray) { + arraysOffline = JSON.parse(localStorageArray); } - + let updateMsg = { + project: rootState.project_slug, + type: 'put', + featureId: state.form.feature_id, + geojson: geojson + }; + arraysOffline.push(updateMsg); + localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline)); + router.push({ + name: "offline-signalement", + params: { + slug_type_signal: rootState.feature_type.current_feature_type_slug + }, + }); + } + else { + console.error(error) throw error; - }); - } else { - return axios - .post(`${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/`, geojson) - .then((response) => { - if (response.status === 201 && response.data) { - if (state.attachmentFormset.length > 0 || state.linkedFormset.length > 0) { - handleOtherForms(response.data.id) - } else { - redirect(response.data.id) - } - } - }) - .catch((error) => { - commit("DISCARD_LOADER", null, { root: true }) - if (error.message === "Network Error" || window.navigator.onLine === false) { - let arraysOffline = []; - let localStorageArray = localStorage.getItem("geocontrib_offline"); - if (localStorageArray) { - arraysOffline = JSON.parse(localStorageArray); - } - let updateMsg = { - project: rootState.project_slug, - type: 'post', - geojson: geojson - }; - arraysOffline.push(updateMsg); - localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline)); - router.push({ - name: "offline-signalement", - params: { - slug_type_signal: rootState.feature_type.current_feature_type_slug - }, - }); - - } - else { - console.log(error) - throw error; - } - - }); - } - // this.$store.dispatch("GET_ALL_PROJECTS"), //* & refresh project list + } + throw error; + }); }, async SEND_ATTACHMENTS({ state, rootState, dispatch }, featureId) { const DJANGO_API_BASE = rootState.configuration.VUE_APP_DJANGO_API_BASE; - + function addFile(attachment, attchmtId) { let formdata = new FormData(); formdata.append("file", attachment.fileToImport, attachment.fileToImport.name); return axios .put(`${DJANGO_API_BASE}features/${featureId}/attachments/${attchmtId}/upload-file/`, formdata) .then((response) => { - console.log(response) - if (response && response.status === 200) { - console.log(response.status) - } return response; }) .catch((error) => { @@ -345,37 +291,25 @@ const feature = { formdata.append("title", attachment.title); formdata.append("info", attachment.info); - if (!attachment.id) { //* used to check if doesn't exist in DB and should be send through post (useless now) - return axios - .post(`${DJANGO_API_BASE}features/${featureId}/attachments/`, formdata) - .then((response) => { - console.log(response) - if (response && response.status === 201 && attachment.fileToImport) { - console.log(response.status) - return addFile(attachment, response.data.id); - } - return response - }) - .catch((error) => { - console.error(error); - return error - }); - } else { - return axios - .put(`${DJANGO_API_BASE}features/${featureId}/attachments/${attachment.id}/`, formdata) - .then((response) => { - console.log(response) - if (response && response.status === 200 && attachment.fileToImport) { - console.log(response.status) - return addFile(attachment, response.data.id); - } - }) - .catch((error) => { - console.error(error); - return error - }); - + let url = `${DJANGO_API_BASE}features/${featureId}/attachments/` + if (attachment.id) { + url += `${attachment.id}/` } + + return axios({ + url, + method: attachment.id ? "PUT" : "POST", + data: formdata + }).then((response) => { + if (response && (response.status === 200 || response.status === 201) && attachment.fileToImport) { + return addFile(attachment, response.data.id); + } + return response + }) + .catch((error) => { + console.error(error); + return error + }); } function deleteAttachement(attachmentsId, featureId) { @@ -386,6 +320,7 @@ const feature = { return dispatch("DELETE_ATTACHMENTS", payload) .then((response) => response); } + const promisesResult = await Promise.all([ ...state.attachmentFormset.map((attachment) => putOrPostAttachement(attachment)), ...state.attachmentsToDelete.map((attachmentsId) => deleteAttachement(attachmentsId, featureId)) @@ -402,7 +337,6 @@ const feature = { .delete(url) .then((response) => { if (response && response.status === 204) { - console.log(response) commit("REMOVE_ATTACHMENTS_ID_TO_DELETE", payload.attachmentsId) return response } @@ -418,7 +352,6 @@ const feature = { .put(`${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/${featureId}/feature-links/`, state.linkedFormset) .then((response) => { if (response.status === 200 && response.data) { - console.log(response, response.data) return "La relation a bien été ajouté" } }) @@ -427,8 +360,7 @@ const feature = { }); }, - DELETE_FEATURE({ state, rootState }, feature_id) { - console.log("Deleting feature:", feature_id, state) + DELETE_FEATURE({ rootState }, feature_id) { const url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/${feature_id}/?` + `feature_type__slug=${rootState.feature_type.current_feature_type_slug}` + `&project__slug=${rootState.project_slug}`; diff --git a/src/store/modules/map.js b/src/store/modules/map.js index b9843087d53556c34c8fd0b7831b5e4560755305..57ae63836919b88664930870cdbfe96b7d83034f 100644 --- a/src/store/modules/map.js +++ b/src/store/modules/map.js @@ -11,6 +11,7 @@ import { mapUtil } from "@/assets/js/map-util.js"; const map = { namespaced: true, state: { + map: null, basemaps: null, basemapsToDelete: [], features: [], @@ -18,6 +19,9 @@ const map = { availableLayers: null, }, mutations: { + SET_MAP(state, payload) { + state.map = payload; + }, SET_LAYERS(state, availableLayers) { state.availableLayers = availableLayers; }, @@ -110,7 +114,7 @@ const map = { }); }, - INITIATE_MAP({ state, rootGetters }, el) { + INITIATE_MAP({ state, rootGetters, commit }, el) { const project = rootGetters.project let mapDefaultViewCenter = [46, 2]; // defaultMapView.center; let mapDefaultViewZoom = 5; // defaultMapView.zoom; @@ -118,6 +122,7 @@ const map = { mapDefaultViewCenter, mapDefaultViewZoom, }); + commit('SET_MAP', mapUtil.getMap()); // Load the layers. // - if one basemap exists, check in the localstorage if one active basemap is set diff --git a/src/views/Index.vue b/src/views/Index.vue index 33ced862f9a5074b1d1184ce1d75dbb4877b4ecd..96f4a9b021ac0c93a4ba879913061afbbf09986c 100644 --- a/src/views/Index.vue +++ b/src/views/Index.vue @@ -62,7 +62,7 @@ >Niveau d'autorisation requis : {{ project.access_level_pub_feature }}</span ><br /> - <span> + <span v-if="user"> Mon niveau d'autorisation : <span v-if="USER_LEVEL_PROJECTS && project">{{ USER_LEVEL_PROJECTS[project.slug] diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue index f14f24213bdcbb6724d3199aa492664df66e6f0c..1203b2652d9c91605698d6ffcfba74894a23a46a 100644 --- a/src/views/feature/Feature_detail.vue +++ b/src/views/feature/Feature_detail.vue @@ -347,7 +347,7 @@ <script> import frag from "vue-frag"; -import { mapGetters, mapState } from "vuex"; +import { mapGetters, mapState, mapActions } from "vuex"; import { mapUtil } from "@/assets/js/map-util.js"; import featureAPI from "@/services/feature-api"; import axios from '@/axios-client.js'; @@ -381,9 +381,18 @@ export default { }, computed: { - ...mapState(["user", "USER_LEVEL_PROJECTS"]), - ...mapGetters(["permissions", "project"]), - ...mapState("feature", ["linked_features", "statusChoices"]), + ...mapState([ + 'user', + 'USER_LEVEL_PROJECTS' + ]), + ...mapGetters([ + 'permissions', + 'project' + ]), + ...mapState('feature', [ + 'linked_features', + 'statusChoices' + ]), DJANGO_BASE_URL() { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, @@ -438,6 +447,9 @@ export default { }, methods: { + ...mapActions('feature', [ + 'GET_PROJECT_FEATURES' + ]), isOffline() { return navigator.onLine == false; }, @@ -562,12 +574,9 @@ export default { .dispatch("feature/DELETE_FEATURE", this.feature.feature_id) .then((response) => { if (response.status === 204) { - this.$store.dispatch( - "feature/GET_PROJECT_FEATURES", - { - project_slug: this.$route.params.slug - } - ); + this.GET_PROJECT_FEATURES({ + project_slug: this.$route.params.slug + }); this.goBackToProject(); } }); diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue index 183929cbf0ff5a4c567a724442353ceb5440fdd1..1b8a9f1ffddf514d68f28c54af9f70fcaf25b664 100644 --- a/src/views/feature/Feature_edit.vue +++ b/src/views/feature/Feature_edit.vue @@ -181,11 +181,6 @@ /> <div class="ui tab active map-container" data-tab="map"> <div id="map" ref="map"></div> - <!-- // todo: ajouter v-if --> - <!-- {% if serialized_base_maps|length > 0 %} {% include - "geocontrib/map-layers/sidebar-layers.html" with - basemaps=serialized_base_maps layers=serialized_layers - project=project.slug%} {% endif %} --> <SidebarLayers v-if="basemaps && map" /> </div> </div> @@ -506,11 +501,9 @@ export default { }, georeferencement() { - console.log("georeferencement"); const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}exif-geom-reader/`; let formData = new FormData(); formData.append("image_file", this.file); - console.log(">> formData >> ", formData); axios .post(url, formData, { headers: { @@ -518,7 +511,6 @@ export default { }, }) .then((response) => { - console.log("SUCCESS!!", response.data); if (response.data.geom.indexOf("POINT") >= 0) { let regexp = /POINT\s\((.*)\s(.*)\)/; let arr = regexp.exec(response.data.geom); @@ -544,7 +536,7 @@ export default { }) .catch((error) => { - console.log({ error }); + console.error({ error }); if (error && error.response && error.response) { this.erreurUploadMessage = error.response.data.error; } else { @@ -580,7 +572,6 @@ export default { }, addAttachment(attachment) { - console.log(attachment); this.$store.commit("feature/ADD_ATTACHMENT_FORM", { dataKey: this.attachmentDataKey, title: attachment.title, @@ -850,7 +841,10 @@ export default { if (this.currentRouteName === "editer-signalement") { this.map.addControl(this.drawControlEditOnly); - } else this.map.addControl(this.drawControlFull); + } else { + this.map.addControl(this.drawControlFull); + } + this.changeMobileBtnOrder(); this.map.on( "draw:created", @@ -889,7 +883,6 @@ export default { updateMap(geomFeatureJSON) { if (this.drawnItems) this.drawnItems.clearLayers(); - console.log("update map"); var geomType = this.feature_type.geom_type; if (geomFeatureJSON) { var geomJSON = flip(geomFeatureJSON.geometry); //turf.flip(geomFeatureJSON) @@ -940,7 +933,6 @@ export default { axios .get(url) .then((response) => { - console.log(response.data.features); const features = response.data.features; if (features) { const allFeaturesExceptCurrent = features.filter( @@ -984,6 +976,24 @@ export default { } }, + changeMobileBtnOrder() { //* move large toolbar for polygon creation, cutting map in the middle + function changeDisplay() { + let buttons = document.querySelector(".leaflet-draw-actions.leaflet-draw-actions-top.leaflet-draw-actions-bottom") + if (buttons && buttons.style) { + buttons.style.display = "flex" + buttons.style["flex-direction"] = "column" + } + } + if (window.screen.availWidth < 767) { //* change button order all the time to keep homogeinity on mobile + let wrapper = document.querySelector(".leaflet-top.leaflet-right"); + if (wrapper) wrapper.appendChild(wrapper.children[0]); + if (this.feature_type.geom_type === "polygon") { //* if it's a polygon, change tools direction to vertical + let polygonBtn = document.querySelector(".leaflet-draw-draw-polygon"); //* since elements are generated + if (polygonBtn) polygonBtn.addEventListener("click", changeDisplay) //* it should be done at each click + } + } + }, + getFeatureAttachments() { featureAPI .getFeatureAttachments(this.$route.params.slug_signal) diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue index c31ad0879058b2a0a117cd71012851e6df2bb8c3..e72194a62133f38071157354004fc5d170ad3aa3 100644 --- a/src/views/feature/Feature_list.vue +++ b/src/views/feature/Feature_list.vue @@ -181,7 +181,7 @@ </template> <script> -import { mapGetters, mapState } from "vuex"; +import { mapGetters, mapState, mapActions } from "vuex"; import { mapUtil } from "@/assets/js/map-util.js"; import featureAPI from "@/services/feature-api"; import SidebarLayers from "@/components/map-layers/SidebarLayers"; @@ -235,6 +235,7 @@ export default { lng: null, featuresCount: 0, paginatedFeatures: [], + currentLayer: null, pagination: { currentPage: 1, pagesize: 15, @@ -259,13 +260,56 @@ export default { "form.status.selected.value"() { this.fetchPagedFeatures(); }, + map(newValue) { + if (newValue && this.paginatedFeatures && this.paginatedFeatures.length) { + if (this.currentLayer) { + this.map.removeLayer(this.currentLayer); + } + this.currentLayer = mapUtil.addFeatures( + this.paginatedFeatures, + {}, + true, + this.feature_types + ); + } + }, + paginatedFeatures: { + deep: true, + handler(newValue, oldValue) { + if (newValue && newValue.length && newValue !== oldValue && this.map) { + if (this.currentLayer) { + this.map.removeLayer(this.currentLayer); + this.currentLayer = null; + } + this.currentLayer = mapUtil.addFeatures( + newValue, + {}, + true, + this.feature_types + ); + } else if (newValue && newValue.length === 0) { + if (this.currentLayer) { + this.map.removeLayer(this.currentLayer); + this.currentLayer = null; + } + } + } + } }, computed: { - ...mapGetters(["project", "permissions"]), - ...mapState("feature", ["checkedFeatures"]), - ...mapState("feature_type", ["feature_types"]), - ...mapState("map", ["basemaps"]), + ...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; @@ -284,6 +328,9 @@ export default { }, methods: { + ...mapActions('feature', [ + 'GET_PROJECT_FEATURES' + ]), modalAllDelete() { this.modalAllDeleteOpen = !this.modalAllDeleteOpen; }, @@ -294,10 +341,9 @@ export default { .delete(url, {}) .then(() => { if (!this.modalAllDeleteOpen) { - this.$store - .dispatch("feature/GET_PROJECT_FEATURES", { - project_slug: this.project.slug, - }) + this.GET_PROJECT_FEATURES({ + project_slug: this.project.slug, + }) .then(() => { this.fetchPagedFeatures(); this.getNloadGeojsonFeatures(); @@ -427,17 +473,18 @@ export default { "DISPLAY_LOADER", "Récupération des signalements en cours..." ); - featureAPI.getPaginatedFeatures(url).then((data) => { - if (data) { - this.featuresCount = data.count; - this.previous = data.previous; - this.next = data.next; - this.paginatedFeatures = data.results.features; - } - //* bbox needs to be updated with the same filters - if (queryString) this.fetchBboxNfit(queryString); - this.$store.commit("DISCARD_LOADER"); - }); + featureAPI.getPaginatedFeatures(url) + .then((data) => { + if (data) { + this.featuresCount = data.count; + this.previous = data.previous; + this.next = data.next; + this.paginatedFeatures = data.results.features; + } + //* bbox needs to be updated with the same filters + if (this.paginatedFeatures.length) this.fetchBboxNfit(queryString); + this.$store.commit("DISCARD_LOADER"); + }); }, //* Pagination for table *// diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue index 07dbfc9c86a745b70a2737aefed54f505a5c0641..cf4ddc8f768ef7d5d7fa868f163da6c911eec6b5 100644 --- a/src/views/feature_type/Feature_type_detail.vue +++ b/src/views/feature_type/Feature_type_detail.vue @@ -222,7 +222,7 @@ </template> <script> -import { mapGetters, mapState } from "vuex"; +import { mapActions, mapMutations, mapGetters, mapState } from "vuex"; import ImportTask from "@/components/ImportTask"; import featureAPI from "@/services/feature-api"; @@ -256,9 +256,18 @@ export default { }, 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( @@ -293,7 +302,41 @@ export default { }, }, + watch:{ + structure(newValue){ + if (newValue.slug){ + this.GET_IMPORTS({ + feature_type: this.$route.params.feature_type_slug + }); + } + } + }, + + created() { + if (!this.project) { + this.GET_PROJECT_INFO(this.$route.params.slug); + } + this.setCurrentFeatureTypeSlug(); + // .then(res => resolve(res)) + // .catch(err => reject(err)); + 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' + ]), toggleShowImport() { this.showImport = !this.showImport; if (this.showImport) { @@ -409,39 +452,18 @@ export default { }, async setCurrentFeatureTypeSlug(){ const response = await - this.$store.dispatch('feature/GET_PROJECT_FEATURES', { + this.GET_PROJECT_FEATURES({ project_slug: this.$route.params.slug, feature_type__slug : this.$route.params.feature_type_slug, ordering: '-created_on', limit: '5' - }) + }); if (response){ this.featuresLoading = false; } } - }, - watch:{ - 'structure'(newValue){ - if (newValue.slug){ - this.$store.dispatch("feature_type/GET_IMPORTS", { - feature_type: this.$route.params.feature_type_slug - }); - } - } - }, - created() { - if (!this.project) { - this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug); - } - this.setCurrentFeatureTypeSlug(); - // .then(res => resolve(res)) - // .catch(err => reject(err)); - this.$store.commit( - "feature_type/SET_CURRENT_FEATURE_TYPE_SLUG", - this.$route.params.feature_type_slug - ); - }, + } }; </script> diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue index 375d3d442f25efd344f263e02945a0c2fcb3cb79..26bf6819a8c874cb1a8511b8578123593bb58132 100644 --- a/src/views/feature_type/Feature_type_edit.vue +++ b/src/views/feature_type/Feature_type_edit.vue @@ -63,7 +63,7 @@ <!-- {{ form.geom_type.errors }} --> </div> - <div class="required field"> + <div v-if="selectedGeomType !== 'Point'" class="required field"> <label :for="form.color.id_for_label">{{ form.color.label }}</label> <input type="color" @@ -102,22 +102,6 @@ :placeholder="'Sélectionner la liste de valeurs'" /> </div> - <div class="colors_selection" id="id_colors_selection" hidden> - <div - v-for="(value, key, index) in form.colors_style.value.colors" - :key="'colors_style-' + index" - > - <div v-if="key" class="color-input"> - <label>{{ key }}</label - ><input - :name="key" - type="color" - :value="value" - @input="setColorStyles" - /> - </div> - </div> - </div> </div> <span v-if="action === 'duplicate' || action === 'edit'"> </span> diff --git a/src/views/feature_type/Feature_type_symbology.vue b/src/views/feature_type/Feature_type_symbology.vue index 67d0c7efa1956e69ced868544e0cc3702da6071f..619efa1d9a4b0b74e802bf234f98c421d343e3ab 100644 --- a/src/views/feature_type/Feature_type_symbology.vue +++ b/src/views/feature_type/Feature_type_symbology.vue @@ -5,7 +5,14 @@ </div> <div id="message" class="fullwidth"> <div v-if="error" class="ui negative message"> - <p><i class="cross icon"></i> {{ error }}</p> + <p><i class="close icon"></i> {{ error }}</p> + </div> + <div v-if="success" class="ui positive message"> + <i + class="close icon" + @click="success = null" + /> + <p>{{ success }}</p> </div> </div> <div class="fourteen wide column"> @@ -61,10 +68,16 @@ > <SymbologySelector :title="option" - :initColor="feature_type.colors_style.value.colors[option] ? - feature_type.colors_style.value.colors[option].value : - feature_type.colors_style.value.colors[option]" - :initIcon="feature_type.colors_style.value.icons[option]" + :initColor="feature_type.colors_style.value ? + feature_type.colors_style.value.colors[option] ? + feature_type.colors_style.value.colors[option].value : + feature_type.colors_style.value.colors[option] + : null + " + :initIcon="feature_type.colors_style.value ? + feature_type.colors_style.value.icons[option] : + null + " :geomType="feature_type.customfield_set.geomType" @set="setColorsStyle" /> @@ -74,6 +87,7 @@ <button class="ui teal icon button margin-25" type="button" + :disabled="!canSaveSymbology" @click="sendFeatureSymbology" > <i class="white save icon"></i> @@ -86,6 +100,7 @@ <script> import frag from 'vue-frag'; +import { isEqual } from 'lodash'; import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; @@ -106,24 +121,30 @@ export default { return { loading: false, error: null, + success: null, selectedCustomfield: null, form: { color: '#000000', icon: 'circle', colors_style: { fields: [], + colors: {}, + icons: {}, + custom_field_name: '', value: { colors: {}, - icons: {}, - custom_field_name: '', - }, + icons: {} + } }, - } + }, + canSaveSymbology: false } }, computed: { - ...mapGetters(['project']), + ...mapGetters([ + 'project' + ]), ...mapState('feature_type', [ 'customForms', 'colorsStyleList' @@ -135,7 +156,32 @@ export default { watch: { selectedCustomfield(newValue) { - this.form.colors_style.value.custom_field_name = newValue; + this.form.colors_style.custom_field_name = newValue; + }, + feature_type(newValue) { + if (newValue) { + // Init form + this.form.color = JSON.parse(JSON.stringify(newValue.color)); + this.form.icon = JSON.parse(JSON.stringify(newValue.icon)); + this.form.colors_style = { + ...this.form.colors_style, + ...JSON.parse(JSON.stringify(newValue.colors_style)) + }; + } + }, + form: { + deep: true, + handler(newValue) { + if (isEqual(newValue, { + color: this.feature_type.color, + icon: this.feature_type.icon, + colors_style: this.feature_type.colors_style + })) { + this.canSaveSymbology = false; + } else { + this.canSaveSymbology = true; + } + } } }, @@ -144,6 +190,15 @@ export default { this.GET_PROJECT_INFO(this.$route.params.slug); } this.SET_CURRENT_FEATURE_TYPE_SLUG(this.$route.params.slug_type_signal); + if (this.feature_type) { + // Init form + this.form.color = JSON.parse(JSON.stringify(this.feature_type.color)); + this.form.icon = JSON.parse(JSON.stringify(this.feature_type.icon)); + this.form.colors_style = { + ...this.form.colors_style, + ...JSON.parse(JSON.stringify(this.feature_type.colors_style)) + }; + } }, methods: { @@ -151,7 +206,8 @@ export default { 'SET_CURRENT_FEATURE_TYPE_SLUG' ]), ...mapActions('feature_type', [ - 'SEND_FEATURE_SYMBOLOGY' + 'SEND_FEATURE_SYMBOLOGY', + 'GET_PROJECT_FEATURE_TYPES' ]), ...mapActions([ 'GET_PROJECT_INFO' @@ -165,6 +221,8 @@ export default { setColorsStyle(e) { const { name, value } = e; + this.form.colors_style.colors[name] = value.color; + this.form.colors_style.icons[name] = value.icon; this.form.colors_style.value.colors[name] = value.color; this.form.colors_style.value.icons[name] = value.icon; }, @@ -173,11 +231,19 @@ export default { this.loading = true; this.SEND_FEATURE_SYMBOLOGY(this.form) .then(() => { - this.loading = false; + this.GET_PROJECT_FEATURE_TYPES(this.$route.params.slug) + .then(() => { + this.loading = false; + this.success = 'La modification de la symbologie a été prise en compte.' + }) + .catch((err) => { + console.error(err); + }) }) - .catch(() => { + .catch((err) => { + console.error(err); this.loading = false; - }) + }); } } } diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue index e332498ebf363245396fc4353edc226c301044af..a24c49fcd1aa459a80974b5e3202f7766d5da00b 100644 --- a/src/views/project/Project_detail.vue +++ b/src/views/project/Project_detail.vue @@ -353,6 +353,14 @@ </div> </div> <div class="seven wide column"> + <div + :class="{ active : mapLoading }" + class="ui inverted dimmer" + > + <div class="ui text loader"> + Chargement de la carte... + </div> + </div> <div id="map" ref="map"></div> </div> </div> @@ -374,8 +382,8 @@ </div> <div class="ui relaxed list"> <div - v-for="(item, index) in features" - :key="item.title + index" + v-for="(item, index) in features.slice(-5)" + :key="item.properties.title + index" class="item" > <div class="content"> @@ -385,21 +393,27 @@ name: 'details-signalement', params: { slug: project.slug, - slug_type_signal: item.feature_type.slug, - slug_signal: item.feature_id, + slug_type_signal: item.properties.feature_type.slug, + slug_signal: item.id, }, }" - >{{ item.title || item.feature_id }}</router-link + >{{ item.properties.title || item.id }}</router-link > </div> <div class="description"> - <i - >[{{ item.created_on | setDate - }}<span v-if="user && item.display_creator" - >, par {{ item.display_creator }} + <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> - ]</i - > + ] + </i> </div> </div> </div> @@ -645,7 +659,9 @@ export default { projectInfoLoading: true, featureTypeImporting: false, featuresLoading: true, - isFileSizeModalOpen: false + isFileSizeModalOpen: false, + // mapFeatures: null, + mapLoading: true, }; }, @@ -666,6 +682,9 @@ export default { 'user', 'reloadIntervalId' ]), + ...mapState('map', [ + 'map' + ]), DJANGO_BASE_URL() { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, @@ -703,9 +722,62 @@ export default { 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 + ); + 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 }) + .then((data) => (this.is_suscriber = data.is_suscriber)); + } + this.$store.commit("feature_type/SET_FEATURE_TYPES", []); //* empty feature_types remaining from previous project + }, + + mounted() { + this.GET_PROJECT_INFO(this.slug) + .then(() => { + this.projectInfoLoading = false; + setTimeout(this.initMap, 1000); + }) + .catch((err) => { + console.error(err) + this.projectInfoLoading = false; + }); + + if (this.message) { + this.tempMessage = this.message; + document + .getElementById("message") + .scrollIntoView({ block: "end", inline: "nearest" }); + setTimeout(() => (this.tempMessage = null), 5000); //* hide message after 5 seconds + } + }, + + destroyed() { + this.CLEAR_RELOAD_INTERVAL_ID(); + }, + methods: { ...mapMutations([ 'SET_RELOAD_INTERVAL_ID', @@ -714,6 +786,9 @@ export default { ...mapActions([ 'GET_PROJECT_INFO' ]), + ...mapActions('map', [ + 'INITIATE_MAP' + ]), ...mapActions('feature_type', [ 'GET_IMPORTS' ]), @@ -756,7 +831,6 @@ export default { let self = this; this.arraysOfflineErrors = []; this.arraysOffline.forEach((feature) => { - console.log(feature); if (feature.type === "post") { promises.push( axios @@ -770,7 +844,7 @@ export default { } }) .catch((error) => { - console.log(error); + console.error(error); self.arraysOfflineErrors.push(feature); }) ); @@ -782,7 +856,6 @@ export default { feature.geojson ) .then((response) => { - console.log(response); if (response.status === 200 && response.data) { return "OK" } @@ -791,7 +864,7 @@ export default { } }) .catch((error) => { - console.log(error); + console.error(error); self.arraysOfflineErrors.push(feature); }) ); @@ -883,9 +956,9 @@ export default { setTimeout(() => (this.infoMessage = ""), 3000); }); }, - initMap() { + async initMap() { if (this.project && this.permissions.can_view_project) { - this.$store.dispatch("map/INITIATE_MAP", this.$refs.map); + await this.INITIATE_MAP(this.$refs.map); 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}`; @@ -894,7 +967,6 @@ export default { this.$route.params.slug, this.$store.state.feature_type.feature_types ); - this.arraysOffline.forEach((x) => (x.geojson.properties.color = "red")); const features = this.arraysOffline.map((x) => x.geojson); mapUtil.addFeatures( @@ -904,6 +976,20 @@ export default { this.$store.state.feature_type.feature_types ); + this.GET_PROJECT_FEATURES({ + project_slug: this.slug, + ordering: '-created_on', + limit: null, + geojson: true + }) + .then(() => { + this.featuresLoading = false; + }) + .catch((err) => { + console.error(err) + this.featuresLoading = false; + }); + featureAPI .getFeaturesBbox(this.project.slug) .then((bbox) => { @@ -914,45 +1000,6 @@ export default { } }, }, - - created() { - if (this.user) { - projectAPI - .getProjectSubscription({ projectSlug: this.$route.params.slug }) - .then((data) => (this.is_suscriber = data.is_suscriber)); - } - this.$store.commit("feature_type/SET_FEATURE_TYPES", []); //* empty feature_types remaining from previous project - }, - - mounted() { - this.GET_PROJECT_INFO(this.slug) - .then(() => { - this.projectInfoLoading = false; - setTimeout(this.initMap, 1000); - }) - .catch(() => { - this.projectInfoLoading = false; - }); - this.GET_PROJECT_FEATURES({ - project_slug: this.slug, - ordering: '-created_on', - limit: 5 - }) - .then(() => { - this.featuresLoading = false; - }) - .catch(() => { - this.featuresLoading = false; - }); - - if (this.message) { - this.tempMessage = this.message; - document - .getElementById("message") - .scrollIntoView({ block: "end", inline: "nearest" }); - setTimeout(() => (this.tempMessage = null), 5000); //* hide message after 5 seconds - } - }, }; </script> diff --git a/src/views/project/Project_edit.vue b/src/views/project/Project_edit.vue index f925b211dbabb87f780c1cf4be0b959c518abcbf..5aed3f7d69d9175da7fb9aa3fb84d954ec500821 100644 --- a/src/views/project/Project_edit.vue +++ b/src/views/project/Project_edit.vue @@ -371,6 +371,7 @@ export default { goBackNrefresh(slug) { Promise.all([ + this.$store.dispatch("GET_USER_LEVEL_PROJECTS"), //* refresh projects user levels this.$store.dispatch("GET_USER_LEVEL_PERMISSIONS"), //* refresh projects permissions this.$store.dispatch("GET_ALL_PROJECTS"), //* & refresh project list ]).then(() => diff --git a/src/views/project/Project_mapping.vue b/src/views/project/Project_mapping.vue index 34397ecb7b5f37acb1814dac5b3e6236cb799654..7ab8de8b85ed98b6d09f9a00100cfb7e8180b97b 100644 --- a/src/views/project/Project_mapping.vue +++ b/src/views/project/Project_mapping.vue @@ -87,7 +87,6 @@ export default { checkTitles() { let isValid = true; this.basemaps.forEach((basemap) => { - console.log(basemap); if (basemap.title === null || basemap.title === "") { basemap.errors = "Veuillez compléter ce champ."; isValid = false; @@ -134,7 +133,7 @@ export default { ); }) .catch((error) => { - console.log(error); + console.error(error); }); } },