Compare commits

...

306 commits

Author SHA1 Message Date
Yohan Boniface
a3a520dec4 3.0.5
Some checks failed
Release Charts / release (push) Has been cancelled
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-25 17:45:37 +02:00
Yohan Boniface
4b4f9bbc5c i18n 2025-04-25 17:40:47 +02:00
Yohan Boniface
279717e630 chore: fix badge visibility in filter tab in browser panel
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-25 17:29:18 +02:00
Yohan Boniface
39e4e2a33c
fix: make sure DataLayer rank is always set (#2682) 2025-04-25 17:20:10 +02:00
Yohan Boniface
e5dbca21b0 fix: make sure DataLayer rank is always set
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-25 17:12:17 +02:00
Yohan Boniface
1ecddc1c02
chore: use details/summary for datalayers boxes in browser (#2680)
![image](https://github.com/user-attachments/assets/978e2f05-b7f3-4648-afec-92a24a88226a)
2025-04-25 16:29:06 +02:00
Yohan Boniface
8658e7eba7 chore: use details/summary for datalayers boxes in browser 2025-04-25 16:20:37 +02:00
Yohan Boniface
6ac3685172
fix: fix error when saving and deleting heatmap layer (#2681) 2025-04-25 15:57:17 +02:00
Yohan Boniface
1085861d42 chore: add --maxfail to py.test in make test command
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-25 15:56:20 +02:00
Yohan Boniface
fab0c8f9ea fix: fix error when saving and deleting heatmap layer
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-25 15:47:33 +02:00
Yohan Boniface
858768896e
fix: loading remote data should not make the map dirty (#2679)
See the second commit for the logic change.
2025-04-25 15:35:38 +02:00
Yohan Boniface
bffbeb5230
fix: allow to save/undo/sync drag'n'drop of datalayers (#2677)
This also:
- introduces a new DataLayerManager
- removes the _umap_options coming from the geojson form the server
- removes all backup related functions (now we have undo/redo)

fix #2674
2025-04-25 15:35:23 +02:00
Yohan Boniface
f01a74f19f i18n 2025-04-25 11:29:43 +02:00
Yohan Boniface
00228ccf92 fix: loading remote data should not make the map dirty 2025-04-25 11:25:54 +02:00
Yohan Boniface
6c8046456a chore: remove unused isDirty flags 2025-04-25 09:44:49 +02:00
Yohan Boniface
626b669d89 fixup: fix tests 2025-04-25 07:09:31 +02:00
Yohan Boniface
5af41b4528 fix: allow to save/undo/sync drag'n'drop of datalayers
This also:
- introduces a new DataLayerManager
- removes the _umap_options coming from the geojson form the server
- removes all backup related functions (now we have undo/redo)

Co-authored-by: David Larlet <david@larlet.fr>
2025-04-24 18:38:02 +02:00
Yohan Boniface
1a9c325f16
fix: setting center and zoom manually should set dirty status (#2676)
Some checks failed
Release Charts / release (push) Has been cancelled
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-23 18:51:36 +02:00
Yohan Boniface
19d16ac01b fix: setting center and zoom manually should set dirty status
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-23 18:00:48 +02:00
Yohan Boniface
efaa765b82
chore: cleaning core utils and removing DomUtil/DomEvent from modules (#2671) 2025-04-23 17:51:45 +02:00
Yohan Boniface
92ca581fb6
fix: allow to save a remote data with unloaded data (#2657)
When loading remote data fails, the layer is in state "unloaded", and
thus it was not possible to save it.
This "isLoaded" check is made for non remote layer so that we don't save
it by mistake with no data.

Also, let's allow to edit non loaded layers, this check was there when
settings was not on db, so not all loaded at map init, again not to
override with incomplete metadata.
2025-04-23 17:49:12 +02:00
Yohan Boniface
6687cd53ba
feat: add a back button in rules form (#2673)
To go back in rules list.

fix #2631


![image](https://github.com/user-attachments/assets/d0ad67fe-90c1-45c5-8bca-5ac30ef8366a)
2025-04-23 17:43:22 +02:00
Yohan Boniface
4997ee8860
feat: naive support for GeometryCollection as Feature geometry (#2658)
Currently, we just skip those, but sometimes togeojson produces this
output from a KML.
This will create one feature per geometry, while in an ideal world this
should be a multi, but we lack reliable geometry tools to merge the
geometries without risking to create mistakes.
So let's say it's a first improvement.
2025-04-23 17:43:05 +02:00
Yohan Boniface
a708316604
fix: make rules reordering syncable, savable and undoable (#2672) 2025-04-23 17:42:47 +02:00
Yohan Boniface
71d92aa610
fix: show an error message if saving layer failed (#2670)
This could occur when server is down or there is no network.
2025-04-23 17:40:19 +02:00
Yohan Boniface
41752bd0c6
fix: do not display "saved" message if some request failed (#2669) 2025-04-23 17:39:59 +02:00
Yohan Boniface
5b6138a210
chore: move pure Leaflet controls to modules (#2668)
pure == inheriting from Leaflet itself, not from some plugin (which
aren't ESM ready…)
2025-04-23 17:39:33 +02:00
Yohan Boniface
07363fa5fe chore: remove unused DomEvent.once 2025-04-23 16:52:55 +02:00
Yohan Boniface
7991d6cdbe chore: remove DomUtil.after/before 2025-04-23 16:50:13 +02:00
Yohan Boniface
60ac4b35f2 chore: remove most of DomUtil/DomEvent from browser.js 2025-04-23 16:24:15 +02:00
Yohan Boniface
bf2e9dc175 chore: remove call to DomUtil.createIcon in umap.js 2025-04-23 11:33:12 +02:00
Yohan Boniface
67ed6d5b44 feat: add a back button in rules form
To go back in rules list.

fix #2631
2025-04-23 10:55:39 +02:00
Yohan Boniface
fad182c5f3 fix: make rules reordering syncable, savable and undoable 2025-04-23 10:19:19 +02:00
Yohan Boniface
3f5d282477 chore: remove DomUtil and DomEvent dependency from rules.js 2025-04-23 10:14:22 +02:00
Yohan Boniface
49496348d2 chore: remove unused L.DomUtil.createLink method 2025-04-23 09:21:35 +02:00
Yohan Boniface
f8b13639aa fix: show an error message if saving layer failed
This could occur when server is down or there is no network.
2025-04-23 09:02:25 +02:00
Yohan Boniface
4c71710641 fix: do not display "saved" message if some request failed 2025-04-23 08:58:17 +02:00
Yohan Boniface
92d5c47844 chore: move pure Leaflet controls to modules
pure == inheriting from Leaflet itself, not from some plugin
(which aren't ESM ready…)
2025-04-22 20:14:06 +02:00
Yohan Boniface
05493d8a48
chore: bump uvicorn from 0.34.1 to 0.34.2 (#2664)
Some checks failed
Release Charts / release (push) Has been cancelled
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-22 15:06:34 +02:00
Yohan Boniface
fd8f403a69
chore: bump mkdocs-material from 9.6.11 to 9.6.12 (#2665) 2025-04-22 15:06:19 +02:00
Yohan Boniface
a6412c9539
chore: bump ruff from 0.11.4 to 0.11.6 (#2666) 2025-04-22 15:06:01 +02:00
Yohan Boniface
fe65a5351b
chore: bump moto[s3] from 5.1.3 to 5.1.4 (#2667) 2025-04-22 15:05:44 +02:00
dependabot[bot]
2ede25f541
chore: bump moto[s3] from 5.1.3 to 5.1.4
Bumps [moto[s3]](https://github.com/getmoto/moto) from 5.1.3 to 5.1.4.
- [Release notes](https://github.com/getmoto/moto/releases)
- [Changelog](https://github.com/getmoto/moto/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getmoto/moto/compare/5.1.3...5.1.4)

---
updated-dependencies:
- dependency-name: moto[s3]
  dependency-version: 5.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 17:46:08 +00:00
dependabot[bot]
b7acdcfd93
chore: bump ruff from 0.11.4 to 0.11.6
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.4 to 0.11.6.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.4...0.11.6)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.11.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 17:39:19 +00:00
dependabot[bot]
a3d2330661
chore: bump mkdocs-material from 9.6.11 to 9.6.12
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.11 to 9.6.12.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.11...9.6.12)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-version: 9.6.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 17:33:21 +00:00
dependabot[bot]
20ae374173
chore: bump uvicorn from 0.34.1 to 0.34.2
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.34.1 to 0.34.2.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/docs/release-notes.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.34.1...0.34.2)

---
updated-dependencies:
- dependency-name: uvicorn
  dependency-version: 0.34.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 17:29:12 +00:00
David Larlet
162473da9d
chore: more design system elements (#2661)
Some checks failed
Release Charts / release (push) Has been cancelled
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-18 10:03:12 -04:00
David Larlet
78d333c217
chore: more design system elements 2025-04-17 17:29:43 -04:00
Yohan Boniface
b0fe95dbd9 feat: naive support for GeometryCollection as Feature geometry
Currently, we just skip those, but sometimes togeojson produces this
output from a KML.
This will create one feature per geometry, while in an ideal world this
should be a multi, but we lack reliable geometry tools to merge the
geometries without risking to create mistakes.
So let's say it's a first improvement.
2025-04-16 18:28:23 +02:00
Yohan Boniface
23b82975f5 chore: bump togeojson
Some checks failed
Release Charts / release (push) Has been cancelled
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-16 17:30:17 +02:00
Yohan Boniface
169be73488 fix: allow to save a remote data with unloaded data
When loading remote data fails, the layer is in state "unloaded",
and thus it was not possible to save it.
This "isLoaded" check is made for non remote layer so that we don't
save it by mistake with no data.

Also, let's allow to edit non loaded layers, this check was there
when settings was not on db, so not all loaded at map init, again
not to override with incomplete metadata.
2025-04-16 16:00:26 +02:00
Yohan Boniface
6945a5e867
feat: pass CSRF_TRUSTED_ORIGINS env to settings (#2656)
Some checks are pending
Release Charts / release (push) Waiting to run
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
Allow to manage djangos CSRF_TRUSTED_ORIGINS by environment variables.

Closes #2655
2025-04-16 12:34:49 +02:00
Oliver Lippert
2ed890202e
code formatting 2025-04-16 12:25:17 +02:00
Oliver Lippert
cc7685ca3f
pass CSRF_TRUSTED_ORIGINS env to settings
fixes https://github.com/umap-project/umap/issues/2655
2025-04-16 12:23:09 +02:00
David Larlet
23688b6444
feat: implement a design system for UI consistency (#2654)
Some checks are pending
Release Charts / release (push) Waiting to run
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-04-15 08:19:31 -04:00
David Larlet
d3c0947fa5
feat: implement a design system for UI consistency 2025-04-14 23:20:55 -04:00
Yohan Boniface
a135e5c3e1
chore: bump pytest-django from 4.10.0 to 4.11.1 (#2653)
Some checks are pending
Release Charts / release (push) Waiting to run
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-04-14 19:50:30 +02:00
Yohan Boniface
2ad46046f8
chore: bump uvicorn from 0.34.0 to 0.34.1 (#2651) 2025-04-14 19:50:14 +02:00
Yohan Boniface
5271d7c19d
chore: bump pydantic from 2.11.2 to 2.11.3 (#2652) 2025-04-14 19:36:42 +02:00
Yohan Boniface
a535c86f6b
chore: bump mkdocs-material from 9.6.10 to 9.6.11 (#2649) 2025-04-14 19:36:16 +02:00
Yohan Boniface
9aa1f58dc8
chore: bump pillow from 11.1.0 to 11.2.1 (#2650)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 11.1.0 to
11.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/python-pillow/Pillow/releases">pillow's
releases</a>.</em></p>
<blockquote>
<h2>11.2.1</h2>
<p><a
href="https://pillow.readthedocs.io/en/stable/releasenotes/11.2.1.html">https://pillow.readthedocs.io/en/stable/releasenotes/11.2.1.html</a></p>
<h2>Deprecations</h2>
<ul>
<li>Moved get_child_images() to ImageFile <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8689">#8689</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
</ul>
<h2>Documentation</h2>
<ul>
<li>Add 11.2.1 release notes <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8885">#8885</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added avif to config settings <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8875">#8875</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added release notes for <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8330">#8330</a>
<a
href="https://redirect.github.com/python-pillow/Pillow/issues/8853">#8853</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added release notes for <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8781">#8781</a>
and <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8837">#8837</a>
<a
href="https://redirect.github.com/python-pillow/Pillow/issues/8843">#8843</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added media_white_point to ImageCms documentation <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8829">#8829</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Removed FIXME <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8825">#8825</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated comment <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8822">#8822</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added release notes for <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8807">#8807</a>
<a
href="https://redirect.github.com/python-pillow/Pillow/issues/8824">#8824</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>DXT3 images are read in RGBA mode <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8817">#8817</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>JPEG comments are from the COM marker <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8788">#8788</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update Sphinx to 8.2 to remove nitpick ignore <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8763">#8763</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated AffineTransform docstring to mention it uses the inverse
matrix <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8735">#8735</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added MozJPEG documentation <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8699">#8699</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added Sphinx configuration key <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8691">#8691</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated macOS tested Pillow versions <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8654">#8654</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
</ul>
<h2>Dependencies</h2>
<ul>
<li>Updated xz to 5.8.1 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8868">#8868</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated harfbuzz to 11.0.1 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8870">#8870</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update scientific-python/upload-nightly-action action to v0.6.2 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8865">#8865</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Updated xz to 5.8.0 in macOS and Linux wheels, but not on
manylinux2014 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8836">#8836</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update dependency cibuildwheel to v2.23.2 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8832">#8832</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Updated harfbuzz to 11.0.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8830">#8830</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update dependency cibuildwheel to v2.23.1 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8818">#8818</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Updated Ghostscript to 10.5.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8814">#8814</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated libtiff to 4.7.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8812">#8812</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>[pre-commit.ci] pre-commit autoupdate <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8795">#8795</a>
[@<a
href="https://github.com/apps/pre-commit-ci">pre-commit-ci[bot]</a>]</li>
<li>Updated harfbuzz to 10.4.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8770">#8770</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update dependency mypy to v1.15.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8791">#8791</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Updated libpng to 1.6.47 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8764">#8764</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated lcms2 to 2.17 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8742">#8742</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update dependency cibuildwheel to v2.23.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8785">#8785</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Updated zlib-ng to 2.2.4 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8745">#8745</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated libimagequant to 4.3.4 on Windows <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8744">#8744</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>[pre-commit.ci] pre-commit autoupdate <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8729">#8729</a>
[@<a
href="https://github.com/apps/pre-commit-ci">pre-commit-ci[bot]</a>]</li>
<li>Updated harfbuzz to 10.2.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8688">#8688</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated xz to 5.6.4 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8711">#8711</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated libpng to 1.6.46 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8712">#8712</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated libimagequant to 4.3.4 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8710">#8710</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Updated libpng to 1.6.45 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8670">#8670</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst">pillow's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog (Pillow)</h1>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="339bc5db93"><code>339bc5d</code></a>
11.2.1 version bump</li>
<li><a
href="857b8846ea"><code>857b884</code></a>
Merge pull request <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8885">#8885</a>
from radarhere/releasenotes</li>
<li><a
href="7a0092f207"><code>7a0092f</code></a>
Remove incomplete 11.2.0 release, bill as 11.2.1 instead</li>
<li><a
href="d52c2db317"><code>d52c2db</code></a>
Do not include libavif in wheels</li>
<li><a
href="8dafc38371"><code>8dafc38</code></a>
Added 11.2.1 release notes</li>
<li><a
href="07d7800248"><code>07d7800</code></a>
Removed release notes update</li>
<li><a
href="04909483a7"><code>0490948</code></a>
Remove GPL v2 license (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/8884">#8884</a>)</li>
<li><a
href="774d0aedce"><code>774d0ae</code></a>
Merge pull request <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8868">#8868</a>
from radarhere/xz_upgrade</li>
<li><a
href="d1e27fc86c"><code>d1e27fc</code></a>
Merge pull request <a
href="https://redirect.github.com/python-pillow/Pillow/issues/8870">#8870</a>
from radarhere/harfbuzz_upgrade</li>
<li><a
href="c8d98d56a0"><code>c8d98d5</code></a>
Added avif to config settings (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/8875">#8875</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python-pillow/Pillow/compare/11.1.0...11.2.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pillow&package-manager=pip&previous-version=11.1.0&new-version=11.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-04-14 19:36:00 +02:00
dependabot[bot]
102104f818
chore: bump pytest-django from 4.10.0 to 4.11.1
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.10.0 to 4.11.1.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.10.0...v4.11.1)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-version: 4.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:30:01 +00:00
dependabot[bot]
35e5a4bda6
chore: bump pydantic from 2.11.2 to 2.11.3
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.11.2 to 2.11.3.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.11.2...v2.11.3)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-version: 2.11.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:29:38 +00:00
dependabot[bot]
6bae315efe
chore: bump uvicorn from 0.34.0 to 0.34.1
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.34.0 to 0.34.1.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/docs/release-notes.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.34.0...0.34.1)

---
updated-dependencies:
- dependency-name: uvicorn
  dependency-version: 0.34.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:29:19 +00:00
dependabot[bot]
93120d91d6
chore: bump pillow from 11.1.0 to 11.2.1
Bumps [pillow](https://github.com/python-pillow/Pillow) from 11.1.0 to 11.2.1.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/11.1.0...11.2.1)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 11.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:29:05 +00:00
dependabot[bot]
f037973a03
chore: bump mkdocs-material from 9.6.10 to 9.6.11
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.10 to 9.6.11.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.10...9.6.11)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-version: 9.6.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:28:43 +00:00
Yohan Boniface
c4614354ae 3.0.4 2025-04-14 17:57:12 +02:00
Yohan Boniface
9ed466ea9b
chore: update colors (#2647) 2025-04-14 17:55:19 +02:00
Yohan Boniface
168cc0c996 i18n 2025-04-14 17:49:09 +02:00
Yohan Boniface
ae4e7eb3e2 chore: update colors
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-14 17:45:11 +02:00
Yohan Boniface
3670b7dca6
Adapt chart to match La Suite's expectations (#2646)
- env vars and config files can be loaded from existing secrets
- chart is deployed on a helm repository

to make the helm repository work with github pages, create an empty
orphaned branch called gh-pages, and under settings>pages>source select
deploy from branch and use gh-pages
2025-04-14 17:36:31 +02:00
David Larlet
1c3cf9a7c5
chore: switch helm chart job to master branch 2025-04-14 11:31:06 -04:00
Yohan Boniface
ada44fc0fc
fix: remove "hide home button" shown twice in map settings (#2645) 2025-04-14 17:30:52 +02:00
Yohan Boniface
ac6964c9f4 fix: remove "hide home button" shown twice in map settings
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-14 16:30:38 +02:00
David Larlet
82dcd90405
fix: do not show "back to home" button in iframes (#2644) 2025-04-14 10:21:21 -04:00
Yohan Boniface
d9e983aed4 fix: do not show "back to home" button in iframes
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-14 16:12:35 +02:00
Yohan Boniface
071a8c539d 3.0.3
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-11 18:09:14 +02:00
Yohan Boniface
ec8fa87b41 i18n 2025-04-11 17:33:22 +02:00
Yohan Boniface
ef072f0a8e
feat: allow to hide the back to home button (#2638) 2025-04-11 17:30:15 +02:00
Yohan Boniface
33f407fd60
feat: hidden download button in browser when embedControl=false (#2640)
cf #2629
2025-04-11 17:27:02 +02:00
David Larlet
324c5cf6bf feat: allow to hide the back to home button
Co-authored-by: Yohan Boniface <yohanboniface@free.fr>
2025-04-11 17:22:09 +02:00
Yohan Boniface
e53cdcb04e feat: hidden download button in browser when embedControl=false
cf #2629

Co-authored-by: David Larlet <david@larlet.fr>
2025-04-11 17:15:39 +02:00
David Larlet
5e3170891a
feat: allow to hide the layer switcher from bottom bar (#2639) 2025-04-11 10:58:54 -04:00
David Larlet
495286c261
feat: allow to hide the layer switcher from bottom bar 2025-04-11 10:44:01 -04:00
Yohan Boniface
15972bab3d
document that nginx needs to be added in Docker stack to serve statics (#2636) 2025-04-11 16:19:47 +02:00
Yohan Boniface
bd91934544
fix: do not try to remove a feature not yet added (#2637)
cf #2625

This happens while drawing a line or polygon and then hitting escape
while the path is not yet valid.
2025-04-11 16:19:29 +02:00
Yohan Boniface
581140e08a
fix: do not try to remove a feature not yet added
cf #2625

This happens while drawing a line or polygon and then hitting escape
while the path is not yet valid.
2025-04-11 10:02:31 -04:00
David Larlet
10f87c0b6e
fix: display search category on list page (#2635) 2025-04-11 08:24:07 -04:00
Yohan Boniface
0ec4e74f8f wip: add nginx in docker-compose.yml 2025-04-11 11:31:54 +02:00
Yohan Boniface
89033e04a2 chore: add a deploy overview doc page 2025-04-11 10:09:24 +02:00
David Larlet
38f4fd5bb3
fix: display search category on list page 2025-04-10 17:13:33 -04:00
Yohan Boniface
985d91a9c7
fix: display back help button in switch fields (#2634)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
cf #2615

Before:

![image](https://github.com/user-attachments/assets/bac68a6b-6c74-4f10-8d3c-26536dc1ecad)

After:

![image](https://github.com/user-attachments/assets/43c4a0b3-a892-423a-8c20-b7c6304f3182)
2025-04-10 21:46:27 +02:00
Yohan Boniface
7348f0bf4f fix: display back help button in switch fields
cf #2615
2025-04-10 20:24:35 +02:00
Yohan Boniface
dc35e7df6d
fix: fix pictogram categories always hidden (#2630)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-09 17:17:29 +02:00
Yohan Boniface
d9378a484d fix: fix pictogram categories always hidden 2025-04-09 16:06:20 +02:00
Yohan Boniface
cfcdfb9ed8
chore: add missing margin-bottom in importers (#2627) 2025-04-09 15:59:00 +02:00
Yohan Boniface
0b8c7ee381
chore: redirect to user dashboard after map delete (#2626)
If user is authenticated.

We do not display alert messages on the home page.
2025-04-09 15:45:11 +02:00
Yohan Boniface
36e9433cf9
Apply suggestions from code review
Co-authored-by: David Larlet <3556+davidbgk@users.noreply.github.com>
2025-04-09 15:44:36 +02:00
Yohan Boniface
425f66b181
fix: fix text overflow on search results (#2628)
Before:
![Screenshot From 2025-04-09
09-41-21](https://github.com/user-attachments/assets/727ead82-7bb7-4cdb-b676-994f84ed8eaf)

After:
![Screenshot From 2025-04-09
09-40-58](https://github.com/user-attachments/assets/e778ba59-a255-4230-9531-cdba67c444cc)

(Please don't ask :p )
2025-04-09 15:42:57 +02:00
Yohan Boniface
18f0b6e2a7 chore: rename variable to make it more explicit 2025-04-09 11:27:29 +02:00
Yohan Boniface
50f23b4e02 fix: fix text overflow on search results 2025-04-09 09:41:37 +02:00
Yohan Boniface
36d58993a0 chore: add missing margin-bottom in importers 2025-04-09 09:32:54 +02:00
Yohan Boniface
5f2e104eec
feat: use Last-Modified header from remote data when available (#2624)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
fix #2589
2025-04-09 09:09:40 +02:00
Yohan Boniface
5c38bc7970 chore: redirect to user dashboard after map delete
If user is authenticated.

We do not display alert messages on the home page.
2025-04-09 08:54:44 +02:00
Yohan Boniface
dcce3ad054
Update umap/static/umap/js/modules/umap.js
Co-authored-by: David Larlet <3556+davidbgk@users.noreply.github.com>
2025-04-08 18:13:05 +02:00
Yohan Boniface
88ddb1cab3 3.0.2
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-04-08 17:23:15 +02:00
Yohan Boniface
dd7540596c
fix: give priority to small usernames on autocomplete (#2604)
Basically, when the search is "joe" we first try to search for an exact
account named "joe", and fallback to normal flow when nothing matches.

fix #2591
2025-04-08 17:21:14 +02:00
Yohan Boniface
2baeaace24 feat: use Last-Modified header from remote data when available
fix #2589
2025-04-08 17:03:06 +02:00
Yohan Boniface
14663bc56e fixup: order users autocomplete by username length
cf #2591
2025-04-08 15:47:06 +02:00
Yohan Boniface
fea0f02b80
fix: fix min-height of select in caption bar (#2622)
Before:
![Screenshot From 2025-04-08
15-26-28](https://github.com/user-attachments/assets/372d3410-a360-4ff3-a6f2-d7c18a3f26e3)

After:
![Screenshot From 2025-04-08
15-27-44](https://github.com/user-attachments/assets/defb737e-aed3-40b0-91b6-5b8c38675e55)
2025-04-08 15:37:56 +02:00
Yohan Boniface
85ba05f4b7
fix: fix result tools buttons background color (#2620) 2025-04-08 15:32:58 +02:00
Yohan Boniface
7b582a8ec1
fix: properly call endEdit for markers (#2617)
fix #2607
2025-04-08 15:32:09 +02:00
Yohan Boniface
3c70fc4267
fix: fix categorized layer crashing with null value (#2621)
Do not call toString on a null value
2025-04-08 15:31:51 +02:00
Yohan Boniface
b5d12282e0
fix: fix copiable input CSS (#2616)
Before:
![Screenshot From 2025-04-08
10-02-15](https://github.com/user-attachments/assets/49fd5f63-ac98-40bd-a7bc-befd24920f07)

After:
![Screenshot From 2025-04-08
10-21-33](https://github.com/user-attachments/assets/ce62ef66-6ad7-45dd-a37c-c0fb20d71e13)
2025-04-08 15:30:20 +02:00
Yohan Boniface
672d92152e fix: fix min-height of select in caption bar 2025-04-08 15:27:10 +02:00
Yohan Boniface
5b5102f909 fix: fix categorized layer crashing with null value
Do not call toString on a null value
2025-04-08 15:21:27 +02:00
Yohan Boniface
0a154daa6f fix: fix result tools buttons background color 2025-04-08 12:14:22 +02:00
Yohan Boniface
c38ec2c18d fix: fix copiable input CSS 2025-04-08 11:46:31 +02:00
Yohan Boniface
1e204ac16c fix: properly call endEdit for markers
fix #2607
2025-04-08 11:05:54 +02:00
Yohan Boniface
e2fed5a19d
chore: bump hatch from 1.14.0 to 1.14.1 (#2614) 2025-04-08 10:43:37 +02:00
Yohan Boniface
061b5fc60e
chore: bump pydantic from 2.11.1 to 2.11.2 (#2612) 2025-04-08 10:23:13 +02:00
dependabot[bot]
8c9d4e5777
chore: bump pydantic from 2.11.1 to 2.11.2
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.11.1 to 2.11.2.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.11.1...v2.11.2)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-version: 2.11.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 07:43:11 +00:00
dependabot[bot]
efde6899bd
chore: bump hatch from 1.14.0 to 1.14.1
Bumps [hatch](https://github.com/pypa/hatch) from 1.14.0 to 1.14.1.
- [Release notes](https://github.com/pypa/hatch/releases)
- [Commits](https://github.com/pypa/hatch/compare/hatch-v1.14.0...hatch-v1.14.1)

---
updated-dependencies:
- dependency-name: hatch
  dependency-version: 1.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 07:42:51 +00:00
Yohan Boniface
38e862c04a
chore: bump moto[s3] from 5.1.1 to 5.1.3 (#2610)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-04-08 09:42:12 +02:00
Yohan Boniface
2d0325f1fb
chore: bump ruff from 0.11.2 to 0.11.4 (#2611) 2025-04-08 09:41:39 +02:00
Yohan Boniface
b8ab86b075
chore: bump django-storages[s3] from 1.14.5 to 1.14.6 (#2613) 2025-04-08 09:41:11 +02:00
dependabot[bot]
7e774bc3aa
chore: bump django-storages[s3] from 1.14.5 to 1.14.6
Bumps [django-storages[s3]](https://github.com/jschneier/django-storages) from 1.14.5 to 1.14.6.
- [Changelog](https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jschneier/django-storages/compare/1.14.5...1.14.6)

---
updated-dependencies:
- dependency-name: django-storages[s3]
  dependency-version: 1.14.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 18:35:07 +00:00
dependabot[bot]
f4e3e679a9
chore: bump ruff from 0.11.2 to 0.11.4
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.2 to 0.11.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.2...0.11.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.11.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 18:30:12 +00:00
dependabot[bot]
6d391a51be
chore: bump moto[s3] from 5.1.1 to 5.1.3
Bumps [moto[s3]](https://github.com/getmoto/moto) from 5.1.1 to 5.1.3.
- [Release notes](https://github.com/getmoto/moto/releases)
- [Changelog](https://github.com/getmoto/moto/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getmoto/moto/compare/5.1.1...5.1.3)

---
updated-dependencies:
- dependency-name: moto[s3]
  dependency-version: 5.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 18:28:07 +00:00
Yohan Boniface
aa43d4efa8 3.0.1
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-04-07 20:01:53 +02:00
Yohan Boniface
4679742b96
fix: fix showLabel wrongly using MultiChoices (#2609) 2025-04-07 20:01:05 +02:00
Yohan Boniface
53329d19fd fix: fix showLabel wrongly using MultiChoices
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 19:53:20 +02:00
Yohan Boniface
c09c2c20ee 3.0.0 2025-04-07 18:55:50 +02:00
Yohan Boniface
c0c55075b7 chore: rename WEBSOCKET_ENABLED in REALTIME_ENABLED
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:55:18 +02:00
Yohan Boniface
3670c47af9 i18n 2025-04-07 18:32:05 +02:00
Yohan Boniface
f1f18ed518
Remove confirm delete for features and datalayers (#2603)
Now that we have granular undo, I'd say we can simplify the delete
process.
2025-04-07 18:24:25 +02:00
Yohan Boniface
5e47a59d07
chore: refine main search form (#2608)
![image](https://github.com/user-attachments/assets/dd73a323-6f80-4b5b-8691-79a3f92f3723)
2025-04-07 18:23:52 +02:00
Yohan Boniface
a59b0110fc
chore: refine undo/redo buttons (#2605)
![image](https://github.com/user-attachments/assets/884b3a8c-ff4e-48e2-9bdf-16d31fb7512a)
2025-04-07 18:23:37 +02:00
Yohan Boniface
e1272ec6cd fix: do not cut kbd in tooltip
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:23:08 +02:00
Yohan Boniface
55babfde34
chore: refine map list card CSS (#2606) 2025-04-07 18:17:26 +02:00
Yohan Boniface
82b8564520 chore: refine undo/redo buttons
Co-authored-by: David Larlet <david@larlet.fr>
Co-authored-by: Aurélie Jallut <aurelie.jallut@beta.gouv.fr>
2025-04-07 18:16:37 +02:00
Yohan Boniface
5070a5e5b4 chore: refine main search form
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:11:49 +02:00
Yohan Boniface
06baeb718e fix: fix Textarea trying to clear this.input
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:09:35 +02:00
Yohan Boniface
f186d3266c chore: refine map list card CSS
Co-authored-by: David Larlet <david@larlet.fr>
Co-authored-by: Aurélie Jallut <aurelie.jallut@beta.gouv.fr>
2025-04-07 16:34:09 +02:00
Yohan Boniface
f4ae51ae7e fix: give priority to small usernames when query is small
Basically, when the search is "joe" we first try to search for
an exact account named "joe", and fallback to normal flow when
nothing matches.

fix #2591
2025-04-07 15:24:44 +02:00
Yohan Boniface
49bba24b90 feat: remove confirm for feature delete 2025-04-07 10:48:34 +02:00
Yohan Boniface
a2749ce805 feat: remove confirm for datalayer delete
Now that we have granular undo, no needs for this I'd say.
2025-04-07 10:35:39 +02:00
Yohan Boniface
190cac3105 i18n
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-04-04 18:54:51 +02:00
Yohan Boniface
50e354cb18
fix: explicit batch instead of blindly on add data (#2601) 2025-04-04 18:54:31 +02:00
Yohan Boniface
34e4955891
fix: use the multichoices for ttl in remote data form (#2599) 2025-04-04 18:49:23 +02:00
Yohan Boniface
91c3b098df wip: return data in DataLayer.importRaw 2025-04-04 18:45:31 +02:00
Yohan Boniface
2967c023f3
fix: do not add auto zoom and center in undo stack (#2602) 2025-04-04 18:23:31 +02:00
David Larlet
862f19ee43 fix: use the multichoices for ttl in remote data form 2025-04-04 18:22:51 +02:00
David Larlet
fd8915355e
fix: do not export layer ids in umap backup (#2600) 2025-04-04 11:54:30 -04:00
David Larlet
02d3e19450
fix: do not add auto zoom and center in undo stack
Co-authored-by: Yohan Boniface <yohanboniface@free.fr>
2025-04-04 11:54:00 -04:00
David Larlet
b342480f3b
fix: explicit batch instead of blindly on add data
Co-authored-by: Yohan Boniface <yohanboniface@free.fr>
2025-04-04 11:45:26 -04:00
David Larlet
c5c352cfac
fix: do not export layer ids in umap backup 2025-04-04 11:26:10 -04:00
David Larlet
d6f591b365
fix: remote data loading on import from umap backup (#2598) 2025-04-04 11:15:23 -04:00
David Larlet
90bbc72320
fix: restore width and height for default marker icon
Co-authored-by: Yohan Boniface <yohanboniface@free.fr>
2025-04-04 11:15:03 -04:00
David Larlet
b05e6ec28c
fix: remote data loading on import from umap backup 2025-04-04 11:05:33 -04:00
David Larlet
0e56e71e87
fix: Minimize the default svg icon for marker
Co-authored-by: Yohan Boniface <yohanboniface@free.fr>
2025-04-04 10:28:43 -04:00
Yohan Boniface
5c51a7a735
feat: add keyboard shortcut for redo (ctrl+shift+z) (#2596)
I've reworked a bit the shortcut handling, as it was only dealing with
ctrl/meta only ones (no shift).
2025-04-04 16:25:04 +02:00
Yohan Boniface
563aee81e1 feat: add keyboard shortcut for redo (ctrl+shift+z) 2025-04-04 16:14:04 +02:00
Yohan Boniface
3720ccff01
feat: add minimal "raw" icon shape (#2597)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
Basically, it means "no shape".


![image](https://github.com/user-attachments/assets/7ddaf76a-2128-49fc-8664-754b09d2b9ef)

It's a 48x48 max square (but if image is smaller it will stay smaller),
popup and tooltip always centered.

Let's see how this will be used and add more controls if needed later
(like size, center position…).

Also I've added a small border to the default white round icon, so it's
visible even on a white background.

(Not sure why the flower size is 47.8 instead of 48, cf screenshot,
sounds like a Leaflet rounding issue…)

cf #125
2025-04-04 16:08:04 +02:00
Yohan Boniface
9e5c985d6c feat: add minimal "raw" icon shape 2025-04-04 12:02:46 +02:00
Yohan Boniface
32b9217bd2
feat: add Map.tags and allow to edit from client (#2530)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
cf #2283

Note: this PR uses ArrayField, which is Postgres only, so this would
officially remove the support of spatialite as it is. I'm not sure at
all uMap still works with spatialite, so maybe that the opportunity to
either add spatialite in the CI and make sure we support it, or remove
it and only target Postgres/PostGIS.
2025-04-03 18:52:17 +02:00
Yohan Boniface
4fd57e0c11 chore: remove tag icons for now
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 18:29:39 +02:00
Yohan Boniface
54420568af chore: refine map fragment card CSS
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 18:20:50 +02:00
Yohan Boniface
8c90535105 chore: better CSS for tags in maps list
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 17:51:37 +02:00
Yohan Boniface
80a969917a chore: simplify search form CSS and HTML
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 17:51:20 +02:00
Yohan Boniface
6582e85f18
Update the Dockerfile to expose websockets (#2576)
The Dockerfile now uses ASGI by default (via uvicorn).
2025-04-03 17:16:56 +02:00
Yohan Boniface
023645a160 wip: make Redis service optional in Docker image
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 17:12:12 +02:00
Yohan Boniface
e24695b68c wip: display tags in maps list 2025-04-03 14:51:04 +02:00
Yohan Boniface
db72bfad8d wip: sort tags by label, not by value 2025-04-03 11:10:36 +02:00
Yohan Boniface
738af24dfc chore: fix tags related test 2025-04-03 11:10:36 +02:00
Yohan Boniface
06f963c07f chore: align search form elements
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 11:10:36 +02:00
Yohan Boniface
c6ed896a6d feat: associate icons to tags
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-03 11:10:36 +02:00
Yohan Boniface
1344fe6b46 feat: basic filtering by tags 2025-04-03 11:10:36 +02:00
Yohan Boniface
39f38a9cdf feat: add Map.tags and allow to edit from client
cf #2283
2025-04-03 11:10:33 +02:00
Yohan Boniface
e2f154f62e
feat: add atomic undo redo (#2570)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
Todo:

- [ ] undo/sync a version restore
- [x] add test for scenario where two peers create a layer and one click
on save (both should be saved)
- [x] undo/sync of conditional rules
- [x] undo/sync of filter management from table editor
2025-04-03 10:32:47 +02:00
Yohan Boniface
7196ffe101
chore: bump mkdocs-material from 9.6.9 to 9.6.10 (#2593) 2025-04-03 08:55:19 +02:00
Yohan Boniface
99ea09e79e
chore: bump pydantic from 2.10.6 to 2.11.1 (#2594) 2025-04-03 08:55:01 +02:00
Yohan Boniface
b3f587ccf3
chore: bump django from 5.1.7 to 5.1.8 (#2595) 2025-04-03 08:49:20 +02:00
dependabot[bot]
64cf408233
chore: bump django from 5.1.7 to 5.1.8
Bumps [django](https://github.com/django/django) from 5.1.7 to 5.1.8.
- [Commits](https://github.com/django/django/compare/5.1.7...5.1.8)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 20:41:42 +00:00
dependabot[bot]
e26e8edc8a
chore: bump pydantic from 2.10.6 to 2.11.1
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.10.6 to 2.11.1.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.10.6...v2.11.1)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 17:38:06 +00:00
dependabot[bot]
1b8e217768
chore: bump mkdocs-material from 9.6.9 to 9.6.10
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.9 to 9.6.10.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.9...9.6.10)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 17:38:01 +00:00
Yohan Boniface
5259cab027 chore: remove saving.js import added by mistake during rebase 2025-03-28 18:00:14 +01:00
Yohan Boniface
7ede27bf0f chore: top edit bar responsiveness
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
5807cfbbcd wip: move undo/redo buttons to the left
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
e41ad4e069 wip: allow to sync version restore
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
c933df585c wip: add test to make sure saving also save remote dirty datalayers 2025-03-28 18:00:14 +01:00
Yohan Boniface
50f2c08ecb wip: do not call document during JS unittests 2025-03-28 18:00:14 +01:00
Yohan Boniface
d61e045903 wip: allow to sync/undo filter added/removed from table editor 2025-03-28 18:00:14 +01:00
Yohan Boniface
6b2038e83e wip: permissions does not inherit from ServerStored anymore 2025-03-28 18:00:14 +01:00
Yohan Boniface
0389e9a185 wip: allow to undo/sync rules
When editing Rule(s), we are not editing the map data itself, but a
sort of proxy objects. This was done mainly because map.properties.rules
is an array of object, and at this time Leaflet.FormBuilder did not know
how to edit an array (something like properties.rules.0.condition).
Now that we integrated FormBuilder, it still does not know how to do this
but we could teach it, or find another way (real Proxy or use reference
to the original object in the Rule).
2025-03-28 18:00:14 +01:00
Yohan Boniface
a2e864ad73 wip: uncreated map should always appear as dirty 2025-03-28 18:00:14 +01:00
Yohan Boniface
d0fb85d552 wip: DataLayer does not inherit anymore from ServerStored 2025-03-28 18:00:14 +01:00
Yohan Boniface
fa83764c8b wip: allow DataLayer.clear to be sync and undone 2025-03-28 18:00:14 +01:00
Yohan Boniface
d438a007e4 wip: uMap does not inherit anymore from ServerStored
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
be52e7ca2f wip: remove not effective code
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
172de0e2d0 wip: add permissions related fields in schema
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
77da6425c2 wip: allow to mark an operation as not undoable
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
093ed061c1 wip: tests pass
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
5cb7cb2738 fixup: make sure to toggle remote client state at save too
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
dfdfae0080 wip: derive the dirty status from the undoManager
This should pave the way for removing the SaveManager.

Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
4fd066387d Update the tests and remove cancel edits
Co-authored-by: Alexis Métaireau <alexis@notmyidea.org>
2025-03-28 18:00:14 +01:00
fa3ba46ca8 Add integration test for batch undo/redo 2025-03-28 18:00:14 +01:00
Yohan Boniface
cb46a5f875 Batch operations
Co-authored-by: Alexis Métaireau <alexis@notmyidea.org>
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 18:00:14 +01:00
Yohan Boniface
cc2625bfac wip: undo redo
Co-authored-by: Alexis Métaireau <alexis@notmyidea.org>
2025-03-28 18:00:14 +01:00
Yohan Boniface
8292608365 chore: fix HLC comparison
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
This change was made by biome, but it breaks unittests, not
sure why but let's revert for now.
2025-03-28 17:59:35 +01:00
Yohan Boniface
ae8cbf39ad
feat: display maps list as a grid now (#2590)
![image](https://github.com/user-attachments/assets/db9eafd1-b4ea-48a1-a359-3e55d0011f4b)
2025-03-28 16:15:51 +01:00
Yohan Boniface
7c5d821ec8
feat: layers selector in bottom bar (#2579) 2025-03-28 16:15:20 +01:00
Yohan Boniface
4e9e828c8f feat: display maps list as a grid now
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 16:05:11 +01:00
Yohan Boniface
79d60d0995 fix: update datalayers switcher when datalayer visibility changes
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-28 15:56:28 +01:00
Yohan Boniface
75457b6d5c
fix: do not fail when trying to read metadata of a missing geojson (#2592)
Some geojson have been removed by mistake time ago (cf #1003), when
someone tries to load a map referencing them, it was until recently just
showing an error message, but since recently we try to get the metadata
from it, and this will crash.
2025-03-28 15:28:13 +01:00
Yohan Boniface
8538db278d
feat: add titles in the text formatting dialog (#2584)
![image](https://github.com/user-attachments/assets/c90549b6-6081-4b1d-8b90-49c1df42ded2)

fix #813
2025-03-28 15:27:30 +01:00
Yohan Boniface
ba9e8ffe9b
chore: apply Biome check (#2588)
This is mostly imports ordering but there are a couple of subtleties 🐉 

There are still 9 errors before we can automatize the check with the CI!
2025-03-28 15:26:52 +01:00
Yohan Boniface
dcf5f1a763
fix: make sure umap.properties.slideshow is defined (#2583) 2025-03-28 15:25:19 +01:00
Yohan Boniface
41264e740f fix: do not fail when trying to read metadata of a missing geojson
Some geojson have been removed by mistake time ago (cf #1003), when someone
tries to load a map referencing them, it was until recently just
showing an error message, but since recently we try to get the
metadata from it, and this will crash.
2025-03-28 12:58:07 +01:00
Yohan Boniface
953b37a181 fixup: fix tests 2025-03-27 13:14:20 +01:00
Yohan Boniface
9eaf33c118 wip: only show layer selector if there are at least two layers 2025-03-27 13:11:24 +01:00
David Larlet
f2cde6af4e fixup: positionning of caption bar elements 2025-03-27 13:11:24 +01:00
Yohan Boniface
a4abecbd2c fixup: only show datalayers with inCaption=true in switcher 2025-03-27 13:11:24 +01:00
Yohan Boniface
254a2018f5 chore: use toggle to switch visibility in datalayer switcher 2025-03-27 13:11:24 +01:00
Yohan Boniface
3df52e002d wip 2025-03-27 13:11:24 +01:00
David Larlet
82208d618a
chore: apply Biome check 2025-03-26 14:37:56 -04:00
Yohan Boniface
64c7fe1ec9 fix: fix icon and button for version restore
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-26 18:05:01 +01:00
Yohan Boniface
e993aa7dbc chore: bump eslint ecmaVersion from 2020 to 2021 2025-03-26 11:30:08 +01:00
Yohan Boniface
be83eddbd0
chore: bump ruff from 0.11.0 to 0.11.2 (#2587)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-03-25 13:04:07 +01:00
dependabot[bot]
4df201107e
chore: bump ruff from 0.11.0 to 0.11.2
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.0 to 0.11.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.0...0.11.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-24 17:42:02 +00:00
Yohan Boniface
60f16cbc76
chore: remove old JS tests (#2585)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
Those are not run since more than one year, so let's trash.

fix #2260
2025-03-20 11:50:48 +01:00
Yohan Boniface
2fa88c36f8
chore: bump ruff from 0.9.10 to 0.11.0 (#2582)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-03-19 08:22:32 +01:00
Yohan Boniface
47c5c0a2f0 chore: remove old JS tests
Those are not ran since more than one year, so let's trash.

fix #2260
2025-03-19 08:16:38 +01:00
Yohan Boniface
ecca66ccc2 feat: add titles in the text formatting dialog
fix #813
2025-03-19 08:14:33 +01:00
Yohan Boniface
360ca100ba fix: make sure umap.properties.slideshow is defined 2025-03-18 07:35:10 +01:00
dependabot[bot]
e548ec60f1
chore: bump ruff from 0.9.10 to 0.11.0
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.10 to 0.11.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.10...0.11.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-18 05:58:20 +00:00
Yohan Boniface
190acbfaf0
chore: bump mkdocs-material from 9.6.7 to 9.6.9 (#2580)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
2025-03-18 06:57:13 +01:00
Yohan Boniface
1370b1a0e8
chore: bump psycopg from 3.2.5 to 3.2.6 (#2581)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-03-17 21:27:56 +01:00
dependabot[bot]
aa75b323c8
chore: bump psycopg from 3.2.5 to 3.2.6
Bumps [psycopg](https://github.com/psycopg/psycopg) from 3.2.5 to 3.2.6.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.2.5...3.2.6)

---
updated-dependencies:
- dependency-name: psycopg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 18:07:46 +00:00
dependabot[bot]
1c00545095
chore: bump mkdocs-material from 9.6.7 to 9.6.9
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.7 to 9.6.9.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.7...9.6.9)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 18:07:38 +00:00
Yohan Boniface
54a3aae912
chore: order importers by name instead of id (#2578) 2025-03-17 16:46:22 +01:00
Yohan Boniface
9d4069d9ae chore: order importers by name instead of id
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-17 16:44:23 +01:00
Yohan Boniface
167bab70c5
feat: add experimental BAN importer (#2565)
This importer takes a CSV as input, sends it to the BAN API, and then
paste it into the import textarea, so it can be imported as usual.



https://github.com/user-attachments/assets/c13f8580-5c09-4b35-b092-baac664a57a1
2025-03-17 16:39:55 +01:00
Yohan Boniface
d3ed46356d feat: add experimental BAN importer
This importer takes a CSV as input, sends it to the BAN API, and
then paste it into the import textarea, so it can be imported as usual.

Co-authored-by: David Larlet <david@larlet.fr>
2025-03-17 16:20:57 +01:00
d72debdeb2
Docs: Add documentation for local docker development 2025-03-14 15:29:25 +01:00
33525a1837
Docs: Remove old references to websocket configuration 2025-03-14 15:29:25 +01:00
3e0a6b8f10
Update the Dockerfile to expose websockets
The Dockerfile now uses ASGI by default (via uvicorn) and embeds a
redis server that is used for the synchronization.
2025-03-14 15:29:17 +01:00
Yohan Boniface
dd5add96b4
fix: iconUrl field was broken on older browsers (#2575)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
fix #2554
2025-03-14 15:07:14 +01:00
Yohan Boniface
f26536bff3 fix: iconUrl field was broken on older browsers
fix #2554
2025-03-14 14:50:47 +01:00
Yohan Boniface
1b058ce862
fixup: hide home button in edit mode (#2562)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
The button is already on the edit bar.

Would be nicer to have a css transition (like for the bar itself), but
at least with this change it is not duplicated.
2025-03-13 16:52:41 +01:00
Yohan Boniface
a46430c420
fix: import iconUrl as absolute when possible (#2563)
This will only cover the cases where the icon is set at the map or at
the layer level, not the one of the marker itself.

cf #2552
2025-03-13 16:52:19 +01:00
Yohan Boniface
05e3f5ce3d
fix: use real redraw for datalayer, instead of hide/show (#2568)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
The problem we've tried to fix is, during sync:
- peer A is editing a feature
- peer B changes the datalayer of this feature
- edit panel is closed for peer A
2025-03-12 17:41:18 +01:00
Yohan Boniface
c417e94698
fix(sync): fix tilelayer change not synced (#2569) 2025-03-12 17:39:19 +01:00
Yohan Boniface
e53d208d7c
fix: cast value to string before calling trim (#2567)
fix #2566
2025-03-12 17:36:42 +01:00
Yohan Boniface
e20648104b fix: fix tilelayer change not synced
Co-authored-by: Alexis Métaireau <alexis@notmyidea.org>
2025-03-12 13:01:26 +01:00
Yohan Boniface
0c9d5325ba fix: use real redraw for datalayer, instead of hide/show
The problem we've tried to fix is, during sync:
- peer A is editing a feature
- peer B changes the datalayer of this feature
- edit panel is closed for peer A

Co-authored-by: Alexis Métaireau <alexis@notmyidea.org>
2025-03-12 12:23:54 +01:00
Yohan Boniface
90be14ae89 fix: cast value to string before calling trim
fix #2566
2025-03-11 21:43:21 +01:00
Yohan Boniface
003b25d5e0 fix: import iconUrl as absolute when possible
This will only cover the cases where the icon is set at the map or
at the layer level, not the one of the marker itself.

cf #2552
2025-03-11 16:20:58 +01:00
Yohan Boniface
ef80396784 fixup: hide home button in edit mode
The button is already on the edit bar.

Would be nicer to have a css transition, but at least with this
change it is not duplicated.
2025-03-11 15:32:01 +01:00
Yohan Boniface
d85fc648b1
feat: add new "Back to home" icon (#2551)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
![image](https://github.com/user-attachments/assets/415a7e36-fb34-459e-8890-cd3c6830512b)
2025-03-10 22:31:42 +01:00
Yohan Boniface
b037915aae
chore: bump django-storages[s3] from 1.14.4 to 1.14.5 (#2560) 2025-03-10 22:06:29 +01:00
Yohan Boniface
17bbbe38bd
chore: new icon, colors and title for search buttons (#2556)
![image](https://github.com/user-attachments/assets/eca715dd-9450-4602-9e76-e8835d228df4)
2025-03-10 22:05:39 +01:00
Yohan Boniface
6cbe8cb9ad
chore: bump pytest from 8.3.4 to 8.3.5 (#2559) 2025-03-10 22:04:29 +01:00
dependabot[bot]
28741a9c94
chore: bump pytest from 8.3.4 to 8.3.5
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 20:37:28 +00:00
Yohan Boniface
1ae1a6c51b
chore: bump moto[s3] from 5.0.28 to 5.1.1 (#2557) 2025-03-10 21:36:17 +01:00
Yohan Boniface
d5fb5b02c0
chore: bump ruff from 0.9.9 to 0.9.10 (#2558) 2025-03-10 21:35:58 +01:00
Yohan Boniface
4be64ae918
chore: bump mkdocs-material from 9.6.4 to 9.6.7 (#2561) 2025-03-10 21:35:40 +01:00
dependabot[bot]
85e9bcfa7c
chore: bump mkdocs-material from 9.6.4 to 9.6.7
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.4 to 9.6.7.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.4...9.6.7)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 18:14:57 +00:00
dependabot[bot]
3cf0be5244
chore: bump django-storages[s3] from 1.14.4 to 1.14.5
Bumps [django-storages[s3]](https://github.com/jschneier/django-storages) from 1.14.4 to 1.14.5.
- [Changelog](https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jschneier/django-storages/compare/1.14.4...1.14.5)

---
updated-dependencies:
- dependency-name: django-storages[s3]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 18:14:52 +00:00
dependabot[bot]
5ebb840b94
chore: bump ruff from 0.9.9 to 0.9.10
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.9 to 0.9.10.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.9...0.9.10)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 18:14:38 +00:00
dependabot[bot]
9e9369f14b
chore: bump moto[s3] from 5.0.28 to 5.1.1
Bumps [moto[s3]](https://github.com/getmoto/moto) from 5.0.28 to 5.1.1.
- [Release notes](https://github.com/getmoto/moto/releases)
- [Changelog](https://github.com/getmoto/moto/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getmoto/moto/compare/5.0.28...5.1.1)

---
updated-dependencies:
- dependency-name: moto[s3]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 18:14:26 +00:00
Yohan Boniface
bfb17788a4 chore: new icon, colors and title for search buttons 2025-03-10 19:06:39 +01:00
Yohan Boniface
3b195e562a
feat: add more users counts in /stats/ (#2555)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-03-10 16:56:29 +01:00
Yohan Boniface
8599199afa feat: add more users counts in /stats/
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-10 16:38:53 +01:00
Yohan Boniface
7a2bf9fc4c fixup: let the importer deal with getting the OSM url in search
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-07 17:58:56 +01:00
Yohan Boniface
b3e39bf654 fixup: square buttons in search results
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-07 17:40:16 +01:00
Yohan Boniface
89e2a01d60 fixup: do not close panel when clicking on search edit buttons
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-07 17:39:42 +01:00
Yohan Boniface
0def3292e1 fix: only display search edit tools in edit mode
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-07 17:26:46 +01:00
Yohan Boniface
beae551367 feat: add new "Back to home" icon
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-07 17:20:35 +01:00
Yohan Boniface
4ccd1e6799 changelog 2025-03-07 16:31:14 +01:00
Yohan Boniface
d4885f386a i18n 2025-03-07 16:24:11 +01:00
Yohan Boniface
869db90b28 chore: update oauth provider deprecation message
Mention that it's important to logout and login again to have the
new provider replace the old one in the session
2025-03-07 16:17:26 +01:00
David Larlet
33cbe1ab71
a11y: turn embeded maps into inert elements (#2533)
One of the side-effects is to make the content of the map un-focusable
but we also loose the ability to interact with the map itself.
2025-03-07 10:10:29 -05:00
Yohan Boniface
8bad104803
chore: refactor search UX (#2545)
This is just the UI part of #419


![image](https://github.com/user-attachments/assets/88c76b9f-b1cd-48fa-b20e-caf1c044dbf8)
2025-03-07 16:05:01 +01:00
David Larlet
1fd34be300
chore: bump django from 5.1.6 to 5.1.7 (#2546)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
Bumps [django](https://github.com/django/django) from 5.1.6 to 5.1.7.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="691e945530"><code>691e945</code></a>
[5.1.x] Bumped version for 5.1.7 release.</li>
<li><a
href="8dbb44d342"><code>8dbb44d</code></a>
[5.1.x] Fixed CVE-2025-26699 -- Mitigated potential DoS in wordwrap
template ...</li>
<li><a
href="d7dc1f6db0"><code>d7dc1f6</code></a>
[5.1.x] Fixed typo in docs/ref/checks.txt.</li>
<li><a
href="dbd94e7ac9"><code>dbd94e7</code></a>
[5.1.x] Fixed <a
href="https://redirect.github.com/django/django/issues/36227">#36227</a>
-- Fixed outdated PostgreSQL documentation links.</li>
<li><a
href="cc405e1546"><code>cc405e1</code></a>
[5.1.x] Fixed <a
href="https://redirect.github.com/django/django/issues/36128">#36128</a>
-- Clarified auto-generated unique constraint on m2m thr...</li>
<li><a
href="03ace756ea"><code>03ace75</code></a>
[5.1.x] Fixed <a
href="https://redirect.github.com/django/django/issues/36217">#36217</a>
-- Restored pre_save/post_save signal emission via LogEn...</li>
<li><a
href="76a9f12b60"><code>76a9f12</code></a>
[5.1.x] Added some heading labels to to docs/topics/cache.txt.</li>
<li><a
href="558c616c95"><code>558c616</code></a>
[5.1.x] Added stub release notes and release date for 5.1.7, 5.0.13, and
4.2.20.</li>
<li><a
href="11243cc8f3"><code>11243cc</code></a>
[5.1.x] Added security guideline on reasonable size limitations when
renderin...</li>
<li><a
href="b80288a16d"><code>b80288a</code></a>
[5.1.x] Added security reporting guidelines.</li>
<li>Additional commits viewable in <a
href="https://github.com/django/django/compare/5.1.6...5.1.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=django&package-manager=pip&previous-version=5.1.6&new-version=5.1.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/umap-project/umap/network/alerts).

</details>
2025-03-06 18:32:52 -05:00
dependabot[bot]
6d324cdb13
chore: bump django from 5.1.6 to 5.1.7
Bumps [django](https://github.com/django/django) from 5.1.6 to 5.1.7.
- [Commits](https://github.com/django/django/compare/5.1.6...5.1.7)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-06 22:58:33 +00:00
Yohan Boniface
782386bad4 feat: display a target on hover on search results
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-06 18:51:58 +01:00
Yohan Boniface
ae5bc9746c feat: allow to import full geometries from search results
Co-authored-by: David Larlet <david@larlet.fr>
2025-03-06 17:03:13 +01:00
Yohan Boniface
a044bfd672 chore: refactor search UX
cf #419
2025-03-06 15:48:51 +01:00
Yohan Boniface
188a0d6e98 chore: bump Leaflet.Photon
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
To display state in results, cf #419
2025-03-06 09:38:51 +01:00
Yohan Boniface
b7cce7079d
chore: bump social-auth-app-django from 5.4.2 to 5.4.3 (#2518)
Some checks are pending
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
2025-03-05 17:50:16 +01:00
dependabot[bot]
0394f1f45d
chore: bump social-auth-app-django from 5.4.2 to 5.4.3
Bumps [social-auth-app-django](https://github.com/python-social-auth/social-app-django) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/python-social-auth/social-app-django/releases)
- [Changelog](https://github.com/python-social-auth/social-app-django/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python-social-auth/social-app-django/compare/5.4.2...5.4.3)

---
updated-dependencies:
- dependency-name: social-auth-app-django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-05 16:23:20 +00:00
Yohan Boniface
0d6326a7aa
chore: bump social-auth-core from 4.5.4 to 4.5.6 (#2517)
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-03-05 17:22:07 +01:00
Yohan Boniface
9414d6220c
chore: bump psycopg from 3.2.4 to 3.2.5 (#2536)
Bumps [psycopg](https://github.com/psycopg/psycopg) from 3.2.4 to 3.2.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psycopg/psycopg/blob/master/docs/news.rst">psycopg's
changelog</a>.</em></p>
<blockquote>
<p>.. currentmodule:: psycopg</p>
<p>.. index::
single: Release notes
single: News</p>
<h1><code>psycopg</code> release notes</h1>
<h2>Future releases</h2>
<p>Python 3.3.0 (unreleased)
^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Drop support for Python 3.8.</li>
</ul>
<h2>Current release</h2>
<p>Psycopg 3.2.5
^^^^^^^^^^^^^</p>
<ul>
<li>3x faster UUID loading thanks to C implementation
(🎟️<code>[#447](https://github.com/psycopg/psycopg/issues/447),
[#998](https://github.com/psycopg/psycopg/issues/998)</code>).</li>
</ul>
<p>Psycopg 3.2.4
^^^^^^^^^^^^^</p>
<ul>
<li>Don't lose notifies received whilst the
<code>~Connection.notifies()</code> iterator
is not running
(🎫<code>[#962](https://github.com/psycopg/psycopg/issues/962)</code>).</li>
<li>Make sure that the notifies callback is called during the use of the
<code>~Connection.notifies()</code> generator
(🎫<code>[#972](https://github.com/psycopg/psycopg/issues/972)</code>).</li>
<li>Raise the correct error returned by the database (such as
<code>!AdminShutdown</code>
or <code>!IdleInTransactionSessionTimeout</code>) instead of a generic
<code>OperationalError</code> when a server error causes a client
disconnection

(🎫<code>[#988](https://github.com/psycopg/psycopg/issues/988)</code>).</li>
<li>Build macOS dependencies from sources instead using the Homebrew
versions
in order to avoid problems with <code>MACOSX_DEPLOYMENT_TARGET</code>
(🎫<code>[#858](https://github.com/psycopg/psycopg/issues/858)</code>).</li>
<li>Bump libpq to 17.2 in Linux and macOS binary packages.</li>
<li>Bump libpq to 16.4 in Windows binary packages, using the <code>vcpkg
library</code>__

(🎫<code>[#966](https://github.com/psycopg/psycopg/issues/966)</code>).</li>
</ul>
<p>.. __: <a
href="https://vcpkg.io/en/package/libpq">https://vcpkg.io/en/package/libpq</a></p>
<p>Psycopg 3.2.3
^^^^^^^^^^^^^</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="664b2a12d6"><code>664b2a1</code></a>
chore: bump psycopg package version to 3.2.5</li>
<li><a
href="cd6589bf35"><code>cd6589b</code></a>
chore: bump build libraries</li>
<li><a
href="68f8603ec6"><code>68f8603</code></a>
Merge branch 'cython-uuid-3.2' into maint-3.2</li>
<li><a
href="dd1cefc3ee"><code>dd1cefc</code></a>
docs: mention UUID speedup in release news</li>
<li><a
href="7f950cb843"><code>7f950cb</code></a>
chore(c): remove C UUIDDumper and UUIDBinaryDumper</li>
<li><a
href="393e162fc3"><code>393e162</code></a>
perf(uuid): speed up UUID creation using a writable subclass</li>
<li><a
href="57a3889949"><code>57a3889</code></a>
perf(c): use PyObject_CallFunctionObjArgs in UUIDBinaryLoader</li>
<li><a
href="88f73fedd2"><code>88f73fe</code></a>
perf(c): use PyObject_CallFunctionObjArgs in UUIDLoader</li>
<li><a
href="3a9ade78e7"><code>3a9ade7</code></a>
test(c): test UUID.<strong>slots</strong></li>
<li><a
href="811cb51123"><code>811cb51</code></a>
perf(c): Use hex_to_int_map in UUIDLoader</li>
<li>Additional commits viewable in <a
href="https://github.com/psycopg/psycopg/compare/3.2.4...3.2.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=psycopg&package-manager=pip&previous-version=3.2.4&new-version=3.2.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-03-05 17:21:51 +01:00
Yohan Boniface
5d1f5de551
feat: expose active sessions in stats endpoint (#2544) 2025-03-05 16:41:44 +01:00
Yohan Boniface
1981f73212 feat: expose active sessions in stats endpoint 2025-03-05 10:02:42 +01:00
Yohan Boniface
9974852975 2.9.2
Some checks are pending
Test & Docs / tests (postgresql, 3.10) (push) Waiting to run
Test & Docs / tests (postgresql, 3.12) (push) Waiting to run
Test & Docs / lint (push) Waiting to run
2025-03-04 15:56:23 +01:00
Yohan Boniface
fb2fd217ab
fix: be defensive when getting the backend name from the session (#2540)
Seems that in some situation it is not defined.

We have this error in Sentry, but I'm not able to reproduce myself to
get a better context:


https://umap.sentry.io/issues/6351694806/?alert_rule_id=14960738&alert_timestamp=1741028858715&alert_type=email&environment=osmfr&notification_uuid=2c437997-d14d-4e0f-a62f-55bd19739ad2&project=4506656504020992&referrer=alert_email
2025-03-04 15:51:05 +01:00
Yohan Boniface
86d60f0b8e
fix: measure/drawing tooltip was misplaced (#2541)
Broken since 70f87d8636

fix #2539

Before:


![image](https://github.com/user-attachments/assets/5e68628c-a9f7-422a-b4b9-dd5daf0d77cd)


After:


![image](https://github.com/user-attachments/assets/c1857ab2-a8d1-43eb-a3d0-11bb24286bd6)
2025-03-04 15:48:04 +01:00
Yohan Boniface
3297296d59 fix: measure/drawing tooltip was misplaced
Since 70f87d8636

fix #2539
2025-03-04 11:52:06 +01:00
Yohan Boniface
470fc14d6d fix: be defensive when getting the backend name from the session
Seems that in some situation it is not defined.
2025-03-04 11:20:49 +01:00
dependabot[bot]
434de70c02
chore: bump psycopg from 3.2.4 to 3.2.5
Bumps [psycopg](https://github.com/psycopg/psycopg) from 3.2.4 to 3.2.5.
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.2.4...3.2.5)

---
updated-dependencies:
- dependency-name: psycopg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 17:19:37 +00:00
David Larlet
abe49cc1ba
a11y: turn embeded maps into inert elements
One of the side-effects is to make the content of the map un-focusable but we also loose the ability to interact with the map itself.
2025-02-28 16:18:28 -05:00
dependabot[bot]
c5eac8a8a9
chore: bump social-auth-core from 4.5.4 to 4.5.6
Bumps [social-auth-core](https://github.com/python-social-auth/social-core) from 4.5.4 to 4.5.6.
- [Release notes](https://github.com/python-social-auth/social-core/releases)
- [Changelog](https://github.com/python-social-auth/social-core/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python-social-auth/social-core/compare/4.5.4...4.5.6)

---
updated-dependencies:
- dependency-name: social-auth-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-27 14:49:50 +00:00
Oscar Hemelaar
8f3f67588a
chore: deploy charts to repository under github pages 2025-01-29 16:22:25 +01:00
Oscar Hemelaar
e97b619da8
feat: allow configuring env and conf using existing secret
useful for when the secret is created out of band using a vault api for
example
2025-01-29 15:49:05 +01:00
270 changed files with 10074 additions and 6330 deletions

View file

@ -5,7 +5,7 @@
"es6": true "es6": true
}, },
"parserOptions": { "parserOptions": {
"ecmaVersion": 2020, "ecmaVersion": 2021,
"sourceType": "module" "sourceType": "module"
} }
} }

26
.github/workflows/release-helm.yml vendored Normal file
View file

@ -0,0 +1,26 @@
name: Release Charts
on:
push:
branches:
- master
jobs:
release:
# depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions
# see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Publish Helm charts
uses: stefanprodan/helm-gh-pages@v1.7.0
with:
charts_dir: charts
linting: off
token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,10 +1,9 @@
# This part installs deps needed at runtime. # This part installs deps needed at runtime.
FROM python:3.11-slim AS common FROM python:3.12-slim AS common
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
tini \ tini \
uwsgi \
sqlite3 \ sqlite3 \
libpq-dev \ libpq-dev \
gdal-bin \ gdal-bin \
@ -39,7 +38,7 @@ WORKDIR /srv/umap
COPY . /srv/umap COPY . /srv/umap
RUN /venv/bin/pip install .[docker,s3] RUN /venv/bin/pip install .[docker,s3,sync]
FROM common FROM common

View file

@ -65,7 +65,7 @@ publish: ## Publish the Python package to Pypi
test: testpy testjs test: testpy testjs
testpy: testpy:
pytest -vv umap/tests/ --dist=loadgroup --reruns 1 pytest -vv umap/tests/ --dist=loadgroup --reruns 1 --maxfail 10
test-integration: test-integration:
pytest -xv umap/tests/integration/ --dist=loadgroup pytest -xv umap/tests/integration/ --dist=loadgroup

View file

@ -1,11 +1,7 @@
{ {
"files": { "files": {
"include": [ "include": ["umap/static/umap/js/**"],
"umap/static/umap/js/**" "ignore": ["umap/static/umap/vendors/**"]
],
"ignore": [
"umap/static/umap/vendors/**"
]
}, },
"formatter": { "formatter": {
"enabled": true, "enabled": true,
@ -22,7 +18,11 @@
"rules": { "rules": {
"style": { "style": {
"useBlockStatements": "off", "useBlockStatements": "off",
"noShoutyConstants": "warn" "noShoutyConstants": "warn",
"noParameterAssign": "off"
},
"complexity": {
"noForEach": "off"
}, },
"performance": { "performance": {
"noDelete": "off" "noDelete": "off"

View file

@ -66,7 +66,11 @@ spec:
{{- end }} {{- end }}
envFrom: envFrom:
- secretRef: - secretRef:
{{- if .Values.umap.envFromSecret }}
name: {{ .Values.umap.envFromSecret }}
{{- else }}
name: {{ include "umap.fullname" . }}-env name: {{ include "umap.fullname" . }}-env
{{- end }}
volumeMounts: volumeMounts:
- name: config - name: config
mountPath: /etc/umap/ mountPath: /etc/umap/
@ -80,7 +84,11 @@ spec:
volumes: volumes:
- name: config - name: config
secret: secret:
{{- if .Values.umap.configFromSecret }}
secretName: {{ .Values.umap.configFromSecret }}
{{- else }}
secretName: {{ include "umap.fullname" . }}-config secretName: {{ include "umap.fullname" . }}-config
{{- end }}
- name: statics - name: statics
emptyDir: {} emptyDir: {}
{{- if .Values.persistence.enabled }} {{- if .Values.persistence.enabled }}

View file

@ -1,3 +1,4 @@
{{ if not .Values.umap.configFromSecret }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
@ -7,3 +8,4 @@ metadata:
type: Opaque type: Opaque
data: data:
umap.conf: {{ .Values.umap.config | b64enc }} umap.conf: {{ .Values.umap.config | b64enc }}
{{- end }}

View file

@ -1,3 +1,4 @@
{{ if not .Values.umap.envFromSecret }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
@ -9,3 +10,4 @@ data:
{{- range $key, $value := .Values.umap.environment }} {{- range $key, $value := .Values.umap.environment }}
{{ $key }}: "{{ $value | b64enc }}" {{ $key }}: "{{ $value | b64enc }}"
{{- end }} {{- end }}
{{- end }}

View file

@ -77,11 +77,18 @@ umap:
SECRET_KEY: CHANGE_ME SECRET_KEY: CHANGE_ME
STATIC_ROOT: /srv/umap/static STATIC_ROOT: /srv/umap/static
MEDIA_ROOT: /srv/umap/uploads MEDIA_ROOT: /srv/umap/uploads
# Configure environment variables using an existing secret in the same namespace.
# In this case the values above are not used
envFromSecret: null
# You can also provide umap.conf content here: # You can also provide umap.conf content here:
config: | config: |
from umap.settings.base import * from umap.settings.base import *
# See: https://github.com/umap-project/umap/blob/master/umap/settings/local.py.sample # See: https://github.com/umap-project/umap/blob/master/umap/settings/local.py.sample
# Configure config file using an existing secret in the same namespace.
# In this case the values above are not used
configFromSecret: null
persistence: persistence:
enabled: true enabled: true

View file

@ -1,5 +1,15 @@
services: services:
# Usefull only to use the real time collaboration
redis:
image: redis:latest
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
interval: 1s
timeout: 3s
retries: 5
command: ["redis-server"]
db: db:
healthcheck: healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ] test: [ "CMD-SHELL", "pg_isready -U postgres" ]
@ -14,18 +24,35 @@ services:
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy
image: umap/umap:2.0.2 redis:
ports: condition: service_healthy
- "${PORT-8000}:8000" image: umap/umap:3.0.2
environment: environment:
- STATIC_ROOT=/srv/umap/static
- MEDIA_ROOT=/srv/umap/uploads
- DATABASE_URL=postgis://postgres@db/postgres - DATABASE_URL=postgis://postgres@db/postgres
- SECRET_KEY=some-long-and-weirdly-unrandom-secret-key - SECRET_KEY=some-long-and-weirdly-unrandom-secret-key
- SITE_URL=https://umap.local/ - SITE_URL=https://umap.local/
- UMAP_ALLOW_ANONYMOUS=True - UMAP_ALLOW_ANONYMOUS=True
- DEBUG=1 - DEBUG=1
- REALTIME_ENABLED=1
- REDIS_URL=redis://redis:6379
volumes: volumes:
- data:/srv/umap/uploads - data:/srv/umap/uploads
- static:/srv/umap/static
proxy:
image: nginx:latest
ports:
- "8000:80"
volumes:
- ./docker/nginx.conf:/etc/nginx/nginx.conf:ro
- static:/static:ro
- data:/data:ro
depends_on:
- app
volumes: volumes:
data: data:
static:
db: db:

View file

@ -9,5 +9,5 @@ umap collectstatic --noinput
umap wait_for_database umap wait_for_database
# then migrate the database # then migrate the database
umap migrate umap migrate
# run uWSGI # run the server
exec uwsgi --ini docker/uwsgi.ini exec uvicorn --proxy-headers --no-access-log --host 0.0.0.0 umap.asgi:application

111
docker/nginx.conf Normal file
View file

@ -0,0 +1,111 @@
events {
worker_connections 1024; # Adjust this to your needs
}
http {
proxy_cache_path /tmp/nginx_ajax_proxy_cache levels=1:2 keys_zone=ajax_proxy:10m inactive=60m;
proxy_cache_key "$uri$is_args$args";
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
types {
application/javascript mjs;
}
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# Server block
server {
listen 80;
server_name localhost;
# Static file serving
location /static/ {
alias /static/;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
expires 365d;
access_log /dev/null;
}
# Geojson files
location /uploads/ {
alias /data/;
expires 30d;
}
location /favicon.ico {
alias /static/favicon.ico;
}
# X-Accel-Redirect
location /internal/ {
internal;
gzip_vary on;
gzip_static on;
add_header X-DataLayer-Version $upstream_http_x_datalayer_version;
alias /data/;
}
# Ajax proxy
location ~ ^/proxy/(.*) {
internal;
add_header X-Proxy-Cache $upstream_cache_status always;
proxy_cache_background_update on;
proxy_cache_use_stale updating;
proxy_cache ajax_proxy;
proxy_cache_valid 1m; # Default. Umap will override using X-Accel-Expires
set $target_url $1;
# URL is encoded, so we need a few hack to clean it back.
if ( $target_url ~ (.+)%3A%2F%2F(.+) ){ # fix :// between scheme and destination
set $target_url $1://$2;
}
if ( $target_url ~ (.+?)%3A(.*) ){ # fix : between destination and port
set $target_url $1:$2;
}
if ( $target_url ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass
set $target_url $1/$2;
}
resolver 8.8.8.8;
add_header X-Proxy-Target $target_url; # For debugging
proxy_pass_request_headers off;
proxy_set_header Content-Type $http_content_type;
proxy_set_header Content-Encoding $http_content_encoding;
proxy_set_header Content-Length $http_content_length;
proxy_read_timeout 10s;
proxy_connect_timeout 5s;
proxy_ssl_server_name on;
proxy_pass $target_url;
proxy_intercept_errors on;
error_page 301 302 307 = @handle_proxy_redirect;
}
location @handle_proxy_redirect {
resolver 8.8.8.8;
set $saved_redirect_location '$upstream_http_location';
proxy_pass $saved_redirect_location;
}
# Proxy pass to ASGI server
location / {
proxy_pass http://app:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_buffering off;
}
}
}

View file

@ -1,26 +0,0 @@
[uwsgi]
http = :$(PORT)
home = /venv
module = umap.wsgi:application
master = True
vacuum = True
max-requests = 5000
processes = 4
enable-threads = true
static-map = /static=/srv/umap/static
static-map = /uploads=/srv/umap/uploads
buffer-size = 32768
; Run the websocket server only when the env variable
; WEBSOCKET_ENABLED is set to True.
; This is enough for the base docker image, but does not
; take into account the settings as the source of truth.
if-env = WEBSOCKET_ENABLED
websocket_enabled = %(_)
endif =
if-opt = websocket_enabled=True
print = Starting the Websocket Server (WEBSOCKET_ENABLED=%(websocket_enabled))
attach-daemon = umap run_websocket_server
endif =
lazy-apps = true

View file

@ -1,5 +1,5 @@
# Force rtfd to use a recent version of mkdocs # Force rtfd to use a recent version of mkdocs
mkdocs==1.6.1 mkdocs==1.6.1
pymdown-extensions==10.14.3 pymdown-extensions==10.14.3
mkdocs-material==9.6.4 mkdocs-material==9.6.12
mkdocs-static-i18n==1.3.0 mkdocs-static-i18n==1.3.0

View file

@ -1,5 +1,142 @@
# Changelog # Changelog
## 3.0.5 - 2025-04-25
* allow to save a remote data with unloaded data by @yohanboniface in #2657
* allow to save/undo/sync drag'n'drop of datalayers by @yohanboniface in #2677
* setting center and zoom manually should set dirty status by @yohanboniface in #2676
* fix error when saving and deleting heatmap layer by @yohanboniface in #2681
* make rules reordering syncable, savable and undoable by @yohanboniface in #2672
* loading remote data should not make the map dirty by @yohanboniface in #2679
* implement a design system for UI consistency by @davidbgk in #2654
* pass CSRF_TRUSTED_ORIGINS env to settings by @lippoliv in #2656
* do not display "saved" message if some request failed by @yohanboniface in #2669
* show an error message if saving layer failed by @yohanboniface in #2670
* naive support for GeometryCollection as Feature geometry by @yohanboniface in #2658
* add a back button in rules form by @yohanboniface in #2673
## New Contributors
* @lippoliv made their first contribution in #2656
## 3.0.4 - 2025-04-14
* do not show "back to home" button in iframes by @yohanboniface in #2644
* remove "hide home button" shown twice in map settings by @yohanboniface in #2645
* adapt Helm chart to match La Suite's expectations by @ohemelaar in #2646
* update colors by @yohanboniface in #2647
## 3.0.3 - 2025-04-11
* do not try to remove a feature not yet added by @yohanboniface in #2637
* document that nginx needs to be added in Docker stack to serve statics by @yohanboniface in #2636
* display back help button in switch fields by @yohanboniface in #2634
* use Last-Modified header from remote data when available by @yohanboniface in #2624
* fix text overflow on search results by @yohanboniface in #2628
* redirect to user dashboard after map delete by @yohanboniface in #2626
* add missing margin-bottom in importers by @yohanboniface in #2627
* fix pictogram categories always hidden by @yohanboniface in #2630
* display search category on list page by @davidbgk in #2635
* allow to hide the layer switcher from bottom bar by @davidbgk in #2639
* hidden download button in browser when embedControl=false by @yohanboniface in #2640
* allow to hide the back to home button by @davidbgk in #2638
## 3.0.2 - 2025-04-08
* fix copiable input CSS by @yohanboniface in #2616
* fix categorized layer crashing with null value by @yohanboniface in #2621
* properly call endEdit for markers by @yohanboniface in #2617
* fix result tools buttons background color by @yohanboniface in #2620
* fix min-height of select in caption bar by @yohanboniface in #2622
* give priority to small usernames on autocomplete by @yohanboniface in #2604
## 3.0.1 - 2025-04-07
* fix showLabel wrongly using MultiChoices by @yohanboniface in #2609
## 3.0.0 - 2025-04-07
This is the first release to officially support colaborative real-time map editing.
It introduces ASGI deployement, to support websockets, and adds Redis in the stack.
But it's still possible to continue deploying in WSGI for now, and Redis is only
mandatory when using the real-time feature.
How to use the real-time editing feature in your instance:
- you need to deploy with ASGI, see https://docs.umap-project.org/en/stable/deploy/asgi/
- you need to set `REALTIME_ENABLED=True` in your settings
Other notable changes:
- a first version of a real undo/redo
- map categories; those are defined through the `UMAP_TAGS` settings
Note: you may want to update your search index to include the category search,
see https://docs.umap-project.org/en/stable/config/settings/#umap_search_configuration
### Breaking change
* The Docker image will not serve assets and data files anymore, an Nginx container must
be configured. See [docker-compose.yml](https://github.com/umap-project/umap/blob/master/docker-compose.yml)
for an example.
### New features
* add collaborative real-time map editing
* add atomic undo redo by @yohanboniface in #2570
* expose active sessions in stats endpoint by @yohanboniface in #2544
* add more users counts in /stats/ by @yohanboniface in #2555
* add new "Back to home" icon by @yohanboniface in #2551
* add experimental BAN importer by @yohanboniface in #2565
* add titles in the text formatting dialog by @yohanboniface in #2584
* layers selector in bottom bar by @yohanboniface in #2579
* display maps list as a grid now by @yohanboniface in #2590
* add Map.tags and allow to edit from client by @yohanboniface in #2530
* add minimal "raw" icon shape by @yohanboniface in #2597
### Bug fixes
* cast value to string before calling trim by @yohanboniface in #2567
* import iconUrl as absolute when possible by @yohanboniface in #2563
* iconUrl field was broken on older browsers by @yohanboniface in #2575
* do not fail when trying to read metadata of a missing geojson by @yohanboniface in #2592
* remote data loading on import from umap backup by @davidbgk in #2598
* do not export layer ids in umap backup by @davidbgk in #2600
* use the multichoices for ttl in remote data form by @davidbgk in #2599
### Internal changes
* refactor search UX by @yohanboniface in #2545
* new icon, colors and title for search buttons by @yohanboniface in #2556
* use real redraw for datalayer, instead of hide/show by @yohanboniface in #2568
* order importers by name instead of id by @yohanboniface in #2578
* update the Dockerfile to expose websockets by @almet in #2576
* remove confirm delete for features and datalayers by @yohanboniface in #2603
### Accessibility
* a11y: turn embeded maps into inert elements by @davidbgk in #2533
### Changed templates
- auth/user_detail.html
- auth/user_stars.html
- umap/content.html
- umap/home.html
- umap/map_fragment.html
- umap/map_list.html
- umap/search.html
- umap/search_bar.html
- umap/team_detail.html
## 2.9.3 - 2025-03-07
* be explicit in the message that logout is needed after adding a new oauth provider
## 2.9.2 - 2025-03-04
* measure/drawing tooltip was misplaced by @yohanboniface in #2541
* be defensive when getting the backend name from the session by @yohanboniface in #2540
## 2.9.1 - 2025-03-03 ## 2.9.1 - 2025-03-03
* be more persuasive in deprecating twitter login backend by @yohanboniface in #2538 * be more persuasive in deprecating twitter login backend by @yohanboniface in #2538

View file

@ -88,6 +88,19 @@ Nginx configuration.
See [Django documentation for MEDIA_ROOT](https://docs.djangoproject.com/en/4.2/ref/settings/#media-root) See [Django documentation for MEDIA_ROOT](https://docs.djangoproject.com/en/4.2/ref/settings/#media-root)
#### REALTIME_ENABLED
Setting `REALTIME_ENABLED` to `True` will allow users to enable real-time collaboration.
A switch will be available for them in the "advanced properties" of the map.
See [the documentation about ASGI deployment](../deploy/asgi.md) for more information.
#### REDIS_URL
Connection URL to the Redis server. Only need for the real-time editing.
Default: `redis://localhost:6379`
#### SECRET_KEY #### SECRET_KEY
Must be defined to something unique and secret. Must be defined to something unique and secret.
@ -121,6 +134,13 @@ The final URL of you instance, including the protocol:
`SITE_URL=http://umap.org` `SITE_URL=http://umap.org`
#### SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_KEY, SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_SECRET
If you use OpenStreetMap as OAuth 2 provider, you can use those settings.
Otherwise, use any valid [python-social-auth configuration](https://python-social-auth.readthedocs.io/en/latest/configuration/django.html).
#### STATIC_ROOT #### STATIC_ROOT
Where uMap should store static files (CSS, JS…), must be consistent with your Where uMap should store static files (CSS, JS…), must be consistent with your
@ -323,7 +343,10 @@ CREATE EXTENSION btree_gin;
ALTER TEXT SEARCH CONFIGURATION umapdict ALTER MAPPING FOR hword, hword_part, word WITH unaccent, simple; ALTER TEXT SEARCH CONFIGURATION umapdict ALTER MAPPING FOR hword, hword_part, word WITH unaccent, simple;
# Now create the index # Now create the index
CREATE INDEX IF NOT EXISTS search_idx ON umap_map USING GIN(to_tsvector('umapdict', COALESCE(name, ''::character varying)::text), share_status); CREATE INDEX IF NOT EXISTS search_idx ON umap_map USING GIN(to_tsvector('umapdict', COALESCE(name, ''::character varying)::text), share_status, tags);
# You should also create an index for tag filtering:
CREATE INDEX IF NOT EXISTS tags_idx ON umap_map USING GIN(share_status, tags);
``` ```
Then set: Then set:
@ -345,61 +368,3 @@ Should uMap gzip datalayers geojson.
Can be set to `X-Accel-Redirect` to enable the [NGINX X-Accel](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/) feature. Can be set to `X-Accel-Redirect` to enable the [NGINX X-Accel](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/) feature.
See the NGINX documentation in addition. See the NGINX documentation in addition.
#### SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_KEY, SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_SECRET
If you use OpenStreetMap as OAuth 2 provider, you can use those settings.
Otherwise, use any valid [python-social-auth configuration](https://python-social-auth.readthedocs.io/en/latest/configuration/django.html).
#### WEBSOCKET_ENABLED
A WebSocket server is packaged with uMap, and can be turned-on to activate
"real-time collaboration". In practice, in order to enable it, a few settings
are exposed.
Setting `WEBSOCKET_ENABLED` to `True` will **not** enable real-time
collaboration on all the maps served by the server. Instead, a switch will be
available in the "advanced properties" of the map.
The websocket server can be started with the following command:
```bash
umap run_websocket_server
```
And can take optional settings `--host` and `--port` (default values are defined in
the settings).
Configuration example:
```python
WEBSOCKET_ENABLED = True
WEBSOCKET_BACK_HOST = "localhost"
WEBSOCKET_BACK_PORT = 8002
WEBSOCKET_FRONT_URI = "ws://localhost:8002"
```
These settings can also be set with the (same names) environment variables.
#### WEBSOCKET_BACK_HOST
#### WEBSOCKET_BACK_PORT
The internal host and port the websocket server will connect to.
#### WEBSOCKET_FRONT_URI
The connection string that will be used by the client to connect to the
websocket server. In practice, as it's useful to put the WebSocket server behind
TLS encryption, the values defined by `WEBSOCKET_FRONT_URI` are different than
the values defined by `WEBSOCKET_BACK_PORT` and `WEBSOCKET_BACK_HOST`.
This value is comprised of three parts:
```
protocol://host:port
```
- `protocol`: can either be `ws` for plain unencrypted WebSockets, or `wss` when using TLS encryption.
- `host`: is the address where the connection will be sent. It should be public facing.
- `port`: is the port that is open on the host.

View file

@ -14,7 +14,7 @@ services:
app: app:
# Check https://hub.docker.com/r/umap/umap/tags to find the latest version # Check https://hub.docker.com/r/umap/umap/tags to find the latest version
image: umap/umap:2.0.2 image: umap/umap:2.9.3
ports: ports:
# modify the external port (8001, on the left) if desired, but make sure it matches SITE_URL, below # modify the external port (8001, on the left) if desired, but make sure it matches SITE_URL, below
- "8001:8000" - "8001:8000"
@ -48,3 +48,45 @@ User accounts can be managed via the Django admin page ({SITE_URL}/admin). The r
```bash ```bash
umap createsuperuser umap createsuperuser
``` ```
## Developping with Docker
If you want to develop with podman or docker, here are commands that might be useful, given that you have a postgreSQL server running locally and that your settings are located at `umap.conf`:
You can build the docker image with:
```bash
podman build -t umap .
```
And run it with:
```bash
podman run -v ./umap.conf:/tmp/umap.conf -e UMAP_SETTINGS=/tmp/umap.conf -it --network host umap
```
## Real time collaboration
To enable real time collaboration when using Docker, a Redis service must be added. Something like this in `docker-compose.py` world:
```yaml title="docker-compose.yml"
services
redis:
image: redis:latest
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
command: ["redis-server"]
app:
depends_on:
redis:
condition: service_healthy
environment:
- REALTIME_ENABLED=1
- REDIS_URL=redis://redis:6379
```

View file

@ -1,84 +1,10 @@
# Configuring Nginx # Configuring Nginx
Here are some configuration files to use umap with nginx and [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/), a server for python, which will handle your processes for you. See [WSGI](wsgi.md) or [ASGI](asgi.md) for a basic setup.
```nginx title="nginx.conf" Then consider adding this configuration
upstream umap {
server unix:///srv/umap/umap.sock;
}
server { ## Static files and geojson
# the port your site will be served on
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
# the domain name it will serve for
server_name your-domain.org;
charset utf-8;
# max upload size
client_max_body_size 5M; # adjust to taste
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass umap;
include /srv/umap/uwsgi_params;
}
}
```
## uWSGI
```nginx title="uwsgi_params"
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
```
```ini title="uwsgi.ini"
[uwsgi]
uid = umap
gid = users
# Python related settings
# the base directory (full path)
chdir = /srv/umap/
# umap's wsgi module
module = umap.wsgi
# the virtualenv (full path)
home = /srv/umap/venv
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 4
# the socket (use the full path to be safe)
socket = /srv/umap/umap.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
stats = /srv/umap/stats.sock
# clear environment on exit
vacuum = true
plugins = python3
```
## Static files
```nginx title="nginx.conf" ```nginx title="nginx.conf"
location /static { location /static {

37
docs/deploy/overview.md Normal file
View file

@ -0,0 +1,37 @@
# Deploying uMap
uMap is a python package, running [Django](https://docs.djangoproject.com/en/5.2/howto/deployment/),
so anyone experimented with this stack will find it familiar, but there are some speficic details
to know about.
## Data
One important design point of uMap is that while metadata are stored in a PostgreSQL database, the
data itself is stored in the file system, as geojson files. This design choice has been made
to make uMap scale better, as there are much more reads than writes, and when some
map is shared a lot (like on a national media) we want to be able to serve it without needing an
overcomplex and costly stack.
So when a request for data is made (that is on a *DataLayer*), the flow is that uMap will read
the request headers to check for permissions, and then it will forward the request to Nginx,
that will properly serve the data (a geojson file), without consuming a python worker, and with
much more efficiency than python.
In DEBUG mode, uMap will serve the geojson itself, but this is not recommended in production,
unless you have a very small audience.
Data can also be stored in a [S3 like storage](../config/storage/#using-s3).
## Assets (JS, CSS…)
As any web app, uMap also needs static files to be served. In DEBUG mode, Django will do this
kindly, but not in production. See [Nginx configuration](nginx.md) for this.
Assets can also be stored in a [S3 like storage](../config/storage/#using-s3).
## python app (metadata, permissions…)
uMap needs a python server, which can either be of [WSGI](wsgi.md) or [ASGI](asgi.md) (this later
is needed in order to use the collaborative live editing).
## Redis
Still when using the collaborative live editing, uMap needs a [Redis](../config/settings.md#redis_url) server, to act as pubsub.

87
docs/deploy/wsgi.md Normal file
View file

@ -0,0 +1,87 @@
# WSGI
WSGI is the historical standard to serve python in general, and uMap in this case.
From recently, uMap also supports [ASGI](asgi.md), which is required to use the
collaborative editing feature.
## uWSGI
In Nginx host, use:
```nginx title="nginx.conf"
upstream umap {
server unix:///srv/umap/umap.sock;
}
server {
# the port your site will be served on
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
# the domain name it will serve for
server_name your-domain.org;
charset utf-8;
# max upload size
client_max_body_size 5M; # adjust to taste
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass umap;
include /srv/umap/uwsgi_params;
}
}
```
```nginx title="uwsgi_params"
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
```
```ini title="uwsgi.ini"
[uwsgi]
uid = umap
gid = users
# Python related settings
# the base directory (full path)
chdir = /srv/umap/
# umap's wsgi module
module = umap.wsgi
# the virtualenv (full path)
home = /srv/umap/venv
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 4
# the socket (use the full path to be safe)
socket = /srv/umap/umap.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
stats = /srv/umap/stats.sock
# clear environment on exit
vacuum = true
plugins = python3
```
See also [Django documentation](https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/).

View file

@ -1,5 +1,5 @@
# Force rtfd to use a recent version of mkdocs # Force rtfd to use a recent version of mkdocs
mkdocs==1.6.1 mkdocs==1.6.1
pymdown-extensions==10.14.3 pymdown-extensions==10.14.3
mkdocs-material==9.6.4 mkdocs-material==9.6.12
mkdocs-static-i18n==1.3.0 mkdocs-static-i18n==1.3.0

View file

@ -18,10 +18,12 @@ nav:
- Storage: config/storage.md - Storage: config/storage.md
- Icon packs: config/icons.md - Icon packs: config/icons.md
- Deployment: - Deployment:
- Overview: deploy/overview.md
- Docker: deploy/docker.md - Docker: deploy/docker.md
- Helm: deploy/helm.md - Helm: deploy/helm.md
- Nginx: deploy/nginx.md - Nginx: deploy/nginx.md
- ASGI: deploy/asgi.md - ASGI: deploy/asgi.md
- WSGI: deploy/wsgi.md
- Changelog: changelog.md - Changelog: changelog.md
theme: theme:
name: material name: material

View file

@ -38,7 +38,7 @@
"dependencies": { "dependencies": {
"@dwayneparton/geojson-to-gpx": "^0.2.0", "@dwayneparton/geojson-to-gpx": "^0.2.0",
"@placemarkio/tokml": "0.3.4", "@placemarkio/tokml": "0.3.4",
"@tmcw/togeojson": "^5.8.0", "@tmcw/togeojson": "^7.1.0",
"colorbrewer": "1.5.7", "colorbrewer": "1.5.7",
"csv2geojson": "github:umap-project/csv2geojson#patched", "csv2geojson": "github:umap-project/csv2geojson#patched",
"dompurify": "3.2.4", "dompurify": "3.2.4",
@ -59,7 +59,7 @@
"leaflet.locatecontrol": "0.81.1", "leaflet.locatecontrol": "0.81.1",
"leaflet.markercluster": "^1.5.3", "leaflet.markercluster": "^1.5.3",
"leaflet.path.drag": "0.0.6", "leaflet.path.drag": "0.0.6",
"leaflet.photon": "0.9.1", "leaflet.photon": "0.9.2",
"osmtogeojson": "^3.0.0-beta.5", "osmtogeojson": "^3.0.0-beta.5",
"simple-statistics": "7.8.5" "simple-statistics": "7.8.5"
}, },

View file

@ -28,26 +28,26 @@ classifiers = [
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
] ]
dependencies = [ dependencies = [
"Django==5.1.6", "Django==5.1.8",
"django-agnocomplete==2.2.0", "django-agnocomplete==2.2.0",
"django-environ==0.12.0", "django-environ==0.12.0",
"django-probes==1.7.0", "django-probes==1.7.0",
"Pillow==11.1.0", "Pillow==11.2.1",
"psycopg==3.2.4", "psycopg==3.2.6",
"requests==2.32.3", "requests==2.32.3",
"rcssmin==1.2.1", "rcssmin==1.2.1",
"rjsmin==1.2.4", "rjsmin==1.2.4",
"social-auth-core==4.5.4", "social-auth-core==4.5.6",
"social-auth-app-django==5.4.2", "social-auth-app-django==5.4.3",
] ]
[project.optional-dependencies] [project.optional-dependencies]
dev = [ dev = [
"hatch==1.14.0", "hatch==1.14.1",
"ruff==0.9.9", "ruff==0.11.6",
"djlint==1.36.4", "djlint==1.36.4",
"mkdocs==1.6.1", "mkdocs==1.6.1",
"mkdocs-material==9.6.4", "mkdocs-material==9.6.12",
"mkdocs-static-i18n==1.3.0", "mkdocs-static-i18n==1.3.0",
"vermin==1.6.0", "vermin==1.6.0",
"pymdown-extensions==10.14.3", "pymdown-extensions==10.14.3",
@ -57,22 +57,23 @@ test = [
"daphne==4.1.2", "daphne==4.1.2",
"factory-boy==3.3.3", "factory-boy==3.3.3",
"playwright>=1.39", "playwright>=1.39",
"pytest==8.3.4", "pytest==8.3.5",
"pytest-django==4.10.0", "pytest-django==4.11.1",
"pytest-playwright==0.7.0", "pytest-playwright==0.7.0",
"pytest-rerunfailures==15.0", "pytest-rerunfailures==15.0",
"pytest-xdist>=3.5.0,<4", "pytest-xdist>=3.5.0,<4",
"moto[s3]==5.0.28" "moto[s3]==5.1.4"
] ]
docker = [ docker = [
"uwsgi==2.0.28", "uvicorn==0.34.2",
] ]
s3 = [ s3 = [
"django-storages[s3]==1.14.4", "django-storages[s3]==1.14.6",
] ]
sync = [ sync = [
"pydantic==2.10.6", "pydantic==2.11.3",
"redis==5.2.1", "redis==5.2.1",
"websockets==15.0.1",
] ]
[project.scripts] [project.scripts]

View file

@ -1 +1 @@
VERSION = "2.9.1" VERSION = "3.0.5"

View file

@ -2,6 +2,7 @@ from agnocomplete.core import AgnocompleteModel
from agnocomplete.register import register from agnocomplete.register import register
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db.models.functions import Length
@register @register
@ -13,3 +14,11 @@ class AutocompleteUser(AgnocompleteModel):
data = super().item(current_item) data = super().item(current_item)
data["url"] = current_item.get_url() data["url"] = current_item.get_url()
return data return data
def build_extra_filtered_queryset(self, queryset, **kwargs):
order_by = []
for field_name in self.fields:
if not field_name[0].isalnum():
field_name = field_name[1:]
order_by.append(Length(field_name).asc())
return queryset.order_by(*order_by)

View file

@ -14,6 +14,7 @@ def settings(request):
"UMAP_DEMO_SITE": djsettings.UMAP_DEMO_SITE, "UMAP_DEMO_SITE": djsettings.UMAP_DEMO_SITE,
"UMAP_HOST_INFOS": djsettings.UMAP_HOST_INFOS, "UMAP_HOST_INFOS": djsettings.UMAP_HOST_INFOS,
"UMAP_ALLOW_EDIT_PROFILE": djsettings.UMAP_ALLOW_EDIT_PROFILE, "UMAP_ALLOW_EDIT_PROFILE": djsettings.UMAP_ALLOW_EDIT_PROFILE,
"UMAP_TAGS": djsettings.UMAP_TAGS,
} }

View file

@ -4,7 +4,6 @@ from django.contrib.auth import get_user_model
from django.contrib.gis.geos import Point from django.contrib.gis.geos import Point
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.utils.translation import gettext_lazy as _
from .models import DataLayer, Map, Team from .models import DataLayer, Map, Team
@ -92,7 +91,7 @@ class MapSettingsForm(forms.ModelForm):
return self.cleaned_data["center"] return self.cleaned_data["center"]
class Meta: class Meta:
fields = ("settings", "name", "center", "slug") fields = ("settings", "name", "center", "slug", "tags")
model = Map model = Map

Binary file not shown.

View file

@ -11,6 +11,7 @@
# hno2 <hno2@gmx.net>, 2013-2014 # hno2 <hno2@gmx.net>, 2013-2014
# Jannis Leidel <jannis@leidel.info>, 2016 # Jannis Leidel <jannis@leidel.info>, 2016
# gislars, 2024 # gislars, 2024
# Metzor Metzingen, 2025
# pgeo, 2023 # pgeo, 2023
# Klumbumbus, 2013-2014,2018-2019 # Klumbumbus, 2013-2014,2018-2019
# YOHAN BONIFACE <yb@enix.org>, 2012 # YOHAN BONIFACE <yb@enix.org>, 2012
@ -18,9 +19,9 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-24 08:39+0000\n" "POT-Creation-Date: 2025-04-04 16:49+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: jakl, 2024\n" "Last-Translator: Metzor Metzingen, 2025\n"
"Language-Team: German (http://app.transifex.com/openstreetmap/umap/language/de/)\n" "Language-Team: German (http://app.transifex.com/openstreetmap/umap/language/de/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -30,193 +31,283 @@ msgstr ""
#: admin.py:16 #: admin.py:16
msgid "CSV Export" msgid "CSV Export"
msgstr "" msgstr "CSV-Export"
#: decorators.py:60 #: decorators.py:60
msgid "This map is not publicly available" msgid "This map is not publicly available"
msgstr "" msgstr "Diese Karte ist nicht öffentlich einsehbar"
#: middleware.py:13 #: middleware.py:19
msgid "Site is readonly for maintenance" msgid "Site is readonly for maintenance"
msgstr "Die Seite ist wegen Wartungsarbeiten im Nur-Lesen-Modus." msgstr "Die Seite ist wegen Wartungsarbeiten im Nur-Lesen-Modus."
#: models.py:60 models.py:79 #: middleware.py:34
#, python-format
msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account"
" and maps. Then, please logout and login again with the new provider."
msgstr "Anmelden mittels “%(name)s” ist veraltet und wird bald nicht mehr möglich sein. Bitte stelle einen anderen Anbieter ein, um den Zugang zum Benutzerkonto und den Karten nicht zu verlieren. Bitte melde dich dann ab und nutze den neuen Anbieter um dich wieder anzumelden."
#: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "Name" msgstr "Name"
#: models.py:62 models.py:475 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "Details" msgstr "Details"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Verlinke auf eine Seite mit der Lizenz." msgstr "Verlinke auf eine Seite mit der Lizenz."
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "Das URL-Template nutzt das OSM Tile Format" msgstr "Das URL-Template nutzt das OSM Tile Format"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Reihenfolge der Karten-Ebenen in der Bearbeiten-Box" msgstr "Reihenfolge der Karten-Ebenen in der Bearbeiten-Box"
#: models.py:175 models.py:469 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Nur mit geheimem Bearbeitungslink zu bearbeiten" msgstr "Nur mit geheimem Bearbeitungslink zu bearbeiten"
#: models.py:176 models.py:470 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Jeder kann bearbeiten" msgstr "Jeder kann bearbeiten"
#: models.py:179 models.py:463 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "Jeder" msgstr "Jeder"
#: models.py:180 models.py:189 models.py:464 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Nur Bearbeiter und Team" msgstr "Nur Bearbeiter und Team"
#: models.py:181 models.py:465 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "Nur Ersteller" msgstr "Nur Ersteller"
#: models.py:184
msgid "Draft (private)"
msgstr ""
#: models.py:185 #: models.py:185
msgid "Draft (private)"
msgstr "Entwurf (privat)"
#: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "Jeder (Öffentlich)" msgstr "Jeder (Öffentlich)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "Jeder mit Link" msgstr "Jeder mit Link"
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "blockiert" msgstr "blockiert"
#: models.py:191 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "" msgstr "Gelöscht"
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "Mittelpunkt" msgstr "Mittelpunkt"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "Zoom" msgstr "Zoom"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "lokalisiere" msgstr "lokalisiere"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Standort des Benutzers beim Seitenaufruf bestimmen?" msgstr "Standort des Benutzers beim Seitenaufruf bestimmen?"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Kartenlizenz auswählen" msgstr "Kartenlizenz auswählen"
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "Lizenz" msgstr "Lizenz"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "Ersteller" msgstr "Ersteller"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "Bearbeiter" msgstr "Bearbeiter"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "Team" msgstr "Team"
#: models.py:229 models.py:491 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "Bearbeitungsstatus" msgstr "Bearbeitungsstatus"
#: models.py:234 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "Teilen-Status" msgstr "Teilen-Status"
#: models.py:237 models.py:486 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "Einstellungen" msgstr "Einstellungen"
#: models.py:402 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Duplikat von" msgstr "Duplikat von"
#: models.py:462 models.py:468 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "erben" msgstr "erben"
#: models.py:481 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "Beim Seitenaufruf einblenden" msgstr "Beim Seitenaufruf einblenden"
#: models.py:482 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Diese Ebene beim Seitenaufruf einblenden." msgstr "Diese Ebene beim Seitenaufruf einblenden."
#: settings/base.py:295
msgid "Art and Culture"
msgstr ""
#: settings/base.py:296
msgid "Cycling"
msgstr ""
#: settings/base.py:297
msgid "Business"
msgstr ""
#: settings/base.py:298
msgid "Environment"
msgstr ""
#: settings/base.py:299
msgid "Education"
msgstr ""
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr ""
#: settings/base.py:301
msgid "Geopolitics"
msgstr ""
#: settings/base.py:302
msgid "Health"
msgstr ""
#: settings/base.py:303
msgid "Hiking"
msgstr ""
#: settings/base.py:304
msgid "History"
msgstr ""
#: settings/base.py:305
msgid "Public sector"
msgstr ""
#: settings/base.py:306
msgid "Science"
msgstr ""
#: settings/base.py:307
msgid "Shopping"
msgstr ""
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr ""
#: settings/base.py:309
msgid "Travel"
msgstr ""
#: settings/base.py:310
msgid "Transports"
msgstr ""
#: settings/base.py:311
msgid "Tourism"
msgstr ""
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
"target=\"_blank\">Find out here the documentation</a> on how to manage maps" "target=\"_blank\">Find out here the documentation</a> on how to manage maps"
" permissions." " permissions."
msgstr "" msgstr "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" target=\"_blank\">Finde hier die Dokumentation</a>wie Berechtigungen der Karte verwaltet werden können."
#: templates/403.html:10 templates/404.html:8 #: templates/403.html:10 templates/404.html:8
msgid "← Go to the homepage" msgid "← Go to the homepage"
msgstr "" msgstr "← Gehe zur Homepage"
#: templates/404.html:7 #: templates/404.html:7
msgid "404 Page Not Found" msgid "404 Page Not Found"
msgstr "" msgstr "404 Seite nicht gefunden"
#: templates/auth/user_detail.html:8 #: templates/auth/user_detail.html:6
#, python-format
msgid "%(current_user)ss maps"
msgstr "Karten von %(current_user)s"
#: templates/auth/user_detail.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's maps" msgid "Browse %(current_user)s's maps"
msgstr "Schaue dir %(current_user)s's Karten an" msgstr "Schaue dir %(current_user)s's Karten an"
#: templates/auth/user_detail.html:17 #: templates/auth/user_detail.html:21
#, python-format #, python-format
msgid "%(current_user)s has no maps." msgid "%(current_user)s has no maps."
msgstr "%(current_user)s hat keine Karten." msgstr "%(current_user)s hat keine Karten."
#: templates/auth/user_form.html:21 templates/umap/team_form.html:21 #: templates/auth/user_form.html:6
msgid "My Profile"
msgstr "Mein Profil"
#: templates/auth/user_form.html:24 templates/umap/team_form.html:25
msgid "Save" msgid "Save"
msgstr "Speichern" msgstr "Speichern"
#: templates/auth/user_form.html:27 #: templates/auth/user_form.html:30
msgid "Your current providers" msgid "Your current providers"
msgstr "Deine aktuellen Anbieter" msgstr "Deine aktuellen Anbieter"
#: templates/auth/user_form.html:39 #: templates/auth/user_form.html:44
msgid "Connect to another provider" msgid "Connect to another provider"
msgstr "Füge einen weiteren Anbieter hinzu" msgstr "Füge einen weiteren Anbieter hinzu"
#: templates/auth/user_form.html:42 #: templates/auth/user_form.html:47
msgid "" msgid ""
"It's a good habit to connect your account to more than one provider, in case" "It's a good habit to connect your account to more than one provider, in case"
" one provider becomes unavailable, temporarily or even permanently." " one provider becomes unavailable, temporarily or even permanently."
msgstr "Es ist eine gute Praxis, das Konto mit mehr als einem Anbieter zu verbinden, für den Fall, dass ein Anbieter vorübergehend oder sogar dauerhaft nicht mehr verfügbar ist." msgstr "Es ist eine gute Praxis, das Konto mit mehr als einem Anbieter zu verbinden, für den Fall, dass ein Anbieter vorübergehend oder sogar dauerhaft nicht mehr verfügbar ist."
#: templates/auth/user_stars.html:8 #: templates/auth/user_stars.html:6
#, python-format
msgid "%(current_user)ss starred maps"
msgstr "Schaue dir die favorisierten Karten von %(current_user)s an"
#: templates/auth/user_stars.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's starred maps" msgid "Browse %(current_user)s's starred maps"
msgstr "Schaue dir %(current_user)s's favorisierten Karten an" msgstr "Schaue dir %(current_user)s's favorisierten Karten an"
#: templates/auth/user_stars.html:17 #: templates/auth/user_stars.html:21
#, python-format #, python-format
msgid "%(current_user)s has no starred maps yet." msgid "%(current_user)s has no starred maps yet."
msgstr "%(current_user)s hat keine favorisierten Karten." msgstr "%(current_user)s hat keine favorisierten Karten."
@ -233,11 +324,11 @@ msgstr "Anmeldung"
#: templates/registration/login.html:22 #: templates/registration/login.html:22
msgid "To save and easily find your maps, identify yourself." msgid "To save and easily find your maps, identify yourself."
msgstr "" msgstr "Um deine Karten einfach zu speichern und wieder zu finden, merke dich an."
#: templates/registration/login.html:25 #: templates/registration/login.html:25
msgid "Please log in with your account:" msgid "Please log in with your account:"
msgstr "" msgstr "Bitte melden Sie sich mit Ihrem Konto an"
#: templates/registration/login.html:42 #: templates/registration/login.html:42
msgid "Username" msgid "Username"
@ -249,7 +340,11 @@ msgstr "Passwort"
#: templates/registration/login.html:52 #: templates/registration/login.html:52
msgid "Please choose a provider:" msgid "Please choose a provider:"
msgstr "" msgstr "Bitte wähle einen Anbieter"
#: templates/umap/about.html:5 templates/umap/navigation.html:22
msgid "About"
msgstr "Über"
#: templates/umap/about_summary.html:12 #: templates/umap/about_summary.html:12
#, python-format #, python-format
@ -402,7 +497,7 @@ msgstr "Meine Teams"
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "Karte aller „uMap“-Karten" msgstr "Karte aller „uMap“-Karten"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Lass dich inspirieren, schau dir diese Karten an." msgstr "Lass dich inspirieren, schau dir diese Karten an."
@ -410,15 +505,19 @@ msgstr "Lass dich inspirieren, schau dir diese Karten an."
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Du bist eingeloggt. Weiterleitung..." msgstr "Du bist eingeloggt. Weiterleitung..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "von" msgstr "von"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr ""
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Mehr" msgstr "Mehr"
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:14 #: templates/umap/map_table.html:8 templates/umap/user_teams.html:18
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@ -442,7 +541,7 @@ msgstr "zuletzt gespeichert"
msgid "Owner" msgid "Owner"
msgstr "Ersteller" msgstr "Ersteller"
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:20 #: templates/umap/map_table.html:26 templates/umap/user_teams.html:24
msgid "Actions" msgid "Actions"
msgstr "Aktionen" msgstr "Aktionen"
@ -455,7 +554,7 @@ msgid "Share"
msgstr "Teilen" msgstr "Teilen"
#: templates/umap/map_table.html:78 templates/umap/map_table.html:80 #: templates/umap/map_table.html:78 templates/umap/map_table.html:80
#: templates/umap/user_teams.html:38 templates/umap/user_teams.html:40 #: templates/umap/user_teams.html:42 templates/umap/user_teams.html:44
msgid "Edit" msgid "Edit"
msgstr "Bearbeiten" msgstr "Bearbeiten"
@ -518,10 +617,6 @@ msgstr "Einloggen"
msgid "Sign in" msgid "Sign in"
msgstr "Anmelden" msgstr "Anmelden"
#: templates/umap/navigation.html:22
msgid "About"
msgstr "Über"
#: templates/umap/navigation.html:30 #: templates/umap/navigation.html:30
msgid "Change password" msgid "Change password"
msgstr "Passwort ändern" msgstr "Passwort ändern"
@ -530,52 +625,58 @@ msgstr "Passwort ändern"
msgid "Log out" msgid "Log out"
msgstr "Ausloggen" msgstr "Ausloggen"
#: templates/umap/password_change.html:7 #: templates/umap/password_change.html:6
#: templates/umap/password_change.html:11
msgid "Password change" msgid "Password change"
msgstr "Passwortänderung" msgstr "Passwortänderung"
#: templates/umap/password_change.html:10 #: templates/umap/password_change.html:14
msgid "" msgid ""
"Please enter your old password, for security's sake, and then enter your new" "Please enter your old password, for security's sake, and then enter your new"
" password twice so we can verify you typed it in correctly." " password twice so we can verify you typed it in correctly."
msgstr "Bitte gib aus Sicherheitsgründen dein altes Passwort ein und dann zweimal dein neues, um sicherzustellen, dass du es korrekt eingegeben hast." msgstr "Bitte gib aus Sicherheitsgründen dein altes Passwort ein und dann zweimal dein neues, um sicherzustellen, dass du es korrekt eingegeben hast."
#: templates/umap/password_change.html:17 #: templates/umap/password_change.html:21
msgid "Old password" msgid "Old password"
msgstr "Altes Passwort" msgstr "Altes Passwort"
#: templates/umap/password_change.html:22 #: templates/umap/password_change.html:26
msgid "New password" msgid "New password"
msgstr "Neues Passwort" msgstr "Neues Passwort"
#: templates/umap/password_change.html:26 #: templates/umap/password_change.html:30
msgid "New password confirmation" msgid "New password confirmation"
msgstr "Neues Passwort bestätigen" msgstr "Neues Passwort bestätigen"
#: templates/umap/password_change.html:27 #: templates/umap/password_change.html:31
msgid "Change my password" msgid "Change my password"
msgstr "Mein Passwort ändern" msgstr "Mein Passwort ändern"
#: templates/umap/password_change_done.html:7 #: templates/umap/password_change_done.html:6
#: templates/umap/password_change_done.html:11
msgid "Password change successful" msgid "Password change successful"
msgstr "Passwortänderung erfolgreich" msgstr "Passwortänderung erfolgreich"
#: templates/umap/password_change_done.html:10 #: templates/umap/password_change_done.html:14
msgid "Your password was changed." msgid "Your password was changed."
msgstr "Ihr Passwort wurde geändert." msgstr "Ihr Passwort wurde geändert."
#: templates/umap/search.html:15 #: templates/umap/search.html:6
msgid "Explore maps"
msgstr "Karten erkunden"
#: templates/umap/search.html:19
#, python-format #, python-format
msgid "%(count)s map found:" msgid "%(count)s map found:"
msgid_plural "%(count)s maps found:" msgid_plural "%(count)s maps found:"
msgstr[0] "%(count)s Karte gefunden:" msgstr[0] "%(count)s Karte gefunden:"
msgstr[1] "%(count)s Karten gefunden:" msgstr[1] "%(count)s Karten gefunden:"
#: templates/umap/search.html:24 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "Keine Karte gefunden." msgstr "Keine Karte gefunden."
#: templates/umap/search.html:29 #: templates/umap/search.html:35
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Zuletzt erstellte Karten" msgstr "Zuletzt erstellte Karten"
@ -583,25 +684,42 @@ msgstr "Zuletzt erstellte Karten"
msgid "Search maps" msgid "Search maps"
msgstr "Karten suchen" msgstr "Karten suchen"
#: templates/umap/search_bar.html:15 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr ""
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Suchen" msgstr "Suchen"
#: templates/umap/team_detail.html:10 #: templates/umap/team_confirm_delete.html:6
msgid "Team deletion"
msgstr "Team löschen"
#: templates/umap/team_detail.html:6
#, python-format
msgid "%(current_team)ss maps"
msgstr "Karten von %(current_team)s"
#: templates/umap/team_detail.html:14
#, python-format #, python-format
msgid "Browse %(current_team)s's maps" msgid "Browse %(current_team)s's maps"
msgstr "Schaue dir %(current_team)s's Karten an" msgstr "Schaue dir %(current_team)s's Karten an"
#: templates/umap/team_detail.html:22 #: templates/umap/team_detail.html:26
#, python-format #, python-format
msgid "%(current_team)s has no public maps." msgid "%(current_team)s has no public maps."
msgstr "%(current_team)s hat keine öffentlichen Karten.." msgstr "%(current_team)s hat keine öffentlichen Karten.."
#: templates/umap/team_form.html:24 #: templates/umap/team_form.html:6
msgid "Create or edit a team"
msgstr "Team erstellen oder bearbeiten"
#: templates/umap/team_form.html:28
msgid "Delete this team" msgid "Delete this team"
msgstr "Dieses Team löschen" msgstr "Dieses Team löschen"
#: templates/umap/team_form.html:47 #: templates/umap/team_form.html:51
msgid "Add user" msgid "Add user"
msgstr "Benutzer hinzufügen" msgstr "Benutzer hinzufügen"
@ -622,78 +740,82 @@ msgstr "Herunterladen von %(count)s Karten"
msgid "You have no map yet." msgid "You have no map yet."
msgstr "Du hast noch keine Karte." msgstr "Du hast noch keine Karte."
#: templates/umap/user_teams.html:17 #: templates/umap/user_teams.html:6
msgid "My Teams"
msgstr "Meine Teams"
#: templates/umap/user_teams.html:21
msgid "Users" msgid "Users"
msgstr "Benutzer" msgstr "Benutzer"
#: templates/umap/user_teams.html:48 #: templates/umap/user_teams.html:52
msgid "New team" msgid "New team"
msgstr "Neues Team" msgstr "Neues Team"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "Teams mit mehr als einem Mitglied können nicht gelöscht werden" msgstr "Teams mit mehr als einem Mitglied können nicht gelöscht werden"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "Team “%(name)s” wurde gelöscht" msgstr "Team “%(name)s” wurde gelöscht"
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Diese Karte anzeigen" msgstr "Diese Karte anzeigen"
#: views.py:825 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "Vollbildanzeige" msgstr "Vollbildanzeige"
#: views.py:968 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Bearbeiter erfolgreich geändert" msgstr "Bearbeiter erfolgreich geändert"
#: views.py:1004 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "Der uMap-Bearbeitungslink für Deine Karte: %(map_name)s" msgstr "Der uMap-Bearbeitungslink für Deine Karte: %(map_name)s"
#: views.py:1007 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Dies ist der geheime Bearbeitungslink: %(link)s" msgstr "Dies ist der geheime Bearbeitungslink: %(link)s"
#: views.py:1014 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "E-Mail kann nicht gesendet werden an %(email)s" msgstr "E-Mail kann nicht gesendet werden an %(email)s"
#: views.py:1017 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "Email gesendet an %(email)s" msgstr "Email gesendet an %(email)s"
#: views.py:1028 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Nur der Ersteller kann die Karte löschen." msgstr "Nur der Ersteller kann die Karte löschen."
#: views.py:1031 #: views.py:1051
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "Karte erfolgreich gelöscht." msgstr "Karte erfolgreich gelöscht."
#: views.py:1057 #: views.py:1077
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Deine Karte wurde kopiert! Wenn du diese Karte von einem anderen Computer aus bearbeiten möchtest, benutze bitte diesen Link: %(anonymous_url)s" msgstr "Deine Karte wurde kopiert! Wenn du diese Karte von einem anderen Computer aus bearbeiten möchtest, benutze bitte diesen Link: %(anonymous_url)s"
#: views.py:1062 #: views.py:1082
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Glückwunsch, deine Karte wurde kopiert!" msgstr "Glückwunsch, deine Karte wurde kopiert!"
#: views.py:1313 #: views.py:1336
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Ebene erfolgreich gelöscht." msgstr "Ebene erfolgreich gelöscht."
#: views.py:1335 #: views.py:1358
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "Berechtigungen erfolgreich aktualisiert!" msgstr "Berechtigungen erfolgreich aktualisiert!"

Binary file not shown.

View file

@ -13,7 +13,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n" "POT-Creation-Date: 2025-04-11 15:30+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: prendi <prendi@openmailbox.org>, 2017\n" "Last-Translator: prendi <prendi@openmailbox.org>, 2017\n"
"Language-Team: Greek (http://app.transifex.com/openstreetmap/umap/language/el/)\n" "Language-Team: Greek (http://app.transifex.com/openstreetmap/umap/language/el/)\n"
@ -40,137 +40,205 @@ msgstr "Λόγω συντήρησης, ο ιστότοπος είναι μόνο
msgid "" msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. " "Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account" "Please configure another provider below before losing access to your account"
" and maps." " and maps. Then, please logout and login again with the new provider."
msgstr "" msgstr "Η χρήση του «%(name)s» για τον έλεγχο ταυτότητας έχει ξεπεραστεί και θα καταργηθεί σύντομα. Παρακαλούμε ρυθμίστε έναν άλλο πάροχο παρακάτω πριν χάσετε την πρόσβαση στο λογαριασμό και τους χάρτες σας. Στη συνέχεια, παρακαλούμε αποσυνδεθείτε και συνδεθείτε ξανά με τον νέο πάροχο."
#: models.py:60 models.py:79 #: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "όνομα" msgstr "όνομα"
#: models.py:62 models.py:485 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "περιγραφή" msgstr "περιγραφή"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "λεπτομέρειες" msgstr "λεπτομέρειες"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Σύνδεσμος σελίδας αναλυτικής Άδειας Χρήσης." msgstr "Σύνδεσμος σελίδας αναλυτικής Άδειας Χρήσης."
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "Πρότυπο URL που χρησιμοποιεί μορφοποίηση πλακιδίων OSM" msgstr "Πρότυπο URL που χρησιμοποιεί μορφοποίηση πλακιδίων OSM"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Σειρά των υπόβαθρων στο πλαίσιο επεξεργασίας" msgstr "Σειρά των υπόβαθρων στο πλαίσιο επεξεργασίας"
#: models.py:175 models.py:479 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Επεξεργάσιμο μόνο με μυστικό σύνδεσμο" msgstr "Επεξεργάσιμο μόνο με μυστικό σύνδεσμο"
#: models.py:176 models.py:480 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Όλοι μπορούν να επεξεργαστούν" msgstr "Όλοι μπορούν να επεξεργαστούν"
#: models.py:179 models.py:473 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "Οποιοσδήποτε" msgstr "Οποιοσδήποτε"
#: models.py:180 models.py:189 models.py:474 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Μόνο συντάκτες και ομάδα" msgstr "Μόνο συντάκτες και ομάδα"
#: models.py:181 models.py:475 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "Μόνο ο κάτοχος" msgstr "Μόνο ο κάτοχος"
#: models.py:184 #: models.py:185
msgid "Draft (private)" msgid "Draft (private)"
msgstr "Πρόχειρο (ιδιωτικό)" msgstr "Πρόχειρο (ιδιωτικό)"
#: models.py:185 #: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "Όλοι (δημόσιος)" msgstr "Όλοι (δημόσιος)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "Οποιοδήποτε με τον σύνδεσμο" msgstr "Οποιοδήποτε με τον σύνδεσμο"
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "Αποκλεισμένος" msgstr "Αποκλεισμένος"
#: models.py:191 models.py:469 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "Διαγράφηκε" msgstr "Διαγράφηκε"
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "κέντρο" msgstr "κέντρο"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "εστίαση" msgstr "εστίαση"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "εντοπισμός θέσης" msgstr "εντοπισμός θέσης"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Εντοπισμός θέσης χρήστη κατά την φόρτωση;" msgstr "Εντοπισμός θέσης χρήστη κατά την φόρτωση;"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Επιλογή άδειας χρήσης του χάρτη." msgstr "Επιλογή άδειας χρήσης του χάρτη."
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "άδεια" msgstr "άδεια"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "ιδιοκτήτης" msgstr "ιδιοκτήτης"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "συντάκτες" msgstr "συντάκτες"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "ομάδα" msgstr "ομάδα"
#: models.py:229 models.py:501 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "κατάσταση επεξεργασίας" msgstr "κατάσταση επεξεργασίας"
#: models.py:234 models.py:506 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "κατάσταση διαμοιρασμού" msgstr "κατάσταση διαμοιρασμού"
#: models.py:237 models.py:496 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "ρυθμίσεις" msgstr "ρυθμίσεις"
#: models.py:407 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Κλώνος του" msgstr "Κλώνος του"
#: models.py:468 models.py:472 models.py:478 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "Κληρονόμοι" msgstr "Κληρονόμοι"
#: models.py:491 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "εμφάνιση κατά τη φόρτωση" msgstr "εμφάνιση κατά τη φόρτωση"
#: models.py:492 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Εμφάνιση αυτού του επιπέδου κατά την φόρτωση." msgstr "Εμφάνιση αυτού του επιπέδου κατά την φόρτωση."
#: settings/base.py:295
msgid "Art and Culture"
msgstr "Τέχνες και Πολιτισμός"
#: settings/base.py:296
msgid "Cycling"
msgstr "Ποδηλασία"
#: settings/base.py:297
msgid "Business"
msgstr "Επιχειρήσεις"
#: settings/base.py:298
msgid "Environment"
msgstr "Περιβάλλον"
#: settings/base.py:299
msgid "Education"
msgstr "Εκπαίδευση"
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr "Διατροφή και Γεωργία"
#: settings/base.py:301
msgid "Geopolitics"
msgstr "Γεωπολιτική"
#: settings/base.py:302
msgid "Health"
msgstr "Υγεία"
#: settings/base.py:303
msgid "Hiking"
msgstr "Πεζοπορία-Ορειβασία"
#: settings/base.py:304
msgid "History"
msgstr "Ιστορία"
#: settings/base.py:305
msgid "Public sector"
msgstr "Δημόσιος τομέας"
#: settings/base.py:306
msgid "Science"
msgstr "Επιστήμες"
#: settings/base.py:307
msgid "Shopping"
msgstr "Ψώνια"
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr "Αθλητισμός και ελεύθερος χρόνος"
#: settings/base.py:309
msgid "Travel"
msgstr "Ταξίδια"
#: settings/base.py:310
msgid "Transports"
msgstr "Μεταφορές"
#: settings/base.py:311
msgid "Tourism"
msgstr "Τουρισμός"
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -423,7 +491,7 @@ msgstr "Οι ομάδες μου"
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "Χάρτης των uMaps" msgstr "Χάρτης των uMaps"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Περιηγήσου και αναζήτησε την έμπνευση στους χάρτες!" msgstr "Περιηγήσου και αναζήτησε την έμπνευση στους χάρτες!"
@ -431,11 +499,15 @@ msgstr "Περιηγήσου και αναζήτησε την έμπνευση
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Είστε συνδεδεμένοι. Συνέχεια..." msgstr "Είστε συνδεδεμένοι. Συνέχεια..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "από" msgstr "από"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Δες τον χάρτη"
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Περισσότερα" msgstr "Περισσότερα"
@ -594,11 +666,15 @@ msgid_plural "%(count)s maps found:"
msgstr[0] "%(count)s χάρτης βρέθηκε:" msgstr[0] "%(count)s χάρτης βρέθηκε:"
msgstr[1] "%(count)s χάρτες βρέθηκαν:" msgstr[1] "%(count)s χάρτες βρέθηκαν:"
#: templates/umap/search.html:28 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "Δεν βρέθηκε κανένας χάρτης." msgstr "Δεν βρέθηκε κανένας χάρτης."
#: templates/umap/search.html:33 #: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr "Τελευταία δημιουργημένοι χάρτες στην κατηγορία"
#: templates/umap/search.html:43
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Χάρτες που δημιουργήθηκαν τελευταίοι" msgstr "Χάρτες που δημιουργήθηκαν τελευταίοι"
@ -606,7 +682,11 @@ msgstr "Χάρτες που δημιουργήθηκαν τελευταίοι"
msgid "Search maps" msgid "Search maps"
msgstr "Αναζήτηση χαρτών" msgstr "Αναζήτηση χαρτών"
#: templates/umap/search_bar.html:16 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Οποιαδήποτε κατηγορία"
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Αναζήτηση" msgstr "Αναζήτηση"
@ -670,70 +750,70 @@ msgstr "Χρήστες"
msgid "New team" msgid "New team"
msgstr "Νέα ομάδα" msgstr "Νέα ομάδα"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "Δεν είναι δυνατή η διαγραφή μιας ομάδας που έχει περισσότερα από ένα μέλη" msgstr "Δεν είναι δυνατή η διαγραφή μιας ομάδας που έχει περισσότερα από ένα μέλη"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "Η ομάδα «%(name)s» έχει διαγραφεί." msgstr "Η ομάδα «%(name)s» έχει διαγραφεί."
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Προβολή του χάρτη" msgstr "Προβολή του χάρτη"
#: views.py:838 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "Προβολή πλήρους οθόνης" msgstr "Προβολή πλήρους οθόνης"
#: views.py:981 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Η ενημέρωση των συντακτών χάρτη ήταν επιτυχής!" msgstr "Η ενημέρωση των συντακτών χάρτη ήταν επιτυχής!"
#: views.py:1017 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "Ο uMap σύνδεσμος επεξεργασίας του χάρτη σας: %(map_name)s" msgstr "Ο uMap σύνδεσμος επεξεργασίας του χάρτη σας: %(map_name)s"
#: views.py:1020 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Εδώ είναι ο μυστικός σύνδεσμος επεξεργασίας: %(link)s" msgstr "Εδώ είναι ο μυστικός σύνδεσμος επεξεργασίας: %(link)s"
#: views.py:1027 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "Αδυναμία αποστολής email στο %(email)s" msgstr "Αδυναμία αποστολής email στο %(email)s"
#: views.py:1030 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "Μήνυμα email στάλθηκε στο %(email)s" msgstr "Μήνυμα email στάλθηκε στο %(email)s"
#: views.py:1041 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Μονό ο ιδιοκτήτης μπορεί να διαγράψει αυτό τον χάρτη." msgstr "Μονό ο ιδιοκτήτης μπορεί να διαγράψει αυτό τον χάρτη."
#: views.py:1044 #: views.py:1054
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "Ο χάρτης διαγράφηκε με επιτυχία." msgstr "Ο χάρτης διαγράφηκε με επιτυχία."
#: views.py:1070 #: views.py:1080
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Ο χάρτης κλωνοποιήθηκε! Αν θέλετε να τον επεξεργαστείτε από κάποιον άλλο υπολογιστή, παρακαλώ χρησιμοποιήστε αυτόν τον σύνδεσμο: %(anonymous_url)s" msgstr "Ο χάρτης κλωνοποιήθηκε! Αν θέλετε να τον επεξεργαστείτε από κάποιον άλλο υπολογιστή, παρακαλώ χρησιμοποιήστε αυτόν τον σύνδεσμο: %(anonymous_url)s"
#: views.py:1075 #: views.py:1085
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Συγχαρητήρια ο χάρτης σας κλωνοποιήθηκε!" msgstr "Συγχαρητήρια ο χάρτης σας κλωνοποιήθηκε!"
#: views.py:1329 #: views.py:1339
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Το επίπεδο διαγράφηκε με επιτυχία." msgstr "Το επίπεδο διαγράφηκε με επιτυχία."
#: views.py:1351 #: views.py:1361
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "Τα δικαιώματα ενημερώθηκαν με επιτυχία!" msgstr "Τα δικαιώματα ενημερώθηκαν με επιτυχία!"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n" "POT-Creation-Date: 2025-04-25 15:38+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -34,137 +34,205 @@ msgstr ""
msgid "" msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. " "Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account " "Please configure another provider below before losing access to your account "
"and maps." "and maps. Then, please logout and login again with the new provider."
msgstr "" msgstr ""
#: models.py:60 models.py:79 #: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "" msgstr ""
#: models.py:62 models.py:485 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "" msgstr ""
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "" msgstr ""
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "" msgstr ""
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "" msgstr ""
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "" msgstr ""
#: models.py:175 models.py:479 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "" msgstr ""
#: models.py:176 models.py:480 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "" msgstr ""
#: models.py:179 models.py:473 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "" msgstr ""
#: models.py:180 models.py:189 models.py:474 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "" msgstr ""
#: models.py:181 models.py:475 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "" msgstr ""
#: models.py:184 #: models.py:185
msgid "Draft (private)" msgid "Draft (private)"
msgstr "" msgstr ""
#: models.py:185 #: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "" msgstr ""
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "" msgstr ""
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "" msgstr ""
#: models.py:191 models.py:469 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "" msgstr ""
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "" msgstr ""
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "" msgstr ""
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "" msgstr ""
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "" msgstr ""
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "" msgstr ""
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "" msgstr ""
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "" msgstr ""
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "" msgstr ""
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "" msgstr ""
#: models.py:229 models.py:501 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "" msgstr ""
#: models.py:234 models.py:506 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "" msgstr ""
#: models.py:237 models.py:496 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "" msgstr ""
#: models.py:407 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "" msgstr ""
#: models.py:468 models.py:472 models.py:478 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "" msgstr ""
#: models.py:491 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "" msgstr ""
#: models.py:492 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "" msgstr ""
#: settings/base.py:296
msgid "Art and Culture"
msgstr ""
#: settings/base.py:297
msgid "Cycling"
msgstr ""
#: settings/base.py:298
msgid "Business"
msgstr ""
#: settings/base.py:299
msgid "Environment"
msgstr ""
#: settings/base.py:300
msgid "Education"
msgstr ""
#: settings/base.py:301
msgid "Food and Agriculture"
msgstr ""
#: settings/base.py:302
msgid "Geopolitics"
msgstr ""
#: settings/base.py:303
msgid "Health"
msgstr ""
#: settings/base.py:304
msgid "Hiking"
msgstr ""
#: settings/base.py:305
msgid "History"
msgstr ""
#: settings/base.py:306
msgid "Public sector"
msgstr ""
#: settings/base.py:307
msgid "Science"
msgstr ""
#: settings/base.py:308
msgid "Shopping"
msgstr ""
#: settings/base.py:309
msgid "Sport and Leisure"
msgstr ""
#: settings/base.py:310
msgid "Travel"
msgstr ""
#: settings/base.py:311
msgid "Transports"
msgstr ""
#: settings/base.py:312
msgid "Tourism"
msgstr ""
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -417,7 +485,7 @@ msgstr ""
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "" msgstr ""
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "" msgstr ""
@ -425,11 +493,15 @@ msgstr ""
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "" msgstr ""
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "" msgstr ""
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr ""
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "" msgstr ""
@ -587,11 +659,15 @@ msgid_plural "%(count)s maps found:"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: templates/umap/search.html:28 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "" msgstr ""
#: templates/umap/search.html:33 #: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr ""
#: templates/umap/search.html:43
msgid "Latest created maps" msgid "Latest created maps"
msgstr "" msgstr ""
@ -599,7 +675,11 @@ msgstr ""
msgid "Search maps" msgid "Search maps"
msgstr "" msgstr ""
#: templates/umap/search_bar.html:16 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr ""
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@ -663,70 +743,70 @@ msgstr ""
msgid "New team" msgid "New team"
msgstr "" msgstr ""
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "" msgstr ""
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "" msgstr ""
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "" msgstr ""
#: views.py:838 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "" msgstr ""
#: views.py:981 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "" msgstr ""
#: views.py:1017 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "" msgstr ""
#: views.py:1020 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "" msgstr ""
#: views.py:1027 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "" msgstr ""
#: views.py:1030 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "" msgstr ""
#: views.py:1041 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "" msgstr ""
#: views.py:1044 #: views.py:1054
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "" msgstr ""
#: views.py:1070 #: views.py:1080
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "" msgstr ""
#: views.py:1075 #: views.py:1085
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "" msgstr ""
#: views.py:1329 #: views.py:1339
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "" msgstr ""
#: views.py:1351 #: views.py:1361
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "" msgstr ""

Binary file not shown.

View file

@ -17,7 +17,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n" "POT-Creation-Date: 2025-04-11 15:30+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Ignacio L'Episcopo, 2024-2025\n" "Last-Translator: Ignacio L'Episcopo, 2024-2025\n"
"Language-Team: Spanish (http://app.transifex.com/openstreetmap/umap/language/es/)\n" "Language-Team: Spanish (http://app.transifex.com/openstreetmap/umap/language/es/)\n"
@ -44,137 +44,205 @@ msgstr "Sitio en modo solo lectura por mantenimiento"
msgid "" msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. " "Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account" "Please configure another provider below before losing access to your account"
" and maps." " and maps. Then, please logout and login again with the new provider."
msgstr "" msgstr "El uso de “%(name)s” para autenticar está obsoleto y se eliminará pronto. Por favor, configura otro proveedor a continuación antes de perder acceso a tu cuenta y mapas. Luego, cierra sesión e inicia sesión nuevamente con el nuevo proveedor."
#: models.py:60 models.py:79 #: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "nombre" msgstr "nombre"
#: models.py:62 models.py:485 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "descripción" msgstr "descripción"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "detalles" msgstr "detalles"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Enlace a una página donde se detalla la licencia." msgstr "Enlace a una página donde se detalla la licencia."
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "Plantilla de URL usando el formato de teselas OSM" msgstr "Plantilla de URL usando el formato de teselas OSM"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Orden de las capas de teselas en el cuadro de edición" msgstr "Orden de las capas de teselas en el cuadro de edición"
#: models.py:175 models.py:479 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Solo editable con enlace secreto de edición" msgstr "Solo editable con enlace secreto de edición"
#: models.py:176 models.py:480 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Todos pueden editar" msgstr "Todos pueden editar"
#: models.py:179 models.py:473 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "Todos" msgstr "Todos"
#: models.py:180 models.py:189 models.py:474 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Solo editores y equipo" msgstr "Solo editores y equipo"
#: models.py:181 models.py:475 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "Solo el propietario" msgstr "Solo el propietario"
#: models.py:184 #: models.py:185
msgid "Draft (private)" msgid "Draft (private)"
msgstr "Borrador (privado)" msgstr "Borrador (privado)"
#: models.py:185 #: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "Todos (público)" msgstr "Todos (público)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "Cualquiera con el enlace" msgstr "Cualquiera con el enlace"
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "Bloqueado" msgstr "Bloqueado"
#: models.py:191 models.py:469 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "Eliminado" msgstr "Eliminado"
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "centro" msgstr "centro"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "zoom" msgstr "zoom"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "localizar" msgstr "localizar"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "¿Localizar al usuario al cargar?" msgstr "¿Localizar al usuario al cargar?"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Elige la licencia del mapa." msgstr "Elige la licencia del mapa."
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "licencia" msgstr "licencia"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "propietario" msgstr "propietario"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "editores" msgstr "editores"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "equipo" msgstr "equipo"
#: models.py:229 models.py:501 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "estado de edición" msgstr "estado de edición"
#: models.py:234 models.py:506 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "estado de compartir" msgstr "estado de compartir"
#: models.py:237 models.py:496 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "ajustes" msgstr "ajustes"
#: models.py:407 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Clon de" msgstr "Clon de"
#: models.py:468 models.py:472 models.py:478 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "Heredar" msgstr "Heredar"
#: models.py:491 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "mostrar al cargar" msgstr "mostrar al cargar"
#: models.py:492 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Mostrar esta capa al cargar." msgstr "Mostrar esta capa al cargar."
#: settings/base.py:295
msgid "Art and Culture"
msgstr "Arte y cultura"
#: settings/base.py:296
msgid "Cycling"
msgstr "Ciclismo"
#: settings/base.py:297
msgid "Business"
msgstr "Negocios"
#: settings/base.py:298
msgid "Environment"
msgstr "Medio ambiente"
#: settings/base.py:299
msgid "Education"
msgstr "Educación"
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr "Alimentos y agricultura"
#: settings/base.py:301
msgid "Geopolitics"
msgstr "Geopolítica"
#: settings/base.py:302
msgid "Health"
msgstr "Salud"
#: settings/base.py:303
msgid "Hiking"
msgstr "Senderismo"
#: settings/base.py:304
msgid "History"
msgstr "Historia"
#: settings/base.py:305
msgid "Public sector"
msgstr "Sector público"
#: settings/base.py:306
msgid "Science"
msgstr "Ciencia"
#: settings/base.py:307
msgid "Shopping"
msgstr "Compras"
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr "Deporte y ocio"
#: settings/base.py:309
msgid "Travel"
msgstr "Viajes"
#: settings/base.py:310
msgid "Transports"
msgstr "Transporte"
#: settings/base.py:311
msgid "Tourism"
msgstr "Turismo"
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -427,7 +495,7 @@ msgstr "Mis equipos"
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "Mapa de los uMaps" msgstr "Mapa de los uMaps"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Inspírate, navega por los mapas" msgstr "Inspírate, navega por los mapas"
@ -435,11 +503,15 @@ msgstr "Inspírate, navega por los mapas"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Has iniciado sesión. Continuando..." msgstr "Has iniciado sesión. Continuando..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "por" msgstr "por"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Ver el mapa"
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Más" msgstr "Más"
@ -599,11 +671,15 @@ msgstr[0] "%(count)s mapa encontrado:"
msgstr[1] "%(count)s mapas encontrados:" msgstr[1] "%(count)s mapas encontrados:"
msgstr[2] "%(count)s mapas encontrados:" msgstr[2] "%(count)s mapas encontrados:"
#: templates/umap/search.html:28 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "No se ha encontrado ningún mapa." msgstr "No se ha encontrado ningún mapa."
#: templates/umap/search.html:33 #: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr "Últimos mapas creados en la categoría"
#: templates/umap/search.html:43
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Últimos mapas creados" msgstr "Últimos mapas creados"
@ -611,7 +687,11 @@ msgstr "Últimos mapas creados"
msgid "Search maps" msgid "Search maps"
msgstr "Buscar mapas" msgstr "Buscar mapas"
#: templates/umap/search_bar.html:16 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Cualquier categoría"
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Buscar" msgstr "Buscar"
@ -675,70 +755,70 @@ msgstr "Usuarios"
msgid "New team" msgid "New team"
msgstr "Nuevo equipo" msgstr "Nuevo equipo"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "No se puede eliminar un equipo con más de un miembro" msgstr "No se puede eliminar un equipo con más de un miembro"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "El equipo “%(name)s” ha sido eliminado" msgstr "El equipo “%(name)s” ha sido eliminado"
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Ver el mapa" msgstr "Ver el mapa"
#: views.py:838 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "Ver en pantalla completa" msgstr "Ver en pantalla completa"
#: views.py:981 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "¡Los editores del mapas han sido actualizados con éxito!" msgstr "¡Los editores del mapas han sido actualizados con éxito!"
#: views.py:1017 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "El enlace de edición de uMap para tu mapa: %(map_name)s" msgstr "El enlace de edición de uMap para tu mapa: %(map_name)s"
#: views.py:1020 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Aquí está tu enlace secreto de edición: %(link)s" msgstr "Aquí está tu enlace secreto de edición: %(link)s"
#: views.py:1027 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "No se puede enviar correo electrónico a %(email)s" msgstr "No se puede enviar correo electrónico a %(email)s"
#: views.py:1030 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "Correo electrónico enviado a %(email)s" msgstr "Correo electrónico enviado a %(email)s"
#: views.py:1041 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Sólo el propietario puede borrar el mapa." msgstr "Sólo el propietario puede borrar el mapa."
#: views.py:1044 #: views.py:1054
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "Mapa eliminado correctamente." msgstr "Mapa eliminado correctamente."
#: views.py:1070 #: views.py:1080
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "¡Tu mapa ha sido clonado! Si quieres editar este mapa desde otro ordenador, usa este enlace: %(anonymous_url)s" msgstr "¡Tu mapa ha sido clonado! Si quieres editar este mapa desde otro ordenador, usa este enlace: %(anonymous_url)s"
#: views.py:1075 #: views.py:1085
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "¡Enhorabuena! ¡Tu mapa ha sido clonado!" msgstr "¡Enhorabuena! ¡Tu mapa ha sido clonado!"
#: views.py:1329 #: views.py:1339
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Se eliminó la capa con éxito." msgstr "Se eliminó la capa con éxito."
#: views.py:1351 #: views.py:1361
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "¡Permisos actualizados con éxito!" msgstr "¡Permisos actualizados con éxito!"

Binary file not shown.

View file

@ -4,14 +4,14 @@
# #
# Translators: # Translators:
# Moon Ika, 2020 # Moon Ika, 2020
# Moon Ika, 2020 # Moon Ika, 2020,2025
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-24 08:39+0000\n" "POT-Creation-Date: 2025-03-07 15:18+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Moon Ika, 2020\n" "Last-Translator: Moon Ika, 2020,2025\n"
"Language-Team: Estonian (http://app.transifex.com/openstreetmap/umap/language/et/)\n" "Language-Team: Estonian (http://app.transifex.com/openstreetmap/umap/language/et/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -21,21 +21,29 @@ msgstr ""
#: admin.py:16 #: admin.py:16
msgid "CSV Export" msgid "CSV Export"
msgstr "" msgstr "CSV eksport"
#: decorators.py:60 #: decorators.py:60
msgid "This map is not publicly available" msgid "This map is not publicly available"
msgstr "" msgstr "See kaart pole avalikult kättesaadav"
#: middleware.py:13 #: middleware.py:19
msgid "Site is readonly for maintenance" msgid "Site is readonly for maintenance"
msgstr "Sait on hoolduseks kirjutuskaitstud" msgstr "Sait on hoolduseks kirjutuskaitstud"
#: middleware.py:34
#, python-format
msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account"
" and maps. Then, please logout and login again with the new provider."
msgstr ""
#: models.py:60 models.py:79 #: models.py:60 models.py:79
msgid "name" msgid "name"
msgstr "nimi" msgstr "nimi"
#: models.py:62 models.py:475 #: models.py:62 models.py:485
msgid "description" msgid "description"
msgstr "kirjeldus" msgstr "kirjeldus"
@ -55,33 +63,33 @@ msgstr ""
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "" msgstr ""
#: models.py:175 models.py:469 #: models.py:175 models.py:479
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Muudetav ainult salajase muutmislingiga" msgstr "Muudetav ainult salajase muutmislingiga"
#: models.py:176 models.py:470 #: models.py:176 models.py:480
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Igaüks saab muuta" msgstr "Igaüks saab muuta"
#: models.py:179 models.py:463 #: models.py:179 models.py:473
msgid "Everyone" msgid "Everyone"
msgstr "" msgstr "Kõik"
#: models.py:180 models.py:189 models.py:464 #: models.py:180 models.py:189 models.py:474
msgid "Editors and team only" msgid "Editors and team only"
msgstr "" msgstr "Ainult toimetajad ja meeskond"
#: models.py:181 models.py:465 #: models.py:181 models.py:475
msgid "Owner only" msgid "Owner only"
msgstr "" msgstr "Ainult omanik"
#: models.py:184 #: models.py:184
msgid "Draft (private)" msgid "Draft (private)"
msgstr "" msgstr "Mustand (privaatne)"
#: models.py:185 #: models.py:185
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "" msgstr "Kõik (avalik)"
#: models.py:188 #: models.py:188
msgid "Anyone with link" msgid "Anyone with link"
@ -89,11 +97,11 @@ msgstr ""
#: models.py:190 #: models.py:190
msgid "Blocked" msgid "Blocked"
msgstr "" msgstr "Blokeeritud"
#: models.py:191 #: models.py:191 models.py:469
msgid "Deleted" msgid "Deleted"
msgstr "" msgstr "Kustutatud"
#: models.py:194 #: models.py:194
msgid "center" msgid "center"
@ -109,7 +117,7 @@ msgstr "määra asukoht"
#: models.py:197 #: models.py:197
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Määra kasutaja asukoht laadimisel?" msgstr "Määra laadimisel kasutaja asukoht?"
#: models.py:201 #: models.py:201
msgid "Choose the map licence." msgid "Choose the map licence."
@ -129,33 +137,33 @@ msgstr "toimetajad"
#: models.py:223 #: models.py:223
msgid "team" msgid "team"
msgstr "" msgstr "meeskond"
#: models.py:229 models.py:491 #: models.py:229 models.py:501
msgid "edit status" msgid "edit status"
msgstr "muutmise staatus" msgstr "muutmise staatus"
#: models.py:234 #: models.py:234 models.py:506
msgid "share status" msgid "share status"
msgstr "jagamise staatus" msgstr "jagamise staatus"
#: models.py:237 models.py:486 #: models.py:237 models.py:496
msgid "settings" msgid "settings"
msgstr "seaded" msgstr "seaded"
#: models.py:402 #: models.py:407
msgid "Clone of" msgid "Clone of"
msgstr "Koopia" msgstr "Koopia"
#: models.py:462 models.py:468 #: models.py:468 models.py:472 models.py:478
msgid "Inherit" msgid "Inherit"
msgstr "" msgstr ""
#: models.py:481 #: models.py:491
msgid "display on load" msgid "display on load"
msgstr "kuva laadimisel" msgstr "kuva laadimisel"
#: models.py:482 #: models.py:492
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Kuva seda kihti laadimisel" msgstr "Kuva seda kihti laadimisel"
@ -168,46 +176,60 @@ msgstr ""
#: templates/403.html:10 templates/404.html:8 #: templates/403.html:10 templates/404.html:8
msgid "← Go to the homepage" msgid "← Go to the homepage"
msgstr "" msgstr "← Mine avalehele"
#: templates/404.html:7 #: templates/404.html:7
msgid "404 Page Not Found" msgid "404 Page Not Found"
msgstr "404 Lehte ei leitud"
#: templates/auth/user_detail.html:6
#, python-format
msgid "%(current_user)ss maps"
msgstr "" msgstr ""
#: templates/auth/user_detail.html:8 #: templates/auth/user_detail.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's maps" msgid "Browse %(current_user)s's maps"
msgstr "Sirvi kasutaja %(current_user)s kaarte" msgstr "Sirvi kasutaja %(current_user)s kaarte"
#: templates/auth/user_detail.html:17 #: templates/auth/user_detail.html:21
#, python-format #, python-format
msgid "%(current_user)s has no maps." msgid "%(current_user)s has no maps."
msgstr "Kasutajal %(current_user)s pole kaarte." msgstr "Kasutajal %(current_user)s pole kaarte."
#: templates/auth/user_form.html:21 templates/umap/team_form.html:21 #: templates/auth/user_form.html:6
msgid "Save" msgid "My Profile"
msgstr "" msgstr "Minu profiil"
#: templates/auth/user_form.html:27 #: templates/auth/user_form.html:24 templates/umap/team_form.html:25
msgid "Save"
msgstr "Salvesta"
#: templates/auth/user_form.html:30
msgid "Your current providers" msgid "Your current providers"
msgstr "" msgstr ""
#: templates/auth/user_form.html:39 #: templates/auth/user_form.html:44
msgid "Connect to another provider" msgid "Connect to another provider"
msgstr "" msgstr ""
#: templates/auth/user_form.html:42 #: templates/auth/user_form.html:47
msgid "" msgid ""
"It's a good habit to connect your account to more than one provider, in case" "It's a good habit to connect your account to more than one provider, in case"
" one provider becomes unavailable, temporarily or even permanently." " one provider becomes unavailable, temporarily or even permanently."
msgstr "" msgstr ""
#: templates/auth/user_stars.html:8 #: templates/auth/user_stars.html:6
#, python-format
msgid "%(current_user)ss starred maps"
msgstr ""
#: templates/auth/user_stars.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's starred maps" msgid "Browse %(current_user)s's starred maps"
msgstr "" msgstr ""
#: templates/auth/user_stars.html:17 #: templates/auth/user_stars.html:21
#, python-format #, python-format
msgid "%(current_user)s has no starred maps yet." msgid "%(current_user)s has no starred maps yet."
msgstr "" msgstr ""
@ -224,11 +246,11 @@ msgstr "Logi sisse"
#: templates/registration/login.html:22 #: templates/registration/login.html:22
msgid "To save and easily find your maps, identify yourself." msgid "To save and easily find your maps, identify yourself."
msgstr "" msgstr "Tuvasta end kaartide salvestamiseks ja kiireks leidmiseks."
#: templates/registration/login.html:25 #: templates/registration/login.html:25
msgid "Please log in with your account:" msgid "Please log in with your account:"
msgstr "" msgstr "Palun logi oma kontoga sisse:"
#: templates/registration/login.html:42 #: templates/registration/login.html:42
msgid "Username" msgid "Username"
@ -240,7 +262,11 @@ msgstr "Salasõna"
#: templates/registration/login.html:52 #: templates/registration/login.html:52
msgid "Please choose a provider:" msgid "Please choose a provider:"
msgstr "" msgstr "Vali teenusepakkuja:"
#: templates/umap/about.html:5 templates/umap/navigation.html:22
msgid "About"
msgstr "Teave"
#: templates/umap/about_summary.html:12 #: templates/umap/about_summary.html:12
#, python-format #, python-format
@ -307,23 +333,23 @@ msgstr ""
#: templates/umap/components/alerts/alert.html:37 #: templates/umap/components/alerts/alert.html:37
msgid "Here is your secret link to edit the map, please keep it safe:" msgid "Here is your secret link to edit the map, please keep it safe:"
msgstr "" msgstr "Siin on sinu salalink kaardi toimetamiseks, hoia seda salajas:"
#: templates/umap/components/alerts/alert.html:41 #: templates/umap/components/alerts/alert.html:41
msgid "Copy link" msgid "Copy link"
msgstr "" msgstr "Kopeeri link"
#: templates/umap/components/alerts/alert.html:48 #: templates/umap/components/alerts/alert.html:48
msgid "Enter your email address to receive the secret link:" msgid "Enter your email address to receive the secret link:"
msgstr "" msgstr "Sisesta salalingi saamiseks oma e-posti aadress:"
#: templates/umap/components/alerts/alert.html:54 #: templates/umap/components/alerts/alert.html:54
msgid "Email" msgid "Email"
msgstr "" msgstr "E-post"
#: templates/umap/components/alerts/alert.html:57 #: templates/umap/components/alerts/alert.html:57
msgid "Send me the link" msgid "Send me the link"
msgstr "" msgstr "Saada mulle link"
#: templates/umap/components/alerts/alert.html:81 #: templates/umap/components/alerts/alert.html:81
msgid "See their edits in another tab" msgid "See their edits in another tab"
@ -354,11 +380,11 @@ msgstr ""
#: templates/umap/content_footer.html:5 #: templates/umap/content_footer.html:5
msgid "An OpenStreetMap project" msgid "An OpenStreetMap project"
msgstr "" msgstr "OpenStreetMapi projekt"
#: templates/umap/content_footer.html:6 #: templates/umap/content_footer.html:6
msgid "version" msgid "version"
msgstr "" msgstr "versioon"
#: templates/umap/content_footer.html:7 #: templates/umap/content_footer.html:7
msgid "Hosted by" msgid "Hosted by"
@ -366,32 +392,32 @@ msgstr ""
#: templates/umap/content_footer.html:8 #: templates/umap/content_footer.html:8
msgid "Contact" msgid "Contact"
msgstr "" msgstr "Kontakt"
#: templates/umap/content_footer.html:9 templates/umap/navigation.html:25 #: templates/umap/content_footer.html:9 templates/umap/navigation.html:25
msgid "Help" msgid "Help"
msgstr "" msgstr "Abi"
#: templates/umap/dashboard_menu.html:6 #: templates/umap/dashboard_menu.html:6
#, python-format #, python-format
msgid "My Maps (%(count)s)" msgid "My Maps (%(count)s)"
msgstr "" msgstr "Minu kaardid (%(count)s)"
#: templates/umap/dashboard_menu.html:8 #: templates/umap/dashboard_menu.html:8
msgid "My Maps" msgid "My Maps"
msgstr "" msgstr "Minu kaardid"
#: templates/umap/dashboard_menu.html:12 #: templates/umap/dashboard_menu.html:12
msgid "My profile" msgid "My profile"
msgstr "" msgstr "Minu profiil"
#: templates/umap/dashboard_menu.html:15 #: templates/umap/dashboard_menu.html:15
msgid "My teams" msgid "My teams"
msgstr "" msgstr "Minu meeskonnad"
#: templates/umap/home.html:14 #: templates/umap/home.html:14
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "uMaps'i kaart" msgstr "uMapsi kaart"
#: templates/umap/home.html:24 #: templates/umap/home.html:24
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
@ -401,7 +427,7 @@ msgstr "Sirvi kaarte ja ammuta inspiratsiooni"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Oled sisse logitud. Jätkamine..." msgstr "Oled sisse logitud. Jätkamine..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:11 views.py:438
msgid "by" msgid "by"
msgstr "kasutajalt" msgstr "kasutajalt"
@ -409,31 +435,31 @@ msgstr "kasutajalt"
msgid "More" msgid "More"
msgstr "Rohkem" msgstr "Rohkem"
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:14 #: templates/umap/map_table.html:8 templates/umap/user_teams.html:18
msgid "Name" msgid "Name"
msgstr "" msgstr "Nimi"
#: templates/umap/map_table.html:11 #: templates/umap/map_table.html:11
msgid "Preview" msgid "Preview"
msgstr "" msgstr "Eelvaade"
#: templates/umap/map_table.html:14 #: templates/umap/map_table.html:14
msgid "Who can see" msgid "Who can see"
msgstr "" msgstr "Kes saavad vaadata"
#: templates/umap/map_table.html:17 #: templates/umap/map_table.html:17
msgid "Who can edit" msgid "Who can edit"
msgstr "" msgstr "Kes saavad toimetada"
#: templates/umap/map_table.html:20 #: templates/umap/map_table.html:20
msgid "Last save" msgid "Last save"
msgstr "" msgstr "Viimane salvestamine"
#: templates/umap/map_table.html:23 #: templates/umap/map_table.html:23
msgid "Owner" msgid "Owner"
msgstr "" msgstr "Omanik"
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:20 #: templates/umap/map_table.html:26 templates/umap/user_teams.html:24
msgid "Actions" msgid "Actions"
msgstr "" msgstr ""
@ -443,16 +469,16 @@ msgstr ""
#: templates/umap/map_table.html:72 templates/umap/map_table.html:74 #: templates/umap/map_table.html:72 templates/umap/map_table.html:74
msgid "Share" msgid "Share"
msgstr "" msgstr "Jaga"
#: templates/umap/map_table.html:78 templates/umap/map_table.html:80 #: templates/umap/map_table.html:78 templates/umap/map_table.html:80
#: templates/umap/user_teams.html:38 templates/umap/user_teams.html:40 #: templates/umap/user_teams.html:42 templates/umap/user_teams.html:44
msgid "Edit" msgid "Edit"
msgstr "" msgstr "Redigeeri"
#: templates/umap/map_table.html:84 templates/umap/map_table.html:86 #: templates/umap/map_table.html:84 templates/umap/map_table.html:86
msgid "Download" msgid "Download"
msgstr "" msgstr "Laadi alla"
#: templates/umap/map_table.html:90 templates/umap/map_table.html:92 #: templates/umap/map_table.html:90 templates/umap/map_table.html:92
msgid "Clone" msgid "Clone"
@ -460,38 +486,38 @@ msgstr ""
#: templates/umap/map_table.html:101 templates/umap/map_table.html:103 #: templates/umap/map_table.html:101 templates/umap/map_table.html:103
msgid "Delete" msgid "Delete"
msgstr "" msgstr "Kustuta"
#: templates/umap/map_table.html:117 #: templates/umap/map_table.html:117
msgid "first" msgid "first"
msgstr "" msgstr "esimene"
#: templates/umap/map_table.html:118 #: templates/umap/map_table.html:118
msgid "previous" msgid "previous"
msgstr "" msgstr "eelmine"
#: templates/umap/map_table.html:126 #: templates/umap/map_table.html:126
#, python-format #, python-format
msgid "Page %(maps_number)s of %(num_pages)s" msgid "Page %(maps_number)s of %(num_pages)s"
msgstr "" msgstr "%(maps_number)s. lehekülg %(num_pages)s-st"
#: templates/umap/map_table.html:131 #: templates/umap/map_table.html:131
msgid "next" msgid "next"
msgstr "" msgstr "järgmine"
#: templates/umap/map_table.html:132 #: templates/umap/map_table.html:132
msgid "last" msgid "last"
msgstr "" msgstr "viimane"
#: templates/umap/map_table.html:140 #: templates/umap/map_table.html:140
#, python-format #, python-format
msgid "Lines per page: %(per_page)s" msgid "Lines per page: %(per_page)s"
msgstr "" msgstr "Jooni leheküljel: %(per_page)s"
#: templates/umap/map_table.html:145 #: templates/umap/map_table.html:145
#, python-format #, python-format
msgid "%(count)s maps" msgid "%(count)s maps"
msgstr "" msgstr "%(count)s kaarti"
#: templates/umap/navigation.html:11 templates/umap/user_dashboard.html:6 #: templates/umap/navigation.html:11 templates/umap/user_dashboard.html:6
msgid "My Dashboard" msgid "My Dashboard"
@ -509,10 +535,6 @@ msgstr "Logi sisse"
msgid "Sign in" msgid "Sign in"
msgstr "Loo konto" msgstr "Loo konto"
#: templates/umap/navigation.html:22
msgid "About"
msgstr "Teave"
#: templates/umap/navigation.html:30 #: templates/umap/navigation.html:30
msgid "Change password" msgid "Change password"
msgstr "Muuda salasõna" msgstr "Muuda salasõna"
@ -521,88 +543,107 @@ msgstr "Muuda salasõna"
msgid "Log out" msgid "Log out"
msgstr "Logi välja" msgstr "Logi välja"
#: templates/umap/password_change.html:7 #: templates/umap/password_change.html:6
#: templates/umap/password_change.html:11
msgid "Password change" msgid "Password change"
msgstr "Salasõna vahetamine" msgstr "Salasõna vahetamine"
#: templates/umap/password_change.html:10 #: templates/umap/password_change.html:14
msgid "" msgid ""
"Please enter your old password, for security's sake, and then enter your new" "Please enter your old password, for security's sake, and then enter your new"
" password twice so we can verify you typed it in correctly." " password twice so we can verify you typed it in correctly."
msgstr "Sisesta palun oma vana salasõna, seejärel kaks korda uus salasõna." msgstr "Sisesta palun oma vana salasõna, seejärel kaks korda uus salasõna."
#: templates/umap/password_change.html:17 #: templates/umap/password_change.html:21
msgid "Old password" msgid "Old password"
msgstr "Vana salasõna" msgstr "Vana salasõna"
#: templates/umap/password_change.html:22 #: templates/umap/password_change.html:26
msgid "New password" msgid "New password"
msgstr "Uus salasõna" msgstr "Uus salasõna"
#: templates/umap/password_change.html:26 #: templates/umap/password_change.html:30
msgid "New password confirmation" msgid "New password confirmation"
msgstr "Uue salasõna kinnitamine" msgstr "Uue salasõna kinnitamine"
#: templates/umap/password_change.html:27 #: templates/umap/password_change.html:31
msgid "Change my password" msgid "Change my password"
msgstr "Muuda salasõna" msgstr "Muuda salasõna"
#: templates/umap/password_change_done.html:7 #: templates/umap/password_change_done.html:6
#: templates/umap/password_change_done.html:11
msgid "Password change successful" msgid "Password change successful"
msgstr "Salasõna vahetamine õnnestus" msgstr "Salasõna vahetamine õnnestus"
#: templates/umap/password_change_done.html:10 #: templates/umap/password_change_done.html:14
msgid "Your password was changed." msgid "Your password was changed."
msgstr "Sinu salasõna on muudetud." msgstr "Sinu salasõna on muudetud."
#: templates/umap/search.html:15 #: templates/umap/search.html:6
msgid "Explore maps"
msgstr ""
#: templates/umap/search.html:19
#, python-format #, python-format
msgid "%(count)s map found:" msgid "%(count)s map found:"
msgid_plural "%(count)s maps found:" msgid_plural "%(count)s maps found:"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: templates/umap/search.html:24 #: templates/umap/search.html:28
msgid "No map found." msgid "No map found."
msgstr "" msgstr "Kaarti ei leitud."
#: templates/umap/search.html:29 #: templates/umap/search.html:33
msgid "Latest created maps" msgid "Latest created maps"
msgstr "" msgstr "Viimati loodud kaardid."
#: templates/umap/search_bar.html:4 #: templates/umap/search_bar.html:4
msgid "Search maps" msgid "Search maps"
msgstr "Otsi kaarte" msgstr "Otsi kaarte"
#: templates/umap/search_bar.html:15 #: templates/umap/search_bar.html:16
msgid "Search" msgid "Search"
msgstr "Otsi" msgstr "Otsi"
#: templates/umap/team_detail.html:10 #: templates/umap/team_confirm_delete.html:6
msgid "Team deletion"
msgstr ""
#: templates/umap/team_detail.html:6
#, python-format
msgid "%(current_team)ss maps"
msgstr ""
#: templates/umap/team_detail.html:14
#, python-format #, python-format
msgid "Browse %(current_team)s's maps" msgid "Browse %(current_team)s's maps"
msgstr "" msgstr ""
#: templates/umap/team_detail.html:22 #: templates/umap/team_detail.html:26
#, python-format #, python-format
msgid "%(current_team)s has no public maps." msgid "%(current_team)s has no public maps."
msgstr "" msgstr ""
#: templates/umap/team_form.html:24 #: templates/umap/team_form.html:6
msgid "Delete this team" msgid "Create or edit a team"
msgstr "" msgstr ""
#: templates/umap/team_form.html:47 #: templates/umap/team_form.html:28
msgid "Delete this team"
msgstr "Kustuta see meeskond"
#: templates/umap/team_form.html:51
msgid "Add user" msgid "Add user"
msgstr "" msgstr "Lisa kasutaja"
#: templates/umap/user_dashboard.html:9 templates/umap/user_dashboard.html:25 #: templates/umap/user_dashboard.html:9 templates/umap/user_dashboard.html:25
msgid "Search my maps" msgid "Search my maps"
msgstr "" msgstr "Otsi minu kaarte"
#: templates/umap/user_dashboard.html:17 templates/umap/user_dashboard.html:22 #: templates/umap/user_dashboard.html:17 templates/umap/user_dashboard.html:22
msgid "Maps title" msgid "Maps title"
msgstr "" msgstr "Kaardi pealkiri"
#: templates/umap/user_dashboard.html:30 #: templates/umap/user_dashboard.html:30
#, python-format #, python-format
@ -613,78 +654,82 @@ msgstr ""
msgid "You have no map yet." msgid "You have no map yet."
msgstr "" msgstr ""
#: templates/umap/user_teams.html:17 #: templates/umap/user_teams.html:6
msgid "My Teams"
msgstr "Minu meeskonnad"
#: templates/umap/user_teams.html:21
msgid "Users" msgid "Users"
msgstr "" msgstr "Kasutajad"
#: templates/umap/user_teams.html:48 #: templates/umap/user_teams.html:52
msgid "New team" msgid "New team"
msgstr "" msgstr "Uus meeskond"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "" msgstr ""
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "" msgstr "Meeskond “%(name)s” on kustutatud"
#: views.py:442 #: views.py:443
msgid "View the map" msgid "View the map"
msgstr "Vaata kaarti" msgstr "Vaata kaarti"
#: views.py:825 #: views.py:839
msgid "See full screen" msgid "See full screen"
msgstr "" msgstr "Vaata täisekraanil"
#: views.py:968 #: views.py:982
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Kaardi toimetajaid uuendati edukalt!" msgstr "Kaardi toimetajaid uuendati edukalt!"
#: views.py:1004 #: views.py:1018
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "" msgstr "Redigeerimislink sinu uMapi kaardile: %(map_name)s"
#: views.py:1007 #: views.py:1021
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "" msgstr "Siin on sinu salajane redigeerimislink: %(link)s"
#: views.py:1014
#, python-format
msgid "Can't send email to %(email)s"
msgstr ""
#: views.py:1017
#, python-format
msgid "Email sent to %(email)s"
msgstr ""
#: views.py:1028 #: views.py:1028
msgid "Only its owner can delete the map." #, python-format
msgstr "Kaarti saab kustutada vaid selle omanik." msgid "Can't send email to %(email)s"
msgstr "Ei saa saata e-kirja aadressile %(email)s"
#: views.py:1031 #: views.py:1031
msgid "Map successfully deleted." #, python-format
msgstr "" msgid "Email sent to %(email)s"
msgstr "E-kiri saadetud aadressile %(email)s"
#: views.py:1057 #: views.py:1042
msgid "Only its owner can delete the map."
msgstr "Kaardi saab kustutada vaid selle omanik."
#: views.py:1045
msgid "Map successfully deleted."
msgstr "Kaart on kustutatud."
#: views.py:1071
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Sinu kaart on kopeeritud! Kui sa soovid oma kaarti muuta teisest arvutist, kasuta palun seda linki: %(anonymous_url)s" msgstr "Sinu kaart on kopeeritud! Kui sa soovid oma kaarti muuta teisest arvutist, kasuta palun seda linki: %(anonymous_url)s"
#: views.py:1062 #: views.py:1076
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Sinu kaart on kopeeritud!" msgstr "Sinu kaart on kopeeritud!"
#: views.py:1313 #: views.py:1330
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Kiht on kustutatud." msgstr "Kiht on kustutatud."
#: views.py:1335 #: views.py:1352
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "" msgstr ""

Binary file not shown.

View file

@ -3,15 +3,15 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Alexander Gabilondo <alexgabi@disroot.org>, 2024 # Alexander Gabilondo <alexgabi@disroot.org>, 2024-2025
# Mikel Larreategi <mlarreategi@codesyntax.com>, 2023 # Mikel Larreategi <mlarreategi@codesyntax.com>, 2023
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-24 08:39+0000\n" "POT-Creation-Date: 2025-03-07 15:18+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Alexander Gabilondo <alexgabi@disroot.org>, 2024\n" "Last-Translator: Alexander Gabilondo <alexgabi@disroot.org>, 2024-2025\n"
"Language-Team: Basque (http://app.transifex.com/openstreetmap/umap/language/eu/)\n" "Language-Team: Basque (http://app.transifex.com/openstreetmap/umap/language/eu/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -25,17 +25,25 @@ msgstr "CSV esportazioa"
#: decorators.py:60 #: decorators.py:60
msgid "This map is not publicly available" msgid "This map is not publicly available"
msgstr "" msgstr "Mapa hau ez dago publikoki erabilgarri"
#: middleware.py:13 #: middleware.py:19
msgid "Site is readonly for maintenance" msgid "Site is readonly for maintenance"
msgstr "Webgunea irakurtzeko moduan dago mantentze-lanak direla-eta" msgstr "Webgunea irakurtzeko moduan dago mantentze-lanak direla-eta"
#: middleware.py:34
#, python-format
msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account"
" and maps. Then, please logout and login again with the new provider."
msgstr ""
#: models.py:60 models.py:79 #: models.py:60 models.py:79
msgid "name" msgid "name"
msgstr "izena" msgstr "izena"
#: models.py:62 models.py:475 #: models.py:62 models.py:485
msgid "description" msgid "description"
msgstr "deskribapena" msgstr "deskribapena"
@ -55,23 +63,23 @@ msgstr "URLaren txantiloia OSMren lauzen formatua erabiliz"
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Lauzen geruzek edizio kutxan duten ordena" msgstr "Lauzen geruzek edizio kutxan duten ordena"
#: models.py:175 models.py:469 #: models.py:175 models.py:479
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Bakarrik esteka sekretuarekin bakarrik editatu daiteke" msgstr "Bakarrik esteka sekretuarekin bakarrik editatu daiteke"
#: models.py:176 models.py:470 #: models.py:176 models.py:480
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Edonork editatu dezake" msgstr "Edonork editatu dezake"
#: models.py:179 models.py:463 #: models.py:179 models.py:473
msgid "Everyone" msgid "Everyone"
msgstr "Edonork" msgstr "Edonork"
#: models.py:180 models.py:189 models.py:464 #: models.py:180 models.py:189 models.py:474
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Editoreak eta taldea soilik" msgstr "Editoreak eta taldea soilik"
#: models.py:181 models.py:465 #: models.py:181 models.py:475
msgid "Owner only" msgid "Owner only"
msgstr "Jabea bakarrik" msgstr "Jabea bakarrik"
@ -91,7 +99,7 @@ msgstr "Esteka duen edonork"
msgid "Blocked" msgid "Blocked"
msgstr "Blokeatuta" msgstr "Blokeatuta"
#: models.py:191 #: models.py:191 models.py:469
msgid "Deleted" msgid "Deleted"
msgstr "Ezabatua" msgstr "Ezabatua"
@ -131,31 +139,31 @@ msgstr "editoreak"
msgid "team" msgid "team"
msgstr "taldea" msgstr "taldea"
#: models.py:229 models.py:491 #: models.py:229 models.py:501
msgid "edit status" msgid "edit status"
msgstr "editatu egoera" msgstr "editatu egoera"
#: models.py:234 #: models.py:234 models.py:506
msgid "share status" msgid "share status"
msgstr "partekatu egoera" msgstr "partekatu egoera"
#: models.py:237 models.py:486 #: models.py:237 models.py:496
msgid "settings" msgid "settings"
msgstr "ezarpenak" msgstr "ezarpenak"
#: models.py:402 #: models.py:407
msgid "Clone of" msgid "Clone of"
msgstr "Beste honen klona" msgstr "Beste honen klona"
#: models.py:462 models.py:468 #: models.py:468 models.py:472 models.py:478
msgid "Inherit" msgid "Inherit"
msgstr "Heredatu" msgstr "Heredatu"
#: models.py:481 #: models.py:491
msgid "display on load" msgid "display on load"
msgstr "erakutsi kargatzean" msgstr "erakutsi kargatzean"
#: models.py:482 #: models.py:492
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Erakutsi geruza hau kargatzean" msgstr "Erakutsi geruza hau kargatzean"
@ -164,50 +172,64 @@ msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
"target=\"_blank\">Find out here the documentation</a> on how to manage maps" "target=\"_blank\">Find out here the documentation</a> on how to manage maps"
" permissions." " permissions."
msgstr "" msgstr " <a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" target=\"_blank\">Ikusi hemen</a> maparen baimenak kudeatzeko dokumentazioa."
#: templates/403.html:10 templates/404.html:8 #: templates/403.html:10 templates/404.html:8
msgid "← Go to the homepage" msgid "← Go to the homepage"
msgstr "" msgstr "← Joan hasierara"
#: templates/404.html:7 #: templates/404.html:7
msgid "404 Page Not Found" msgid "404 Page Not Found"
msgstr "" msgstr "404 Ez da orrialdea aurkitu"
#: templates/auth/user_detail.html:8 #: templates/auth/user_detail.html:6
#, python-format
msgid "%(current_user)ss maps"
msgstr "%(current_user)s-ren mapak"
#: templates/auth/user_detail.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's maps" msgid "Browse %(current_user)s's maps"
msgstr "Arakatu %(current_user)s erabiltzailearen mapak" msgstr "Arakatu %(current_user)s erabiltzailearen mapak"
#: templates/auth/user_detail.html:17 #: templates/auth/user_detail.html:21
#, python-format #, python-format
msgid "%(current_user)s has no maps." msgid "%(current_user)s has no maps."
msgstr "%(current_user)s erabiltzaileak ez du maparik." msgstr "%(current_user)s erabiltzaileak ez du maparik."
#: templates/auth/user_form.html:21 templates/umap/team_form.html:21 #: templates/auth/user_form.html:6
msgid "My Profile"
msgstr "Nire profila"
#: templates/auth/user_form.html:24 templates/umap/team_form.html:25
msgid "Save" msgid "Save"
msgstr "Gorde" msgstr "Gorde"
#: templates/auth/user_form.html:27 #: templates/auth/user_form.html:30
msgid "Your current providers" msgid "Your current providers"
msgstr "Zure egungo hornitzaileak" msgstr "Zure egungo hornitzaileak"
#: templates/auth/user_form.html:39 #: templates/auth/user_form.html:44
msgid "Connect to another provider" msgid "Connect to another provider"
msgstr "Konektatu beste hornitzaile batekin" msgstr "Konektatu beste hornitzaile batekin"
#: templates/auth/user_form.html:42 #: templates/auth/user_form.html:47
msgid "" msgid ""
"It's a good habit to connect your account to more than one provider, in case" "It's a good habit to connect your account to more than one provider, in case"
" one provider becomes unavailable, temporarily or even permanently." " one provider becomes unavailable, temporarily or even permanently."
msgstr "Ohitura ona da zure kontua hornitzaile bati baino gehiagori konektatzea, hornitzaileren bat erabilgarri ez badago, aldi baterako edo baita betiko." msgstr "Ohitura ona da zure kontua hornitzaile bati baino gehiagori konektatzea, hornitzaileren bat erabilgarri ez badago, aldi baterako edo baita betiko."
#: templates/auth/user_stars.html:8 #: templates/auth/user_stars.html:6
#, python-format
msgid "%(current_user)ss starred maps"
msgstr "%(current_user)s-ren mapa izardunak"
#: templates/auth/user_stars.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's starred maps" msgid "Browse %(current_user)s's starred maps"
msgstr "Arakatu %(current_user)s erabiltzailearen gogoko mapak" msgstr "Arakatu %(current_user)s erabiltzailearen gogoko mapak"
#: templates/auth/user_stars.html:17 #: templates/auth/user_stars.html:21
#, python-format #, python-format
msgid "%(current_user)s has no starred maps yet." msgid "%(current_user)s has no starred maps yet."
msgstr "%(current_user)s erabiltzaileak ez du gogoko maparik oraindik." msgstr "%(current_user)s erabiltzaileak ez du gogoko maparik oraindik."
@ -242,6 +264,10 @@ msgstr "Pasahitza"
msgid "Please choose a provider:" msgid "Please choose a provider:"
msgstr "Aukeratu hornitzaile bat:" msgstr "Aukeratu hornitzaile bat:"
#: templates/umap/about.html:5 templates/umap/navigation.html:22
msgid "About"
msgstr "Honi buruz"
#: templates/umap/about_summary.html:12 #: templates/umap/about_summary.html:12
#, python-format #, python-format
msgid "" msgid ""
@ -401,7 +427,7 @@ msgstr "Inspira zaitez dauden mapak arakatzen"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Sartu egin zara. Jarraitu..." msgstr "Sartu egin zara. Jarraitu..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:11 views.py:438
msgid "by" msgid "by"
msgstr "nork eginda" msgstr "nork eginda"
@ -409,7 +435,7 @@ msgstr "nork eginda"
msgid "More" msgid "More"
msgstr "Gehiago" msgstr "Gehiago"
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:14 #: templates/umap/map_table.html:8 templates/umap/user_teams.html:18
msgid "Name" msgid "Name"
msgstr "Izena" msgstr "Izena"
@ -427,13 +453,13 @@ msgstr "Nork edita dezake"
#: templates/umap/map_table.html:20 #: templates/umap/map_table.html:20
msgid "Last save" msgid "Last save"
msgstr "Azken gordetzea" msgstr "Gordetako azkena"
#: templates/umap/map_table.html:23 #: templates/umap/map_table.html:23
msgid "Owner" msgid "Owner"
msgstr "Jabea" msgstr "Jabea"
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:20 #: templates/umap/map_table.html:26 templates/umap/user_teams.html:24
msgid "Actions" msgid "Actions"
msgstr "Ekintzak" msgstr "Ekintzak"
@ -446,7 +472,7 @@ msgid "Share"
msgstr "Partekatu" msgstr "Partekatu"
#: templates/umap/map_table.html:78 templates/umap/map_table.html:80 #: templates/umap/map_table.html:78 templates/umap/map_table.html:80
#: templates/umap/user_teams.html:38 templates/umap/user_teams.html:40 #: templates/umap/user_teams.html:42 templates/umap/user_teams.html:44
msgid "Edit" msgid "Edit"
msgstr "Editatu" msgstr "Editatu"
@ -509,10 +535,6 @@ msgstr "Sartu"
msgid "Sign in" msgid "Sign in"
msgstr "Izena eman" msgstr "Izena eman"
#: templates/umap/navigation.html:22
msgid "About"
msgstr "Honi buruz"
#: templates/umap/navigation.html:30 #: templates/umap/navigation.html:30
msgid "Change password" msgid "Change password"
msgstr "Aldatu pasahitza" msgstr "Aldatu pasahitza"
@ -521,52 +543,58 @@ msgstr "Aldatu pasahitza"
msgid "Log out" msgid "Log out"
msgstr "Irten" msgstr "Irten"
#: templates/umap/password_change.html:7 #: templates/umap/password_change.html:6
#: templates/umap/password_change.html:11
msgid "Password change" msgid "Password change"
msgstr "Pasahiz aldaketa" msgstr "Pasahiz aldaketa"
#: templates/umap/password_change.html:10 #: templates/umap/password_change.html:14
msgid "" msgid ""
"Please enter your old password, for security's sake, and then enter your new" "Please enter your old password, for security's sake, and then enter your new"
" password twice so we can verify you typed it in correctly." " password twice so we can verify you typed it in correctly."
msgstr "Idatzi zure pasahitz zaharra, eta ondoren zure pasahitz berria birritan, horrela ondo sartu duzula egiaztatuko dugu." msgstr "Idatzi zure pasahitz zaharra, eta ondoren zure pasahitz berria birritan, horrela ondo sartu duzula egiaztatuko dugu."
#: templates/umap/password_change.html:17 #: templates/umap/password_change.html:21
msgid "Old password" msgid "Old password"
msgstr "Pasahitz zaharra" msgstr "Pasahitz zaharra"
#: templates/umap/password_change.html:22 #: templates/umap/password_change.html:26
msgid "New password" msgid "New password"
msgstr "Pasahitz berria" msgstr "Pasahitz berria"
#: templates/umap/password_change.html:26 #: templates/umap/password_change.html:30
msgid "New password confirmation" msgid "New password confirmation"
msgstr "Pasahitz berriaren egiaztapena" msgstr "Pasahitz berriaren egiaztapena"
#: templates/umap/password_change.html:27 #: templates/umap/password_change.html:31
msgid "Change my password" msgid "Change my password"
msgstr "Aldatu nire pasahitza" msgstr "Aldatu nire pasahitza"
#: templates/umap/password_change_done.html:7 #: templates/umap/password_change_done.html:6
#: templates/umap/password_change_done.html:11
msgid "Password change successful" msgid "Password change successful"
msgstr "Pasahitza ondo aldatu da" msgstr "Pasahitza ondo aldatu da"
#: templates/umap/password_change_done.html:10 #: templates/umap/password_change_done.html:14
msgid "Your password was changed." msgid "Your password was changed."
msgstr "Zure pasahitza aldatu egin da" msgstr "Zure pasahitza aldatu egin da"
#: templates/umap/search.html:15 #: templates/umap/search.html:6
msgid "Explore maps"
msgstr "Arakatu mapak"
#: templates/umap/search.html:19
#, python-format #, python-format
msgid "%(count)s map found:" msgid "%(count)s map found:"
msgid_plural "%(count)s maps found:" msgid_plural "%(count)s maps found:"
msgstr[0] "mapa %(count)s aurkitu da:" msgstr[0] "mapa %(count)s aurkitu da:"
msgstr[1] "%(count)s mapa aurkitu dira:" msgstr[1] "%(count)s mapa aurkitu dira:"
#: templates/umap/search.html:24 #: templates/umap/search.html:28
msgid "No map found." msgid "No map found."
msgstr "Ez da maparik aurkitu" msgstr "Ez da maparik aurkitu"
#: templates/umap/search.html:29 #: templates/umap/search.html:33
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Sortutako azken mapak" msgstr "Sortutako azken mapak"
@ -574,25 +602,38 @@ msgstr "Sortutako azken mapak"
msgid "Search maps" msgid "Search maps"
msgstr "Bilatu mapak" msgstr "Bilatu mapak"
#: templates/umap/search_bar.html:15 #: templates/umap/search_bar.html:16
msgid "Search" msgid "Search"
msgstr "Bilatu" msgstr "Bilatu"
#: templates/umap/team_detail.html:10 #: templates/umap/team_confirm_delete.html:6
msgid "Team deletion"
msgstr "Taldea ezabatzea"
#: templates/umap/team_detail.html:6
#, python-format
msgid "%(current_team)ss maps"
msgstr "%(current_team)s-ren mapak"
#: templates/umap/team_detail.html:14
#, python-format #, python-format
msgid "Browse %(current_team)s's maps" msgid "Browse %(current_team)s's maps"
msgstr "Arakatu %(current_team)s-ren mapak" msgstr "Arakatu %(current_team)s-ren mapak"
#: templates/umap/team_detail.html:22 #: templates/umap/team_detail.html:26
#, python-format #, python-format
msgid "%(current_team)s has no public maps." msgid "%(current_team)s has no public maps."
msgstr "%(current_team)s-k ez dauka mapa publikorik." msgstr "%(current_team)s-k ez dauka mapa publikorik."
#: templates/umap/team_form.html:24 #: templates/umap/team_form.html:6
msgid "Create or edit a team"
msgstr "Sortu edo editatu talde bat"
#: templates/umap/team_form.html:28
msgid "Delete this team" msgid "Delete this team"
msgstr "Ezabatu talde hau" msgstr "Ezabatu talde hau"
#: templates/umap/team_form.html:47 #: templates/umap/team_form.html:51
msgid "Add user" msgid "Add user"
msgstr "Gehitu erabiltzailea" msgstr "Gehitu erabiltzailea"
@ -613,78 +654,82 @@ msgstr "Deskargatu %(count)s mapa"
msgid "You have no map yet." msgid "You have no map yet."
msgstr "Oraindik ez daukazu maparik." msgstr "Oraindik ez daukazu maparik."
#: templates/umap/user_teams.html:17 #: templates/umap/user_teams.html:6
msgid "My Teams"
msgstr "Nire taldeak"
#: templates/umap/user_teams.html:21
msgid "Users" msgid "Users"
msgstr "Erabiltzaileak" msgstr "Erabiltzaileak"
#: templates/umap/user_teams.html:48 #: templates/umap/user_teams.html:52
msgid "New team" msgid "New team"
msgstr "Talde berria" msgstr "Talde berria"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "Ezin da ezabatu kide bat baino gehiago dituen talde bat" msgstr "Ezin da ezabatu kide bat baino gehiago dituen talde bat"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "“%(name)s” taldea ezabatu da" msgstr "“%(name)s” taldea ezabatu da"
#: views.py:442 #: views.py:443
msgid "View the map" msgid "View the map"
msgstr "Mapa ikusi" msgstr "Mapa ikusi"
#: views.py:825 #: views.py:839
msgid "See full screen" msgid "See full screen"
msgstr "Ikusi pantaila osoan" msgstr "Ikusi pantaila osoan"
#: views.py:968 #: views.py:982
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Maparen editoreak ondo eguneratu dira!" msgstr "Maparen editoreak ondo eguneratu dira!"
#: views.py:1004 #: views.py:1018
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "Zure mapa editatzeko uMap-en esteka: %(map_name)s" msgstr "Zure mapa editatzeko uMap-en esteka: %(map_name)s"
#: views.py:1007 #: views.py:1021
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Hona hemen zure editatzeko esteka sekretua:: %(link)s" msgstr "Hona hemen zure editatzeko esteka sekretua:: %(link)s"
#: views.py:1014 #: views.py:1028
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "Ezin da posta elektronikorik bidali %(email)s-ri" msgstr "Ezin da posta elektronikorik bidali %(email)s-ri"
#: views.py:1017 #: views.py:1031
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "Posta elektronikoa bidalita %(email)s-ri" msgstr "Posta elektronikoa bidalita %(email)s-ri"
#: views.py:1028 #: views.py:1042
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Jabeak bakarrik ezabatu dezake mapa." msgstr "Jabeak bakarrik ezabatu dezake mapa."
#: views.py:1031 #: views.py:1045
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "Mapa behar bezala ezabatu da." msgstr "Mapa behar bezala ezabatu da."
#: views.py:1057 #: views.py:1071
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Zure mapa klonatu egin da! Mapa hau beste nabigatzaile batetik editatzeko erabili esteka hau: %(anonymous_url)s" msgstr "Zure mapa klonatu egin da! Mapa hau beste nabigatzaile batetik editatzeko erabili esteka hau: %(anonymous_url)s"
#: views.py:1062 #: views.py:1076
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Zorionak, zure mapa ondo klonatu da!" msgstr "Zorionak, zure mapa ondo klonatu da!"
#: views.py:1313 #: views.py:1330
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Geruza ondo ezabatu da." msgstr "Geruza ondo ezabatu da."
#: views.py:1335 #: views.py:1352
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "Baimenak behar bezala eguneratu dira!" msgstr "Baimenak behar bezala eguneratu dira!"

Binary file not shown.

View file

@ -24,7 +24,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n" "POT-Creation-Date: 2025-04-11 15:30+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: yohanboniface <yohanboniface@free.fr>, 2013-2014,2018-2019,2023-2025\n" "Last-Translator: yohanboniface <yohanboniface@free.fr>, 2013-2014,2018-2019,2023-2025\n"
"Language-Team: French (http://app.transifex.com/openstreetmap/umap/language/fr/)\n" "Language-Team: French (http://app.transifex.com/openstreetmap/umap/language/fr/)\n"
@ -51,137 +51,205 @@ msgstr "Le site est en lecture seule pour maintenance."
msgid "" msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. " "Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account" "Please configure another provider below before losing access to your account"
" and maps." " and maps. Then, please logout and login again with the new provider."
msgstr "Lutilisation de “%(name)s” pour sauthentifier est dépréciée et sera bientôt rendue impossible. Veuillez configurer un nouveau fournisseur ci-dessous avant de perdre laccès à votre compte et à vos cartes." msgstr "Lutilisation de “%(name)s” pour sauthentifier est dépréciée et sera bientôt rendue impossible. Veuillez configurer un nouveau fournisseur ci-dessous avant de perdre laccès à votre compte et à vos cartes. Puis veuillez vous déconnecter et reconnecter avec le nouveau fournisseur."
#: models.py:60 models.py:79 #: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
#: models.py:62 models.py:485 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "description" msgstr "description"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "détails" msgstr "détails"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Lien vers une page détaillant la licence." msgstr "Lien vers une page détaillant la licence."
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "Modèle d'URL au format des tuiles OSM" msgstr "Modèle d'URL au format des tuiles OSM"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Ordre des calques de tuiles dans le panneau de modification" msgstr "Ordre des calques de tuiles dans le panneau de modification"
#: models.py:175 models.py:479 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Modifiable seulement avec le lien de modification secret" msgstr "Modifiable seulement avec le lien de modification secret"
#: models.py:176 models.py:480 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Tout le monde peut modifier" msgstr "Tout le monde peut modifier"
#: models.py:179 models.py:473 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "Tout le monde" msgstr "Tout le monde"
#: models.py:180 models.py:189 models.py:474 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Éditeurs et équipe seulement" msgstr "Éditeurs et équipe seulement"
#: models.py:181 models.py:475 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "Propriétaire uniquement" msgstr "Propriétaire uniquement"
#: models.py:184 #: models.py:185
msgid "Draft (private)" msgid "Draft (private)"
msgstr "Brouillon (privé)" msgstr "Brouillon (privé)"
#: models.py:185 #: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "Tout le monde (public)" msgstr "Tout le monde (public)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "Quiconque a le lien" msgstr "Quiconque a le lien"
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "Bloquée" msgstr "Bloquée"
#: models.py:191 models.py:469 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "Supprimé" msgstr "Supprimé"
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "centre" msgstr "centre"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "zoom" msgstr "zoom"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "géolocaliser" msgstr "géolocaliser"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Géolocaliser l'utilisateur au chargement ?" msgstr "Géolocaliser l'utilisateur au chargement ?"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Choisir une licence pour la carte" msgstr "Choisir une licence pour la carte"
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "licence" msgstr "licence"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "créateur" msgstr "créateur"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "éditeurs" msgstr "éditeurs"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "équipe" msgstr "équipe"
#: models.py:229 models.py:501 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "statut de modification" msgstr "statut de modification"
#: models.py:234 models.py:506 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "qui a accès" msgstr "qui a accès"
#: models.py:237 models.py:496 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "réglages" msgstr "réglages"
#: models.py:407 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Clone de" msgstr "Clone de"
#: models.py:468 models.py:472 models.py:478 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "Par défaut" msgstr "Par défaut"
#: models.py:491 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "afficher au chargement." msgstr "afficher au chargement."
#: models.py:492 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Afficher ce calque au chargement." msgstr "Afficher ce calque au chargement."
#: settings/base.py:295
msgid "Art and Culture"
msgstr "Art et culture"
#: settings/base.py:296
msgid "Cycling"
msgstr "Vélo"
#: settings/base.py:297
msgid "Business"
msgstr "Économie"
#: settings/base.py:298
msgid "Environment"
msgstr "Environnement"
#: settings/base.py:299
msgid "Education"
msgstr "Éducation"
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr "Nourriture et agriculture"
#: settings/base.py:301
msgid "Geopolitics"
msgstr "Géopolitique"
#: settings/base.py:302
msgid "Health"
msgstr "Santé"
#: settings/base.py:303
msgid "Hiking"
msgstr "Rando"
#: settings/base.py:304
msgid "History"
msgstr "Histoire"
#: settings/base.py:305
msgid "Public sector"
msgstr "Secteur public"
#: settings/base.py:306
msgid "Science"
msgstr "Science"
#: settings/base.py:307
msgid "Shopping"
msgstr "Commerces"
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr "Sport et loisirs"
#: settings/base.py:309
msgid "Travel"
msgstr "Voyage"
#: settings/base.py:310
msgid "Transports"
msgstr "Transports"
#: settings/base.py:311
msgid "Tourism"
msgstr "Tourisme"
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -434,7 +502,7 @@ msgstr "Mes équipes"
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "La carte des uMaps" msgstr "La carte des uMaps"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Naviguer dans les cartes" msgstr "Naviguer dans les cartes"
@ -442,11 +510,15 @@ msgstr "Naviguer dans les cartes"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Vous êtes maintenant identifié. Merci de patienter..." msgstr "Vous êtes maintenant identifié. Merci de patienter..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "par" msgstr "par"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Voir la carte"
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Plus" msgstr "Plus"
@ -606,11 +678,15 @@ msgstr[0] "%(count)s carte trouvée:"
msgstr[1] "%(count)s cartes trouvées:" msgstr[1] "%(count)s cartes trouvées:"
msgstr[2] "%(count)s cartes trouvées :" msgstr[2] "%(count)s cartes trouvées :"
#: templates/umap/search.html:28 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "Aucune carte trouvée." msgstr "Aucune carte trouvée."
#: templates/umap/search.html:33 #: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr "Dernières cartes créées dans la catégorie"
#: templates/umap/search.html:43
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Dernières cartes créées." msgstr "Dernières cartes créées."
@ -618,7 +694,11 @@ msgstr "Dernières cartes créées."
msgid "Search maps" msgid "Search maps"
msgstr "Chercher des cartes" msgstr "Chercher des cartes"
#: templates/umap/search_bar.html:16 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Toutes catégories"
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Chercher" msgstr "Chercher"
@ -682,70 +762,70 @@ msgstr "Membres"
msgid "New team" msgid "New team"
msgstr "Nouvelle équipe" msgstr "Nouvelle équipe"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "Impossible de supprimer une équipe ayant plus d'un membre" msgstr "Impossible de supprimer une équipe ayant plus d'un membre"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "L'équipe «%(name)s» a été supprimée" msgstr "L'équipe «%(name)s» a été supprimée"
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Voir la carte" msgstr "Voir la carte"
#: views.py:838 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "Plein écran" msgstr "Plein écran"
#: views.py:981 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Éditeurs de la carte mis à jour !" msgstr "Éditeurs de la carte mis à jour !"
#: views.py:1017 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "Le lien d'édition uMap pour votre carte : %(map_name)s" msgstr "Le lien d'édition uMap pour votre carte : %(map_name)s"
#: views.py:1020 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Voici votre lien d'édition secret : %(link)s" msgstr "Voici votre lien d'édition secret : %(link)s"
#: views.py:1027 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "Impossible d'envoyer un courriel vers %(email)s" msgstr "Impossible d'envoyer un courriel vers %(email)s"
#: views.py:1030 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "Courriel envoyé à %(email)s" msgstr "Courriel envoyé à %(email)s"
#: views.py:1041 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Seul le créateur de la carte peut la supprimer." msgstr "Seul le créateur de la carte peut la supprimer."
#: views.py:1044 #: views.py:1054
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "La carte a bien été supprimée." msgstr "La carte a bien été supprimée."
#: views.py:1070 #: views.py:1080
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Votre carte a été dupliquée ! Si vous souhaitez la modifier depuis un autre ordinateur, veuillez utiliser ce lien : %(anonymous_url)s" msgstr "Votre carte a été dupliquée ! Si vous souhaitez la modifier depuis un autre ordinateur, veuillez utiliser ce lien : %(anonymous_url)s"
#: views.py:1075 #: views.py:1085
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Votre carte a été dupliquée !" msgstr "Votre carte a été dupliquée !"
#: views.py:1329 #: views.py:1339
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Calque supprimé." msgstr "Calque supprimé."
#: views.py:1351 #: views.py:1361
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "Les permissions ont bien été modifiées !" msgstr "Les permissions ont bien été modifiées !"

Binary file not shown.

View file

@ -3,15 +3,15 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2024 # Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2025
# Peter Velosy <peter.velosy@gmail.com>, 2017 # Peter Velosy <peter.velosy@gmail.com>, 2017
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-24 08:39+0000\n" "POT-Creation-Date: 2025-04-04 16:49+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2024\n" "Last-Translator: Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2025\n"
"Language-Team: Hungarian (http://app.transifex.com/openstreetmap/umap/language/hu/)\n" "Language-Team: Hungarian (http://app.transifex.com/openstreetmap/umap/language/hu/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -27,138 +27,214 @@ msgstr "CSV exportálás"
msgid "This map is not publicly available" msgid "This map is not publicly available"
msgstr "Ez a térkép nem nyilvános" msgstr "Ez a térkép nem nyilvános"
#: middleware.py:13 #: middleware.py:19
msgid "Site is readonly for maintenance" msgid "Site is readonly for maintenance"
msgstr "Karbantartás miatt a webhely csak olvasható" msgstr "Karbantartás miatt a webhely csak olvasható"
#: models.py:60 models.py:79 #: middleware.py:34
#, python-format
msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account"
" and maps. Then, please logout and login again with the new provider."
msgstr "A „%(name)s” használata a hitelesítéshez elavult, és hamarosan eltávolításra kerül. Kérjük, állítson be egy másik szolgáltatót az alábbiakban, mielőtt elveszítené a fiókjához és a térképekhez való hozzáférést. Ezután jelentkezzen ki, majd jelentkezzen be újra az új szolgáltatóval."
#: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "név" msgstr "név"
#: models.py:62 models.py:475 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "leírás" msgstr "leírás"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "részletek" msgstr "részletek"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Link egy részletes licencinformációkat tartalmazó lapra." msgstr "Link egy részletes licencinformációkat tartalmazó lapra."
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "OSM-csempeformátumot használó URL-sablon" msgstr "OSM-csempeformátumot használó URL-sablon"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Csemperétegek sorrendje a szerkesztődobozban" msgstr "Csemperétegek sorrendje a szerkesztődobozban"
#: models.py:175 models.py:469 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Kizárólag titkos szerkesztési linkkel szerkeszthető" msgstr "Kizárólag titkos szerkesztési linkkel szerkeszthető"
#: models.py:176 models.py:470 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Bárki szerkesztheti" msgstr "Bárki szerkesztheti"
#: models.py:179 models.py:463 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "Mindenki" msgstr "Mindenki"
#: models.py:180 models.py:189 models.py:464 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Csak a szerkesztők és a csoport" msgstr "Csak a szerkesztők és a csoport"
#: models.py:181 models.py:465 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "Csak a tulajdonos" msgstr "Csak a tulajdonos"
#: models.py:184 #: models.py:185
msgid "Draft (private)" msgid "Draft (private)"
msgstr "Piszkozat (privát)" msgstr "Piszkozat (privát)"
#: models.py:185 #: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "Mindenki (nyilvános)" msgstr "Mindenki (nyilvános)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "A link birtokában bárki" msgstr "A link birtokában bárki"
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "Blokkolva" msgstr "Blokkolva"
#: models.py:191 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "Törölve" msgstr "Törölve"
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "középpont" msgstr "középpont"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "nagyítás" msgstr "nagyítás"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "helymeghatározás" msgstr "helymeghatározás"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Bekérje a felhasználó pozícióját betöltéskor?" msgstr "Bekérje a felhasználó pozícióját betöltéskor?"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Térképlicenc kiválasztása" msgstr "Térképlicenc kiválasztása"
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "licenc" msgstr "licenc"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "tulajdonos" msgstr "tulajdonos"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "szerkesztők" msgstr "szerkesztők"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "csoport" msgstr "csoport"
#: models.py:229 models.py:491 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "szerkeszthetőség" msgstr "szerkeszthetőség"
#: models.py:234 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "megoszthatóság" msgstr "megoszthatóság"
#: models.py:237 models.py:486 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "beállítások" msgstr "beállítások"
#: models.py:402 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Másolat erről: " msgstr "Másolat erről: "
#: models.py:462 models.py:468 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "Öröklés" msgstr "Öröklés"
#: models.py:481 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "megjelenítés betöltéskor" msgstr "megjelenítés betöltéskor"
#: models.py:482 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Réteg megjelenítése betöltéskor" msgstr "Réteg megjelenítése betöltéskor"
#: settings/base.py:295
msgid "Art and Culture"
msgstr ""
#: settings/base.py:296
msgid "Cycling"
msgstr ""
#: settings/base.py:297
msgid "Business"
msgstr ""
#: settings/base.py:298
msgid "Environment"
msgstr ""
#: settings/base.py:299
msgid "Education"
msgstr ""
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr ""
#: settings/base.py:301
msgid "Geopolitics"
msgstr ""
#: settings/base.py:302
msgid "Health"
msgstr ""
#: settings/base.py:303
msgid "Hiking"
msgstr ""
#: settings/base.py:304
msgid "History"
msgstr ""
#: settings/base.py:305
msgid "Public sector"
msgstr ""
#: settings/base.py:306
msgid "Science"
msgstr ""
#: settings/base.py:307
msgid "Shopping"
msgstr ""
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr ""
#: settings/base.py:309
msgid "Travel"
msgstr ""
#: settings/base.py:310
msgid "Transports"
msgstr ""
#: settings/base.py:311
msgid "Tourism"
msgstr ""
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -174,40 +250,54 @@ msgstr "← Ugrás a főoldalra"
msgid "404 Page Not Found" msgid "404 Page Not Found"
msgstr "404 hiba: ez az oldal nem található. Eltévedtél a térképek között" msgstr "404 hiba: ez az oldal nem található. Eltévedtél a térképek között"
#: templates/auth/user_detail.html:8 #: templates/auth/user_detail.html:6
#, python-format
msgid "%(current_user)ss maps"
msgstr "%(current_user)s térképei"
#: templates/auth/user_detail.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's maps" msgid "Browse %(current_user)s's maps"
msgstr "%(current_user)s térképeinek böngészése" msgstr "%(current_user)s térképeinek böngészése"
#: templates/auth/user_detail.html:17 #: templates/auth/user_detail.html:21
#, python-format #, python-format
msgid "%(current_user)s has no maps." msgid "%(current_user)s has no maps."
msgstr "%(current_user)s felhasználónak nincs térképe." msgstr "%(current_user)s felhasználónak nincs térképe."
#: templates/auth/user_form.html:21 templates/umap/team_form.html:21 #: templates/auth/user_form.html:6
msgid "My Profile"
msgstr "Profilom"
#: templates/auth/user_form.html:24 templates/umap/team_form.html:25
msgid "Save" msgid "Save"
msgstr "Mentés" msgstr "Mentés"
#: templates/auth/user_form.html:27 #: templates/auth/user_form.html:30
msgid "Your current providers" msgid "Your current providers"
msgstr "Jelenlegi szolgáltatói" msgstr "Jelenlegi szolgáltatói"
#: templates/auth/user_form.html:39 #: templates/auth/user_form.html:44
msgid "Connect to another provider" msgid "Connect to another provider"
msgstr "Újabb szolgáltató csatlakoztatása" msgstr "Újabb szolgáltató csatlakoztatása"
#: templates/auth/user_form.html:42 #: templates/auth/user_form.html:47
msgid "" msgid ""
"It's a good habit to connect your account to more than one provider, in case" "It's a good habit to connect your account to more than one provider, in case"
" one provider becomes unavailable, temporarily or even permanently." " one provider becomes unavailable, temporarily or even permanently."
msgstr "Jó szokás, ha fiókját több szolgáltatóhoz is hozzáköti, ha esetleg az egyik szolgáltató átmenetileg vagy akár véglegesen elérhetetlenné válna." msgstr "Jó szokás, ha fiókját több szolgáltatóhoz is hozzáköti, ha esetleg az egyik szolgáltató átmenetileg vagy akár véglegesen elérhetetlenné válna."
#: templates/auth/user_stars.html:8 #: templates/auth/user_stars.html:6
#, python-format
msgid "%(current_user)ss starred maps"
msgstr "%(current_user)s megcsillagozott térképei"
#: templates/auth/user_stars.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's starred maps" msgid "Browse %(current_user)s's starred maps"
msgstr "%(current_user)s megcsillagozott térképeinek böngészése" msgstr "%(current_user)s megcsillagozott térképeinek böngészése"
#: templates/auth/user_stars.html:17 #: templates/auth/user_stars.html:21
#, python-format #, python-format
msgid "%(current_user)s has no starred maps yet." msgid "%(current_user)s has no starred maps yet."
msgstr "%(current_user)s felhasználónak még nincs megcsillagozott térképe." msgstr "%(current_user)s felhasználónak még nincs megcsillagozott térképe."
@ -242,6 +332,10 @@ msgstr "Jelszó"
msgid "Please choose a provider:" msgid "Please choose a provider:"
msgstr "Válassz egy szolgáltatót:" msgstr "Válassz egy szolgáltatót:"
#: templates/umap/about.html:5 templates/umap/navigation.html:22
msgid "About"
msgstr "Névjegy"
#: templates/umap/about_summary.html:12 #: templates/umap/about_summary.html:12
#, python-format #, python-format
msgid "" msgid ""
@ -383,7 +477,7 @@ msgstr "Térképeim"
#: templates/umap/dashboard_menu.html:12 #: templates/umap/dashboard_menu.html:12
msgid "My profile" msgid "My profile"
msgstr "Saját profil" msgstr "Profilom"
#: templates/umap/dashboard_menu.html:15 #: templates/umap/dashboard_menu.html:15
msgid "My teams" msgid "My teams"
@ -393,7 +487,7 @@ msgstr "Csoportjaim"
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "uMap-térképek térképe" msgstr "uMap-térképek térképe"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Szerezzen ihletet, böngésszen a térképek között!" msgstr "Szerezzen ihletet, böngésszen a térképek között!"
@ -401,15 +495,19 @@ msgstr "Szerezzen ihletet, böngésszen a térképek között!"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Be van jelentkezve. Továbblépés…" msgstr "Be van jelentkezve. Továbblépés…"
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr " készítette:" msgstr " készítette:"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr ""
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Még több" msgstr "Még több"
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:14 #: templates/umap/map_table.html:8 templates/umap/user_teams.html:18
msgid "Name" msgid "Name"
msgstr "Név" msgstr "Név"
@ -433,7 +531,7 @@ msgstr "Utolsó mentés"
msgid "Owner" msgid "Owner"
msgstr "Tulajdonos" msgstr "Tulajdonos"
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:20 #: templates/umap/map_table.html:26 templates/umap/user_teams.html:24
msgid "Actions" msgid "Actions"
msgstr "Műveletek" msgstr "Műveletek"
@ -446,7 +544,7 @@ msgid "Share"
msgstr "Megosztás" msgstr "Megosztás"
#: templates/umap/map_table.html:78 templates/umap/map_table.html:80 #: templates/umap/map_table.html:78 templates/umap/map_table.html:80
#: templates/umap/user_teams.html:38 templates/umap/user_teams.html:40 #: templates/umap/user_teams.html:42 templates/umap/user_teams.html:44
msgid "Edit" msgid "Edit"
msgstr "Szerkesztés" msgstr "Szerkesztés"
@ -509,10 +607,6 @@ msgstr "Bejelentkezés"
msgid "Sign in" msgid "Sign in"
msgstr "Regisztráció" msgstr "Regisztráció"
#: templates/umap/navigation.html:22
msgid "About"
msgstr "Névjegy"
#: templates/umap/navigation.html:30 #: templates/umap/navigation.html:30
msgid "Change password" msgid "Change password"
msgstr "Jelszó módosítása" msgstr "Jelszó módosítása"
@ -521,52 +615,58 @@ msgstr "Jelszó módosítása"
msgid "Log out" msgid "Log out"
msgstr "Kijelentkezés" msgstr "Kijelentkezés"
#: templates/umap/password_change.html:7 #: templates/umap/password_change.html:6
#: templates/umap/password_change.html:11
msgid "Password change" msgid "Password change"
msgstr "Jelszó módosítása" msgstr "Jelszó módosítása"
#: templates/umap/password_change.html:10 #: templates/umap/password_change.html:14
msgid "" msgid ""
"Please enter your old password, for security's sake, and then enter your new" "Please enter your old password, for security's sake, and then enter your new"
" password twice so we can verify you typed it in correctly." " password twice so we can verify you typed it in correctly."
msgstr "Biztonsági okokból írja be a régi jelszavát, majd adja meg kétszer a kívánt új jelszót!" msgstr "Biztonsági okokból írja be a régi jelszavát, majd adja meg kétszer a kívánt új jelszót!"
#: templates/umap/password_change.html:17 #: templates/umap/password_change.html:21
msgid "Old password" msgid "Old password"
msgstr "Régi jelszó" msgstr "Régi jelszó"
#: templates/umap/password_change.html:22 #: templates/umap/password_change.html:26
msgid "New password" msgid "New password"
msgstr "Új jelszó" msgstr "Új jelszó"
#: templates/umap/password_change.html:26 #: templates/umap/password_change.html:30
msgid "New password confirmation" msgid "New password confirmation"
msgstr "Új jelszó ismét" msgstr "Új jelszó ismét"
#: templates/umap/password_change.html:27 #: templates/umap/password_change.html:31
msgid "Change my password" msgid "Change my password"
msgstr "Jelszavam módosítása" msgstr "Jelszavam módosítása"
#: templates/umap/password_change_done.html:7 #: templates/umap/password_change_done.html:6
#: templates/umap/password_change_done.html:11
msgid "Password change successful" msgid "Password change successful"
msgstr "A jelszómódosítás sikeres" msgstr "A jelszómódosítás sikeres"
#: templates/umap/password_change_done.html:10 #: templates/umap/password_change_done.html:14
msgid "Your password was changed." msgid "Your password was changed."
msgstr "A jelszava megváltozott." msgstr "A jelszava megváltozott."
#: templates/umap/search.html:15 #: templates/umap/search.html:6
msgid "Explore maps"
msgstr "Térképek felfedezése"
#: templates/umap/search.html:19
#, python-format #, python-format
msgid "%(count)s map found:" msgid "%(count)s map found:"
msgid_plural "%(count)s maps found:" msgid_plural "%(count)s maps found:"
msgstr[0] "%(count)s térképet találtunk:" msgstr[0] "%(count)s térképet találtunk:"
msgstr[1] "%(count)s térképet találtunk:" msgstr[1] "%(count)s térképet találtunk:"
#: templates/umap/search.html:24 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "Nem található ilyen térkép." msgstr "Nem található ilyen térkép."
#: templates/umap/search.html:29 #: templates/umap/search.html:35
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Legutóbb létrehozott térképek" msgstr "Legutóbb létrehozott térképek"
@ -574,25 +674,42 @@ msgstr "Legutóbb létrehozott térképek"
msgid "Search maps" msgid "Search maps"
msgstr "Térképek keresése" msgstr "Térképek keresése"
#: templates/umap/search_bar.html:15 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr ""
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Keresés" msgstr "Keresés"
#: templates/umap/team_detail.html:10 #: templates/umap/team_confirm_delete.html:6
msgid "Team deletion"
msgstr "Csoport törlése"
#: templates/umap/team_detail.html:6
#, python-format
msgid "%(current_team)ss maps"
msgstr "%(current_team)s csoport térképei"
#: templates/umap/team_detail.html:14
#, python-format #, python-format
msgid "Browse %(current_team)s's maps" msgid "Browse %(current_team)s's maps"
msgstr "%(current_team)s csoport térképeinek böngészése" msgstr "%(current_team)s csoport térképeinek böngészése"
#: templates/umap/team_detail.html:22 #: templates/umap/team_detail.html:26
#, python-format #, python-format
msgid "%(current_team)s has no public maps." msgid "%(current_team)s has no public maps."
msgstr "%(current_team)s csoportnak nincs nyilvános térképe." msgstr "%(current_team)s csoportnak nincs nyilvános térképe."
#: templates/umap/team_form.html:24 #: templates/umap/team_form.html:6
msgid "Create or edit a team"
msgstr "Csoport létrehozása vagy szerkesztése"
#: templates/umap/team_form.html:28
msgid "Delete this team" msgid "Delete this team"
msgstr "Csoport törlése" msgstr "Csoport törlése"
#: templates/umap/team_form.html:47 #: templates/umap/team_form.html:51
msgid "Add user" msgid "Add user"
msgstr "Felhasználó hozzáadása" msgstr "Felhasználó hozzáadása"
@ -613,78 +730,82 @@ msgstr "%(count)s térkép letöltése"
msgid "You have no map yet." msgid "You have no map yet."
msgstr "Önnek még nincs térképe." msgstr "Önnek még nincs térképe."
#: templates/umap/user_teams.html:17 #: templates/umap/user_teams.html:6
msgid "My Teams"
msgstr "Csoportjaim"
#: templates/umap/user_teams.html:21
msgid "Users" msgid "Users"
msgstr "Felhasználók" msgstr "Felhasználók"
#: templates/umap/user_teams.html:48 #: templates/umap/user_teams.html:52
msgid "New team" msgid "New team"
msgstr "Új csoport" msgstr "Új csoport"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "Egynél több tagú csoport nem törölhető" msgstr "Egynél több tagú csoport nem törölhető"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "%(name)s csoport törölve" msgstr "%(name)s csoport törölve"
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Térkép megtekintése" msgstr "Térkép megtekintése"
#: views.py:825 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "Teljes képernyős nézet megtekintése" msgstr "Teljes képernyős nézet megtekintése"
#: views.py:968 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "A térképszerkesztők sikeresen frissültek." msgstr "A térképszerkesztők sikeresen frissültek."
#: views.py:1004 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "A térképéhez tartozó uMap szerkesztési link: %(map_name)s" msgstr "A térképéhez tartozó uMap szerkesztési link: %(map_name)s"
#: views.py:1007 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Az Ön titkos szerkesztési linkje: %(link)s" msgstr "Az Ön titkos szerkesztési linkje: %(link)s"
#: views.py:1014 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "Nem sikerül e-mailt küldeni ide: %(email)s" msgstr "Nem sikerül e-mailt küldeni ide: %(email)s"
#: views.py:1017 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "E-mail elküldve ide: %(email)s" msgstr "E-mail elküldve ide: %(email)s"
#: views.py:1028 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "A térképet csak a tulajdonosa törölheti." msgstr "A térképet csak a tulajdonosa törölheti."
#: views.py:1031 #: views.py:1051
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "Térkép sikeresen törölve." msgstr "Térkép sikeresen törölve."
#: views.py:1057 #: views.py:1077
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Elkészült a térképe másolata. Ha egy másik számítógépről szeretné szerkeszteni, ezt a linket használja: %(anonymous_url)s" msgstr "Elkészült a térképe másolata. Ha egy másik számítógépről szeretné szerkeszteni, ezt a linket használja: %(anonymous_url)s"
#: views.py:1062 #: views.py:1082
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Gratulálunk, elkészült a térképe másolata!" msgstr "Gratulálunk, elkészült a térképe másolata!"
#: views.py:1313 #: views.py:1336
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "A réteg sikeresen törlődött." msgstr "A réteg sikeresen törlődött."
#: views.py:1335 #: views.py:1358
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "Az engedélyek sikeresen frissültek!" msgstr "Az engedélyek sikeresen frissültek!"

Binary file not shown.

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-24 08:39+0000\n" "POT-Creation-Date: 2025-04-04 16:49+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>, 2020\n" "Last-Translator: Sveinn í Felli <sv1@fellsnet.is>, 2020\n"
"Language-Team: Icelandic (http://app.transifex.com/openstreetmap/umap/language/is/)\n" "Language-Team: Icelandic (http://app.transifex.com/openstreetmap/umap/language/is/)\n"
@ -20,202 +20,292 @@ msgstr ""
#: admin.py:16 #: admin.py:16
msgid "CSV Export" msgid "CSV Export"
msgstr "" msgstr "CSV-útflutningur"
#: decorators.py:60 #: decorators.py:60
msgid "This map is not publicly available" msgid "This map is not publicly available"
msgstr "" msgstr "Þetta kort er ekki aðgengilegt opinberlega"
#: middleware.py:13 #: middleware.py:19
msgid "Site is readonly for maintenance" msgid "Site is readonly for maintenance"
msgstr "Vefsvæðið er núna skrifvarið vegna viðhaldsvinnu" msgstr "Vefsvæðið er núna skrifvarið vegna viðhaldsvinnu"
#: models.py:60 models.py:79 #: middleware.py:34
#, python-format
msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account"
" and maps. Then, please logout and login again with the new provider."
msgstr "Notkun á “%(name)s” til auðkenningar er úreld aðferð sem verður fljótlega fjarlægð. Veldu aðra þjónustuveitu hér fyrir neðan áður en þú missir aðgang að aðgangnum þínum kortum. Síðan skaltu skrá þig út og svo aftur inn í gegnum nýju þjónustuveituna."
#: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "nafn" msgstr "nafn"
#: models.py:62 models.py:475 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "lýsing" msgstr "lýsing"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "nánar" msgstr "nánar"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Tengill á síðu þar sem notkunarleyfi er útskýrt." msgstr "Tengill á síðu þar sem notkunarleyfi er útskýrt."
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "URL-sniðmát sem notar OSM-kortatíglasnið" msgstr "URL-sniðmát sem notar OSM-kortatíglasnið"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Röð kortatíglalaga í breytingareitnum" msgstr "Röð kortatíglalaga í breytingareitnum"
#: models.py:175 models.py:469 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Aðeins breytanlegt með leynilegum breytingatengli" msgstr "Aðeins breytanlegt með leynilegum breytingatengli"
#: models.py:176 models.py:470 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Allir geta breytt" msgstr "Allir geta breytt"
#: models.py:179 models.py:463 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "" msgstr "Allir"
#: models.py:180 models.py:189 models.py:464 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "" msgstr "Einungis ritstjórar og teymið"
#: models.py:181 models.py:465 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "" msgstr "Aðeins eigandi"
#: models.py:184
msgid "Draft (private)"
msgstr ""
#: models.py:185 #: models.py:185
msgid "Draft (private)"
msgstr "Drög (einka)"
#: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "" msgstr "Allir (opinbert)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "" msgstr "Hver sá sem er með tengil"
#: models.py:190
msgid "Blocked"
msgstr ""
#: models.py:191 #: models.py:191
msgid "Deleted" msgid "Blocked"
msgstr "" msgstr "Útilokað"
#: models.py:194 #: models.py:192 models.py:477
msgid "Deleted"
msgstr "Eytt"
#: models.py:195
msgid "center" msgid "center"
msgstr "miðja" msgstr "miðja"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "aðdráttur" msgstr "aðdráttur"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "staðsetja" msgstr "staðsetja"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Staðsetja notanda við innhleðslu?" msgstr "Staðsetja notanda við innhleðslu?"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Veldu notkunarleyfi fyrir kortið." msgstr "Veldu notkunarleyfi fyrir kortið."
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "notkunarleyfi" msgstr "notkunarleyfi"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "eigandi" msgstr "eigandi"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "ritstjórar" msgstr "ritstjórar"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "" msgstr "teymi"
#: models.py:229 models.py:491 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "staða vinnslu" msgstr "staða vinnslu"
#: models.py:234 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "staða deilingar" msgstr "staða deilingar"
#: models.py:237 models.py:486 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "stillingar" msgstr "stillingar"
#: models.py:402 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Klón af" msgstr "Klón af"
#: models.py:462 models.py:468 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "" msgstr "Erfa"
#: models.py:481 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "birta við innhleðslu" msgstr "birta við innhleðslu"
#: models.py:482 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Birta þetta lag við innhleðslu." msgstr "Birta þetta lag við innhleðslu."
#: settings/base.py:295
msgid "Art and Culture"
msgstr ""
#: settings/base.py:296
msgid "Cycling"
msgstr ""
#: settings/base.py:297
msgid "Business"
msgstr ""
#: settings/base.py:298
msgid "Environment"
msgstr ""
#: settings/base.py:299
msgid "Education"
msgstr ""
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr ""
#: settings/base.py:301
msgid "Geopolitics"
msgstr ""
#: settings/base.py:302
msgid "Health"
msgstr ""
#: settings/base.py:303
msgid "Hiking"
msgstr ""
#: settings/base.py:304
msgid "History"
msgstr ""
#: settings/base.py:305
msgid "Public sector"
msgstr ""
#: settings/base.py:306
msgid "Science"
msgstr ""
#: settings/base.py:307
msgid "Shopping"
msgstr ""
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr ""
#: settings/base.py:309
msgid "Travel"
msgstr ""
#: settings/base.py:310
msgid "Transports"
msgstr ""
#: settings/base.py:311
msgid "Tourism"
msgstr ""
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
"target=\"_blank\">Find out here the documentation</a> on how to manage maps" "target=\"_blank\">Find out here the documentation</a> on how to manage maps"
" permissions." " permissions."
msgstr "" msgstr "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" target=\"_blank\">Hér geturðu fundið leiðbeiningar</a> um hvernig sé hægt að stýra heimildum landakortsins."
#: templates/403.html:10 templates/404.html:8 #: templates/403.html:10 templates/404.html:8
msgid "← Go to the homepage" msgid "← Go to the homepage"
msgstr "" msgstr "← Fara á heimasíðuna"
#: templates/404.html:7 #: templates/404.html:7
msgid "404 Page Not Found" msgid "404 Page Not Found"
msgstr "" msgstr "404 Síðan finnst ekki"
#: templates/auth/user_detail.html:8 #: templates/auth/user_detail.html:6
#, python-format
msgid "%(current_user)ss maps"
msgstr "Kort frá %(current_user)s"
#: templates/auth/user_detail.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's maps" msgid "Browse %(current_user)s's maps"
msgstr "Skoða landakort frá %(current_user)s" msgstr "Skoða landakort frá %(current_user)s"
#: templates/auth/user_detail.html:17 #: templates/auth/user_detail.html:21
#, python-format #, python-format
msgid "%(current_user)s has no maps." msgid "%(current_user)s has no maps."
msgstr "%(current_user)s er ekki með nein landakort." msgstr "%(current_user)s er ekki með nein landakort."
#: templates/auth/user_form.html:21 templates/umap/team_form.html:21 #: templates/auth/user_form.html:6
msgid "My Profile"
msgstr "Sniðið mitt"
#: templates/auth/user_form.html:24 templates/umap/team_form.html:25
msgid "Save" msgid "Save"
msgstr "" msgstr "Vista"
#: templates/auth/user_form.html:27 #: templates/auth/user_form.html:30
msgid "Your current providers" msgid "Your current providers"
msgstr "" msgstr "Núverandi þjónustur þínar"
#: templates/auth/user_form.html:39 #: templates/auth/user_form.html:44
msgid "Connect to another provider" msgid "Connect to another provider"
msgstr "" msgstr "Tengjast við aðra þjónustu"
#: templates/auth/user_form.html:42 #: templates/auth/user_form.html:47
msgid "" msgid ""
"It's a good habit to connect your account to more than one provider, in case" "It's a good habit to connect your account to more than one provider, in case"
" one provider becomes unavailable, temporarily or even permanently." " one provider becomes unavailable, temporarily or even permanently."
msgstr "" msgstr "Það er góð regla að tengja aðganginn þinn við fleiri en eina þjónustuveitu, fari svo að tiltekin þjónusta verði óaðgengileg, hvort sem er tímabundið eða endanlega."
#: templates/auth/user_stars.html:8 #: templates/auth/user_stars.html:6
#, python-format
msgid "%(current_user)ss starred maps"
msgstr "Stjörnumerkt landakort frá %(current_user)s"
#: templates/auth/user_stars.html:12
#, python-format #, python-format
msgid "Browse %(current_user)s's starred maps" msgid "Browse %(current_user)s's starred maps"
msgstr "" msgstr "Skoða stjörnumerkt landakort frá %(current_user)s"
#: templates/auth/user_stars.html:17 #: templates/auth/user_stars.html:21
#, python-format #, python-format
msgid "%(current_user)s has no starred maps yet." msgid "%(current_user)s has no starred maps yet."
msgstr "" msgstr "%(current_user)s er ekki ennþá með nein stjörnumerkt kort."
#: templates/base.html:13 #: templates/base.html:13
msgid "" msgid ""
"uMap lets you create maps with OpenStreetMap layers in a minute and embed " "uMap lets you create maps with OpenStreetMap layers in a minute and embed "
"them in your site." "them in your site."
msgstr "" msgstr "uMap gerir þér kleift að útbúa landakort með OpenStreetMap lögum á nokkrum mínútum og birta þau á vefsvæðinu þínu."
#: templates/registration/login.html:6 templates/registration/login.html:46 #: templates/registration/login.html:6 templates/registration/login.html:46
msgid "Login" msgid "Login"
@ -223,11 +313,11 @@ msgstr "Innskráning"
#: templates/registration/login.html:22 #: templates/registration/login.html:22
msgid "To save and easily find your maps, identify yourself." msgid "To save and easily find your maps, identify yourself."
msgstr "" msgstr "Til þess að finna aftur kortin þín á einfaldan máta, skaltu auðkenna þig."
#: templates/registration/login.html:25 #: templates/registration/login.html:25
msgid "Please log in with your account:" msgid "Please log in with your account:"
msgstr "" msgstr "Skráðu þig inn í notandaaðganginn þinn:"
#: templates/registration/login.html:42 #: templates/registration/login.html:42
msgid "Username" msgid "Username"
@ -239,7 +329,11 @@ msgstr "Lykilorð"
#: templates/registration/login.html:52 #: templates/registration/login.html:52
msgid "Please choose a provider:" msgid "Please choose a provider:"
msgstr "" msgstr "Veldu þjónustu:"
#: templates/umap/about.html:5 templates/umap/navigation.html:22
msgid "About"
msgstr "Um hugbúnaðinn"
#: templates/umap/about_summary.html:12 #: templates/umap/about_summary.html:12
#, python-format #, python-format
@ -294,7 +388,7 @@ msgstr "Leiktu þér með sýnisútgáfuna"
#: templates/umap/components/alerts/alert.html:66 #: templates/umap/components/alerts/alert.html:66
#: templates/umap/components/alerts/alert.html:94 #: templates/umap/components/alerts/alert.html:94
msgid "Close" msgid "Close"
msgstr "" msgstr "Loka"
#: templates/umap/components/alerts/alert.html:32 #: templates/umap/components/alerts/alert.html:32
#, python-format #, python-format
@ -302,45 +396,45 @@ msgid ""
"Pro-tip: to easily find back your maps, <a href=\"%(login_url)s\" " "Pro-tip: to easily find back your maps, <a href=\"%(login_url)s\" "
"target=\"_blank\">create an account</a> or <a href=\"%(login_url)s\" " "target=\"_blank\">create an account</a> or <a href=\"%(login_url)s\" "
"target=\"_blank\">log in</a>." "target=\"_blank\">log in</a>."
msgstr "" msgstr "Til þess að finna aftur kortin þín á einfaldan máta, skaltu annaðhvort <a href=\"%(login_url)s\" target=\"_blank\">búa til aðgang</a> eða <a href=\"%(login_url)s\" target=\"_blank\">skrá þig inn</a>."
#: templates/umap/components/alerts/alert.html:37 #: templates/umap/components/alerts/alert.html:37
msgid "Here is your secret link to edit the map, please keep it safe:" msgid "Here is your secret link to edit the map, please keep it safe:"
msgstr "" msgstr "Hér er leynilegi tengillinn þinn til að breyta kortinu, haltu honum öruggum:"
#: templates/umap/components/alerts/alert.html:41 #: templates/umap/components/alerts/alert.html:41
msgid "Copy link" msgid "Copy link"
msgstr "" msgstr "Afrita tengil"
#: templates/umap/components/alerts/alert.html:48 #: templates/umap/components/alerts/alert.html:48
msgid "Enter your email address to receive the secret link:" msgid "Enter your email address to receive the secret link:"
msgstr "" msgstr "Settu inn tölvupóstfangið þitt til að taka við leynilega tenglinum:"
#: templates/umap/components/alerts/alert.html:54 #: templates/umap/components/alerts/alert.html:54
msgid "Email" msgid "Email"
msgstr "" msgstr "Tölvupóstur"
#: templates/umap/components/alerts/alert.html:57 #: templates/umap/components/alerts/alert.html:57
msgid "Send me the link" msgid "Send me the link"
msgstr "" msgstr "Senda mér tengilinn"
#: templates/umap/components/alerts/alert.html:81 #: templates/umap/components/alerts/alert.html:81
msgid "See their edits in another tab" msgid "See their edits in another tab"
msgstr "" msgstr "Skoða breytingar þeirra í öðrum flipa"
#: templates/umap/components/alerts/alert.html:84 #: templates/umap/components/alerts/alert.html:84
msgid "Keep your changes and loose theirs" msgid "Keep your changes and loose theirs"
msgstr "" msgstr "Halda þínum breytingum og tapa þeirra"
#: templates/umap/components/alerts/alert.html:87 #: templates/umap/components/alerts/alert.html:87
msgid "Keep their changes and loose yours" msgid "Keep their changes and loose yours"
msgstr "" msgstr "Halda breytingum þeirra og tapa þínum"
#: templates/umap/content.html:26 #: templates/umap/content.html:26
msgid "" msgid ""
"This instance of uMap is currently in read only mode, no creation/edit is " "This instance of uMap is currently in read only mode, no creation/edit is "
"allowed." "allowed."
msgstr "" msgstr "Þetta uMap-tilvik er nú í skrifvörðum ham, engin ný kort eða breytingar eru mögulegar."
#: templates/umap/content.html:34 #: templates/umap/content.html:34
#, python-format #, python-format
@ -353,46 +447,46 @@ msgstr "Þetta er sýnitilvik, notað fyrir prófanir og skoðun á eiginleikum
#: templates/umap/content_footer.html:5 #: templates/umap/content_footer.html:5
msgid "An OpenStreetMap project" msgid "An OpenStreetMap project"
msgstr "" msgstr "OpenStreetMap-verkefni"
#: templates/umap/content_footer.html:6 #: templates/umap/content_footer.html:6
msgid "version" msgid "version"
msgstr "" msgstr "útgáfa"
#: templates/umap/content_footer.html:7 #: templates/umap/content_footer.html:7
msgid "Hosted by" msgid "Hosted by"
msgstr "" msgstr "Hýst hjá"
#: templates/umap/content_footer.html:8 #: templates/umap/content_footer.html:8
msgid "Contact" msgid "Contact"
msgstr "" msgstr "Hafa samband"
#: templates/umap/content_footer.html:9 templates/umap/navigation.html:25 #: templates/umap/content_footer.html:9 templates/umap/navigation.html:25
msgid "Help" msgid "Help"
msgstr "" msgstr "Hjálp"
#: templates/umap/dashboard_menu.html:6 #: templates/umap/dashboard_menu.html:6
#, python-format #, python-format
msgid "My Maps (%(count)s)" msgid "My Maps (%(count)s)"
msgstr "" msgstr "Kortin mín (%(count)s)"
#: templates/umap/dashboard_menu.html:8 #: templates/umap/dashboard_menu.html:8
msgid "My Maps" msgid "My Maps"
msgstr "" msgstr "Kortin mín"
#: templates/umap/dashboard_menu.html:12 #: templates/umap/dashboard_menu.html:12
msgid "My profile" msgid "My profile"
msgstr "" msgstr "Sniðið mitt"
#: templates/umap/dashboard_menu.html:15 #: templates/umap/dashboard_menu.html:15
msgid "My teams" msgid "My teams"
msgstr "" msgstr "Teymin mín"
#: templates/umap/home.html:14 #: templates/umap/home.html:14
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "Kort í uMaps" msgstr "Kort í uMaps"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Fáðu hugmyndir, skoðaðu önnur landakort" msgstr "Fáðu hugmyndir, skoðaðu önnur landakort"
@ -400,105 +494,109 @@ msgstr "Fáðu hugmyndir, skoðaðu önnur landakort"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "Þú ert skráð/ur inn. Held áfram..." msgstr "Þú ert skráð/ur inn. Held áfram..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "eftir" msgstr "eftir"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr ""
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Meira" msgstr "Meira"
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:14 #: templates/umap/map_table.html:8 templates/umap/user_teams.html:18
msgid "Name" msgid "Name"
msgstr "" msgstr "Nafn"
#: templates/umap/map_table.html:11 #: templates/umap/map_table.html:11
msgid "Preview" msgid "Preview"
msgstr "" msgstr "Forskoðun"
#: templates/umap/map_table.html:14 #: templates/umap/map_table.html:14
msgid "Who can see" msgid "Who can see"
msgstr "" msgstr "Hver getur skoðað"
#: templates/umap/map_table.html:17 #: templates/umap/map_table.html:17
msgid "Who can edit" msgid "Who can edit"
msgstr "" msgstr "Hver getur breytt"
#: templates/umap/map_table.html:20 #: templates/umap/map_table.html:20
msgid "Last save" msgid "Last save"
msgstr "" msgstr "Síðast vistað"
#: templates/umap/map_table.html:23 #: templates/umap/map_table.html:23
msgid "Owner" msgid "Owner"
msgstr "" msgstr "Eigandi"
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:20 #: templates/umap/map_table.html:26 templates/umap/user_teams.html:24
msgid "Actions" msgid "Actions"
msgstr "" msgstr "Aðgerðir"
#: templates/umap/map_table.html:41 templates/umap/map_table.html:43 #: templates/umap/map_table.html:41 templates/umap/map_table.html:43
msgid "Open preview" msgid "Open preview"
msgstr "" msgstr "Opna forskoðun"
#: templates/umap/map_table.html:72 templates/umap/map_table.html:74 #: templates/umap/map_table.html:72 templates/umap/map_table.html:74
msgid "Share" msgid "Share"
msgstr "" msgstr "Deila"
#: templates/umap/map_table.html:78 templates/umap/map_table.html:80 #: templates/umap/map_table.html:78 templates/umap/map_table.html:80
#: templates/umap/user_teams.html:38 templates/umap/user_teams.html:40 #: templates/umap/user_teams.html:42 templates/umap/user_teams.html:44
msgid "Edit" msgid "Edit"
msgstr "" msgstr "Breyta"
#: templates/umap/map_table.html:84 templates/umap/map_table.html:86 #: templates/umap/map_table.html:84 templates/umap/map_table.html:86
msgid "Download" msgid "Download"
msgstr "" msgstr "Sækja"
#: templates/umap/map_table.html:90 templates/umap/map_table.html:92 #: templates/umap/map_table.html:90 templates/umap/map_table.html:92
msgid "Clone" msgid "Clone"
msgstr "" msgstr "Klóna"
#: templates/umap/map_table.html:101 templates/umap/map_table.html:103 #: templates/umap/map_table.html:101 templates/umap/map_table.html:103
msgid "Delete" msgid "Delete"
msgstr "" msgstr "Eyða"
#: templates/umap/map_table.html:117 #: templates/umap/map_table.html:117
msgid "first" msgid "first"
msgstr "" msgstr "fyrsta"
#: templates/umap/map_table.html:118 #: templates/umap/map_table.html:118
msgid "previous" msgid "previous"
msgstr "" msgstr "fyrra"
#: templates/umap/map_table.html:126 #: templates/umap/map_table.html:126
#, python-format #, python-format
msgid "Page %(maps_number)s of %(num_pages)s" msgid "Page %(maps_number)s of %(num_pages)s"
msgstr "" msgstr "Síða %(maps_number)s af %(num_pages)s"
#: templates/umap/map_table.html:131 #: templates/umap/map_table.html:131
msgid "next" msgid "next"
msgstr "" msgstr "næsta"
#: templates/umap/map_table.html:132 #: templates/umap/map_table.html:132
msgid "last" msgid "last"
msgstr "" msgstr "síðasta"
#: templates/umap/map_table.html:140 #: templates/umap/map_table.html:140
#, python-format #, python-format
msgid "Lines per page: %(per_page)s" msgid "Lines per page: %(per_page)s"
msgstr "" msgstr "Línur á síðu: %(per_page)s"
#: templates/umap/map_table.html:145 #: templates/umap/map_table.html:145
#, python-format #, python-format
msgid "%(count)s maps" msgid "%(count)s maps"
msgstr "" msgstr "%(count)s landakort"
#: templates/umap/navigation.html:11 templates/umap/user_dashboard.html:6 #: templates/umap/navigation.html:11 templates/umap/user_dashboard.html:6
msgid "My Dashboard" msgid "My Dashboard"
msgstr "" msgstr "Stjórnskjárinn minn"
#: templates/umap/navigation.html:14 #: templates/umap/navigation.html:14
msgid "Starred maps" msgid "Starred maps"
msgstr "" msgstr "Stjörnumerkt kort"
#: templates/umap/navigation.html:18 #: templates/umap/navigation.html:18
msgid "Log in" msgid "Log in"
@ -508,10 +606,6 @@ msgstr "Skrá inn"
msgid "Sign in" msgid "Sign in"
msgstr "Nýskrá" msgstr "Nýskrá"
#: templates/umap/navigation.html:22
msgid "About"
msgstr "Um hugbúnaðinn"
#: templates/umap/navigation.html:30 #: templates/umap/navigation.html:30
msgid "Change password" msgid "Change password"
msgstr "Breyta lykilorði" msgstr "Breyta lykilorði"
@ -520,170 +614,197 @@ msgstr "Breyta lykilorði"
msgid "Log out" msgid "Log out"
msgstr "Skrá út" msgstr "Skrá út"
#: templates/umap/password_change.html:7 #: templates/umap/password_change.html:6
#: templates/umap/password_change.html:11
msgid "Password change" msgid "Password change"
msgstr "Breyting á lykilorði" msgstr "Breyting á lykilorði"
#: templates/umap/password_change.html:10 #: templates/umap/password_change.html:14
msgid "" msgid ""
"Please enter your old password, for security's sake, and then enter your new" "Please enter your old password, for security's sake, and then enter your new"
" password twice so we can verify you typed it in correctly." " password twice so we can verify you typed it in correctly."
msgstr "Settu gamla lykilorðið þitt inn í öryggisskyni og settu síðan nýja lykilorðið þitt inn tvisvar, svo að við getum sannreynt að þú hafir slegið það rétt inn." msgstr "Settu gamla lykilorðið þitt inn í öryggisskyni og settu síðan nýja lykilorðið þitt inn tvisvar, svo að við getum sannreynt að þú hafir slegið það rétt inn."
#: templates/umap/password_change.html:17 #: templates/umap/password_change.html:21
msgid "Old password" msgid "Old password"
msgstr "Gamla lykilorðið" msgstr "Gamla lykilorðið"
#: templates/umap/password_change.html:22 #: templates/umap/password_change.html:26
msgid "New password" msgid "New password"
msgstr "Nýtt lykilorð" msgstr "Nýtt lykilorð"
#: templates/umap/password_change.html:26 #: templates/umap/password_change.html:30
msgid "New password confirmation" msgid "New password confirmation"
msgstr "Staðfesting á nýju lykilorði" msgstr "Staðfesting á nýju lykilorði"
#: templates/umap/password_change.html:27 #: templates/umap/password_change.html:31
msgid "Change my password" msgid "Change my password"
msgstr "Breyta lykilorðinu mínu" msgstr "Breyta lykilorðinu mínu"
#: templates/umap/password_change_done.html:7 #: templates/umap/password_change_done.html:6
#: templates/umap/password_change_done.html:11
msgid "Password change successful" msgid "Password change successful"
msgstr "Breyting á lykilorði tókst" msgstr "Breyting á lykilorði tókst"
#: templates/umap/password_change_done.html:10 #: templates/umap/password_change_done.html:14
msgid "Your password was changed." msgid "Your password was changed."
msgstr "Lykilorðinu þínu hefur verið breytt" msgstr "Lykilorðinu þínu hefur verið breytt"
#: templates/umap/search.html:15 #: templates/umap/search.html:6
msgid "Explore maps"
msgstr "Skoða landakort"
#: templates/umap/search.html:19
#, python-format #, python-format
msgid "%(count)s map found:" msgid "%(count)s map found:"
msgid_plural "%(count)s maps found:" msgid_plural "%(count)s maps found:"
msgstr[0] "" msgstr[0] "%(count)s kort fannst:"
msgstr[1] "" msgstr[1] "%(count)s kort fundust:"
#: templates/umap/search.html:24 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "" msgstr "Engin kort fundust."
#: templates/umap/search.html:29 #: templates/umap/search.html:35
msgid "Latest created maps" msgid "Latest created maps"
msgstr "" msgstr "Síðast útbúnu kortin"
#: templates/umap/search_bar.html:4 #: templates/umap/search_bar.html:4
msgid "Search maps" msgid "Search maps"
msgstr "Leita í landakortum" msgstr "Leita í landakortum"
#: templates/umap/search_bar.html:15 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr ""
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Leita" msgstr "Leita"
#: templates/umap/team_detail.html:10 #: templates/umap/team_confirm_delete.html:6
msgid "Team deletion"
msgstr "Eyðing teymis"
#: templates/umap/team_detail.html:6
#, python-format
msgid "%(current_team)ss maps"
msgstr "Kort frá %(current_team)s"
#: templates/umap/team_detail.html:14
#, python-format #, python-format
msgid "Browse %(current_team)s's maps" msgid "Browse %(current_team)s's maps"
msgstr "" msgstr "Skoða kort frá %(current_team)s"
#: templates/umap/team_detail.html:22 #: templates/umap/team_detail.html:26
#, python-format #, python-format
msgid "%(current_team)s has no public maps." msgid "%(current_team)s has no public maps."
msgstr "" msgstr "%(current_team)s er ekki með nein opinber landakort."
#: templates/umap/team_form.html:24 #: templates/umap/team_form.html:6
msgid "Create or edit a team"
msgstr "Búa til eða breyta teymi"
#: templates/umap/team_form.html:28
msgid "Delete this team" msgid "Delete this team"
msgstr "" msgstr "Eyða þessu teymi"
#: templates/umap/team_form.html:47 #: templates/umap/team_form.html:51
msgid "Add user" msgid "Add user"
msgstr "" msgstr "Bæta við notanda"
#: templates/umap/user_dashboard.html:9 templates/umap/user_dashboard.html:25 #: templates/umap/user_dashboard.html:9 templates/umap/user_dashboard.html:25
msgid "Search my maps" msgid "Search my maps"
msgstr "" msgstr "Leita í landakortunum mínum"
#: templates/umap/user_dashboard.html:17 templates/umap/user_dashboard.html:22 #: templates/umap/user_dashboard.html:17 templates/umap/user_dashboard.html:22
msgid "Maps title" msgid "Maps title"
msgstr "" msgstr "Titill landakortsins"
#: templates/umap/user_dashboard.html:30 #: templates/umap/user_dashboard.html:30
#, python-format #, python-format
msgid "Download %(count)s maps" msgid "Download %(count)s maps"
msgstr "" msgstr "Sækja %(count)s landakort"
#: templates/umap/user_dashboard.html:40 #: templates/umap/user_dashboard.html:40
msgid "You have no map yet." msgid "You have no map yet."
msgstr "" msgstr "Þú ert ekki með nein kort ennþá."
#: templates/umap/user_teams.html:17 #: templates/umap/user_teams.html:6
msgid "My Teams"
msgstr "Teymin mín"
#: templates/umap/user_teams.html:21
msgid "Users" msgid "Users"
msgstr "" msgstr "Notendur"
#: templates/umap/user_teams.html:48 #: templates/umap/user_teams.html:52
msgid "New team" msgid "New team"
msgstr "" msgstr "Nýtt teymi"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "" msgstr "Get ekki eytt teymi með fleiri en einum meðlim"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "" msgstr "Teyminu “%(name)s” hefur verið eytt"
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Skoða kortið" msgstr "Skoða kortið"
#: views.py:825 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "" msgstr "Fylla skjáinn"
#: views.py:968 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Tókst að uppfæra vinnslu korta!" msgstr "Tókst að uppfæra vinnslu korta!"
#: views.py:1004 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "" msgstr "uMap-breytingatengillinn fyrir landakortið þitt: %(map_name)s"
#: views.py:1007 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "" msgstr "Hér er leynilegi breytingatengillinn þinn: %(link)s"
#: views.py:1014 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "" msgstr "Tekst ekki að senda tölvupóst á %(email)s"
#: views.py:1017 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "" msgstr "Tölvupóstur var sendur á %(email)s"
#: views.py:1028 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Aðeins eigandinn getur eytt landakortinu." msgstr "Aðeins eigandinn getur eytt landakortinu."
#: views.py:1031 #: views.py:1051
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "" msgstr "Tókst að eyða korti."
#: views.py:1057 #: views.py:1077
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Það tókst að klóna landakortið þitt! Ef þú ætlar að breyta þessu landakorti úr annarri tölvu, ættirðu að nota þennan tengil: %(anonymous_url)s" msgstr "Það tókst að klóna landakortið þitt! Ef þú ætlar að breyta þessu landakorti úr annarri tölvu, ættirðu að nota þennan tengil: %(anonymous_url)s"
#: views.py:1062 #: views.py:1082
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Til hamingju, það tókst að klóna landakortið þitt!" msgstr "Til hamingju, það tókst að klóna landakortið þitt!"
#: views.py:1313 #: views.py:1336
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Tókst að eyða lagi." msgstr "Tókst að eyða lagi."
#: views.py:1335 #: views.py:1358
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "" msgstr "Tókst að uppfæra heimildir!"

Binary file not shown.

View file

@ -11,7 +11,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: uMap\n" "Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n" "POT-Creation-Date: 2025-04-11 15:30+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n" "PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Gideon van Melle <translations@gvmelle.com>, 2025\n" "Last-Translator: Gideon van Melle <translations@gvmelle.com>, 2025\n"
"Language-Team: Dutch (http://app.transifex.com/openstreetmap/umap/language/nl/)\n" "Language-Team: Dutch (http://app.transifex.com/openstreetmap/umap/language/nl/)\n"
@ -38,137 +38,205 @@ msgstr "Site is 'alleen lezen' wegens onderhoud"
msgid "" msgid ""
"Using “%(name)s” to authenticate is deprecated and will be removed soon. " "Using “%(name)s” to authenticate is deprecated and will be removed soon. "
"Please configure another provider below before losing access to your account" "Please configure another provider below before losing access to your account"
" and maps." " and maps. Then, please logout and login again with the new provider."
msgstr "" msgstr "Het gebruik van %(name)s om te verifiëren is afgeschaft en zal binnenkort worden verwijderd. Configureer hieronder een andere provider voordat u de toegang tot uw account en kaarten verliest. Log uit en log opnieuw in met de nieuwe provider."
#: models.py:60 models.py:79 #: models.py:61 models.py:80
msgid "name" msgid "name"
msgstr "naam" msgstr "naam"
#: models.py:62 models.py:485 #: models.py:63 models.py:493
msgid "description" msgid "description"
msgstr "omschrijving" msgstr "omschrijving"
#: models.py:110 #: models.py:111
msgid "details" msgid "details"
msgstr "details" msgstr "details"
#: models.py:111 #: models.py:112
msgid "Link to a page where the licence is detailed." msgid "Link to a page where the licence is detailed."
msgstr "Link naar pagina waar de licentie details staan" msgstr "Link naar pagina waar de licentie details staan"
#: models.py:121 #: models.py:122
msgid "URL template using OSM tile format" msgid "URL template using OSM tile format"
msgstr "URL-sjabloon met OSM tegel-formaat" msgstr "URL-sjabloon met OSM tegel-formaat"
#: models.py:127 #: models.py:128
msgid "Order of the tilelayers in the edit box" msgid "Order of the tilelayers in the edit box"
msgstr "Volgorde van de tegel-lagen in het bewerkingsvak." msgstr "Volgorde van de tegel-lagen in het bewerkingsvak."
#: models.py:175 models.py:479 #: models.py:176 models.py:487
msgid "Only editable with secret edit link" msgid "Only editable with secret edit link"
msgstr "Alleen te bewerken met een geheime link" msgstr "Alleen te bewerken met een geheime link"
#: models.py:176 models.py:480 #: models.py:177 models.py:488
msgid "Everyone can edit" msgid "Everyone can edit"
msgstr "Iedereen kan wijzigingen maken" msgstr "Iedereen kan wijzigingen maken"
#: models.py:179 models.py:473 #: models.py:180 models.py:481
msgid "Everyone" msgid "Everyone"
msgstr "Iedereen" msgstr "Iedereen"
#: models.py:180 models.py:189 models.py:474 #: models.py:181 models.py:190 models.py:482
msgid "Editors and team only" msgid "Editors and team only"
msgstr "Alleen redacteuren en team" msgstr "Alleen redacteuren en team"
#: models.py:181 models.py:475 #: models.py:182 models.py:483
msgid "Owner only" msgid "Owner only"
msgstr "Alleen eigenaar" msgstr "Alleen eigenaar"
#: models.py:184 #: models.py:185
msgid "Draft (private)" msgid "Draft (private)"
msgstr "Ontwerp (privé)" msgstr "Ontwerp (privé)"
#: models.py:185 #: models.py:186
msgid "Everyone (public)" msgid "Everyone (public)"
msgstr "Iedereen (openbaar)" msgstr "Iedereen (openbaar)"
#: models.py:188 #: models.py:189
msgid "Anyone with link" msgid "Anyone with link"
msgstr "Iedereen met een link" msgstr "Iedereen met een link"
#: models.py:190 #: models.py:191
msgid "Blocked" msgid "Blocked"
msgstr "geblokkeerd" msgstr "geblokkeerd"
#: models.py:191 models.py:469 #: models.py:192 models.py:477
msgid "Deleted" msgid "Deleted"
msgstr "Verwijderd" msgstr "Verwijderd"
#: models.py:194 #: models.py:195
msgid "center" msgid "center"
msgstr "centreer" msgstr "centreer"
#: models.py:195 #: models.py:196
msgid "zoom" msgid "zoom"
msgstr "zoom" msgstr "zoom"
#: models.py:197 #: models.py:198
msgid "locate" msgid "locate"
msgstr "zoek" msgstr "zoek"
#: models.py:197 #: models.py:198
msgid "Locate user on load?" msgid "Locate user on load?"
msgstr "Gebruiker zoeken tijdens laden?" msgstr "Gebruiker zoeken tijdens laden?"
#: models.py:201 #: models.py:202
msgid "Choose the map licence." msgid "Choose the map licence."
msgstr "Kies de kaartlicentie" msgstr "Kies de kaartlicentie"
#: models.py:202 #: models.py:203
msgid "licence" msgid "licence"
msgstr "Licentie" msgstr "Licentie"
#: models.py:213 #: models.py:214
msgid "owner" msgid "owner"
msgstr "eigenaar" msgstr "eigenaar"
#: models.py:217 #: models.py:218
msgid "editors" msgid "editors"
msgstr "editors" msgstr "editors"
#: models.py:223 #: models.py:224
msgid "team" msgid "team"
msgstr "team" msgstr "team"
#: models.py:229 models.py:501 #: models.py:230 models.py:509
msgid "edit status" msgid "edit status"
msgstr "wijzig status" msgstr "wijzig status"
#: models.py:234 models.py:506 #: models.py:235 models.py:514
msgid "share status" msgid "share status"
msgstr "deel status" msgstr "deel status"
#: models.py:237 models.py:496 #: models.py:238 models.py:504
msgid "settings" msgid "settings"
msgstr "instellingen" msgstr "instellingen"
#: models.py:407 #: models.py:410
msgid "Clone of" msgid "Clone of"
msgstr "Kopie van" msgstr "Kopie van"
#: models.py:468 models.py:472 models.py:478 #: models.py:476 models.py:480 models.py:486
msgid "Inherit" msgid "Inherit"
msgstr "overerven" msgstr "overerven"
#: models.py:491 #: models.py:499
msgid "display on load" msgid "display on load"
msgstr "toon tijdens laden" msgstr "toon tijdens laden"
#: models.py:492 #: models.py:500
msgid "Display this layer on load." msgid "Display this layer on load."
msgstr "Toon deze laag tijdens laden." msgstr "Toon deze laag tijdens laden."
#: settings/base.py:295
msgid "Art and Culture"
msgstr "Kunst en cultuur"
#: settings/base.py:296
msgid "Cycling"
msgstr "Fietsen"
#: settings/base.py:297
msgid "Business"
msgstr "Zakelijk"
#: settings/base.py:298
msgid "Environment"
msgstr "Mlieu"
#: settings/base.py:299
msgid "Education"
msgstr "Educatie"
#: settings/base.py:300
msgid "Food and Agriculture"
msgstr "Voedsel en landbouw"
#: settings/base.py:301
msgid "Geopolitics"
msgstr "Geopolitiek"
#: settings/base.py:302
msgid "Health"
msgstr "Gezondheid"
#: settings/base.py:303
msgid "Hiking"
msgstr "Hiking"
#: settings/base.py:304
msgid "History"
msgstr "Geschiedenis"
#: settings/base.py:305
msgid "Public sector"
msgstr "Publieke sector"
#: settings/base.py:306
msgid "Science"
msgstr "Wetenschap"
#: settings/base.py:307
msgid "Shopping"
msgstr "Winkelen"
#: settings/base.py:308
msgid "Sport and Leisure"
msgstr "Sport en vrijetijd"
#: settings/base.py:309
msgid "Travel"
msgstr "Reizen"
#: settings/base.py:310
msgid "Transports"
msgstr "Transport"
#: settings/base.py:311
msgid "Tourism"
msgstr "Toerisme"
#: templates/403.html:8 #: templates/403.html:8
msgid "" msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" " "<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -421,7 +489,7 @@ msgstr "Mijn teams"
msgid "Map of the uMaps" msgid "Map of the uMaps"
msgstr "Kaart van de uMaps" msgstr "Kaart van de uMaps"
#: templates/umap/home.html:24 #: templates/umap/home.html:25
msgid "Get inspired, browse maps" msgid "Get inspired, browse maps"
msgstr "Laat u inspireren, blader door kaarten" msgstr "Laat u inspireren, blader door kaarten"
@ -429,11 +497,15 @@ msgstr "Laat u inspireren, blader door kaarten"
msgid "You are logged in. Continuing..." msgid "You are logged in. Continuing..."
msgstr "U bent ingelogd. Ga verder..." msgstr "U bent ingelogd. Ga verder..."
#: templates/umap/map_list.html:11 views.py:437 #: templates/umap/map_list.html:18 views.py:444
msgid "by" msgid "by"
msgstr "door" msgstr "door"
#: templates/umap/map_list.html:20 #: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Zie de kaart"
#: templates/umap/map_list.html:28
msgid "More" msgid "More"
msgstr "Meer" msgstr "Meer"
@ -592,11 +664,15 @@ msgid_plural "%(count)s maps found:"
msgstr[0] "%(count)s kaarten gevonden:" msgstr[0] "%(count)s kaarten gevonden:"
msgstr[1] "%(count)s kaarten gevonden:" msgstr[1] "%(count)s kaarten gevonden:"
#: templates/umap/search.html:28 #: templates/umap/search.html:30
msgid "No map found." msgid "No map found."
msgstr "Geen kaart gevonden." msgstr "Geen kaart gevonden."
#: templates/umap/search.html:33 #: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr "Laatst gemaakte kaarten in categorie"
#: templates/umap/search.html:43
msgid "Latest created maps" msgid "Latest created maps"
msgstr "Laatste gemaakte kaarten" msgstr "Laatste gemaakte kaarten"
@ -604,7 +680,11 @@ msgstr "Laatste gemaakte kaarten"
msgid "Search maps" msgid "Search maps"
msgstr "Zoek kaarten" msgstr "Zoek kaarten"
#: templates/umap/search_bar.html:16 #: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Elke categorie"
#: templates/umap/search_bar.html:19
msgid "Search" msgid "Search"
msgstr "Zoeken" msgstr "Zoeken"
@ -668,70 +748,70 @@ msgstr "Gebruikers"
msgid "New team" msgid "New team"
msgstr "Nieuw Team" msgstr "Nieuw Team"
#: views.py:234 #: views.py:235
msgid "Cannot delete a team with more than one member" msgid "Cannot delete a team with more than one member"
msgstr "Kan een team met meer dan één lid niet verwijderen" msgstr "Kan een team met meer dan één lid niet verwijderen"
#: views.py:238 #: views.py:239
#, python-format #, python-format
msgid "Team “%(name)s” has been deleted" msgid "Team “%(name)s” has been deleted"
msgstr "Team “%(name)s” is verwijderd" msgstr "Team “%(name)s” is verwijderd"
#: views.py:442 #: views.py:449
msgid "View the map" msgid "View the map"
msgstr "Bekijk de kaart" msgstr "Bekijk de kaart"
#: views.py:838 #: views.py:845
msgid "See full screen" msgid "See full screen"
msgstr "Volledig scherm weergeven" msgstr "Volledig scherm weergeven"
#: views.py:981 #: views.py:988
msgid "Map editors updated with success!" msgid "Map editors updated with success!"
msgstr "Kaarteditors met succes bijgewerkt!" msgstr "Kaarteditors met succes bijgewerkt!"
#: views.py:1017 #: views.py:1024
#, python-format #, python-format
msgid "The uMap edit link for your map: %(map_name)s" msgid "The uMap edit link for your map: %(map_name)s"
msgstr "De uMap-bewerkingslink voor uw kaart: %(map_name)s" msgstr "De uMap-bewerkingslink voor uw kaart: %(map_name)s"
#: views.py:1020 #: views.py:1027
#, python-format #, python-format
msgid "Here is your secret edit link: %(link)s" msgid "Here is your secret edit link: %(link)s"
msgstr "Hier is je geheime bewerkingslink: %(link)s" msgstr "Hier is je geheime bewerkingslink: %(link)s"
#: views.py:1027 #: views.py:1034
#, python-format #, python-format
msgid "Can't send email to %(email)s" msgid "Can't send email to %(email)s"
msgstr "Kan geen e-mail verzenden naar %(email)s" msgstr "Kan geen e-mail verzenden naar %(email)s"
#: views.py:1030 #: views.py:1037
#, python-format #, python-format
msgid "Email sent to %(email)s" msgid "Email sent to %(email)s"
msgstr "E-mail verzonden naar %(email)s" msgstr "E-mail verzonden naar %(email)s"
#: views.py:1041 #: views.py:1048
msgid "Only its owner can delete the map." msgid "Only its owner can delete the map."
msgstr "Kaart kan alleen door eigenaar worden verwijderd." msgstr "Kaart kan alleen door eigenaar worden verwijderd."
#: views.py:1044 #: views.py:1054
msgid "Map successfully deleted." msgid "Map successfully deleted."
msgstr "Kaart succesvol verwijderd." msgstr "Kaart succesvol verwijderd."
#: views.py:1070 #: views.py:1080
#, python-format #, python-format
msgid "" msgid ""
"Your map has been cloned! If you want to edit this map from another " "Your map has been cloned! If you want to edit this map from another "
"computer, please use this link: %(anonymous_url)s" "computer, please use this link: %(anonymous_url)s"
msgstr "Uw kaart is gekopieerd! Als u deze kaart wilt wijzigen vanaf een andere computer, gebruik dan deze link: %(anonymous_url)s" msgstr "Uw kaart is gekopieerd! Als u deze kaart wilt wijzigen vanaf een andere computer, gebruik dan deze link: %(anonymous_url)s"
#: views.py:1075 #: views.py:1085
msgid "Congratulations, your map has been cloned!" msgid "Congratulations, your map has been cloned!"
msgstr "Gefeliciteerd, uw kaart is gekopieerd!" msgstr "Gefeliciteerd, uw kaart is gekopieerd!"
#: views.py:1329 #: views.py:1339
msgid "Layer successfully deleted." msgid "Layer successfully deleted."
msgstr "Laag is verwijderd." msgstr "Laag is verwijderd."
#: views.py:1351 #: views.py:1361
msgid "Permissions updated with success!" msgid "Permissions updated with success!"
msgstr "Machtigingen met succes bijgewerkt!" msgstr "Machtigingen met succes bijgewerkt!"

View file

@ -34,7 +34,8 @@ def deprecated_auth_backend(get_response):
"Using “%(name)s” to authenticate is deprecated and will be " "Using “%(name)s” to authenticate is deprecated and will be "
"removed soon. " "removed soon. "
"Please configure another provider below before losing access " "Please configure another provider below before losing access "
"to your account and maps." "to your account and maps. Then, please logout and login "
"again with the new provider."
) )
% {"name": name}, % {"name": name},
) )

View file

@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2025-02-26 16:18
import django.contrib.postgres.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("umap", "0026_datalayer_modified_at_datalayer_share_status"),
]
operations = [
migrations.AddField(
model_name="map",
name="tags",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.CharField(max_length=200),
blank=True,
default=list,
size=None,
),
),
]

View file

@ -4,6 +4,7 @@ import uuid
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.contrib.postgres.fields import ArrayField
from django.core.files.base import File from django.core.files.base import File
from django.core.files.storage import storages from django.core.files.storage import storages
from django.core.signing import Signer from django.core.signing import Signer
@ -236,6 +237,7 @@ class Map(NamedModel):
settings = models.JSONField( settings = models.JSONField(
blank=True, null=True, verbose_name=_("settings"), default=dict blank=True, null=True, verbose_name=_("settings"), default=dict
) )
tags = ArrayField(models.CharField(max_length=200), blank=True, default=list)
objects = models.Manager() objects = models.Manager()
public = PublicManager() public = PublicManager()
@ -296,6 +298,7 @@ class Map(NamedModel):
with datalayer.geojson.open("rb") as f: with datalayer.geojson.open("rb") as f:
layer = json.loads(f.read()) layer = json.loads(f.read())
if datalayer.settings: if datalayer.settings:
datalayer.settings.pop("id", None)
layer["_umap_options"] = datalayer.settings layer["_umap_options"] = datalayer.settings
datalayers.append(layer) datalayers.append(layer)
umapjson["layers"] = datalayers umapjson["layers"] = datalayers
@ -415,12 +418,17 @@ class Map(NamedModel):
datalayer.clone(map_inst=new) datalayer.clone(map_inst=new)
return new return new
def get_tags_display(self):
labels = dict(settings.UMAP_TAGS)
return [(t, labels.get(t, t)) for t in self.tags]
@classproperty @classproperty
def extra_schema(self): def extra_schema(self):
return { return {
"iconUrl": { "iconUrl": {
"default": "%sumap/img/marker.svg" % settings.STATIC_URL, "default": "%sumap/img/marker.svg" % settings.STATIC_URL,
} },
"tags": {"choices": sorted(settings.UMAP_TAGS, key=lambda i: i[0])},
} }
@ -526,7 +534,10 @@ class DataLayer(NamedModel):
metadata = self.settings metadata = self.settings
if not metadata: if not metadata:
# Fallback to file for old datalayers. # Fallback to file for old datalayers.
data = json.loads(self.geojson.read().decode()) try:
data = json.loads(self.geojson.read().decode())
except FileNotFoundError:
data = {}
metadata = data.get("_umap_options") metadata = data.get("_umap_options")
if not metadata: if not metadata:
metadata = { metadata = {
@ -540,6 +551,7 @@ class DataLayer(NamedModel):
if self.old_id: if self.old_id:
metadata["old_id"] = self.old_id metadata["old_id"] = self.old_id
metadata["id"] = self.pk metadata["id"] = self.pk
metadata["rank"] = self.rank
metadata["permissions"] = {"edit_status": self.edit_status} metadata["permissions"] = {"edit_status": self.edit_status}
metadata["editMode"] = "advanced" if self.can_edit(request) else "disabled" metadata["editMode"] = "advanced" if self.can_edit(request) else "disabled"
metadata["_referenceVersion"] = self.reference_version metadata["_referenceVersion"] = self.reference_version

View file

@ -6,6 +6,7 @@ from email.utils import parseaddr
import environ import environ
from django.conf.locale import LANG_INFO from django.conf.locale import LANG_INFO
from django.utils.translation import gettext_lazy as _
import umap as project_module import umap as project_module
@ -18,6 +19,7 @@ env = environ.Env()
INTERNAL_IPS = env.list("INTERNAL_IPS", default=["127.0.0.1"]) INTERNAL_IPS = env.list("INTERNAL_IPS", default=["127.0.0.1"])
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["*"]) ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["*"])
CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=[])
ADMINS = tuple(parseaddr(email) for email in env.list("ADMINS", default=[])) ADMINS = tuple(parseaddr(email) for email in env.list("ADMINS", default=[]))
ASGI_APPLICATION = "umap.asgi.application" ASGI_APPLICATION = "umap.asgi.application"
@ -163,8 +165,8 @@ LOGIN_REDIRECT_URL = "login_popup_end"
STATIC_URL = "/static/" STATIC_URL = "/static/"
MEDIA_URL = "/uploads/" MEDIA_URL = "/uploads/"
STATIC_ROOT = os.path.join("static") STATIC_ROOT = env("STATIC_ROOT", default=os.path.join("static"))
MEDIA_ROOT = os.path.join("uploads") MEDIA_ROOT = env("MEDIA_ROOT", default=os.path.join("uploads"))
STATICFILES_FINDERS = [ STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.FileSystemFinder",
@ -290,6 +292,25 @@ UMAP_HOME_FEED = "latest"
UMAP_IMPORTERS = {} UMAP_IMPORTERS = {}
UMAP_HOST_INFOS = {} UMAP_HOST_INFOS = {}
UMAP_LABEL_KEYS = ["name", "title"] UMAP_LABEL_KEYS = ["name", "title"]
UMAP_TAGS = (
("arts", _("Art and Culture")),
("cycling", _("Cycling")),
("business", _("Business")),
("environment", _("Environment")),
("education", _("Education")),
("food", _("Food and Agriculture")),
("geopolitics", _("Geopolitics")),
("health", _("Health")),
("hiking", _("Hiking")),
("history", _("History")),
("public", _("Public sector")),
("science", _("Science")),
("shopping", _("Shopping")),
("sport", _("Sport and Leisure")),
("travel", _("Travel")),
("transports", _("Transports")),
("tourism", _("Tourism")),
)
UMAP_READONLY = env("UMAP_READONLY", default=False) UMAP_READONLY = env("UMAP_READONLY", default=False)
UMAP_GZIP = True UMAP_GZIP = True
@ -340,10 +361,8 @@ LOGGING = {
}, },
} }
# WebSocket configuration # Real-time editing configuration
WEBSOCKET_ENABLED = env.bool("WEBSOCKET_ENABLED", default=False) REALTIME_ENABLED = env.bool("REALTIME_ENABLED", default=False)
WEBSOCKET_BACK_HOST = env("WEBSOCKET_BACK_HOST", default="localhost")
WEBSOCKET_BACK_PORT = env.int("WEBSOCKET_BACK_PORT", default=8001)
REDIS_URL = "redis://localhost:6379" REDIS_URL = env("REDIS_URL", default="redis://localhost:6379")

View file

@ -3,9 +3,7 @@
*/ */
body, div, ul, ol, li, a, section, nav, body, div, ul, ol, li, a, section, nav,
h1, h2, h3, h4, h5, h6, label, h1, h2, h3, h4, h5, h6, label,
hr, input, textarea { hr, input, textarea, select {
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -19,7 +17,11 @@ h1, h2, h3, h4, h5, h6, label, hr {
} }
a { a {
text-decoration: none; text-decoration: none;
color: #1F5C39; color: var(--link-color);
}
a.main {
font-weight: bold;
text-decoration: underline;
} }
a[href^="http"]:not(nav.umap-nav a) { a[href^="http"]:not(nav.umap-nav a) {
text-decoration: underline; text-decoration: underline;
@ -81,10 +83,12 @@ hgroup > * {
hgroup { hgroup {
margin-bottom: var(--box-margin); margin-bottom: var(--box-margin);
} }
hgroup > :not(:first-child):last-child { hgroup p,
font-weight: normal; hgroup button {
margin: 0;
} }
/* /*
* List * List
*/ */
@ -158,10 +162,23 @@ dt {
} }
.grid-container { .grid-container {
display: grid; display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr)); --grid-layout-gap: calc(var(--gutter) * 2);
--grid-column-count: 3;
--grid-item--min-width: 300px;
/**
* Calculated values.
*/
--gap-count: calc(var(--grid-column-count) - 1);
--total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));
--grid-item--max-width: calc((100% - var(--total-gap-width)) / var(--grid-column-count));
grid-template-columns: repeat(auto-fill, minmax(max(var(--grid-item--min-width), var(--grid-item--max-width)), 1fr));
grid-gap: var(--grid-layout-gap);
} }
.grid-container.by4 { .grid-container.by4 {
grid-template-columns: repeat(4, minmax(0, 1fr)); --grid-column-count: 4;
--grid-item--min-width: 60px;
} }
.grid-container > * { .grid-container > * {
text-align: center; text-align: center;
@ -184,6 +201,10 @@ dt {
/* Various */ /* Various */
/* *********** */ /* *********** */
.nobr {
white-space: nowrap;
}
.text { .text {
word-break: break-word; word-break: break-word;
white-space: pre-line; white-space: pre-line;
@ -202,3 +223,19 @@ dt {
height: 100vh; height: 100vh;
opacity: 0.5; opacity: 0.5;
} }
.table-scrollable {
background-image: linear-gradient(to right, var(--background-color), var(--background-color)),
linear-gradient(to right, var(--background-color), var(--background-color)),
linear-gradient(to right, rgba(0, 0, 20, .50), rgba(255, 255, 255, 0)),
linear-gradient(to left, rgba(0, 0, 20, .50), rgba(255, 255, 255, 0));
background-position: left center, right center, left center, right center;
background-repeat: no-repeat;
background-size: 20px 100%, 20px 100%, 10px 100%, 10px 100%;
background-attachment: local, local, scroll, scroll;
display: block;
overflow-x: auto;
}
mark {
background-color: var(--color-lightCyan);
padding: 0 var(--small-box-padding);
}

View file

@ -16,6 +16,21 @@ input::-webkit-input-placeholder, ::-webkit-input-placeholder {
input:-moz-placeholder, :-moz-placeholder { input:-moz-placeholder, :-moz-placeholder {
color: #a5a5a5; color: #a5a5a5;
} }
.search-form {
display: flex;
align-items: baseline;
max-width: 800px;
margin: 0 auto;
}
.search-form select {
max-width: 200px;
}
.search-form input[type=submit] {
min-width: 200px;
}
.flex-break {
justify-content: center;
}
/* **************** */ /* **************** */
@ -56,30 +71,12 @@ body.login header {
.map_fragment { .map_fragment {
width: 100%; width: 100%;
} }
.map_list .map_fragment, .map_fragment,
.demo_map .map_fragment { .demo_map .map_fragment {
height: 210px; height: var(--map-fragment-height);
} }
.map_list .legend { .grid-container hgroup {
padding-top: 7px; text-align: left;
margin-bottom: 28px;
text-align: center;
font-size: 1.2em;
}
.map_list .legend a {
color: #222;
font-weight: bold;
}
.map_list .legend em,
.map_list .legend em a {
color: #444;
font-weight: normal;
}
.map_list hr {
display: none;
}
.map_list .wide + hr {
display: block;
} }
.umap-features-list ul { .umap-features-list ul {
margin-top: 14px; margin-top: 14px;
@ -164,13 +161,59 @@ h2.tabs a:hover {
color: #efefef; color: #efefef;
text-decoration: underline; text-decoration: underline;
} }
.more_button {
min-height: var(--map-fragment-height);
}
.tag-list {
margin-top: var(--text-margin);
margin-bottom: var(--text-margin);
display: flex;
flex-wrap: wrap;
gap: calc(var(--gutter) / 2 );
}
.tag-list li {
border: 1px solid var(--color-darkBlue);
border-radius: 3vmin;
display: inline-block;
padding: var(--button-padding-small);
}
.tag-list li a {
color: var(--color-darkBlue);
max-width: 125px;
display: inline-block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
font-size: small;
padding: 0 3px;
}
.card {
border: 1px solid var(--color-lightGray);
border-radius: var(--border-radius);
padding: var(--box-padding);
display: flex;
flex-direction: column;
}
.card .button {
margin-bottom: 0;
}
.card hgroup {
display: flex;
flex-direction: column;
justify-content: space-between;
margin-bottom: 0;
flex-grow: 1;
gap: var(--gutter);
}
.card h3 {
margin-bottom: 0;
}
/* **************************** */ /* **************************** */
/* colors */ /* colors */
/* **************************** */ /* **************************** */
input[type="submit"],
.button { .button {
background-color: var(--button-primary-background); background-color: var(--button-primary-background);
color: var(--button-primary-color); color: var(--button-primary-color);
@ -362,22 +405,9 @@ html[dir="rtl"] .content .icon-delete {
align-items: center; align-items: center;
} }
} }
.table-header form input {
border: 2px solid var(--color-darkBlue);
border-radius: 0;
padding: .5rem 1rem;
margin-bottom: 0;
line-height: inherit;
height: 40px;
}
.table-header form input[type="search"] { .table-header form input[type="search"] {
width: 30ch; width: 30ch;
} }
.table-header form input[type="submit"] {
background-color: var(--color-darkBlue);
color: white;
font-weight: bold;
}
.table-header .button-download { .table-header .button-download {
width: inherit; width: inherit;
@ -538,4 +568,9 @@ dialog::backdrop {
.mhide { .mhide {
display: none; display: none;
} }
.flex-break {
flex-direction: column;
align-items: center;
}
} }

View file

@ -1,9 +1,10 @@
.umap-main-edit-toolbox [type=button] { .umap-main-edit-toolbox [type=button] {
color: #fff; color: #fff;
font-size: 1em; font-size: 0.8rem;
background-color: var(--color-darkGray); background-color: var(--color-darkGray);
width: auto; width: auto;
margin-bottom: 0; margin-bottom: 0;
min-height: initial;
} }
.umap-main-edit-toolbox [type=button]:hover { .umap-main-edit-toolbox [type=button]:hover {
text-decoration: underline; text-decoration: underline;
@ -13,12 +14,18 @@
padding: 0 var(--text-margin); padding: 0 var(--text-margin);
background-color: inherit; background-color: inherit;
} }
.leaflet-container .edit-undo {
margin-left: var(--box-margin);
}
.leaflet-container .edit-undo[disabled],
.leaflet-container .edit-redo[disabled] {
filter: invert(.5);
}
.leaflet-container .edit-save, .leaflet-container .edit-save,
.leaflet-container .edit-cancel,
.leaflet-container .edit-disable, .leaflet-container .edit-disable,
.leaflet-container .connected-peers .leaflet-container .connected-peers
{ {
display: block; display: inline-block;
height: 32px; height: 32px;
line-height: 30px; line-height: 30px;
padding: 0 20px; padding: 0 20px;
@ -39,7 +46,6 @@
color: var(--color-darkGray); color: var(--color-darkGray);
} }
.leaflet-container .edit-cancel:hover,
.leaflet-container .edit-disable:hover { .leaflet-container .edit-disable:hover {
border: 0.5px solid rgba(153, 153, 153, 0.80); border: 0.5px solid rgba(153, 153, 153, 0.80);
text-decoration: none; text-decoration: none;
@ -76,19 +82,13 @@
background: rgba(66, 236, 230, 0.10); background: rgba(66, 236, 230, 0.10);
} }
.leaflet-container .edit-save, .leaflet-container .edit-save,
.leaflet-container .edit-cancel,
.leaflet-container .edit-disable,
.umap-edit-enabled .edit-enable { .umap-edit-enabled .edit-enable {
display: none; display: none;
} }
.umap-edit-enabled .edit-save, .umap-edit-enabled .edit-save,
.umap-edit-enabled .edit-disable, .umap-edit-enabled .edit-disable {
.umap-edit-enabled.umap-is-dirty .edit-cancel {
display: inline-block; display: inline-block;
} }
.umap-is-dirty .edit-disable {
display: none;
}
.umap-caption-bar { .umap-caption-bar {
display: none; display: none;
} }
@ -115,8 +115,6 @@
.umap-right-edit-toolbox { .umap-right-edit-toolbox {
display: flex; display: flex;
column-gap: 10px; column-gap: 10px;
}
.umap-right-edit-toolbox {
align-items: center; align-items: center;
} }
@ -135,17 +133,20 @@
text-indent: -9999px; text-indent: -9999px;
} }
.umap-main-edit-toolbox .map-name { .umap-main-edit-toolbox .map-name {
display: inline-block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: bold; font-weight: bold;
text-align: start; text-align: start;
} }
.truncate {
display: inline-flex;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.umap-main-edit-toolbox .username {
max-width: 100px;
}
.umap-main-edit-toolbox .share-status { .umap-main-edit-toolbox .share-status {
font-style: italic; font-style: italic;
overflow: hidden;
text-overflow: ellipsis;
} }
.map-name:after { .map-name:after {
content: '\00a0'; content: '\00a0';
@ -163,11 +164,13 @@
.umap-main-edit-toolbox h3 { .umap-main-edit-toolbox h3 {
display: inline; display: inline;
} }
.umap-caption-bar button { .umap-caption-bar .umap-map-author {
margin-inline-start: 10px; margin-inline-end: 10px;
} }
.umap-caption-bar button + button:before { .umap-caption-bar:has(select:not([hidden])) > button + button:after,
.umap-caption-bar > button + button:before {
content: '|'; content: '|';
padding-inline-start: 10px;
padding-inline-end: 10px; padding-inline-end: 10px;
} }
.umap-main-edit-toolbox .umap-user:hover { .umap-main-edit-toolbox .umap-user:hover {
@ -196,7 +199,16 @@
z-index: var(--zindex-panels); z-index: var(--zindex-panels);
} }
.umap-caption-bar-enabled .umap-caption-bar { .umap-caption-bar-enabled .umap-caption-bar {
display: block; display: flex;
align-items: baseline;
}
.umap-caption-bar select {
margin-top: 0;
line-height: initial;
height: initial;
min-height: initial;
width: auto;
padding: 0 var(--text-margin);
} }
.umap-caption-bar-enabled { .umap-caption-bar-enabled {
--current-footer-height: var(--footer-height); --current-footer-height: var(--footer-height);
@ -233,3 +245,14 @@
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
@media all and (max-width: 980px) {
.umap-main-edit-toolbox button span {
display: none;
}
}
@media all and (max-width: 770px) {
.umap-main-edit-toolbox .umap-help-link,
.umap-main-edit-toolbox .share-status {
display: none !important;
}
}

View file

@ -2,7 +2,7 @@
z-index: var(--zindex-dialog); z-index: var(--zindex-dialog);
margin: auto; margin: auto;
margin-top: 100px; margin-top: 100px;
width: 40vw; width: var(--dialog-width);
max-width: 100vw; max-width: 100vw;
max-height: 50vh; max-height: 50vh;
padding: 20px; padding: 20px;
@ -14,6 +14,9 @@
height: fit-content; height: fit-content;
max-height: 90vh; max-height: 90vh;
} }
.umap-dialog ul + h4 {
margin-top: var(--box-margin);
}
:where([data-component="no-dialog"]:not([hidden])) { :where([data-component="no-dialog"]:not([hidden])) {
display: block; display: block;
position: relative; position: relative;

View file

@ -6,17 +6,15 @@ input[type="text"], input[type="password"], input[type="date"],
input[type="datetime-local"], input[type="email"], input[type="number"], input[type="datetime-local"], input[type="email"], input[type="number"],
input[type="search"], input[type="tel"], input[type="time"], input[type="file"], input[type="search"], input[type="tel"], input[type="time"], input[type="file"],
input[type="url"], textarea { input[type="url"], textarea {
background-color: white; background-color: var(--color-light);
border: 1px solid #CCCCCC; border: 2px solid var(--color-darkBlue);
border-radius: 2px 2px 2px 2px; color: var(--text-color);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset;
color: rgba(0, 0, 0, 0.75);
display: block; display: block;
font-family: inherit; font-family: inherit;
margin: 0; margin: 0;
margin-bottom: var(--box-margin); padding: .5rem 1rem;
padding: 7px;
width: 100%; width: 100%;
min-height: 40px;
} }
input[type="range"] { input[type="range"] {
margin-top: 10px; margin-top: 10px;
@ -47,10 +45,14 @@ input[type=checkbox]:checked:after {
content: '✓'; content: '✓';
color: var(--color-darkGray); color: var(--color-darkGray);
} }
input[data-modified=true] { input[data-modified=true] {
background-color: var(--color-lightCyan); background-color: var(--color-lightCyan);
border: 1px solid var(--color-darkGray); border: 1px solid var(--color-veryDarkGray);
}
input + select,
select + input,
input + input {
border-left: none;
} }
textarea { textarea {
height: inherit; height: inherit;
@ -59,16 +61,18 @@ textarea {
min-height: 6rlh; min-height: 6rlh;
} }
select { select {
border: 1px solid #222; border: 2px solid var(--color-darkBlue);
width: 100%; width: 100%;
height: 28px; padding: var(--button-padding);
line-height: 28px; background-color: var(--background-color);
margin-top: 5px; color: var(--text-color);
margin-bottom: var(--box-margin); min-height: 40px;
} }
.dark select { .dark select {
color: #efefef; color: var(--text-color);
background-color: #393F3F; background-color: var(--color-darkGray);
border-color: var(--color-veryDarkGray);
border-width: 1px;
} }
select[multiple="multiple"] { select[multiple="multiple"] {
height: auto; height: auto;
@ -78,33 +82,36 @@ select[multiple="multiple"] {
input[type="submit"] { input[type="submit"] {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 14px;
text-align: center; text-align: center;
border-radius: 2px;
font-weight: normal;
cursor: pointer; cursor: pointer;
padding: var(--button-padding); padding: var(--button-padding);
border: none; border: none;
text-decoration: none; text-decoration: none;
background-color: white;
justify-content: center; justify-content: center;
background-color: var(--color-darkBlue);
color: var(--color-light);
font-weight: normal;
min-height: 40px;
} }
.dark .button, .dark .button,
.dark [type="button"] { .dark [type="button"] {
background-color: var(--color-darkerGray); background-color: var(--color-darkerGray);
color: var(--text-color); color: var(--text-color);
border: 1px solid #1b1f20; border: 1px solid var(--color-veryDarkGray);
}
.button.primary {
font-weight: bold;
} }
.dark .button.primary:not([disabled]), .dark .button.primary:not([disabled]),
.dark [type="button"].primary:not([disabled]) { .dark [type="button"].primary:not([disabled]) {
background-color: var(--color-brightCyan); background-color: var(--color-verySoftCyan);
color: var(--color-dark); color: var(--color-dark);
border: 1px solid #1b1f20; border: 1px solid var(--color-veryDarkGray);
} }
.dark .button:hover, .dark .button:hover,
.dark [type="button"]:hover, .dark [type="button"]:hover,
.dark input[type="submit"]:hover { .dark input[type="submit"]:hover {
background-color: #2e3436; background-color: var(--color-darkerGray);
} }
.dark a { .dark a {
color: var(--text-color); color: var(--text-color);
@ -144,14 +151,14 @@ button.round.small {
display: block; display: block;
padding: 7px 7px; padding: 7px 7px;
margin-bottom: 14px; margin-bottom: 14px;
background: #393F3F; background: var(--color-mediumGray);
color: var(--color-lightGray); color: var(--color-lightGray);
font-size: 10px; font-size: 10px;
border-radius: 0 2px; border-radius: 0 2px;
} }
.content .helptext { .content .helptext {
background-color: #eee; background-color: var(--color-lightGray);
color: #000; color: var(--color-dark);
} }
input + .help-text { input + .help-text {
margin-top: -14px; margin-top: -14px;
@ -163,6 +170,14 @@ input + .help-text {
.formbox.with-switch { .formbox.with-switch {
padding-top: 2px; padding-top: 2px;
} }
.with-switch {
overflow: hidden;
}
.formbox select,
.formbox textarea,
.formbox input {
margin-bottom: var(--text-margin);
}
fieldset.formbox { fieldset.formbox {
border: none; border: none;
border-top: 1px solid var(--color-lightGray); border-top: 1px solid var(--color-lightGray);
@ -190,8 +205,8 @@ input + .error {
margin-top: -14px; margin-top: -14px;
margin-bottom: 14px; margin-bottom: 14px;
background: var(--color-lightGray); background: var(--color-lightGray);
color: #fff; color: var(--color-light);
background-color: #cc0000; background-color: var(--color-red);
font-size: 11px; font-size: 11px;
border-radius: 0 2px; border-radius: 0 2px;
} }
@ -199,13 +214,14 @@ input[type="file"] + .error {
margin-top: 0; margin-top: 0;
} }
input[value]:invalid { input[value]:invalid {
border-color: red; border-color: var(--color-red);
background-color: darkred; background-color: var(--color-darkRed);
} }
.dark input, .dark textarea { .dark input, .dark textarea {
background-color: #232729; background-color: var(--color-darkerGray);
border-color: #1b1f20; border-color: var(--color-veryDarkGray);
color: #efefef; border-width: 1px;
color: var(--color-lightGray);
} }
details { details {
margin-bottom: 5px; margin-bottom: 5px;
@ -213,7 +229,7 @@ details {
border-start-end-radius: 4px; border-start-end-radius: 4px;
} }
.dark details { .dark details {
border: 1px solid #222; border: 1px solid var(--color-veryDarkGray);
} }
details fieldset { details fieldset {
overflow: hidden; overflow: hidden;
@ -229,8 +245,8 @@ details summary {
padding: 0 5px; padding: 0 5px;
} }
.dark details summary { .dark details summary {
background-color: #232729; background-color: var(--color-darkerGray);
color: #fff; color: var(--color-light);
} }
.dark details fieldset { .dark details fieldset {
border: 1px solid var(--color-darkGray); border: 1px solid var(--color-darkGray);
@ -280,9 +296,6 @@ input.switch:empty ~ label {
text-indent: 6em; text-indent: 6em;
margin: 0.2em 0; margin: 0.2em 0;
cursor: pointer; cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; user-select: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.1); text-shadow: 0 1px rgba(0, 0, 0, 0.1);
width: 80px; width: 80px;
@ -298,33 +311,34 @@ input.switch:empty ~ label:after {
width: 6em; width: 6em;
-webkit-transition: all 100ms ease-in; -webkit-transition: all 100ms ease-in;
transition: all 100ms ease-in; transition: all 100ms ease-in;
color: #c9c9c7; color: var(--color-mediumGray);
font-weight: bold; font-weight: bold;
background-color: #ededed; background-color: var(--color-lighterGray);
} }
.dark input.switch:empty ~ label:before, .dark input.switch:empty ~ label:before,
.dark input.switch:empty ~ label:after { .dark input.switch:empty ~ label:after {
background-color: #272c2e; background-color: var(--color-darkerGray);
} }
input.switch:empty ~ label:after { input.switch:empty ~ label:after {
width: 3em; width: 3em;
margin-inline-start: 0.1em; margin-inline-start: 0.1em;
background-color: #ededed; background-color: var(--color-lightGray);
content: "OFF"; content: "OFF";
text-indent: 3.5em; text-indent: 3.5em;
border: 1px solid #374E75; border: 1px solid var(--color-darkerGray);
font-weight: bold; font-weight: bold;
} }
.dark input.switch:empty ~ label:after { .dark input.switch:empty ~ label:after {
border: 1px solid #202425; border: 1px solid var(--color-veryDarkGray);
background-color: #2c3233; background-color: var(--color-darkerGray);
color: var(--color-lightGray);
} }
input.switch:checked:empty ~ label:after { input.switch:checked:empty ~ label:after {
content: ' '; content: ' ';
} }
.dark input.switch:checked ~ label:before, .dark input.switch:checked ~ label:before,
input.switch:checked ~ label:before { input.switch:checked ~ label:before {
background-color: var(--color-lightCyan); background-color: var(--color-verySoftCyan);
border: 1px solid var(--color-lightGray); border: 1px solid var(--color-lightGray);
color: var(--color-darkGray); color: var(--color-darkGray);
content: "ON"; content: "ON";
@ -334,7 +348,7 @@ input.switch:checked ~ label:before {
} }
.dark input.switch:checked ~ label:before { .dark input.switch:checked ~ label:before {
border: none; border: none;
background-color: var(--color-accent); background-color: var(--color-verySoftCyan);
} }
input.switch:checked ~ label:after { input.switch:checked ~ label:after {
margin-inline-start: 3em; margin-inline-start: 3em;
@ -374,9 +388,9 @@ input.switch:checked ~ label:after {
display: none; display: none;
} }
.umap-multiplechoice label { .umap-multiplechoice label {
border: 1px solid #374E75; border: 1px solid var(--color-veryDarkGray);
cursor: pointer; cursor: pointer;
background-color: #c9c9c7; background-color: var(--color-lightGray);
min-height: 30px; min-height: 30px;
line-height: 30px; line-height: 30px;
text-align: center; text-align: center;
@ -384,12 +398,11 @@ input.switch:checked ~ label:after {
display: inline-block; display: inline-block;
} }
.dark .umap-multiplechoice label { .dark .umap-multiplechoice label {
border: 1px solid black; border: 1px solid var(--color-veryDarkGray);
background-color: #2c3233; background-color: var(--color-darkGray);
} }
.umap-multiplechoice input[type='radio']:checked + label { .umap-multiplechoice input[type='radio']:checked + label {
background-color: var(--color-accent); background-color: var(--color-verySoftCyan);
box-shadow: inset 0 0 6px 0px #2c3233;
color: var(--color-darkGray); color: var(--color-darkGray);
} }
.inheritable .header .buttons { .inheritable .header .buttons {
@ -407,7 +420,7 @@ input.switch:checked ~ label:after {
width: initial; width: initial;
} }
.inheritable + .inheritable { .inheritable + .inheritable {
border-top: 1px solid #222; border-top: 1px solid var(--color-darkerGray);
padding-top: 5px; padding-top: 5px;
margin-top: 5px; margin-top: 5px;
} }
@ -487,14 +500,11 @@ i.info {
padding: 0 5px; padding: 0 5px;
} }
.flat-tabs { .flat-tabs {
display: none; display: flex;
justify-content: space-around; justify-content: space-around;
font-size: 1.2em; font-size: 1.2em;
margin-bottom: 20px; margin-bottom: 20px;
border-bottom: 1px solid #bebebe; border-bottom: 1px solid var(--color-lighterGray);
}
.flat-tabs:has(.flat) {
display: flex;
} }
.flat-tabs button { .flat-tabs button {
padding: 10px; padding: 10px;
@ -505,14 +515,14 @@ i.info {
.flat-tabs button:hover, .flat-tabs button:hover,
.flat-tabs .on { .flat-tabs .on {
font-weight: bold; font-weight: bold;
border-bottom: 1px solid #444; border-bottom: 1px solid var(--color-mediumGray);
} }
.dark .flat-tabs button { .dark .flat-tabs button {
color: #fff; color: var(--color-light);
} }
.dark .flat-tabs button:hover, .dark .flat-tabs button:hover,
.dark .flat-tabs .on { .dark .flat-tabs .on {
border-bottom: 1px solid #fff; border-bottom: 1px solid var(--color-light);
} }
.umap-pictogram-category h6 { .umap-pictogram-category h6 {
font-size: 1.3em; font-size: 1.3em;
@ -528,12 +538,13 @@ i.info {
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
cursor: pointer; cursor: pointer;
background-color: #999; background-color: var(--color-lightGray);
text-align: center; text-align: center;
margin-bottom: 5px; margin-bottom: 5px;
display: inline-block; display: inline-block;
color: black; color: var(--color-dark);
font-weight: bold; font-weight: bold;
overflow: hidden;
} }
.umap-pictogram-choice img { .umap-pictogram-choice img {
vertical-align: middle; vertical-align: middle;
@ -541,10 +552,10 @@ i.info {
} }
.umap-pictogram-choice:hover, .umap-pictogram-choice:hover,
.umap-color-picker span:hover { .umap-color-picker span:hover {
background-color: #bebebe; background-color: var(--color-lighterGray);
} }
.umap-pictogram-choice.selected { .umap-pictogram-choice.selected {
box-shadow: inset 0 0 0 1px #e9e9e9; box-shadow: inset 0 0 0 1px var(--color-lighterGray);
} }
.umap-pictogram-choice .leaflet-marker-icon { .umap-pictogram-choice .leaflet-marker-icon {
@ -572,6 +583,7 @@ input.blur {
vertical-align: middle; vertical-align: middle;
border-start-end-radius: 0; border-start-end-radius: 0;
border-end-end-radius: 0; border-end-end-radius: 0;
margin-bottom: 0;
} }
.blur + .button, .blur + .button,
.blur + [type="button"] { .blur + [type="button"] {
@ -598,13 +610,11 @@ input[type=hidden].blur + [type="button"] {
border-radius: initial; border-radius: initial;
} }
.copiable-input button { .copiable-input button {
background-position: -46px -92px; background-color: var(--background-color);
display: inline; color: var(--text-color);
padding: 0 10px; border: 2px solid var(--color-darkBlue);
height: 32px; border-left: none;
width: 32px; width: 40px;
border: 1px solid #202425;
border-radius: initial;
} }
input.highlightable:not(:placeholder-shown) { input.highlightable:not(:placeholder-shown) {
border: 1px solid var(--color-brightCyan); border: 1px solid var(--color-brightCyan);

View file

@ -75,7 +75,7 @@ html[dir="rtl"] .icon {
background-position: calc(var(--tile) * 4) 0; background-position: calc(var(--tile) * 4) 0;
} }
.icon-copy { .icon-copy {
background-position: calc(var(--tile) * 2) calc(var(--tile) * 4); background-position: calc(var(--tile) * 4) calc(var(--tile) * 7);
} }
.icon-delete { .icon-delete {
background-position: calc(var(--tile) * 5) calc(var(--tile) * 2); background-position: calc(var(--tile) * 5) calc(var(--tile) * 2);
@ -143,6 +143,9 @@ html[dir="rtl"] .icon {
.icon-marker { .icon-marker {
background-position: calc(var(--tile) * 7) var(--tile); background-position: calc(var(--tile) * 7) var(--tile);
} }
.icon-marker-plus {
background-position: calc(var(--tile) * 8) var(--tile);
}
.icon-multipolygon { .icon-multipolygon {
background-position: calc(var(--tile) * 7) calc(var(--tile) * 5); background-position: calc(var(--tile) * 7) calc(var(--tile) * 5);
} }
@ -155,17 +158,24 @@ html[dir="rtl"] .icon {
.icon-polygon { .icon-polygon {
background-position: calc(var(--tile) * 7) calc(var(--tile) * 4); background-position: calc(var(--tile) * 7) calc(var(--tile) * 4);
} }
.icon-polygon-plus {
background-position: calc(var(--tile) * 8) calc(var(--tile) * 4);
}
.icon-polyline { .icon-polyline {
background-position: calc(var(--tile) * 7) calc(var(--tile) * 6); background-position: calc(var(--tile) * 7) calc(var(--tile) * 6);
} }
.icon-profile { .icon-profile {
background-position: 0 calc(var(--tile) * 4); background-position: 0 calc(var(--tile) * 4);
} }
.icon-redo {
background-position: calc(var(--tile) * 3) calc(var(--tile) * 7);
}
.icon-resize { .icon-resize {
background-position: calc(var(--tile) * 3) calc(var(--tile) * 6); background-position: calc(var(--tile) * 3) calc(var(--tile) * 6);
} }
.icon-undo,
.icon-restore { .icon-restore {
background-position: calc(var(--tile) * 5) calc(var(--tile) * 3); background-position: calc(var(--tile) * 2) calc(var(--tile) * 7);
} }
.expanded .icon-resize { .expanded .icon-resize {
background-position: calc(var(--tile) * 2) calc(var(--tile) * 6); background-position: calc(var(--tile) * 2) calc(var(--tile) * 6);

View file

@ -55,3 +55,10 @@
.importers ul .datasets:before { .importers ul .datasets:before {
background-image: url(../img/importers/datasets.svg); background-image: url(../img/importers/datasets.svg);
} }
.importer.banfr h3:before,
.importers ul .banfr:before {
background-image: url(../img/importers/banfr.svg);
}
.importer table {
width: calc(var(--dialog-width) - 2 * var(--box-margin));
}

View file

@ -59,3 +59,16 @@
.tooltip-accent li:last-of-type { .tooltip-accent li:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
.umap-tooltip-container.tooltip-right:before {
right: 100%;
top: calc(50% - var(--arrow-size));
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-right-color: var(--tooltip-color);
border-width: var(--arrow-size);
}

View file

@ -1,4 +1,4 @@
<svg id="svg2" width="192" height="192" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <svg id="svg2" width="216" height="192" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<defs id="defs4"> <defs id="defs4">
<clipPath id="clip0_241_10857"> <clipPath id="clip0_241_10857">
<rect id="rect586" width="18.05" height="19.01" fill="#fff"/> <rect id="rect586" width="18.05" height="19.01" fill="#fff"/>
@ -15,6 +15,12 @@
<clipPath id="clip0_2695_1939"> <clipPath id="clip0_2695_1939">
<rect id="rect1" width="20" height="20" fill="#fff"/> <rect id="rect1" width="20" height="20" fill="#fff"/>
</clipPath> </clipPath>
<clipPath id="clip0_3071_861">
<rect id="rect3" width="18" height="20" fill="#fff"/>
</clipPath>
<clipPath id="clip0_241_10857-3">
<rect id="rect586-6" width="18.05" height="19.01" fill="#fff"/>
</clipPath>
</defs> </defs>
<metadata id="metadata7"> <metadata id="metadata7">
<rdf:RDF> <rdf:RDF>
@ -64,9 +70,12 @@
</g> </g>
</g> </g>
<path id="path4873" d="m108.15 816.36v3.8267h3.8544v-3.8267zm0.51755 4.3517-1.2459 2.3132 1.1669 0.61848 1.244-2.3151zm-1.8689 3.4717-0.27666 0.51571h-2.426v2.2441l-4.0916 4.064 1.3626 1.3528 3.862-3.8342h2.7214v-3.6959l0.015-0.028-0.015-8e-3v-0.0953h-0.17879l-0.97303-0.51571z" color="#000000" color-rendering="auto" fill="#f2f2f2" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> <path id="path4873" d="m108.15 816.36v3.8267h3.8544v-3.8267zm0.51755 4.3517-1.2459 2.3132 1.1669 0.61848 1.244-2.3151zm-1.8689 3.4717-0.27666 0.51571h-2.426v2.2441l-4.0916 4.064 1.3626 1.3528 3.862-3.8342h2.7214v-3.6959l0.015-0.028-0.015-8e-3v-0.0953h-0.17879l-0.97303-0.51571z" color="#000000" color-rendering="auto" fill="#f2f2f2" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
<g id="g4244" transform="matrix(.51357 -.54309 .54309 .51357 -518.02 506.23)"> <g id="g4244" transform="matrix(.51357 -.54309 .54309 .51357 -590.02 601.73)">
<path id="path4240" transform="matrix(.91922 .97205 -.97205 .91922 152.14 647.93)" d="m220.49 133.52c-0.33017 0.01-0.66239 0.0456-0.99414 0.10742-2.2249 0.41425-4.0267 1.9575-4.832 4.0098l-0.87696-1.8164a0.50005 0.50005 0 0 0-0.83398-0.11328 0.50005 0.50005 0 0 0-0.0664 0.54883l1.459 3.0195a0.50005 0.50005 0 0 0 0.60742 0.25586l2.8438-0.94532a0.50028 0.50028 0 1 0-0.31641-0.94922l-2.002 0.66797c0.61312-1.8902 2.2073-3.3241 4.2012-3.6953 2.2474-0.41845 4.5146 0.59912 5.6953 2.5566 1.1807 1.9575 1.022 4.4377-0.39648 6.2305-1.4185 1.7928-3.7961 2.5154-5.9727 1.8164a0.50005 0.50005 0 1 0-0.30469 0.95117c2.5704 0.82539 5.3874-0.0294 7.0625-2.1465 0.4188-0.52924 0.74532-1.1114 0.97657-1.7207 0.69373-1.828 0.53599-3.9147-0.50977-5.6484-1.22-2.0227-3.4291-3.1977-5.7402-3.1289z" color="#000000" color-rendering="auto" fill="#f2f2f2" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-linecap="round" stroke-linejoin="round" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> <path id="path4240" transform="matrix(.91922 .97205 -.97205 .91922 152.14 647.93)" d="m220.49 133.52c-0.33017 0.01-0.66239 0.0456-0.99414 0.10742-2.2249 0.41425-4.0267 1.9575-4.832 4.0098l-0.87696-1.8164a0.50005 0.50005 0 0 0-0.83398-0.11328 0.50005 0.50005 0 0 0-0.0664 0.54883l1.459 3.0195a0.50005 0.50005 0 0 0 0.60742 0.25586l2.8438-0.94532a0.50028 0.50028 0 1 0-0.31641-0.94922l-2.002 0.66797c0.61312-1.8902 2.2073-3.3241 4.2012-3.6953 2.2474-0.41845 4.5146 0.59912 5.6953 2.5566 1.1807 1.9575 1.022 4.4377-0.39648 6.2305-1.4185 1.7928-3.7961 2.5154-5.9727 1.8164a0.50005 0.50005 0 1 0-0.30469 0.95117c2.5704 0.82539 5.3874-0.0294 7.0625-2.1465 0.4188-0.52924 0.74532-1.1114 0.97657-1.7207 0.69373-1.828 0.53599-3.9147-0.50977-5.6484-1.22-2.0227-3.4291-3.1977-5.7402-3.1289z" color="#000000" color-rendering="auto" fill="#f2f2f2" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-linecap="round" stroke-linejoin="round" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g> </g>
<g id="g4244-6" transform="matrix(-.51357 -.54309 -.54309 .51357 734.02 601.73)">
<path id="path4240-7" transform="matrix(.91922 .97205 -.97205 .91922 152.14 647.93)" d="m220.49 133.52c-0.33017 0.01-0.66239 0.0456-0.99414 0.10742-2.2249 0.41425-4.0267 1.9575-4.832 4.0098l-0.87696-1.8164a0.50005 0.50005 0 0 0-0.83398-0.11328 0.50005 0.50005 0 0 0-0.0664 0.54883l1.459 3.0195a0.50005 0.50005 0 0 0 0.60742 0.25586l2.8438-0.94532a0.50028 0.50028 0 1 0-0.31641-0.94922l-2.002 0.66797c0.61312-1.8902 2.2073-3.3241 4.2012-3.6953 2.2474-0.41845 4.5146 0.59912 5.6953 2.5566 1.1807 1.9575 1.022 4.4377-0.39648 6.2305-1.4185 1.7928-3.7961 2.5154-5.9727 1.8164a0.50005 0.50005 0 1 0-0.30469 0.95117c2.5704 0.82539 5.3874-0.0294 7.0625-2.1465 0.4188-0.52924 0.74532-1.1114 0.97657-1.7207 0.69373-1.828 0.53599-3.9147-0.50977-5.6484-1.22-2.0227-3.4291-3.1977-5.7402-3.1289z" color="#000000" color-rendering="auto" fill="#f2f2f2" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-linecap="round" stroke-linejoin="round" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g>
<g id="delete-vertex" transform="translate(-90,-64)"> <g id="delete-vertex" transform="translate(-90,-64)">
<path id="path4349-2-2-9-3-8-3-5" transform="translate(0 852.36)" d="m227.55 53.105-6.0547 3.0273h-3.4414v3.5176l-2.9512 5.9023 1.7891 0.89453 3.1562-6.3145h2.0059v-2.043l6.3906-3.1953z" color="#000000" color-rendering="auto" fill="#f2f2f2" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> <path id="path4349-2-2-9-3-8-3-5" transform="translate(0 852.36)" d="m227.55 53.105-6.0547 3.0273h-3.4414v3.5176l-2.9512 5.9023 1.7891 0.89453 3.1562-6.3145h2.0059v-2.043l6.3906-3.1953z" color="#000000" color-rendering="auto" fill="#f2f2f2" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stroke="#999" stroke-width=".25" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
<path id="path4353-1-6-1-3-5-1-9" d="m217 907.36 6 6" fill="none" stroke="#fff" stroke-width="2.482"/> <path id="path4353-1-6-1-3-5-1-9" d="m217 907.36 6 6" fill="none" stroke="#fff" stroke-width="2.482"/>
@ -140,6 +149,10 @@
<path id="path580" d="m1.07 4.41h9.42c0.9234-0.0066 1.8391 0.16957 2.6941 0.5184 0.8551 0.34883 1.6327 0.8634 2.288 1.5141s1.1754 1.4246 1.5303 2.2771c0.3549 0.85256 0.5376 1.767 0.5376 2.6904 0.0067 0.9277-0.1712 1.8474-0.5231 2.7058-0.3519 0.8583-0.871 1.6382-1.527 2.2941-0.656 0.656-1.4358 1.1751-2.2941 1.527-0.8584 0.352-1.7781 0.5298-2.7058 0.5231h-9.42"/> <path id="path580" d="m1.07 4.41h9.42c0.9234-0.0066 1.8391 0.16957 2.6941 0.5184 0.8551 0.34883 1.6327 0.8634 2.288 1.5141s1.1754 1.4246 1.5303 2.2771c0.3549 0.85256 0.5376 1.767 0.5376 2.6904 0.0067 0.9277-0.1712 1.8474-0.5231 2.7058-0.3519 0.8583-0.871 1.6382-1.527 2.2941-0.656 0.656-1.4358 1.1751-2.2941 1.527-0.8584 0.352-1.7781 0.5298-2.7058 0.5231h-9.42"/>
<path id="path582" d="m4.75 8.45-4.04-4.05 4.04-4.05"/> <path id="path582" d="m4.75 8.45-4.04-4.05 4.04-4.05"/>
</g> </g>
<g id="undo-5" transform="matrix(-.71301 0 0 .66261 90.012 938.13)" clip-path="url(#clip0_241_10857-3)" fill="none" stroke="#f2f2f2" stroke-miterlimit="10" stroke-width="1.4549">
<path id="path580-3" d="m1.07 4.41h9.42c0.9234-0.0066 1.8391 0.16957 2.6941 0.5184 0.8551 0.34883 1.6327 0.8634 2.288 1.5141s1.1754 1.4246 1.5303 2.2771c0.3549 0.85256 0.5376 1.767 0.5376 2.6904 0.0067 0.9277-0.1712 1.8474-0.5231 2.7058-0.3519 0.8583-0.871 1.6382-1.527 2.2941-0.656 0.656-1.4358 1.1751-2.2941 1.527-0.8584 0.352-1.7781 0.5298-2.7058 0.5231h-9.42"/>
<path id="path582-5" d="m4.75 8.45-4.04-4.05 4.04-4.05"/>
</g>
<g id="g1" transform="translate(144 -24)" fill="none" stroke="#999"> <g id="g1" transform="translate(144 -24)" fill="none" stroke="#999">
<path id="path438" d="m9 849.94v4.05c0 0.20708 0.1679 0.375 0.375 0.375h5.25c0.20708 0 0.375-0.16792 0.375-0.375v-4.05c0-0.20708-0.16792-0.375-0.375-0.375h-5.25c-0.2071 0-0.375 0.16792-0.375 0.375z"/> <path id="path438" d="m9 849.94v4.05c0 0.20708 0.1679 0.375 0.375 0.375h5.25c0.20708 0 0.375-0.16792 0.375-0.375v-4.05c0-0.20708-0.16792-0.375-0.375-0.375h-5.25c-0.2071 0-0.375 0.16792-0.375 0.375z"/>
<path id="save" d="m15.213 842.36h-8.8376c-0.2071 0-0.375 0.1679-0.375 0.37499v11.25c0 0.20708 0.1679 0.375 0.375 0.375h11.25c0.20708 0 0.375-0.16792 0.375-0.375v-8.6766c0-0.0953-0.0363-0.18697-0.1014-0.25648l-2.4124-2.5733c-0.07095-0.0756-0.16995-0.11853-0.2736-0.11853z"/> <path id="save" d="m15.213 842.36h-8.8376c-0.2071 0-0.375 0.1679-0.375 0.37499v11.25c0 0.20708 0.1679 0.375 0.375 0.375h11.25c0.20708 0 0.375-0.16792 0.375-0.375v-8.6766c0-0.0953-0.0363-0.18697-0.1014-0.25648l-2.4124-2.5733c-0.07095-0.0756-0.16995-0.11853-0.2736-0.11853z"/>
@ -189,7 +202,7 @@
<path id="path8" transform="translate(0 812.36)" d="m8.1903 37.424c-0.48722-0.17411-0.79231-0.44207-0.99467-0.87363l-0.1908-0.40689-1.3703-0.0034c-1.4983-0.0037-1.5911-0.03214-1.5406-0.47225l0.026557-0.23161 2.8423-0.0451 0.19827-0.3895c0.34789-0.68343 0.86349-1.0091 1.5923-1.0058 0.71771 0.0033 1.3415 0.43242 1.6291 1.1207l0.11636 0.27848h4.6574c4.5203 0 4.66 0.0047 4.7428 0.1594 0.1159 0.21656 0.10767 0.30093-0.04419 0.45278-0.11466 0.11466-0.66063 0.1295-4.7632 0.1295h-4.6337l-0.10498 0.2903c-0.15257 0.42194-0.62749 0.84447-1.1103 0.98785-0.49622 0.14736-0.6615 0.14879-1.0524 0.0091zm0.96896-0.84513c0.698-0.33122 0.698-1.3772 0-1.7084-0.35156-0.16682-0.49258-0.16849-0.82704-0.0098-0.33761 0.16021-0.5445 0.51333-0.5445 0.92936 0 0.36801 0.16007 0.60614 0.53566 0.79693 0.31576 0.16039 0.48419 0.15875 0.83587-0.0081z" fill="#f2f2f2" stroke="#999" stroke-width=".25" style="paint-order:fill markers stroke"/> <path id="path8" transform="translate(0 812.36)" d="m8.1903 37.424c-0.48722-0.17411-0.79231-0.44207-0.99467-0.87363l-0.1908-0.40689-1.3703-0.0034c-1.4983-0.0037-1.5911-0.03214-1.5406-0.47225l0.026557-0.23161 2.8423-0.0451 0.19827-0.3895c0.34789-0.68343 0.86349-1.0091 1.5923-1.0058 0.71771 0.0033 1.3415 0.43242 1.6291 1.1207l0.11636 0.27848h4.6574c4.5203 0 4.66 0.0047 4.7428 0.1594 0.1159 0.21656 0.10767 0.30093-0.04419 0.45278-0.11466 0.11466-0.66063 0.1295-4.7632 0.1295h-4.6337l-0.10498 0.2903c-0.15257 0.42194-0.62749 0.84447-1.1103 0.98785-0.49622 0.14736-0.6615 0.14879-1.0524 0.0091zm0.96896-0.84513c0.698-0.33122 0.698-1.3772 0-1.7084-0.35156-0.16682-0.49258-0.16849-0.82704-0.0098-0.33761 0.16021-0.5445 0.51333-0.5445 0.92936 0 0.36801 0.16007 0.60614 0.53566 0.79693 0.31576 0.16039 0.48419 0.15875 0.83587-0.0081z" fill="#f2f2f2" stroke="#999" stroke-width=".25" style="paint-order:fill markers stroke"/>
<path id="path9" transform="translate(0 812.36)" d="m12.773 42.244c-0.4045-0.18728-0.73246-0.52685-0.9029-0.93487l-0.12875-0.30821-7.6214-0.04285-0.026557-0.23161c-0.055311-0.48238-0.16774-0.4688 3.8893-0.46961l3.7189-7.33e-4 0.21287-0.43192c0.65163-1.3222 2.4726-1.2846 3.1257 0.06446l0.17859 0.36892h2.2972c2.2584 0 2.2988 3e-3 2.391 0.17524 0.06808 0.12721 0.06936 0.22886 0.0047 0.37084l-0.08912 0.1956h-4.6108l-0.15493 0.35024c-0.38713 0.87516-1.4373 1.2865-2.2839 0.89448zm1.0632-0.70036c0.37802-0.15795 0.5443-0.42579 0.54116-0.87174-4e-3 -0.57358-0.36338-0.90877-0.9743-0.90877-0.31204 0-0.40386 0.04292-0.64992 0.30383-0.25777 0.27331-0.28248 0.33986-0.2461 0.66262 0.04524 0.40136 0.22819 0.65122 0.5956 0.81339 0.31718 0.14001 0.39991 0.14008 0.73356 6.68e-4z" fill="#f2f2f2" stroke="#999" stroke-width=".25" style="paint-order:fill markers stroke"/> <path id="path9" transform="translate(0 812.36)" d="m12.773 42.244c-0.4045-0.18728-0.73246-0.52685-0.9029-0.93487l-0.12875-0.30821-7.6214-0.04285-0.026557-0.23161c-0.055311-0.48238-0.16774-0.4688 3.8893-0.46961l3.7189-7.33e-4 0.21287-0.43192c0.65163-1.3222 2.4726-1.2846 3.1257 0.06446l0.17859 0.36892h2.2972c2.2584 0 2.2988 3e-3 2.391 0.17524 0.06808 0.12721 0.06936 0.22886 0.0047 0.37084l-0.08912 0.1956h-4.6108l-0.15493 0.35024c-0.38713 0.87516-1.4373 1.2865-2.2839 0.89448zm1.0632-0.70036c0.37802-0.15795 0.5443-0.42579 0.54116-0.87174-4e-3 -0.57358-0.36338-0.90877-0.9743-0.90877-0.31204 0-0.40386 0.04292-0.64992 0.30383-0.25777 0.27331-0.28248 0.33986-0.2461 0.66262 0.04524 0.40136 0.22819 0.65122 0.5956 0.81339 0.31718 0.14001 0.39991 0.14008 0.73356 6.68e-4z" fill="#f2f2f2" stroke="#999" stroke-width=".25" style="paint-order:fill markers stroke"/>
<path id="path1-67-5" d="m154.68 963.54 4.7344 4.7344-5.0508 4.6836-1.3594-1.4668 3.5274-3.2695-3.2656-3.2656z" color="#000000" fill="#f2f2f2" fill-rule="evenodd" stroke="#999" stroke-width=".25"/> <path id="path1-67-5" d="m154.68 963.54 4.7344 4.7344-5.0508 4.6836-1.3594-1.4668 3.5274-3.2695-3.2656-3.2656z" color="#000000" fill="#f2f2f2" fill-rule="evenodd" stroke="#999" stroke-width=".25"/>
<path id="copy" d="m58 914.36v3.5h4v4h3.5v-7.5zm-4 4v7.5h7.5v-7.5z" fill="#f2f2f2" style="paint-order:fill markers stroke"/> <path id="copy" d="m106.17 986.36v3.6522h4.1739v4.1739h3.6522v-7.8261zm-4.1739 4.1739v7.8261h7.8261v-7.8261z" fill="#f2f2f2" style="paint-order:fill markers stroke"/>
<g id="g1-5" transform="translate(.1 .1)"> <g id="g1-5" transform="translate(.1 .1)">
<g id="g24" fill="#f2f2f2" stroke="#999" stroke-width=".2"> <g id="g24" fill="#f2f2f2" stroke="#999" stroke-width=".2">
<path id="path24" d="m12 912.36c-4.4183 0-8 3.5817-8 8 0.00463 1.6156 0.49829 3.1919 1.416 4.5215 0.19802 0.28729 0.41463 0.56131 0.64844 0.82032 1.5128 1.6866 3.6699 2.6526 5.9355 2.6582 2.2669-6e-3 4.4249-0.97357 5.9375-2.6621 0.23535-0.26077 0.45327-0.53676 0.65234-0.82617 0.91377-1.3275 1.4053-2.9001 1.4102-4.5117 0-4.4183-3.5817-8-8-8zm-5.3242 12.506c1.3285-1.5609 3.2745-2.461 5.3242-2.4629 2.0504 1e-3 3.9972 0.90149 5.3262 2.4629 0 0-0.0035-3e-3 0.0059 6e-3 0 0-0.5371 0.5762-0.83984 0.82812-0.17533 0.14821-0.35784 0.2877-0.54687 0.41797-0.06626 0.0467-0.13333 0.0923-0.20117 0.13672-0.2448 0.15763-0.4992 0.29983-0.76172 0.42578-0.93187 0.44366-1.9503 0.67577-2.9824 0.67969-0.61808-5e-3 -1.2328-0.0915-1.8281-0.25781-0.67532-0.18416-1.3192-0.46858-1.9102-0.84375-0.0685-0.0444-0.13622-0.09-0.20312-0.13672-0.00521-4e-3 -0.010422-8e-3 -0.015625-0.0117-0.18766-0.12974-0.36887-0.26858-0.54297-0.41602-0.29972-0.24977-0.57803-0.52416-0.83203-0.82031m-0.5918-0.81445c-0.69766-1.1081-1.0705-2.3898-1.0762-3.6992 0-3.866 3.134-7 7-7l-4.1e-5 -1.6e-4c3.866 0 7 3.134 7 7-0.0054 1.3023-0.37406 2.5773-1.0645 3.6816-1.5163-1.6794-3.6729-2.6381-5.9355-2.6387-2.2613 8e-3 -4.4134 0.97341-5.9238 2.6562" style="paint-order:fill markers stroke"/> <path id="path24" d="m12 912.36c-4.4183 0-8 3.5817-8 8 0.00463 1.6156 0.49829 3.1919 1.416 4.5215 0.19802 0.28729 0.41463 0.56131 0.64844 0.82032 1.5128 1.6866 3.6699 2.6526 5.9355 2.6582 2.2669-6e-3 4.4249-0.97357 5.9375-2.6621 0.23535-0.26077 0.45327-0.53676 0.65234-0.82617 0.91377-1.3275 1.4053-2.9001 1.4102-4.5117 0-4.4183-3.5817-8-8-8zm-5.3242 12.506c1.3285-1.5609 3.2745-2.461 5.3242-2.4629 2.0504 1e-3 3.9972 0.90149 5.3262 2.4629 0 0-0.0035-3e-3 0.0059 6e-3 0 0-0.5371 0.5762-0.83984 0.82812-0.17533 0.14821-0.35784 0.2877-0.54687 0.41797-0.06626 0.0467-0.13333 0.0923-0.20117 0.13672-0.2448 0.15763-0.4992 0.29983-0.76172 0.42578-0.93187 0.44366-1.9503 0.67577-2.9824 0.67969-0.61808-5e-3 -1.2328-0.0915-1.8281-0.25781-0.67532-0.18416-1.3192-0.46858-1.9102-0.84375-0.0685-0.0444-0.13622-0.09-0.20312-0.13672-0.00521-4e-3 -0.010422-8e-3 -0.015625-0.0117-0.18766-0.12974-0.36887-0.26858-0.54297-0.41602-0.29972-0.24977-0.57803-0.52416-0.83203-0.82031m-0.5918-0.81445c-0.69766-1.1081-1.0705-2.3898-1.0762-3.6992 0-3.866 3.134-7 7-7l-4.1e-5 -1.6e-4c3.866 0 7 3.134 7 7-0.0054 1.3023-0.37406 2.5773-1.0645 3.6816-1.5163-1.6794-3.6729-2.6381-5.9355-2.6387-2.2613 8e-3 -4.4134 0.97341-5.9238 2.6562" style="paint-order:fill markers stroke"/>
@ -210,5 +223,13 @@
</g> </g>
<path id="star" class="sprite" d="m7.6698 998.86 1.3886-5.255-4.0585-3.2468h5.1831l1.8193-5.4949 1.8147 5.4939h5.1829l-4.0615 3.2496 1.3838 5.2564-4.3249-3.0123z" fill="#efefef"/> <path id="star" class="sprite" d="m7.6698 998.86 1.3886-5.255-4.0585-3.2468h5.1831l1.8193-5.4949 1.8147 5.4939h5.1829l-4.0615 3.2496 1.3838 5.2564-4.3249-3.0123z" fill="#efefef"/>
<path id="starred" class="sprite" d="m31.67 998.86 1.3886-5.255-4.0585-3.2468h5.1831l1.8193-5.4949 1.8147 5.4939h5.1829l-4.0615 3.2496 1.3838 5.2565-4.3249-3.0123z" fill="none" stroke="#efefef" stroke-linecap="square" stroke-linejoin="round"/> <path id="starred" class="sprite" d="m31.67 998.86 1.3886-5.255-4.0585-3.2468h5.1831l1.8193-5.4949 1.8147 5.4939h5.1829l-4.0615 3.2496 1.3838 5.2565-4.3249-3.0123z" fill="none" stroke="#efefef" stroke-linecap="square" stroke-linejoin="round"/>
<g id="g3" transform="translate(194.89 910.26)" clip-path="url(#clip0_3071_861)" stroke="#efefef">
<path id="path1-9" d="m1.8947 0.69727v2.3256h1.1013l-1.0184 13.953h-1.2671v2.3256h2.3684v-1.3953l9.4737-1.8605v0.9302h2.3684v-2.3255h-0.9237l1.8355-8.1396h1.4448v-2.3256h-2.3685v0.84883l-10.646-2.8605v-1.4767z" clip-rule="evenodd" fill="none" fill-rule="evenodd" stroke-width="1.2"/>
<path id="path2-1" d="m8.5972 6.8457v5.8915" stroke-width="1.0133"/>
<path id="path3-2" d="m11.598 9.791h-6" stroke-width="1.0133"/>
</g>
<path id="path1-0" d="m204.42 838.96c-2.9773 0-5.9659 1.9462-6.8182 5.85 0 2.3354 1.7046 7.0178 6.8182 12.467 5.1136-5.4608 6.8182-10.132 6.8182-12.467-0.8523-3.8924-3.8409-5.85-6.8182-5.85z" fill="none" stroke="#efefef" stroke-width="1.2"/>
<path id="path2-9" d="m204.42 843.98v6.0446" fill="none" stroke="#efefef" stroke-width="1.056"/>
<path id="path3-36" d="m207.42 847h-6" fill="none" stroke="#efefef" stroke-width="1.056"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -62,5 +62,6 @@
</g> </g>
<path id="downloadfile" d="m5.6444 59.434v1.035h1.0542zm1.1759 1.6123h-1.1759c-0.32472 0-0.58796-0.25845-0.58796-0.57727v-1.1545h-2.3519v5.1955h4.1157zm-4.1157-2.3091h3.0616l1.6421 1.6123v4.1605c0 0.31882-0.26324 0.57728-0.58796 0.57728h-4.1157c-0.32472 0-0.58796-0.25845-0.58796-0.57728v-5.1955c0-0.31882 0.26324-0.57727 0.58796-0.57727zm1.7639 3.9214v-1.3236h0.58796v1.3236l0.38009-0.37318 0.41575 0.4082-1.0898 1.07-1.0898-1.07 0.41575-0.4082z" fill="#f2f2f2" fill-rule="evenodd" stroke="#999" stroke-opacity=".5098" stroke-width=".066146"/> <path id="downloadfile" d="m5.6444 59.434v1.035h1.0542zm1.1759 1.6123h-1.1759c-0.32472 0-0.58796-0.25845-0.58796-0.57727v-1.1545h-2.3519v5.1955h4.1157zm-4.1157-2.3091h3.0616l1.6421 1.6123v4.1605c0 0.31882-0.26324 0.57728-0.58796 0.57728h-4.1157c-0.32472 0-0.58796-0.25845-0.58796-0.57728v-5.1955c0-0.31882 0.26324-0.57727 0.58796-0.57727zm1.7639 3.9214v-1.3236h0.58796v1.3236l0.38009-0.37318 0.41575 0.4082-1.0898 1.07-1.0898-1.07 0.41575-0.4082z" fill="#f2f2f2" fill-rule="evenodd" stroke="#999" stroke-opacity=".5098" stroke-width=".066146"/>
<path id="path3014" d="m4.6307 2.6463c-1.5327 0-2.7792 1.2449-2.7792 2.7776 0 1.5327 1.2464 2.7771 2.7792 2.7771 1.5327 0 2.7776-1.2443 2.7776-2.7771 0-1.5327-1.2449-2.7776-2.7776-2.7776zm0 0.26355c1.3898-1e-7 2.5141 1.1243 2.5141 2.5141 0 1.3898-1.1243 2.5135-2.5141 2.5135-1.3898-1e-7 -2.5135-1.1238-2.5135-2.5135 1e-7 -1.3898 1.1238-2.5141 2.5135-2.5141zm-0.0041342 0.75034c-0.14358 0-0.29261 0.015464-0.447 0.046509-0.15439 0.030939-0.3253 0.078749-0.51211 0.14366v0.72864c0.15748-0.10213 0.30911-0.17843 0.45424-0.22944 0.14512-0.052458 0.28009-0.079065 0.40514-0.079065 0.13277 0 0.23595 0.03107 0.31006 0.093018 0.074105 0.06029 0.1111 0.14436 0.1111 0.2527-1.6e-6 0.071155-0.020845 0.1422-0.062528 0.21342-0.040142 0.071155-0.10424 0.14694-0.19224 0.22738l-0.14779 0.13488c-0.16365 0.15162-0.271 0.27666-0.32194 0.37569-0.050949 0.097508-0.076481 0.21007-0.076481 0.33693v0.11369h0.83612v-0.10439c-1.7e-6 -0.069638 0.016152-0.13347 0.048576-0.19069 0.03242-0.058808 0.1012-0.13607 0.20619-0.23203l0.14779-0.13229c0.14512-0.13769 0.24778-0.26586 0.30799-0.38499 0.060208-0.12069 0.090431-0.25714 0.090434-0.40876-2.5e-6 -0.29549-0.098491-0.51969-0.29611-0.67283-0.19762-0.15469-0.48474-0.23203-0.86145-0.23203zm-0.47956 2.7016v0.82579h0.83612v-0.82579h-0.83612z" fill="#f2f2f2" stroke="#999" stroke-width=".066146"/> <path id="path3014" d="m4.6307 2.6463c-1.5327 0-2.7792 1.2449-2.7792 2.7776 0 1.5327 1.2464 2.7771 2.7792 2.7771 1.5327 0 2.7776-1.2443 2.7776-2.7771 0-1.5327-1.2449-2.7776-2.7776-2.7776zm0 0.26355c1.3898-1e-7 2.5141 1.1243 2.5141 2.5141 0 1.3898-1.1243 2.5135-2.5141 2.5135-1.3898-1e-7 -2.5135-1.1238-2.5135-2.5135 1e-7 -1.3898 1.1238-2.5141 2.5135-2.5141zm-0.0041342 0.75034c-0.14358 0-0.29261 0.015464-0.447 0.046509-0.15439 0.030939-0.3253 0.078749-0.51211 0.14366v0.72864c0.15748-0.10213 0.30911-0.17843 0.45424-0.22944 0.14512-0.052458 0.28009-0.079065 0.40514-0.079065 0.13277 0 0.23595 0.03107 0.31006 0.093018 0.074105 0.06029 0.1111 0.14436 0.1111 0.2527-1.6e-6 0.071155-0.020845 0.1422-0.062528 0.21342-0.040142 0.071155-0.10424 0.14694-0.19224 0.22738l-0.14779 0.13488c-0.16365 0.15162-0.271 0.27666-0.32194 0.37569-0.050949 0.097508-0.076481 0.21007-0.076481 0.33693v0.11369h0.83612v-0.10439c-1.7e-6 -0.069638 0.016152-0.13347 0.048576-0.19069 0.03242-0.058808 0.1012-0.13607 0.20619-0.23203l0.14779-0.13229c0.14512-0.13769 0.24778-0.26586 0.30799-0.38499 0.060208-0.12069 0.090431-0.25714 0.090434-0.40876-2.5e-6 -0.29549-0.098491-0.51969-0.29611-0.67283-0.19762-0.15469-0.48474-0.23203-0.86145-0.23203zm-0.47956 2.7016v0.82579h0.83612v-0.82579h-0.83612z" fill="#f2f2f2" stroke="#999" stroke-width=".066146"/>
<path id="copy" d="m42.218 69.321v1.2884h1.4725v1.4725h1.2884v-2.7609zm-1.4725 1.4725v2.7609h2.7609v-2.7609z" fill="#f2f2f2" stroke-width=".26458" style="paint-order:fill markers stroke"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -13,10 +13,10 @@
<text id="text4459" x="65.048965" y="964.36218" font-family="sans-serif" letter-spacing="0px" word-spacing="0px" style="line-height:0%" xml:space="preserve"><tspan id="tspan4461" x="65.048965" y="964.36218" fill="#4d4d4d" font-family="sans-serif" font-size="8px" font-weight="bold" style="line-height:1.25">1</tspan></text> <text id="text4459" x="65.048965" y="964.36218" font-family="sans-serif" letter-spacing="0px" word-spacing="0px" style="line-height:0%" xml:space="preserve"><tspan id="tspan4461" x="65.048965" y="964.36218" fill="#4d4d4d" font-family="sans-serif" font-size="8px" font-weight="bold" style="line-height:1.25">1</tspan></text>
</g> </g>
<g id="markers" class="sprite" transform="matrix(.26458 0 0 .26458 42.862 -225.92)" fill="#4d4d4d"> <g id="markers" class="sprite" transform="matrix(.26458 0 0 .26458 42.862 -225.92)" fill="#4d4d4d">
<path id="rect2985" d="m105.25 934.36c-3.1775 0-6.346 2.1278-7.2539 6.3794 0 2.551 1.8067 7.6679 7.2539 13.62 1.4637-1.5994 2.6694-3.1177 3.644-4.5613-1.4505-2.1639-2.415-4.0873-2.9628-5.7095-0.22599 0.041-0.44225 0.063-0.68112 0.063-2.0056 0-3.644-1.5346-3.644-3.413 0-1.8785 1.6384-3.3811 3.644-3.3811 0.51205 0 0.98854 0.076 1.4303 0.2552 0.64347-0.9222 1.4345-1.6571 2.3158-2.169-1.1444-0.7114-2.4463-1.0845-3.7461-1.0845z"/> <path id="rect2985" d="m105.25 934.36c-3.1775 0-6.6788 2.0702-7.2539 6.3794-0.33746 2.5286 1.8067 7.6679 7.2539 13.62 1.4637-1.5994 2.6694-3.1177 3.644-4.5613-1.4505-2.1639-2.415-4.0873-2.9628-5.7095-0.22599 0.041-0.44225 0.063-0.68112 0.063-2.0056 0-3.644-1.5346-3.644-3.413 0-1.8785 1.6384-3.3811 3.644-3.3811 0.51205 0 0.98854 0.076 1.4303 0.2552 0.64347-0.9222 1.4345-1.6571 2.3158-2.169-1.1444-0.7114-2.4463-1.0845-3.7461-1.0845z"/>
<path id="path3378" d="m111 934.36c-3.0625 0-6.125 2.1277-7 6.383 0 2.5532 1.75 7.6596 7 13.617 5.25-5.9574 7-11.064 7-13.617-0.875-4.2553-3.9375-6.383-7-6.383zm0 2.9788c1.933 0 3.5 1.5241 3.5 3.4042s-1.567 3.4043-3.5 3.4043c-1.933 0-3.5-1.5242-3.5-3.4043s1.567-3.4042 3.5-3.4042z"/> <path id="path3378" d="m111 934.36c-3.0625 0-6.4462 2.0741-7 6.383-0.32545 2.5324 1.75 7.6596 7 13.617 5.25-5.9574 7.3254-11.085 7-13.617-0.55376-4.3089-3.9375-6.383-7-6.383zm0 2.9788c1.933 0 3.5 1.5241 3.5 3.4042s-1.567 3.4043-3.5 3.4043c-1.933 0-3.5-1.5242-3.5-3.4043s1.567-3.4042 3.5-3.4042z"/>
</g> </g>
<path id="marker" class="sprite" d="m71.437 11.179c-0.92604 0-1.8521 0.66146-2.1167 1.9844 0 0.79375 0.52917 2.3812 2.1167 4.2333 1.5875-1.8521 2.1167-3.4396 2.1167-4.2333-0.26458-1.3229-1.1906-1.9844-2.1167-1.9844zm0 0.92604c0.5845 0 1.0583 0.47383 1.0583 1.0583 0 0.5845-0.47383 1.0583-1.0583 1.0583-0.5845 0-1.0583-0.47383-1.0583-1.0583 0-0.5845 0.47383-1.0583 1.0583-1.0583z" fill="#4d4d4d"/> <path id="marker" class="sprite" d="m71.437 11.179c-0.92604 0-1.9493 0.64568-2.1167 1.9844-0.09845 0.78762 0.52917 2.3812 2.1167 4.2333 1.5875-1.8521 2.2151-3.4457 2.1167-4.2333-0.16734-1.3387-1.1906-1.9844-2.1167-1.9844zm0 0.92604c0.5845 0 1.0583 0.47383 1.0583 1.0583 0 0.5845-0.47383 1.0583-1.0583 1.0583-0.5845 0-1.0583-0.47383-1.0583-1.0583 0-0.5845 0.47383-1.0583 1.0583-1.0583z" fill="#4d4d4d"/>
<path id="polyline" class="sprite" d="m69.056 58.737v1.0583h1.0583v-0.22324l2.6458 1.0583v0.47129l-1.8769 2.927h-0.76894v1.0583h1.0583v-1.0253l1.8769-2.9435h0.76894v-1.0583h-1.0583v0.28112l-2.6458-1.0583v-0.5457h-0.92604zm0.26458 0.26458h0.52917v0.52917h-0.52917zm3.7042 1.3229h0.52917v0.52917h-0.52917zm-2.6458 3.9688h0.52917v0.52917h-0.52917z" fill="#4d4d4d" stroke-width=".26458"/> <path id="polyline" class="sprite" d="m69.056 58.737v1.0583h1.0583v-0.22324l2.6458 1.0583v0.47129l-1.8769 2.927h-0.76894v1.0583h1.0583v-1.0253l1.8769-2.9435h0.76894v-1.0583h-1.0583v0.28112l-2.6458-1.0583v-0.5457h-0.92604zm0.26458 0.26458h0.52917v0.52917h-0.52917zm3.7042 1.3229h0.52917v0.52917h-0.52917zm-2.6458 3.9688h0.52917v0.52917h-0.52917z" fill="#4d4d4d" stroke-width=".26458"/>
<path id="polygon" class="sprite" d="m69.321 39.952v1.0583h0.47956l-0.42168 3.7042h-0.58704v1.0583h1.0583v-0.55396l2.6458-0.1819v0.47128h1.0583v-1.0583h-0.43822l0.3638-2.1167h0.60358v-1.0583h-1.0583v0.34726l-2.6458-0.95083v-0.71935h-0.92604zm0.26458 0.26458h0.52917v0.52917h-0.52917zm3.7042 1.3229h0.52917v0.52917h-0.52917zm-0.52917 3.175h0.52917v0.52917h-0.52917zm-3.7042 0.26458h0.52917v0.52917h-0.52917z" fill="#4d4d4d" stroke-width=".26458"/> <path id="polygon" class="sprite" d="m69.321 39.952v1.0583h0.47956l-0.42168 3.7042h-0.58704v1.0583h1.0583v-0.55396l2.6458-0.1819v0.47128h1.0583v-1.0583h-0.43822l0.3638-2.1167h0.60358v-1.0583h-1.0583v0.34726l-2.6458-0.95083v-0.71935h-0.92604zm0.26458 0.26458h0.52917v0.52917h-0.52917zm3.7042 1.3229h0.52917v0.52917h-0.52917zm-0.52917 3.175h0.52917v0.52917h-0.52917zm-3.7042 0.26458h0.52917v0.52917h-0.52917z" fill="#4d4d4d" stroke-width=".26458"/>
<g id="settings" class="sprite" transform="matrix(.064669 0 0 .064669 11.047 39.636)" fill="#4d4d4d"> <g id="settings" class="sprite" transform="matrix(.064669 0 0 .064669 11.047 39.636)" fill="#4d4d4d">
@ -31,7 +31,7 @@
<path id="permissions" class="sprite" d="m60.085 50.8c-0.89012-0.0021-1.6103 0.71168-1.6123 1.5875 2e-3 0.87776 0.72218 1.5861 1.6123 1.5875 0.59351-8.73e-4 1.1105-0.32112 1.3891-0.79375h0.65319l0.5209-0.50436 0.39688 0.38034 0.38034-0.37207 0.38861 0.38034 0.39688-0.38034 0.38861 0.38034 0.67799-0.65319c0.09761-0.09927 0.10002-0.17419 0-0.27285l-0.55397-0.5457h-3.2411c-0.27712-0.47713-0.79976-0.79498-1.3973-0.79375zm-0.7028 1.1576c0.23396-0.0011 0.4199 0.18746 0.42168 0.42168-0.0017 0.23096-0.18761 0.41954-0.42168 0.42168-0.23793-0.0024-0.43214-0.19072-0.42995-0.42168-0.0022-0.23422 0.19202-0.4228 0.42995-0.42168z" fill="#4d4d4d" stroke-width=".26458"/> <path id="permissions" class="sprite" d="m60.085 50.8c-0.89012-0.0021-1.6103 0.71168-1.6123 1.5875 2e-3 0.87776 0.72218 1.5861 1.6123 1.5875 0.59351-8.73e-4 1.1105-0.32112 1.3891-0.79375h0.65319l0.5209-0.50436 0.39688 0.38034 0.38034-0.37207 0.38861 0.38034 0.39688-0.38034 0.38861 0.38034 0.67799-0.65319c0.09761-0.09927 0.10002-0.17419 0-0.27285l-0.55397-0.5457h-3.2411c-0.27712-0.47713-0.79976-0.79498-1.3973-0.79375zm-0.7028 1.1576c0.23396-0.0011 0.4199 0.18746 0.42168 0.42168-0.0017 0.23096-0.18761 0.41954-0.42168 0.42168-0.23793-0.0024-0.43214-0.19072-0.42995-0.42168-0.0022-0.23422 0.19202-0.4228 0.42995-0.42168z" fill="#4d4d4d" stroke-width=".26458"/>
<polygon id="home" class="sprite" transform="matrix(.0635 0 0 .0635 30.162 20.902)" points="12.5 50 12.5 87.5 43.75 87.5 43.75 62.5 56.25 62.5 56.25 87.5 87.5 87.5 87.5 50 100 50 50 0 0 50" fill="#4d4d4d"/> <polygon id="home" class="sprite" transform="matrix(.0635 0 0 .0635 30.162 20.902)" points="12.5 50 12.5 87.5 43.75 87.5 43.75 62.5 56.25 62.5 56.25 87.5 87.5 87.5 87.5 50 100 50 50 0 0 50" fill="#4d4d4d"/>
<path id="geolocation" class="sprite" d="m7.9375 33.338c0-0.11924-0.0078-0.23671-0.02082-0.35278h-0.35666c-0.1591-1.276-1.1688-2.2856-2.4448-2.4451v-0.35631c-0.11606-0.01304-0.23354-0.02082-0.35278-0.02082s-0.23671 0.0078-0.35278 0.02082v0.35666c-1.276 0.1591-2.2856 1.1688-2.4451 2.4448h-0.3563c-0.01305 0.11606-0.02081 0.23354-0.02081 0.35278 0 0.11924 0.0078 0.23671 0.02081 0.35278h0.35666c0.1591 1.276 1.1688 2.2857 2.4448 2.4451v0.35666c0.11606 0.0127 0.23354 0.02037 0.35278 0.02037s0.23671-0.0077 0.35278-0.0209v-0.35666c1.2756-0.15944 2.2856-1.1688 2.4451-2.4448h0.35666c0.0127-0.11571 0.02046-0.23319 0.02046-0.35278zm-2.8222 2.0849v-0.32104c0-0.19508-0.15804-0.35278-0.35278-0.35278-0.19473 0-0.35278 0.15769-0.35278 0.35278v0.32104c-0.88547-0.14888-1.5829-0.84597-1.7318-1.7318l0.32068-2.65e-4c0.19509 0 0.35278-0.15805 0.35278-0.35278s-0.15769-0.35278-0.35278-0.35278h-0.32103c0.14922-0.88547 0.84667-1.5829 1.7321-1.7321v0.32103c0 0.19473 0.15804 0.35278 0.35278 0.35278 0.19473 0 0.35278-0.15804 0.35278-0.35278v-0.32103c0.88582 0.14887 1.5833 0.84632 1.7321 1.7321h-0.32103c-0.19509 0-0.35278 0.15804-0.35278 0.35278s0.15769 0.35278 0.35278 0.35278l0.32103 2.65e-4c-0.14922 0.88582-0.84631 1.5829-1.7321 1.7318z" fill="#4d4d4d" stroke-width=".26458"/> <path id="geolocation" class="sprite" d="m7.9375 33.338c0-0.11924-0.0078-0.23671-0.02082-0.35278h-0.35666c-0.1591-1.276-1.1688-2.2856-2.4448-2.4451v-0.35631c-0.11606-0.01304-0.23354-0.02082-0.35278-0.02082s-0.23671 0.0078-0.35278 0.02082v0.35666c-1.276 0.1591-2.2856 1.1688-2.4451 2.4448h-0.3563c-0.01305 0.11606-0.02081 0.23354-0.02081 0.35278 0 0.11924 0.0078 0.23671 0.02081 0.35278h0.35666c0.1591 1.276 1.1688 2.2857 2.4448 2.4451v0.35666c0.11606 0.0127 0.23354 0.02037 0.35278 0.02037s0.23671-0.0077 0.35278-0.0209v-0.35666c1.2756-0.15944 2.2856-1.1688 2.4451-2.4448h0.35666c0.0127-0.11571 0.02046-0.23319 0.02046-0.35278zm-2.8222 2.0849v-0.32104c0-0.19508-0.15804-0.35278-0.35278-0.35278-0.19473 0-0.35278 0.15769-0.35278 0.35278v0.32104c-0.88547-0.14888-1.5829-0.84597-1.7318-1.7318l0.32068-2.65e-4c0.19509 0 0.35278-0.15805 0.35278-0.35278s-0.15769-0.35278-0.35278-0.35278h-0.32103c0.14922-0.88547 0.84667-1.5829 1.7321-1.7321v0.32103c0 0.19473 0.15804 0.35278 0.35278 0.35278 0.19473 0 0.35278-0.15804 0.35278-0.35278v-0.32103c0.88582 0.14887 1.5833 0.84632 1.7321 1.7321h-0.32103c-0.19509 0-0.35278 0.15804-0.35278 0.35278s0.15769 0.35278 0.35278 0.35278l0.32103 2.65e-4c-0.14922 0.88582-0.84631 1.5829-1.7321 1.7318z" fill="#4d4d4d" stroke-width=".26458"/>
<g id="share" class="sprite" transform="matrix(.26458 0 0 .26458 -2.6458 -229.23)"> <g id="share" class="sprite" transform="matrix(.26458 0 0 .26458 -21.696 -210.18)">
<circle id="path4309" cx="100" cy="992.36" r="11" fill="none" stroke="#464646" stroke-width="2"/> <circle id="path4309" cx="100" cy="992.36" r="11" fill="none" stroke="#464646" stroke-width="2"/>
<circle id="path4819" transform="rotate(248.18)" cx="-963.89" cy="-276.04" r="2.5" fill="#464646"/> <circle id="path4819" transform="rotate(248.18)" cx="-963.89" cy="-276.04" r="2.5" fill="#464646"/>
<circle id="path4819-2" transform="rotate(248.18)" cx="-956.38" cy="-281.16" r="2.5" fill="#464646"/> <circle id="path4819-2" transform="rotate(248.18)" cx="-956.38" cy="-281.16" r="2.5" fill="#464646"/>
@ -47,7 +47,7 @@
<path id="path5801" d="m36.287 38.821c-0.45737 0.45258-0.51256 0.50483-0.93876 0.93452l1.3111-0.30964c0.03951-0.17777 0.08574-0.39794 0.09827-0.44962-0.20697-7e-3 -0.32498-0.0729-0.47056-0.17526zm1.4165-0.51574c-0.04859 0.57856-0.30047 0.62169-0.77774 0.69763-0.034 0.15229-0.05699 0.25818-0.0969 0.43779l1.224 0.30398c0.16421-0.70158 0.29613-1.2699 0.29325-1.2731-0.0043-0.0046-0.32763-0.08748-0.6426-0.16631zm-0.58777-0.14159c-0.0016 0.0027-0.06999 0.30471-0.1581 0.6989 0.55906-0.08996 0.57597-0.27099 0.59287-0.59497-0.2294-0.05691-0.43229-0.10608-0.43477-0.10392zm-0.16448-0.0092c-0.13598 0.01159-0.20407 0.02561-0.35317 0.06753 0.04792 0.09125 0.07023 0.27883-0.20004 0.49792 0.14156 0.08791 0.26526 0.12201 0.39001 0.13735 0.11436-0.5324 0.17296-0.61535 0.1632-0.70284zm-2.6775-0.0065-0.23715 0.94314 0.8058-0.79894c-0.18084-0.04602-0.34599-0.08797-0.56865-0.1442zm5.6125-0.03249c-0.75018 0.19483-1.3621 0.35585-1.3642 0.35855-0.0019 0.0027-0.13728 0.57465-0.30345 1.2809l1.3375-0.33256zm-2.1828-0.19747v0.21176c0.2765 0.0699 0.56006 0.13964 0.61837 0.14029 0 0-0.03096-0.12652-0.06757-0.2832h-0.0026c-0.23872 0.0062-0.32188-0.0081-0.54825-0.06885zm-0.67957-0.31568-0.0026 0.0027 0.09817 0.38583c0.02307-0.0027 0.215 0.04675 0.43095 0.10131 2.4e-5 -0.0864 1.64e-4 -0.15711 0.0013-0.21952-0.18513-0.06365-0.36302-0.15391-0.52785-0.27023zm-2.8662-0.12471 0.13133 0.50016s0.36398 0.08961 0.69742 0.17148l0.03825-0.03769c-0.49456-0.17868-0.50142-0.55268-0.867-0.63396zm5.5794-0.11172c-0.49436 0.4184-0.75886 0.52502-1.3145 0.61446 0.03396 0.13897 0.06369 0.25816 0.07268 0.28581 0.0076 0.02345 0.46733-0.08354 1.3885-0.32089zm-3.2079-0.25462c-0.06109-0.08511-0.11524-0.17367-0.16192-0.26503-0.35986 0.0798-0.95298 0.22249-0.97027 0.23775-0.0073 0.0065 0.04546 0.24465 0.11857 0.54044 0.17884-0.16801 0.38427-0.13773 0.52049-0.04456m0.50728 0.49614c0.125-0.04259 0.29706-0.07581 0.40659-0.08915-0.01373-0.10039-0.0232-0.16366-0.06247-0.26762m-2.9108-0.98342 0.13133 0.52874c0.66252 0.256 0.71188 0.76848 1.0672 0.69763l0.22822-0.22605c-0.07081-0.29894-0.15348-0.61368-0.1734-0.63396-0.0046-0.0046-1.2533-0.36637-1.2533-0.36637zm2.1866-1.1406-0.4437 0.11172c-0.09333 0.39866-0.21902 0.89726-0.29452 1.1926 0.36387-0.10263 0.46268-0.12417 0.8721-0.20785-0.14371-0.34911-0.18889-0.72844-0.13387-1.0964zm-1.8742-0.28581-0.31365 1.2497c0.48303 0.13938 0.76356 0.21858 1.252 0.33515 0.10314-0.32458 0.21945-0.68316 0.30345-1.1978-0.32576-0.10325-0.52105-0.16679-1.2418-0.38712zm2.3511-1.4147-1.2202 0.30269c0.17212 0.76144 0.29818 1.3051 0.306 1.3134 0.0075 0.0078 0.22525-0.03952 0.47302-0.09743 0.11655-0.47002 0.21792-0.6329 0.56355-0.98989-0.03709-0.16213-0.07823-0.3396-0.1224-0.52874zm0.1632-0.01698c0.05038 0.21499 0.05503 0.2305 0.09945 0.41961 0.14044-0.11506 0.29321-0.20863 0.45262-0.2819zm-2.8522 0 0.31875 1.2497c0.7 0.21006 1.2587 0.37524 1.2622 0.37154 0.0038-4e-3 -0.12334-0.58605-0.28305-1.3095zm5.6049-0.01159-0.49342 0.1221c0.22714 0.09573 0.44034 0.23324 0.62857 0.41182zm-2.7174 2.3343c0.10949 0.68124 0.84234 1.1934 1.6065 1.1085 0.28504-0.6862 0.48458-0.65293 0.59454-1.3403 0.0044-0.61101-0.78411-0.23411-1.1425-0.2147-0.61562-0.01995-0.58498-0.75842-0.65178-0.86766-0.19007 0.14237-0.52182 0.58737-0.40673 1.3141zm0.70296-1.5496c0.20064 0.64566 0.24369 0.86631 0.88357 0.61317 0.48132-0.14218 0.86499 0.05125 0.9273 0.28328 0.10209 0.34596-0.06402 0.85291-0.5091 1.642 0.69715-0.37944 0.91768-1.2092 0.66726-1.846-0.34115-0.72645-1.1354-1.0878-1.969-0.69246z"/> <path id="path5801" d="m36.287 38.821c-0.45737 0.45258-0.51256 0.50483-0.93876 0.93452l1.3111-0.30964c0.03951-0.17777 0.08574-0.39794 0.09827-0.44962-0.20697-7e-3 -0.32498-0.0729-0.47056-0.17526zm1.4165-0.51574c-0.04859 0.57856-0.30047 0.62169-0.77774 0.69763-0.034 0.15229-0.05699 0.25818-0.0969 0.43779l1.224 0.30398c0.16421-0.70158 0.29613-1.2699 0.29325-1.2731-0.0043-0.0046-0.32763-0.08748-0.6426-0.16631zm-0.58777-0.14159c-0.0016 0.0027-0.06999 0.30471-0.1581 0.6989 0.55906-0.08996 0.57597-0.27099 0.59287-0.59497-0.2294-0.05691-0.43229-0.10608-0.43477-0.10392zm-0.16448-0.0092c-0.13598 0.01159-0.20407 0.02561-0.35317 0.06753 0.04792 0.09125 0.07023 0.27883-0.20004 0.49792 0.14156 0.08791 0.26526 0.12201 0.39001 0.13735 0.11436-0.5324 0.17296-0.61535 0.1632-0.70284zm-2.6775-0.0065-0.23715 0.94314 0.8058-0.79894c-0.18084-0.04602-0.34599-0.08797-0.56865-0.1442zm5.6125-0.03249c-0.75018 0.19483-1.3621 0.35585-1.3642 0.35855-0.0019 0.0027-0.13728 0.57465-0.30345 1.2809l1.3375-0.33256zm-2.1828-0.19747v0.21176c0.2765 0.0699 0.56006 0.13964 0.61837 0.14029 0 0-0.03096-0.12652-0.06757-0.2832h-0.0026c-0.23872 0.0062-0.32188-0.0081-0.54825-0.06885zm-0.67957-0.31568-0.0026 0.0027 0.09817 0.38583c0.02307-0.0027 0.215 0.04675 0.43095 0.10131 2.4e-5 -0.0864 1.64e-4 -0.15711 0.0013-0.21952-0.18513-0.06365-0.36302-0.15391-0.52785-0.27023zm-2.8662-0.12471 0.13133 0.50016s0.36398 0.08961 0.69742 0.17148l0.03825-0.03769c-0.49456-0.17868-0.50142-0.55268-0.867-0.63396zm5.5794-0.11172c-0.49436 0.4184-0.75886 0.52502-1.3145 0.61446 0.03396 0.13897 0.06369 0.25816 0.07268 0.28581 0.0076 0.02345 0.46733-0.08354 1.3885-0.32089zm-3.2079-0.25462c-0.06109-0.08511-0.11524-0.17367-0.16192-0.26503-0.35986 0.0798-0.95298 0.22249-0.97027 0.23775-0.0073 0.0065 0.04546 0.24465 0.11857 0.54044 0.17884-0.16801 0.38427-0.13773 0.52049-0.04456m0.50728 0.49614c0.125-0.04259 0.29706-0.07581 0.40659-0.08915-0.01373-0.10039-0.0232-0.16366-0.06247-0.26762m-2.9108-0.98342 0.13133 0.52874c0.66252 0.256 0.71188 0.76848 1.0672 0.69763l0.22822-0.22605c-0.07081-0.29894-0.15348-0.61368-0.1734-0.63396-0.0046-0.0046-1.2533-0.36637-1.2533-0.36637zm2.1866-1.1406-0.4437 0.11172c-0.09333 0.39866-0.21902 0.89726-0.29452 1.1926 0.36387-0.10263 0.46268-0.12417 0.8721-0.20785-0.14371-0.34911-0.18889-0.72844-0.13387-1.0964zm-1.8742-0.28581-0.31365 1.2497c0.48303 0.13938 0.76356 0.21858 1.252 0.33515 0.10314-0.32458 0.21945-0.68316 0.30345-1.1978-0.32576-0.10325-0.52105-0.16679-1.2418-0.38712zm2.3511-1.4147-1.2202 0.30269c0.17212 0.76144 0.29818 1.3051 0.306 1.3134 0.0075 0.0078 0.22525-0.03952 0.47302-0.09743 0.11655-0.47002 0.21792-0.6329 0.56355-0.98989-0.03709-0.16213-0.07823-0.3396-0.1224-0.52874zm0.1632-0.01698c0.05038 0.21499 0.05503 0.2305 0.09945 0.41961 0.14044-0.11506 0.29321-0.20863 0.45262-0.2819zm-2.8522 0 0.31875 1.2497c0.7 0.21006 1.2587 0.37524 1.2622 0.37154 0.0038-4e-3 -0.12334-0.58605-0.28305-1.3095zm5.6049-0.01159-0.49342 0.1221c0.22714 0.09573 0.44034 0.23324 0.62857 0.41182zm-2.7174 2.3343c0.10949 0.68124 0.84234 1.1934 1.6065 1.1085 0.28504-0.6862 0.48458-0.65293 0.59454-1.3403 0.0044-0.61101-0.78411-0.23411-1.1425-0.2147-0.61562-0.01995-0.58498-0.75842-0.65178-0.86766-0.19007 0.14237-0.52182 0.58737-0.40673 1.3141zm0.70296-1.5496c0.20064 0.64566 0.24369 0.86631 0.88357 0.61317 0.48132-0.14218 0.86499 0.05125 0.9273 0.28328 0.10209 0.34596-0.06402 0.85291-0.5091 1.642 0.69715-0.37944 0.91768-1.2092 0.66726-1.846-0.34115-0.72645-1.1354-1.0878-1.969-0.69246z"/>
</g> </g>
<g id="delete-marker" class="sprite" transform="matrix(.26458 0 0 .26458 23.529 -228.26)" fill="#4d4d4d"> <g id="delete-marker" class="sprite" transform="matrix(.26458 0 0 .26458 23.529 -228.26)" fill="#4d4d4d">
<path id="path3378-6" d="m178.57 979.22c-3.0625 0-6.125 2.1197-7 6.375 0 2.5532 1.75 7.6676 7 13.625 3.4166-3.877 5.3157-7.3755 6.25-10.062-1.3142-0.1622-2.497-0.7235-3.4062-1.5938-0.63462 0.8653-1.6677 1.4375-2.8438 1.4375-1.933 0-3.5-1.5261-3.5-3.4062s1.567-3.4063 3.5-3.4063c0.36776 0 0.72951 0.085 1.0625 0.1875 0.14352-1.0312 0.55799-1.956 1.1562-2.75-0.72276-0.259-1.4631-0.4062-2.2188-0.4062z"/> <path id="path3378-6" d="m178.57 979.22c-3.0625 0-6.4462 2.0661-7 6.375-0.32545 2.5324 1.75 7.6676 7 13.625 3.4166-3.877 5.3157-7.3755 6.25-10.062-1.3142-0.1622-2.497-0.7235-3.4062-1.5938-0.63462 0.8653-1.6677 1.4375-2.8438 1.4375-1.933 0-3.5-1.5261-3.5-3.4062s1.567-3.4063 3.5-3.4063c0.36776 0 0.72951 0.085 1.0625 0.1875 0.14352-1.0312 0.55799-1.956 1.1562-2.75-0.72276-0.259-1.4631-0.4062-2.2188-0.4062z"/>
<path id="path6764" d="m185.57 978.22c-2.7614 0-5 2.2386-5 5 0 2.7615 2.2386 5 5 5s5-2.2385 5-5c0-2.7614-2.2386-5-5-5zm-1.8182 2.2727 1.8182 1.8182 1.8182-1.8182 0.90909 0.9091-1.8182 1.8182 1.8182 1.8182-0.90909 0.9091-1.8182-1.8182-1.8182 1.8182-0.90909-0.9091 1.8182-1.8182-1.8182-1.8182z"/> <path id="path6764" d="m185.57 978.22c-2.7614 0-5 2.2386-5 5 0 2.7615 2.2386 5 5 5s5-2.2385 5-5c0-2.7614-2.2386-5-5-5zm-1.8182 2.2727 1.8182 1.8182 1.8182-1.8182 0.90909 0.9091-1.8182 1.8182 1.8182 1.8182-0.90909 0.9091-1.8182-1.8182-1.8182 1.8182-0.90909-0.9091 1.8182-1.8182-1.8182-1.8182z"/>
</g> </g>
<g id="multipolygon" class="sprite" transform="matrix(.26458 0 0 .26458 66.121 -220.76)" fill="#4d4d4d"> <g id="multipolygon" class="sprite" transform="matrix(.26458 0 0 .26458 66.121 -220.76)" fill="#4d4d4d">
@ -97,5 +97,6 @@
<path id="path3789" d="m9 1046h-2.3698v-0.3223c0-0.3596 0.072207-0.6775 0.21663-0.9539 0.14442-0.2807 0.44857-0.636 0.91247-1.0658l0.42013-0.3816c0.24945-0.228 0.43107-0.4429 0.54486-0.6446 0.11816-0.2019 0.17724-0.4036 0.17724-0.6053-4.6e-6 -0.3071-0.10504-0.5462-0.3151-0.7171-0.21007-0.1756-0.50329-0.2632-0.87965-0.2632-0.35449 0-0.73742 0.075-1.1488 0.2237-0.41138 0.1446-0.84026 0.3618-1.2867 0.6513v-2.0659c0.52954-0.184 1.0131-0.32 1.4508-0.4077 0.43763-0.088 0.85995-0.1317 1.267-0.1317 1.0678 0 1.8818 0.2194 2.442 0.6579 0.56017 0.4341 0.84026 1.0702 0.84026 1.9078-7e-6 0.4298-0.08535 0.8159-0.25602 1.158-0.17068 0.3377-0.46171 0.7017-0.87308 1.092l-0.42013 0.375c-0.2976 0.272-0.49235 0.4913-0.58425 0.658-0.091909 0.1622-0.13786 0.342-0.13786 0.5394v0.296m-2.3698 0.9739h2.3698v2.342h-2.3698v-2.342" fill="#4d4d4d" stroke-width=".75"/> <path id="path3789" d="m9 1046h-2.3698v-0.3223c0-0.3596 0.072207-0.6775 0.21663-0.9539 0.14442-0.2807 0.44857-0.636 0.91247-1.0658l0.42013-0.3816c0.24945-0.228 0.43107-0.4429 0.54486-0.6446 0.11816-0.2019 0.17724-0.4036 0.17724-0.6053-4.6e-6 -0.3071-0.10504-0.5462-0.3151-0.7171-0.21007-0.1756-0.50329-0.2632-0.87965-0.2632-0.35449 0-0.73742 0.075-1.1488 0.2237-0.41138 0.1446-0.84026 0.3618-1.2867 0.6513v-2.0659c0.52954-0.184 1.0131-0.32 1.4508-0.4077 0.43763-0.088 0.85995-0.1317 1.267-0.1317 1.0678 0 1.8818 0.2194 2.442 0.6579 0.56017 0.4341 0.84026 1.0702 0.84026 1.9078-7e-6 0.4298-0.08535 0.8159-0.25602 1.158-0.17068 0.3377-0.46171 0.7017-0.87308 1.092l-0.42013 0.375c-0.2976 0.272-0.49235 0.4913-0.58425 0.658-0.091909 0.1622-0.13786 0.342-0.13786 0.5394v0.296m-2.3698 0.9739h2.3698v2.342h-2.3698v-2.342" fill="#4d4d4d" stroke-width=".75"/>
</g> </g>
</g> </g>
<path id="copy" d="m42.218 69.321v1.2884h1.4725v1.4725h1.2884v-2.7609zm-1.4725 1.4725v2.7609h2.7609v-2.7609z" fill="#4d4d4d" stroke-width=".26458" style="paint-order:fill markers stroke"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" version="1.1" id="svg3" sodipodi:docname="home.svg" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs3" />
<sodipodi:namedview id="namedview3" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="18.394737" inkscape:cx="19" inkscape:cy="19.027182" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg3" />
<path d="M14.2749 9C12.0205 10.0243 10.1979 11.7511 9.10659 13.8966C8.01529 16.042 7.72026 18.4785 8.27002 20.8054C8.81977 23.1324 10.1816 25.2114 12.1316 26.7006C14.0816 28.1898 16.5038 29.0007 19 29C10.4948 21.4138 8.53607 12.0542 14.2749 9ZM19 29C21.4962 29.0007 23.9184 28.1898 25.8684 26.7006C27.8184 25.2114 29.1802 23.1324 29.73 20.8054C30.2797 18.4785 29.9847 16.042 28.8934 13.8966C27.8021 11.7511 25.9795 10.0243 23.7251 9C29.4639 12.0542 27.5052 21.4138 19 29Z" fill="#263B58" id="path2" />
<path d="M23.072 13.532C23.072 14.0431 22.9666 14.5491 22.762 15.0213C22.5574 15.4934 22.2574 15.9224 21.8793 16.2838C21.5011 16.6452 21.0522 16.9318 20.5582 17.1274C20.0641 17.323 19.5346 17.4236 18.9998 17.4236C18.465 17.4236 17.9355 17.323 17.4415 17.1274C16.9474 16.9318 16.4985 16.6452 16.1203 16.2838C15.7422 15.9224 15.4423 15.4934 15.2376 15.0213C15.033 14.5491 14.9276 14.0431 14.9276 13.532C14.9276 12.4999 15.3567 11.51 16.1203 10.7802C16.884 10.0504 17.9198 9.64039 18.9998 9.64039C20.0798 9.64039 21.1156 10.0504 21.8793 10.7802C22.6429 11.51 23.072 12.4999 23.072 13.532Z" fill="#263B58" id="path3" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" fill="none"><path fill="#bebebe" d="M40 0H10C4.477 0 0 4.477 0 10v30c0 5.523 4.477 10 10 10h30c5.523 0 10-4.477 10-10V10c0-5.523-4.477-10-10-10z" style="stroke-width:1"/><path fill="#bfbfbf" fill-opacity=".9" fill-rule="evenodd" d="M29.023 20.012v6.053a1.226 1.226 0 0 0 2.451 0v-6.053a1.226 1.226 0 0 0-2.451 0z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#E1000F" fill-opacity=".9" fill-rule="evenodd" d="m24.393 18.047 5.242 3.027a1.226 1.226 0 0 0 1.225-2.123l-5.241-3.027a1.226 1.226 0 0 0-1.226 2.123z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#000091" fill-opacity=".9" fill-rule="evenodd" d="m29.635 25.004-5.242 3.026a1.226 1.226 0 0 0 1.226 2.123l5.241-3.027a1.226 1.226 0 0 0-1.225-2.122z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#bfbfbf" fill-opacity=".9" fill-rule="evenodd" d="M20.99 26.065v-6.053a1.226 1.226 0 0 0-2.451 0v6.053a1.226 1.226 0 0 0 2.451 0z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#000091" fill-opacity=".9" fill-rule="evenodd" d="m20.377 21.074 5.242-3.027a1.226 1.226 0 0 0-1.226-2.123l-5.241 3.027a1.226 1.226 0 0 0 1.225 2.123z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#E1000F" fill-opacity=".9" fill-rule="evenodd" d="m14.934 27.326 4.84-.035a1.226 1.226 0 0 0-.018-2.452l-4.84.035a1.226 1.226 0 0 0 .018 2.452z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#bfbfbf" fill-opacity=".9" fill-rule="evenodd" d="M18.62 14.22A9.977 9.977 0 0 1 25 11.924c2.424 0 4.648.864 6.38 2.298a1.226 1.226 0 0 0 1.564-1.888A12.417 12.417 0 0 0 25 9.471a12.417 12.417 0 0 0-7.944 2.862 1.226 1.226 0 0 0 1.564 1.888z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#000091" fill-opacity=".9" fill-rule="evenodd" d="M16.022 25.565c-.622-1.309-1.035-2.553-1.035-3.628a9.998 9.998 0 0 1 3.632-7.716 1.225 1.225 0 1 0-1.563-1.888 12.443 12.443 0 0 0-4.52 9.604c0 1.385.473 2.997 1.271 4.679a1.226 1.226 0 0 0 2.215-1.051z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#E1000F" fill-opacity=".9" fill-rule="evenodd" d="M31.38 14.221a9.997 9.997 0 0 1 3.633 7.716c0 1.682-.967 3.75-2.248 5.846-3.235 5.298-8.629 10.652-8.629 10.652a1.224 1.224 0 1 0 1.728 1.737s5.62-5.586 8.993-11.11c1.551-2.541 2.607-5.087 2.607-7.125 0-3.861-1.759-7.318-4.52-9.604a1.226 1.226 0 0 0-1.564 1.888z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/><path fill="#000091" fill-opacity=".9" fill-rule="evenodd" d="M25.864 38.435s-3.874-3.85-7.03-8.252a1.227 1.227 0 0 0-1.992 1.427c3.275 4.57 7.294 8.562 7.294 8.562.48.478 1.257.475 1.734-.006a1.224 1.224 0 0 0-.006-1.731z" clip-rule="evenodd" style="fill:#323737;fill-opacity:1;stroke-width:1"/></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1,6 +1,3 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15">
<svg version="1.1" id="circle" width="15" height="15" viewBox="0 0 15 15" sodipodi:docname="marker.svg" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <path d="M14 7.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0z" fill="#fff" stroke="#3e4444" stroke-width=".5"/>
<defs id="defs1" />
<sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="53.666667" inkscape:cx="7.4906832" inkscape:cy="7.5" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="circle" />
<path d="M14,7.5c0,3.5899-2.9101,6.5-6.5,6.5S1,11.0899,1,7.5S3.9101,1,7.5,1S14,3.9101,14,7.5z" id="path1" style="fill:#ffffff" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 199 B

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg width="192" height="192" id="svg2" version="1.1" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="16-white.svg" inkscape:export-filename="16-white.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <svg width="216" height="192" id="svg2" version="1.1" inkscape:version="1.4.1 (93de688d07, 2025-03-30)" sodipodi:docname="16-white.svg" inkscape:export-filename="16-white.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs id="defs4"> <defs id="defs4">
<clipPath id="clip0_241_10857"> <clipPath id="clip0_241_10857">
<rect width="18.049999" height="19.01" fill="#ffffff" id="rect586" x="0" y="0" /> <rect width="18.049999" height="19.01" fill="#ffffff" id="rect586" x="0" y="0" />
@ -18,8 +18,14 @@
<clipPath id="clip0_2695_1939"> <clipPath id="clip0_2695_1939">
<rect width="20" height="20" fill="#ffffff" id="rect1" x="0" y="0" /> <rect width="20" height="20" fill="#ffffff" id="rect1" x="0" y="0" />
</clipPath> </clipPath>
<clipPath id="clip0_3071_861">
<rect width="18" height="20" fill="#ffffff" id="rect3" x="0" y="0" />
</clipPath>
<clipPath id="clip0_241_10857-3">
<rect width="18.049999" height="19.01" fill="#ffffff" id="rect586-6" x="0" y="0" />
</clipPath>
</defs> </defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="2.9474763" inkscape:cx="149.28025" inkscape:cy="54.623002" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" inkscape:snap-grids="true" inkscape:snap-to-guides="true" inkscape:showpageshadow="2" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1"> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="25.78129" inkscape:cx="104.97923" inkscape:cy="178.69548" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" inkscape:snap-grids="true" inkscape:snap-to-guides="true" inkscape:showpageshadow="2" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1">
<inkscape:grid type="xygrid" id="grid3004" empspacing="4" visible="true" enabled="true" snapvisiblegridlinesonly="true" originx="0" originy="0" spacingy="1" spacingx="1" units="px" /> <inkscape:grid type="xygrid" id="grid3004" empspacing="4" visible="true" enabled="true" snapvisiblegridlinesonly="true" originx="0" originy="0" spacingy="1" spacingx="1" units="px" />
<inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="24" spacingy="24" empcolor="#203fff" empopacity="0.85490196" color="#3f3fff" opacity="0.1254902" empspacing="1" enabled="true" visible="true" /> <inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="24" spacingy="24" empcolor="#203fff" empopacity="0.85490196" color="#3f3fff" opacity="0.1254902" empspacing="1" enabled="true" visible="true" />
</sodipodi:namedview> </sodipodi:namedview>
@ -75,9 +81,12 @@
</g> </g>
</g> </g>
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 108.14555,816.36218 v 3.8267 h 3.85445 v -3.8267 z m 0.51755,4.35174 -1.24591,2.31321 1.16687,0.61848 1.24404,-2.31507 z m -1.86888,3.47168 -0.27666,0.51571 h -2.42597 v 2.24408 l -4.09159,4.06399 1.36261,1.3528 3.86198,-3.83417 h 2.72145 v -3.6959 l 0.015,-0.028 -0.015,-0.008 v -0.0953 h -0.17879 l -0.97303,-0.51571 z" id="path4873" inkscape:connector-curvature="0" /> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 108.14555,816.36218 v 3.8267 h 3.85445 v -3.8267 z m 0.51755,4.35174 -1.24591,2.31321 1.16687,0.61848 1.24404,-2.31507 z m -1.86888,3.47168 -0.27666,0.51571 h -2.42597 v 2.24408 l -4.09159,4.06399 1.36261,1.3528 3.86198,-3.83417 h 2.72145 v -3.6959 l 0.015,-0.028 -0.015,-0.008 v -0.0953 h -0.17879 l -0.97303,-0.51571 z" id="path4873" inkscape:connector-curvature="0" />
<g id="g4244" transform="matrix(0.51357238,-0.54309229,0.54309229,0.51357238,-518.0199,506.22551)"> <g id="g4244" transform="matrix(0.51357238,-0.54309229,0.54309229,0.51357238,-590.0195,601.72586)">
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#999999;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 220.49219,133.52344 c -0.33017,0.01 -0.66239,0.0456 -0.99414,0.10742 -2.22487,0.41425 -4.02666,1.95747 -4.83203,4.00976 l -0.87696,-1.8164 a 0.50004998,0.50004998 0 0 0 -0.83398,-0.11328 0.50004998,0.50004998 0 0 0 -0.0664,0.54883 l 1.45899,3.01953 a 0.50004998,0.50004998 0 0 0 0.60742,0.25586 l 2.84375,-0.94532 a 0.50028339,0.50028339 0 1 0 -0.31641,-0.94922 l -2.00195,0.66797 c 0.61312,-1.89015 2.20733,-3.32407 4.20117,-3.69531 2.24744,-0.41845 4.51458,0.59912 5.69531,2.55664 1.18073,1.95754 1.02202,4.43774 -0.39648,6.23047 -1.41851,1.79275 -3.79606,2.51535 -5.97266,1.81641 a 0.50004998,0.50004998 0 1 0 -0.30469,0.95117 c 2.57038,0.82539 5.38736,-0.0294 7.0625,-2.14649 0.4188,-0.52924 0.74532,-1.11137 0.97657,-1.7207 0.69373,-1.828 0.53599,-3.91467 -0.50977,-5.64844 -1.22005,-2.02271 -3.42908,-3.19767 -5.74023,-3.1289 z" transform="matrix(0.91921787,0.9720541,-0.9720541,0.91921787,152.1356,647.93271)" id="path4240" inkscape:connector-curvature="0" /> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#999999;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 220.49219,133.52344 c -0.33017,0.01 -0.66239,0.0456 -0.99414,0.10742 -2.22487,0.41425 -4.02666,1.95747 -4.83203,4.00976 l -0.87696,-1.8164 a 0.50004998,0.50004998 0 0 0 -0.83398,-0.11328 0.50004998,0.50004998 0 0 0 -0.0664,0.54883 l 1.45899,3.01953 a 0.50004998,0.50004998 0 0 0 0.60742,0.25586 l 2.84375,-0.94532 a 0.50028339,0.50028339 0 1 0 -0.31641,-0.94922 l -2.00195,0.66797 c 0.61312,-1.89015 2.20733,-3.32407 4.20117,-3.69531 2.24744,-0.41845 4.51458,0.59912 5.69531,2.55664 1.18073,1.95754 1.02202,4.43774 -0.39648,6.23047 -1.41851,1.79275 -3.79606,2.51535 -5.97266,1.81641 a 0.50004998,0.50004998 0 1 0 -0.30469,0.95117 c 2.57038,0.82539 5.38736,-0.0294 7.0625,-2.14649 0.4188,-0.52924 0.74532,-1.11137 0.97657,-1.7207 0.69373,-1.828 0.53599,-3.91467 -0.50977,-5.64844 -1.22005,-2.02271 -3.42908,-3.19767 -5.74023,-3.1289 z" transform="matrix(0.91921787,0.9720541,-0.9720541,0.91921787,152.1356,647.93271)" id="path4240" inkscape:connector-curvature="0" />
</g> </g>
<g id="g4244-6" transform="matrix(-0.51357238,-0.54309229,-0.54309229,0.51357238,734.0195,601.72586)">
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#999999;stroke-width:0.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 220.49219,133.52344 c -0.33017,0.01 -0.66239,0.0456 -0.99414,0.10742 -2.22487,0.41425 -4.02666,1.95747 -4.83203,4.00976 l -0.87696,-1.8164 a 0.50004998,0.50004998 0 0 0 -0.83398,-0.11328 0.50004998,0.50004998 0 0 0 -0.0664,0.54883 l 1.45899,3.01953 a 0.50004998,0.50004998 0 0 0 0.60742,0.25586 l 2.84375,-0.94532 a 0.50028339,0.50028339 0 1 0 -0.31641,-0.94922 l -2.00195,0.66797 c 0.61312,-1.89015 2.20733,-3.32407 4.20117,-3.69531 2.24744,-0.41845 4.51458,0.59912 5.69531,2.55664 1.18073,1.95754 1.02202,4.43774 -0.39648,6.23047 -1.41851,1.79275 -3.79606,2.51535 -5.97266,1.81641 a 0.50004998,0.50004998 0 1 0 -0.30469,0.95117 c 2.57038,0.82539 5.38736,-0.0294 7.0625,-2.14649 0.4188,-0.52924 0.74532,-1.11137 0.97657,-1.7207 0.69373,-1.828 0.53599,-3.91467 -0.50977,-5.64844 -1.22005,-2.02271 -3.42908,-3.19767 -5.74023,-3.1289 z" transform="matrix(0.91921787,0.9720541,-0.9720541,0.91921787,152.1356,647.93271)" id="path4240-7" inkscape:connector-curvature="0" />
</g>
<g id="delete-vertex" transform="translate(-90,-64)"> <g id="delete-vertex" transform="translate(-90,-64)">
<path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#999999;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 227.55273,53.105469 -6.05468,3.027343 h -3.44141 v 3.517579 l -2.95117,5.902343 1.78906,0.894532 3.15625,-6.314454 h 2.00586 v -2.042968 l 6.39063,-3.195313 z" transform="translate(0,852.36218)" id="path4349-2-2-9-3-8-3-5" inkscape:connector-curvature="0" /> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#999999;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 227.55273,53.105469 -6.05468,3.027343 h -3.44141 v 3.517579 l -2.95117,5.902343 1.78906,0.894532 3.15625,-6.314454 h 2.00586 v -2.042968 l 6.39063,-3.195313 z" transform="translate(0,852.36218)" id="path4349-2-2-9-3-8-3-5" inkscape:connector-curvature="0" />
<path sodipodi:nodetypes="cc" style="fill:none;stroke:#ffffff;stroke-width:2.482;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 217,907.36218 6,6" id="path4353-1-6-1-3-5-1-9" inkscape:connector-curvature="0" /> <path sodipodi:nodetypes="cc" style="fill:none;stroke:#ffffff;stroke-width:2.482;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 217,907.36218 6,6" id="path4353-1-6-1-3-5-1-9" inkscape:connector-curvature="0" />
@ -151,6 +160,10 @@
<path d="m 1.07001,4.41003 h 9.41999 c 0.9234,-0.0066 1.8391,0.16957 2.6941,0.5184 0.8551,0.34883 1.6327,0.8634 2.288,1.51407 0.6553,0.65067 1.1754,1.42458 1.5303,2.27713 0.3549,0.85256 0.5376,1.76697 0.5376,2.69037 0.0067,0.9277 -0.1712,1.8474 -0.5231,2.7058 -0.3519,0.8583 -0.871,1.6382 -1.527,2.2941 -0.656,0.656 -1.4358,1.1751 -2.2941,1.527 -0.8584,0.352 -1.7781,0.5298 -2.7058,0.5231 h -9.41999" stroke="#f2f2f2" stroke-miterlimit="10" id="path580" style="fill:none;stroke:#f2f2f2;stroke-width:1.45486;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> <path d="m 1.07001,4.41003 h 9.41999 c 0.9234,-0.0066 1.8391,0.16957 2.6941,0.5184 0.8551,0.34883 1.6327,0.8634 2.288,1.51407 0.6553,0.65067 1.1754,1.42458 1.5303,2.27713 0.3549,0.85256 0.5376,1.76697 0.5376,2.69037 0.0067,0.9277 -0.1712,1.8474 -0.5231,2.7058 -0.3519,0.8583 -0.871,1.6382 -1.527,2.2941 -0.656,0.656 -1.4358,1.1751 -2.2941,1.527 -0.8584,0.352 -1.7781,0.5298 -2.7058,0.5231 h -9.41999" stroke="#f2f2f2" stroke-miterlimit="10" id="path580" style="fill:none;stroke:#f2f2f2;stroke-width:1.45486;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" />
<path d="m 4.75002,8.44998 -4.039998,-4.05 4.039998,-4.050004" stroke="#f2f2f2" stroke-miterlimit="10" id="path582" style="fill:none;stroke:#f2f2f2;stroke-width:1.45486;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" /> <path d="m 4.75002,8.44998 -4.039998,-4.05 4.039998,-4.050004" stroke="#f2f2f2" stroke-miterlimit="10" id="path582" style="fill:none;stroke:#f2f2f2;stroke-width:1.45486;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" />
</g> </g>
<g clip-path="url(#clip0_241_10857-3)" id="undo-5" transform="matrix(-0.71300568,0,0,0.66260978,90.012499,938.13028)" style="fill:none;stroke:#f2f2f2;stroke-width:1.45488;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1">
<path d="m 1.07001,4.41003 h 9.41999 c 0.9234,-0.0066 1.8391,0.16957 2.6941,0.5184 0.8551,0.34883 1.6327,0.8634 2.288,1.51407 0.6553,0.65067 1.1754,1.42458 1.5303,2.27713 0.3549,0.85256 0.5376,1.76697 0.5376,2.69037 0.0067,0.9277 -0.1712,1.8474 -0.5231,2.7058 -0.3519,0.8583 -0.871,1.6382 -1.527,2.2941 -0.656,0.656 -1.4358,1.1751 -2.2941,1.527 -0.8584,0.352 -1.7781,0.5298 -2.7058,0.5231 h -9.41999" stroke="#f2f2f2" stroke-miterlimit="10" id="path580-3" style="fill:none;stroke:#f2f2f2;stroke-width:1.45486;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" />
<path d="m 4.75002,8.44998 -4.039998,-4.05 4.039998,-4.050004" stroke="#f2f2f2" stroke-miterlimit="10" id="path582-5" style="fill:none;stroke:#f2f2f2;stroke-width:1.45486;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g id="g1" transform="translate(144,-24.00004)"> <g id="g1" transform="translate(144,-24.00004)">
<path d="m 9,849.93721 v 4.04997 c 0,0.20708 0.167895,0.375 0.375,0.375 h 5.25 c 0.207075,0 0.375,-0.16792 0.375,-0.375 v -4.04997 c 0,-0.20708 -0.167925,-0.375 -0.375,-0.375 h -5.25 c -0.207105,0 -0.375,0.16792 -0.375,0.375 z" stroke="#f2f2f2" id="path438" style="fill:none;stroke:#999999;stroke-width:0.999997;stroke-opacity:1" /> <path d="m 9,849.93721 v 4.04997 c 0,0.20708 0.167895,0.375 0.375,0.375 h 5.25 c 0.207075,0 0.375,-0.16792 0.375,-0.375 v -4.04997 c 0,-0.20708 -0.167925,-0.375 -0.375,-0.375 h -5.25 c -0.207105,0 -0.375,0.16792 -0.375,0.375 z" stroke="#f2f2f2" id="path438" style="fill:none;stroke:#999999;stroke-width:0.999997;stroke-opacity:1" />
<path d="m 15.21255,842.36218 h -8.83755 c -0.207105,0 -0.375,0.1679 -0.375,0.37499 v 11.24993 c 0,0.20708 0.167895,0.375 0.375,0.375 h 11.25 c 0.207075,0 0.375,-0.16792 0.375,-0.375 v -8.67664 c 0,-0.0953 -0.0363,-0.18697 -0.1014,-0.25648 l -2.41245,-2.57327 c -0.07095,-0.0756 -0.16995,-0.11853 -0.2736,-0.11853 z" stroke="#f2f2f2" id="save" style="fill:none;stroke:#999999;stroke-width:0.999997;stroke-opacity:1" /> <path d="m 15.21255,842.36218 h -8.83755 c -0.207105,0 -0.375,0.1679 -0.375,0.37499 v 11.24993 c 0,0.20708 0.167895,0.375 0.375,0.375 h 11.25 c 0.207075,0 0.375,-0.16792 0.375,-0.375 v -8.67664 c 0,-0.0953 -0.0363,-0.18697 -0.1014,-0.25648 l -2.41245,-2.57327 c -0.07095,-0.0756 -0.16995,-0.11853 -0.2736,-0.11853 z" stroke="#f2f2f2" id="save" style="fill:none;stroke:#999999;stroke-width:0.999997;stroke-opacity:1" />
@ -200,7 +213,7 @@
<path style="fill:#f2f2f2;stroke:#999999;stroke-width:0.25;paint-order:fill markers stroke" d="m 8.1902877,37.423896 c -0.4872187,-0.174113 -0.7923051,-0.442073 -0.9946703,-0.873627 l -0.1907982,-0.406887 -1.3702708,-0.0034 c -1.4982701,-0.0037 -1.5910875,-0.03214 -1.5406237,-0.47225 l 0.026557,-0.23161 1.4211632,-0.02255 1.4211632,-0.02255 0.1982698,-0.389502 c 0.347892,-0.683434 0.8634941,-1.009111 1.592299,-1.005764 0.7177082,0.0033 1.3415151,0.432422 1.6290831,1.120669 l 0.116359,0.278485 h 4.65745 c 4.520341,0 4.659962,0.0047 4.742759,0.159402 0.1159,0.216562 0.107667,0.300926 -0.04419,0.452784 -0.114657,0.114657 -0.660626,0.129501 -4.763204,0.129501 h -4.633703 l -0.104975,0.290304 c -0.152574,0.421935 -0.6274874,0.844474 -1.1103021,0.987854 -0.4962156,0.147361 -0.6614998,0.148792 -1.0523644,0.0091 z m 0.9689602,-0.845129 c 0.6980003,-0.331223 0.6980003,-1.377155 0,-1.708378 -0.3515556,-0.166824 -0.4925823,-0.168492 -0.8270409,-0.0098 -0.3376099,0.160207 -0.5444962,0.513326 -0.5444962,0.929363 0,0.368008 0.1600657,0.606145 0.5356626,0.796928 0.3157622,0.16039 0.4841923,0.158752 0.8358745,-0.0081 z" id="path8" transform="translate(0,812.36218)" /> <path style="fill:#f2f2f2;stroke:#999999;stroke-width:0.25;paint-order:fill markers stroke" d="m 8.1902877,37.423896 c -0.4872187,-0.174113 -0.7923051,-0.442073 -0.9946703,-0.873627 l -0.1907982,-0.406887 -1.3702708,-0.0034 c -1.4982701,-0.0037 -1.5910875,-0.03214 -1.5406237,-0.47225 l 0.026557,-0.23161 1.4211632,-0.02255 1.4211632,-0.02255 0.1982698,-0.389502 c 0.347892,-0.683434 0.8634941,-1.009111 1.592299,-1.005764 0.7177082,0.0033 1.3415151,0.432422 1.6290831,1.120669 l 0.116359,0.278485 h 4.65745 c 4.520341,0 4.659962,0.0047 4.742759,0.159402 0.1159,0.216562 0.107667,0.300926 -0.04419,0.452784 -0.114657,0.114657 -0.660626,0.129501 -4.763204,0.129501 h -4.633703 l -0.104975,0.290304 c -0.152574,0.421935 -0.6274874,0.844474 -1.1103021,0.987854 -0.4962156,0.147361 -0.6614998,0.148792 -1.0523644,0.0091 z m 0.9689602,-0.845129 c 0.6980003,-0.331223 0.6980003,-1.377155 0,-1.708378 -0.3515556,-0.166824 -0.4925823,-0.168492 -0.8270409,-0.0098 -0.3376099,0.160207 -0.5444962,0.513326 -0.5444962,0.929363 0,0.368008 0.1600657,0.606145 0.5356626,0.796928 0.3157622,0.16039 0.4841923,0.158752 0.8358745,-0.0081 z" id="path8" transform="translate(0,812.36218)" />
<path style="fill:#f2f2f2;stroke:#999999;stroke-width:0.25;paint-order:fill markers stroke" d="m 12.773494,42.243521 c -0.4045,-0.187277 -0.732456,-0.526846 -0.902897,-0.934868 l -0.128748,-0.308213 -3.8106837,-0.02143 -3.8106834,-0.02142 -0.026557,-0.23161 c -0.055311,-0.482381 -0.1677415,-0.468805 3.8892984,-0.469606 l 3.7189457,-7.33e-4 0.21287,-0.431917 c 0.651632,-1.322166 2.472575,-1.284611 3.125651,0.06446 l 0.178591,0.36892 h 2.297219 c 2.258426,0 2.298803,0.003 2.391007,0.175244 0.06808,0.127207 0.06936,0.228859 0.0047,0.370843 l -0.08912,0.1956 h -2.305381 -2.30538 l -0.15493,0.350241 c -0.387132,0.875164 -1.437261,1.286451 -2.283867,0.894485 z m 1.063202,-0.700358 c 0.378023,-0.157949 0.544298,-0.425794 0.541165,-0.871741 -0.004,-0.573585 -0.363385,-0.908772 -0.974299,-0.908772 -0.312041,0 -0.40386,0.04292 -0.649922,0.303826 -0.257768,0.273313 -0.282484,0.339859 -0.246104,0.662621 0.04524,0.401361 0.228194,0.651219 0.595596,0.813394 0.317179,0.140006 0.399909,0.140082 0.733564,6.68e-4 z" id="path9" transform="translate(0,812.36218)" /> <path style="fill:#f2f2f2;stroke:#999999;stroke-width:0.25;paint-order:fill markers stroke" d="m 12.773494,42.243521 c -0.4045,-0.187277 -0.732456,-0.526846 -0.902897,-0.934868 l -0.128748,-0.308213 -3.8106837,-0.02143 -3.8106834,-0.02142 -0.026557,-0.23161 c -0.055311,-0.482381 -0.1677415,-0.468805 3.8892984,-0.469606 l 3.7189457,-7.33e-4 0.21287,-0.431917 c 0.651632,-1.322166 2.472575,-1.284611 3.125651,0.06446 l 0.178591,0.36892 h 2.297219 c 2.258426,0 2.298803,0.003 2.391007,0.175244 0.06808,0.127207 0.06936,0.228859 0.0047,0.370843 l -0.08912,0.1956 h -2.305381 -2.30538 l -0.15493,0.350241 c -0.387132,0.875164 -1.437261,1.286451 -2.283867,0.894485 z m 1.063202,-0.700358 c 0.378023,-0.157949 0.544298,-0.425794 0.541165,-0.871741 -0.004,-0.573585 -0.363385,-0.908772 -0.974299,-0.908772 -0.312041,0 -0.40386,0.04292 -0.649922,0.303826 -0.257768,0.273313 -0.282484,0.339859 -0.246104,0.662621 0.04524,0.401361 0.228194,0.651219 0.595596,0.813394 0.317179,0.140006 0.399909,0.140082 0.733564,6.68e-4 z" id="path9" transform="translate(0,812.36218)" />
<path style="color:#000000;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:0.25;stroke-dasharray:none;stroke-opacity:1" d="m 154.67579,963.53902 4.73437,4.73437 -5.05078,4.6836 -1.35938,-1.4668 3.52735,-3.26953 -3.26563,-3.26563 z" id="path1-67-5" /> <path style="color:#000000;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:0.25;stroke-dasharray:none;stroke-opacity:1" d="m 154.67579,963.53902 4.73437,4.73437 -5.05078,4.6836 -1.35938,-1.4668 3.52735,-3.26953 -3.26563,-3.26563 z" id="path1-67-5" />
<path id="copy" style="fill:#f2f2f2;fill-opacity:1;paint-order:fill markers stroke" d="m 58,914.36218 v 3.5 h 4 v 4 h 3.5 v -7.5 z m -4,4 v 7.5 h 7.5 v -7.5 z" /> <path id="copy" style="fill:#f2f2f2;fill-opacity:1;stroke-width:1;paint-order:fill markers stroke" d="m 106.17392,986.36222 v 3.65217 h 4.17391 v 4.17392 h 3.65217 v -7.82609 z m -4.17392,4.17391 v 7.82609 h 7.82609 v -7.82609 z" />
<g id="g1-5" transform="translate(0.1,0.1)"> <g id="g1-5" transform="translate(0.1,0.1)">
<g id="g24"> <g id="g24">
<path d="m 12,912.36218 c -4.4182692,0 -8,3.58172 -8,8 0.00463,1.61557 0.4982915,3.19189 1.4160156,4.52148 0.1980248,0.28729 0.4146342,0.56131 0.6484375,0.82032 1.5128357,1.68659 3.6698868,2.65261 5.9355469,2.6582 2.266949,-0.006 4.424914,-0.97357 5.9375,-2.66211 0.23535,-0.26077 0.45327,-0.53676 0.652344,-0.82617 0.913769,-1.32754 1.405284,-2.9001 1.410156,-4.51172 0,-4.41828 -3.58173,-8 -8,-8 z m -5.3242188,12.50586 c 1.3285496,-1.56088 3.274489,-2.46104 5.3242188,-2.46289 2.050412,10e-4 3.997179,0.90149 5.326172,2.46289 0,0 -0.0035,-0.003 0.0059,0.006 0,0 -0.537098,0.5762 -0.839844,0.82812 -0.175326,0.14821 -0.35784,0.2877 -0.546874,0.41797 -0.06626,0.0467 -0.133328,0.0923 -0.201172,0.13672 -0.244804,0.15763 -0.499205,0.29983 -0.761719,0.42578 -0.931874,0.44366 -1.950332,0.67577 -2.982422,0.67969 -0.618083,-0.005 -1.232807,-0.0915 -1.828125,-0.25781 -0.6753225,-0.18416 -1.3192066,-0.46858 -1.9101562,-0.84375 -0.0685,-0.0444 -0.1362192,-0.09 -0.203125,-0.13672 -0.00521,-0.004 -0.010422,-0.008 -0.015625,-0.0117 -0.1876607,-0.12974 -0.3688672,-0.26858 -0.5429688,-0.41602 -0.2997188,-0.24977 -0.5780329,-0.52416 -0.8320313,-0.82031 m -0.5917968,-0.81445 c -0.6976631,-1.10814 -1.0705109,-2.38976 -1.0761719,-3.69922 0,-3.86599 3.1340146,-7 7,-7 l -4.1e-5,-1.6e-4 c 3.865985,0 7,3.13401 7,7 -0.0054,1.30234 -0.374061,2.57734 -1.064453,3.68164 -1.516341,-1.67935 -3.672913,-2.63806 -5.935547,-2.63867 -2.2612709,0.008 -4.4133749,0.97341 -5.9238281,2.65625" style="fill:#f2f2f2;stroke:#999999;stroke-width:0.2;paint-order:fill markers stroke" id="path24" sodipodi:nodetypes="scccccccsccccccccccccccccccccccc" /> <path d="m 12,912.36218 c -4.4182692,0 -8,3.58172 -8,8 0.00463,1.61557 0.4982915,3.19189 1.4160156,4.52148 0.1980248,0.28729 0.4146342,0.56131 0.6484375,0.82032 1.5128357,1.68659 3.6698868,2.65261 5.9355469,2.6582 2.266949,-0.006 4.424914,-0.97357 5.9375,-2.66211 0.23535,-0.26077 0.45327,-0.53676 0.652344,-0.82617 0.913769,-1.32754 1.405284,-2.9001 1.410156,-4.51172 0,-4.41828 -3.58173,-8 -8,-8 z m -5.3242188,12.50586 c 1.3285496,-1.56088 3.274489,-2.46104 5.3242188,-2.46289 2.050412,10e-4 3.997179,0.90149 5.326172,2.46289 0,0 -0.0035,-0.003 0.0059,0.006 0,0 -0.537098,0.5762 -0.839844,0.82812 -0.175326,0.14821 -0.35784,0.2877 -0.546874,0.41797 -0.06626,0.0467 -0.133328,0.0923 -0.201172,0.13672 -0.244804,0.15763 -0.499205,0.29983 -0.761719,0.42578 -0.931874,0.44366 -1.950332,0.67577 -2.982422,0.67969 -0.618083,-0.005 -1.232807,-0.0915 -1.828125,-0.25781 -0.6753225,-0.18416 -1.3192066,-0.46858 -1.9101562,-0.84375 -0.0685,-0.0444 -0.1362192,-0.09 -0.203125,-0.13672 -0.00521,-0.004 -0.010422,-0.008 -0.015625,-0.0117 -0.1876607,-0.12974 -0.3688672,-0.26858 -0.5429688,-0.41602 -0.2997188,-0.24977 -0.5780329,-0.52416 -0.8320313,-0.82031 m -0.5917968,-0.81445 c -0.6976631,-1.10814 -1.0705109,-2.38976 -1.0761719,-3.69922 0,-3.86599 3.1340146,-7 7,-7 l -4.1e-5,-1.6e-4 c 3.865985,0 7,3.13401 7,7 -0.0054,1.30234 -0.374061,2.57734 -1.064453,3.68164 -1.516341,-1.67935 -3.672913,-2.63806 -5.935547,-2.63867 -2.2612709,0.008 -4.4133749,0.97341 -5.9238281,2.65625" style="fill:#f2f2f2;stroke:#999999;stroke-width:0.2;paint-order:fill markers stroke" id="path24" sodipodi:nodetypes="scccccccsccccccccccccccccccccccc" />
@ -221,5 +234,13 @@
</g> </g>
<path style="fill:#efefef;fill-opacity:1;stroke:none;stroke-width:6.97518;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0010932573" inkscape:transform-center-y="-0.7377641" d="m 7.6698317,998.8588 1.3886278,-5.25497 -4.0584591,-3.24679 h 5.1830926 l 1.819345,-5.49493 1.81469,5.49392 h 5.182872 l -4.06154,3.24965 1.383849,5.25642 -4.324867,-3.01228 z" id="star" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" /> <path style="fill:#efefef;fill-opacity:1;stroke:none;stroke-width:6.97518;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0010932573" inkscape:transform-center-y="-0.7377641" d="m 7.6698317,998.8588 1.3886278,-5.25497 -4.0584591,-3.24679 h 5.1830926 l 1.819345,-5.49493 1.81469,5.49392 h 5.182872 l -4.06154,3.24965 1.383849,5.25642 -4.324867,-3.01228 z" id="star" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" />
<path style="fill:none;fill-opacity:1;stroke:#efefef;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0010925804" inkscape:transform-center-y="-0.73776941" d="m 31.669832,998.8588 1.388628,-5.25501 -4.05846,-3.24679 h 5.183093 l 1.819345,-5.49493 1.814694,5.49392 h 5.182868 l -4.06154,3.24964 1.383849,5.25647 -4.324874,-3.01232 z" id="starred" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" /> <path style="fill:none;fill-opacity:1;stroke:#efefef;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0010925804" inkscape:transform-center-y="-0.73776941" d="m 31.669832,998.8588 1.388628,-5.25501 -4.05846,-3.24679 h 5.183093 l 1.819345,-5.49493 1.814694,5.49392 h 5.182868 l -4.06154,3.24964 1.383849,5.25647 -4.324874,-3.01232 z" id="starred" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" />
<g clip-path="url(#clip0_3071_861)" id="g3" transform="translate(194.88955,910.26491)">
<path fill-rule="evenodd" clip-rule="evenodd" d="m 1.89466,0.697266 v 2.325584 h 1.10132 l -1.01843,13.95345 h -1.267101 v 2.3256 h 2.368421 v -1.3953 l 9.47373,-1.8605 v 0.9302 h 2.3684 v -2.3255 h -0.9237 l 1.8355,-8.13958 h 1.4448 v -2.32558 h -2.3685 v 0.84883 l -10.64602,-2.86046 v -1.476744 z" stroke="#efefef" stroke-width="1.2" id="path1-9" style="fill:none" />
<path d="m 8.59717,6.8457 v 5.8915" stroke="#efefef" stroke-width="1.01333" id="path2-1" />
<path d="m 11.5977,9.79102 h -6.00004" stroke="#efefef" stroke-width="1.01333" id="path3-2" />
</g>
<path d="m 204.41818,838.96218 c -2.97727,0 -5.96591,1.94619 -6.81818,5.85003 0,2.33543 1.70455,7.01777 6.81818,12.46707 5.11362,-5.4608 6.81822,-10.13164 6.81822,-12.46707 -0.8523,-3.89239 -3.8409,-5.85003 -6.81822,-5.85003 z" stroke="#efefef" stroke-width="1.2" id="path1-0" style="fill:none" />
<path d="m 204.41812,843.97585 v 6.04463" stroke="#efefef" stroke-width="1.056" id="path2-9" style="fill:none" />
<path d="m 207.4181,846.99929 h -5.99998" stroke="#efefef" stroke-width="1.056" id="path3-36" style="fill:none" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg width="288" height="288" viewBox="0 0 76.199991 76.199991" version="1.1" id="svg2876" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="24-white.svg" inkscape:export-filename="../24-white.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <svg width="288" height="288" viewBox="0 0 76.199991 76.199991" version="1.1" id="svg2876" inkscape:version="1.4.1 (93de688d07, 2025-03-30)" sodipodi:docname="24-white.svg" inkscape:export-filename="../24-white.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview2878" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="8.896373" inkscape:cx="51.706465" inkscape:cy="46.423413" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1"> <sodipodi:namedview id="namedview2878" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="7.9044052" inkscape:cx="138.0243" inkscape:cy="242.26997" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1">
<inkscape:grid type="xygrid" id="grid2997" empspacing="6" originx="0" originy="0" spacingy="0.2645833" spacingx="0.2645833" units="px" visible="true" /> <inkscape:grid type="xygrid" id="grid2997" empspacing="6" originx="0" originy="0" spacingy="0.2645833" spacingx="0.2645833" units="px" visible="true" />
<inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="9.5249989" spacingy="9.5249989" empcolor="#3f3fff" empopacity="0.25098039" color="#3f3fff" opacity="0.1254902" empspacing="1" dotted="false" gridanglex="30" gridanglez="30" visible="true" /> <inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="9.5249989" spacingy="9.5249989" empcolor="#3f3fff" empopacity="0.25098039" color="#3f3fff" opacity="0.1254902" empspacing="1" dotted="false" gridanglex="30" gridanglez="30" visible="true" />
</sodipodi:namedview> </sodipodi:namedview>
@ -77,5 +77,6 @@
<path d="m 5.6444435,59.43432 v 1.034991 h 1.0541546 z m 1.1759257,1.612262 h -1.1759257 c -0.3247228,0 -0.5879626,-0.258453 -0.5879626,-0.577271 v -1.154545 h -2.3518514 v 5.195451 h 4.1157397 z m -4.1157397,-2.309089 h 3.0615854 l 1.6421175,1.612259 v 4.160465 c 0,0.318822 -0.2632403,0.577275 -0.5879632,0.577275 h -4.1157397 c -0.3247231,0 -0.5879631,-0.258453 -0.5879631,-0.577275 v -5.195451 c 0,-0.31882 0.26324,-0.577273 0.5879631,-0.577273 z m 1.7638882,3.92135 v -1.323625 h 0.5879632 v 1.323625 l 0.3800861,-0.373177 0.415753,0.408196 -1.0898206,1.070004 -1.0898208,-1.070004 0.4157526,-0.408196 z" fill-rule="evenodd" id="downloadfile" style="fill:#f2f2f2;fill-opacity:1;stroke:#999999;stroke-width:0.0661458;stroke-dasharray:none;stroke-opacity:0.509804" /> <path d="m 5.6444435,59.43432 v 1.034991 h 1.0541546 z m 1.1759257,1.612262 h -1.1759257 c -0.3247228,0 -0.5879626,-0.258453 -0.5879626,-0.577271 v -1.154545 h -2.3518514 v 5.195451 h 4.1157397 z m -4.1157397,-2.309089 h 3.0615854 l 1.6421175,1.612259 v 4.160465 c 0,0.318822 -0.2632403,0.577275 -0.5879632,0.577275 h -4.1157397 c -0.3247231,0 -0.5879631,-0.258453 -0.5879631,-0.577275 v -5.195451 c 0,-0.31882 0.26324,-0.577273 0.5879631,-0.577273 z m 1.7638882,3.92135 v -1.323625 h 0.5879632 v 1.323625 l 0.3800861,-0.373177 0.415753,0.408196 -1.0898206,1.070004 -1.0898208,-1.070004 0.4157526,-0.408196 z" fill-rule="evenodd" id="downloadfile" style="fill:#f2f2f2;fill-opacity:1;stroke:#999999;stroke-width:0.0661458;stroke-dasharray:none;stroke-opacity:0.509804" />
<path id="path3014" style="fill:#f2f2f2;stroke:#999999;stroke-opacity:1;stroke-width:0.06614583;stroke-dasharray:none;fill-opacity:1" d="M 4.6307246 2.6463498 C 3.0979756 2.6463498 1.8515665 3.8912088 1.8515664 5.4239577 C 1.8515664 6.9567067 3.0979756 8.2010487 4.6307246 8.2010488 C 6.1634736 8.2010488 7.4083325 6.9567067 7.4083325 5.4239577 C 7.4083325 3.8912088 6.1634735 2.6463498 4.6307246 2.6463498 z M 4.6307246 2.9098996 C 6.0204823 2.9098995 7.1447827 4.0342 7.1447827 5.4239577 C 7.1447827 6.8137155 6.0204823 7.9374991 4.6307246 7.9374991 C 3.2409669 7.937499 2.1171832 6.8137154 2.1171832 5.4239577 C 2.1171833 4.0342 3.2409669 2.9098996 4.6307246 2.9098996 z M 4.6265904 3.6602413 C 4.4830079 3.6602413 4.3339769 3.6757056 4.1795894 3.7067501 C 4.0252001 3.7376887 3.8542856 3.7854994 3.667476 3.8504105 L 3.667476 4.5790481 C 3.8249518 4.476919 3.9765859 4.4006165 4.1217118 4.3496048 C 4.2668361 4.2971467 4.4017991 4.2705399 4.5268549 4.2705399 C 4.6596277 4.2705399 4.7628056 4.3016097 4.8369135 4.3635574 C 4.9110183 4.4238471 4.9480162 4.5079171 4.9480178 4.6162552 C 4.9480162 4.6874104 4.9271727 4.758453 4.8854893 4.8296788 C 4.8453469 4.9008341 4.7812531 4.9766217 4.693253 5.0570551 L 4.5454584 5.1919305 C 4.3818056 5.3435544 4.2744616 5.4685934 4.2235143 5.5676182 C 4.172565 5.6651259 4.1470332 5.7776896 4.1470332 5.9045485 L 4.1470332 6.0182366 L 4.9831578 6.0182366 L 4.9831578 5.9138502 C 4.9831561 5.8442119 4.9993102 5.7803848 5.0317336 5.7231642 C 5.0641535 5.6643561 5.1329366 5.5870926 5.2379226 5.491137 L 5.3857171 5.3588454 C 5.53084 5.2211562 5.6334948 5.0929891 5.6937086 4.973856 C 5.7539162 4.8531707 5.7841399 4.7167194 5.7841424 4.5650955 C 5.7841399 4.2696088 5.6856516 4.0454092 5.4880365 3.8922684 C 5.2904177 3.7375754 5.0032968 3.6602413 4.6265904 3.6602413 z M 4.1470332 6.3618848 L 4.1470332 7.1876741 L 4.9831578 7.1876741 L 4.9831578 6.3618848 L 4.1470332 6.3618848 z " /> <path id="path3014" style="fill:#f2f2f2;stroke:#999999;stroke-opacity:1;stroke-width:0.06614583;stroke-dasharray:none;fill-opacity:1" d="M 4.6307246 2.6463498 C 3.0979756 2.6463498 1.8515665 3.8912088 1.8515664 5.4239577 C 1.8515664 6.9567067 3.0979756 8.2010487 4.6307246 8.2010488 C 6.1634736 8.2010488 7.4083325 6.9567067 7.4083325 5.4239577 C 7.4083325 3.8912088 6.1634735 2.6463498 4.6307246 2.6463498 z M 4.6307246 2.9098996 C 6.0204823 2.9098995 7.1447827 4.0342 7.1447827 5.4239577 C 7.1447827 6.8137155 6.0204823 7.9374991 4.6307246 7.9374991 C 3.2409669 7.937499 2.1171832 6.8137154 2.1171832 5.4239577 C 2.1171833 4.0342 3.2409669 2.9098996 4.6307246 2.9098996 z M 4.6265904 3.6602413 C 4.4830079 3.6602413 4.3339769 3.6757056 4.1795894 3.7067501 C 4.0252001 3.7376887 3.8542856 3.7854994 3.667476 3.8504105 L 3.667476 4.5790481 C 3.8249518 4.476919 3.9765859 4.4006165 4.1217118 4.3496048 C 4.2668361 4.2971467 4.4017991 4.2705399 4.5268549 4.2705399 C 4.6596277 4.2705399 4.7628056 4.3016097 4.8369135 4.3635574 C 4.9110183 4.4238471 4.9480162 4.5079171 4.9480178 4.6162552 C 4.9480162 4.6874104 4.9271727 4.758453 4.8854893 4.8296788 C 4.8453469 4.9008341 4.7812531 4.9766217 4.693253 5.0570551 L 4.5454584 5.1919305 C 4.3818056 5.3435544 4.2744616 5.4685934 4.2235143 5.5676182 C 4.172565 5.6651259 4.1470332 5.7776896 4.1470332 5.9045485 L 4.1470332 6.0182366 L 4.9831578 6.0182366 L 4.9831578 5.9138502 C 4.9831561 5.8442119 4.9993102 5.7803848 5.0317336 5.7231642 C 5.0641535 5.6643561 5.1329366 5.5870926 5.2379226 5.491137 L 5.3857171 5.3588454 C 5.53084 5.2211562 5.6334948 5.0929891 5.6937086 4.973856 C 5.7539162 4.8531707 5.7841399 4.7167194 5.7841424 4.5650955 C 5.7841399 4.2696088 5.6856516 4.0454092 5.4880365 3.8922684 C 5.2904177 3.7375754 5.0032968 3.6602413 4.6265904 3.6602413 z M 4.1470332 6.3618848 L 4.1470332 7.1876741 L 4.9831578 7.1876741 L 4.9831578 6.3618848 L 4.1470332 6.3618848 z " />
<g id="text3784" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.75" transform="matrix(0.35277776,0,0,0.35277776,1.8079862,-363.00384)" /> <g id="text3784" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.75" transform="matrix(0.35277776,0,0,0.35277776,1.8079862,-363.00384)" />
<path id="copy" style="fill:#f2f2f2;stroke-width:0.264582;paint-order:fill markers stroke;fill-opacity:1" d="m 42.218298,69.320832 v 1.288405 h 1.472463 v 1.472465 h 1.288405 v -2.76087 z m -1.472465,1.472463 v 2.760871 h 2.760869 v -2.760871 z" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg width="288" height="288" viewBox="0 0 76.199999 76.199999" version="1.1" id="svg6237" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="24.svg" inkscape:export-filename="../24.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <svg width="288" height="288" viewBox="0 0 76.199999 76.199999" version="1.1" id="svg6237" inkscape:version="1.4.1 (93de688d07, 2025-03-30)" sodipodi:docname="24.svg" inkscape:export-filename="../24.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview6239" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="22.223397" inkscape:cx="25.378659" inkscape:cy="18.269034" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1"> <sodipodi:namedview id="namedview6239" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="8.9060631" inkscape:cx="172.74748" inkscape:cy="256.79135" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1">
<inkscape:grid type="xygrid" id="grid6358" empspacing="6" originx="0" originy="0" spacingy="0.26458333" spacingx="0.26458333" units="px" visible="true" /> <inkscape:grid type="xygrid" id="grid6358" empspacing="6" originx="0" originy="0" spacingy="0.26458333" spacingx="0.26458333" units="px" visible="true" />
<inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="9.5249999" spacingy="9.5249999" empcolor="#3f3fff" empopacity="0.25098039" color="#ff0000" opacity="0.83529412" empspacing="0" dotted="false" gridanglex="30" gridanglez="30" visible="true" /> <inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="9.5249999" spacingy="9.5249999" empcolor="#3f3fff" empopacity="0.25098039" color="#ff0000" opacity="0.83529412" empspacing="0" dotted="false" gridanglex="30" gridanglez="30" visible="true" />
</sodipodi:namedview> </sodipodi:namedview>
@ -26,10 +26,10 @@
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none" x="65.048965" y="964.36218" id="text4459"><tspan sodipodi:role="line" id="tspan4461" x="65.048965" y="964.36218" style="font-weight:bold;font-size:8px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'Sans Bold';fill:#4d4d4d;fill-opacity:1">1</tspan></text> <text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none" x="65.048965" y="964.36218" id="text4459"><tspan sodipodi:role="line" id="tspan4461" x="65.048965" y="964.36218" style="font-weight:bold;font-size:8px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'Sans Bold';fill:#4d4d4d;fill-opacity:1">1</tspan></text>
</g> </g>
<g id="markers" transform="matrix(0.26458333,0,0,0.26458333,42.862499,-225.92402)" class="sprite"> <g id="markers" transform="matrix(0.26458333,0,0,0.26458333,42.862499,-225.92402)" class="sprite">
<path sodipodi:nodetypes="sccccsssccs" inkscape:connector-curvature="0" id="rect2985" d="m 105.25387,934.36268 c -3.17753,0 -6.346004,2.1278 -7.25387,6.3794 0,2.551 1.806672,7.6679 7.25387,13.6201 1.46368,-1.5994 2.66945,-3.1177 3.64397,-4.5613 -1.4505,-2.1639 -2.41497,-4.0873 -2.96285,-5.7095 -0.22599,0.041 -0.44225,0.063 -0.68112,0.063 -2.0056,0 -3.64396,-1.5346 -3.64396,-3.413 0,-1.8785 1.63836,-3.3811 3.64396,-3.3811 0.51205,0 0.98854,0.076 1.43034,0.2552 0.64347,-0.9222 1.4345,-1.6571 2.31579,-2.169 -1.14444,-0.7114 -2.44633,-1.0845 -3.74613,-1.0845 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none" /> <path sodipodi:nodetypes="sscccsssccss" inkscape:connector-curvature="0" id="rect2985" d="m 105.25387,934.36268 c -3.17753,0 -6.678764,2.07016 -7.25387,6.3794 -0.337461,2.52858 1.806672,7.6679 7.25387,13.6201 1.46368,-1.5994 2.66945,-3.1177 3.64397,-4.5613 -1.4505,-2.1639 -2.41497,-4.0873 -2.96285,-5.7095 -0.22599,0.041 -0.44225,0.063 -0.68112,0.063 -2.0056,0 -3.64396,-1.5346 -3.64396,-3.413 0,-1.8785 1.63836,-3.3811 3.64396,-3.3811 0.51205,0 0.98854,0.076 1.43034,0.2552 0.64347,-0.9222 1.4345,-1.6571 2.31579,-2.169 -1.14444,-0.7114 -2.44633,-1.0845 -3.74613,-1.0845 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none" />
<path id="path3378" d="m 111,934.36218 c -3.0625,0 -6.125,2.1277 -7,6.383 0,2.5532 1.75,7.6596 7,13.617 5.25,-5.9574 7,-11.0638 7,-13.617 -0.875,-4.2553 -3.9375,-6.383 -7,-6.383 z m 0,2.9788 c 1.933,0 3.5,1.5241 3.5,3.4042 0,1.8801 -1.567,3.4043 -3.5,3.4043 -1.93299,0 -3.5,-1.5242 -3.5,-3.4043 0,-1.8801 1.56701,-3.4042 3.5,-3.4042 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none" inkscape:connector-curvature="0" /> <path id="path3378" d="m 111,934.36218 c -3.0625,0 -6.44624,2.07411 -7,6.383 -0.32545,2.53237 1.75,7.6596 7,13.617 5.25,-5.9574 7.32545,-11.08463 7,-13.617 -0.55376,-4.30889 -3.9375,-6.383 -7,-6.383 z m 0,2.9788 c 1.933,0 3.5,1.5241 3.5,3.4042 0,1.8801 -1.567,3.4043 -3.5,3.4043 -1.93299,0 -3.5,-1.5242 -3.5,-3.4043 0,-1.8801 1.56701,-3.4042 3.5,-3.4042 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none" inkscape:connector-curvature="0" sodipodi:nodetypes="sscsssssss" />
</g> </g>
<path inkscape:connector-curvature="0" style="fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.264583" d="m 71.437498,11.178646 c -0.926041,0 -1.852083,0.661458 -2.116666,1.984375 0,0.793749 0.529166,2.381249 2.116666,4.233333 1.5875,-1.852084 2.116667,-3.439584 2.116667,-4.233333 -0.264583,-1.322917 -1.190625,-1.984375 -2.116667,-1.984375 z m 0,0.926041 c 0.584502,0 1.058334,0.473832 1.058334,1.058334 0,0.584501 -0.473832,1.058333 -1.058334,1.058333 -0.584501,0 -1.058333,-0.473832 -1.058333,-1.058333 0,-0.584502 0.473832,-1.058334 1.058333,-1.058334 z" id="marker" class="sprite" /> <path inkscape:connector-curvature="0" style="fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.264583" d="m 71.437498,11.178646 c -0.926041,0 -1.949329,0.645677 -2.116666,1.984375 -0.09845,0.78762 0.529166,2.381249 2.116666,4.233333 1.5875,-1.852084 2.215119,-3.445713 2.116667,-4.233333 -0.167337,-1.338698 -1.190625,-1.984375 -2.116667,-1.984375 z m 0,0.926041 c 0.584502,0 1.058334,0.473832 1.058334,1.058334 0,0.584501 -0.473832,1.058333 -1.058334,1.058333 -0.584501,0 -1.058333,-0.473832 -1.058333,-1.058333 0,-0.584502 0.473832,-1.058334 1.058333,-1.058334 z" id="marker" class="sprite" sodipodi:nodetypes="sscsssssss" />
<path inkscape:connector-curvature="0" d="m 69.056248,58.737493 v 0.132291 0.79375 0.132292 h 0.132293 0.79375 0.132292 v -0.132292 -0.09095 l 2.645833,1.058334 v 0.355533 0.115756 l -1.876888,2.926953 h -0.636654 -0.132291 v 0.132291 0.79375 0.132292 h 0.132291 0.79375 0.132292 v -0.132292 -0.79375 -0.09922 l 1.876888,-2.943489 h 0.636654 0.132291 v -0.132292 -0.79375 -0.132291 h -0.132291 -0.79375 -0.132292 v 0.132291 0.148828 l -2.645833,-1.058333 v -0.413411 -0.132292 h -0.132292 -0.79375 z m 0.264584,0.264583 h 0.529166 v 0.529167 h -0.529166 z m 3.704166,1.322917 h 0.529167 v 0.529166 h -0.529167 z m -2.645833,3.96875 h 0.529167 v 0.529166 h -0.529167 z" id="polyline" class="sprite" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" /> <path inkscape:connector-curvature="0" d="m 69.056248,58.737493 v 0.132291 0.79375 0.132292 h 0.132293 0.79375 0.132292 v -0.132292 -0.09095 l 2.645833,1.058334 v 0.355533 0.115756 l -1.876888,2.926953 h -0.636654 -0.132291 v 0.132291 0.79375 0.132292 h 0.132291 0.79375 0.132292 v -0.132292 -0.79375 -0.09922 l 1.876888,-2.943489 h 0.636654 0.132291 v -0.132292 -0.79375 -0.132291 h -0.132291 -0.79375 -0.132292 v 0.132291 0.148828 l -2.645833,-1.058333 v -0.413411 -0.132292 h -0.132292 -0.79375 z m 0.264584,0.264583 h 0.529166 v 0.529167 h -0.529166 z m 3.704166,1.322917 h 0.529167 v 0.529166 h -0.529167 z m -2.645833,3.96875 h 0.529167 v 0.529166 h -0.529167 z" id="polyline" class="sprite" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" />
<path d="m 69.320832,39.952089 v 0.132292 0.793751 0.132291 h 0.132292 0.347265 l -0.421679,3.704167 h -0.454753 -0.132292 v 0.132292 0.79375 0.132291 h 0.132292 0.79375 0.132292 v -0.132291 -0.421667 l 2.645833,-0.181901 v 0.338984 0.132292 h 0.132292 0.79375 0.132291 v -0.132292 -0.79375 -0.132292 h -0.132291 -0.305925 l 0.363802,-2.116667 h 0.471289 0.132292 v -0.132291 -0.793751 -0.132291 h -0.132292 -0.79375 -0.132291 v 0.132291 0.214974 l -2.645834,-0.950833 v -0.587057 -0.132292 h -0.132291 -0.79375 z m 0.264583,0.264584 h 0.529167 v 0.529167 h -0.529167 z m 3.704167,1.322916 h 0.529167 v 0.529167 h -0.529167 z m -0.529167,3.175 h 0.529167 v 0.529167 h -0.529167 z m -3.704166,0.264583 c 0.529166,0 0,0 0.529166,0 v 0.529167 h -0.529166 z" id="polygon" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" class="sprite" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" /> <path d="m 69.320832,39.952089 v 0.132292 0.793751 0.132291 h 0.132292 0.347265 l -0.421679,3.704167 h -0.454753 -0.132292 v 0.132292 0.79375 0.132291 h 0.132292 0.79375 0.132292 v -0.132291 -0.421667 l 2.645833,-0.181901 v 0.338984 0.132292 h 0.132292 0.79375 0.132291 v -0.132292 -0.79375 -0.132292 h -0.132291 -0.305925 l 0.363802,-2.116667 h 0.471289 0.132292 v -0.132291 -0.793751 -0.132291 h -0.132292 -0.79375 -0.132291 v 0.132291 0.214974 l -2.645834,-0.950833 v -0.587057 -0.132292 h -0.132291 -0.79375 z m 0.264583,0.264584 h 0.529167 v 0.529167 h -0.529167 z m 3.704167,1.322916 h 0.529167 v 0.529167 h -0.529167 z m -0.529167,3.175 h 0.529167 v 0.529167 h -0.529167 z m -3.704166,0.264583 c 0.529166,0 0,0 0.529166,0 v 0.529167 h -0.529166 z" id="polygon" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" class="sprite" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" />
<g transform="matrix(0.06466922,0,0,0.06466922,11.047119,39.63557)" id="settings" style="fill:#4d4d4d;fill-opacity:1;stroke:none" class="sprite"> <g transform="matrix(0.06466922,0,0,0.06466922,11.047119,39.63557)" id="settings" style="fill:#4d4d4d;fill-opacity:1;stroke:none" class="sprite">
@ -44,7 +44,7 @@
<path d="m 60.085221,50.800004 c -0.890121,-0.0021 -1.610321,0.711677 -1.612305,1.5875 0.002,0.877761 0.722184,1.586074 1.612305,1.5875 0.593513,-8.73e-4 1.110529,-0.321123 1.389062,-0.79375 h 0.65319 l 0.520899,-0.504362 0.396875,0.380339 0.380338,-0.37207 0.388607,0.380338 0.396875,-0.380338 0.388607,0.380338 0.677994,-0.65319 c 0.09761,-0.09927 0.100016,-0.174188 0,-0.272852 l -0.553971,-0.545703 h -3.241146 c -0.277124,-0.47713 -0.799763,-0.794983 -1.39733,-0.79375 z m -0.7028,1.157552 c 0.233962,-0.0011 0.419905,0.187463 0.42168,0.42168 -0.0017,0.230958 -0.187613,0.419542 -0.42168,0.42168 -0.237929,-0.0024 -0.43214,-0.190722 -0.429948,-0.42168 -0.0022,-0.234217 0.192019,-0.422799 0.429948,-0.42168 z" id="permissions" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" class="sprite" /> <path d="m 60.085221,50.800004 c -0.890121,-0.0021 -1.610321,0.711677 -1.612305,1.5875 0.002,0.877761 0.722184,1.586074 1.612305,1.5875 0.593513,-8.73e-4 1.110529,-0.321123 1.389062,-0.79375 h 0.65319 l 0.520899,-0.504362 0.396875,0.380339 0.380338,-0.37207 0.388607,0.380338 0.396875,-0.380338 0.388607,0.380338 0.677994,-0.65319 c 0.09761,-0.09927 0.100016,-0.174188 0,-0.272852 l -0.553971,-0.545703 h -3.241146 c -0.277124,-0.47713 -0.799763,-0.794983 -1.39733,-0.79375 z m -0.7028,1.157552 c 0.233962,-0.0011 0.419905,0.187463 0.42168,0.42168 -0.0017,0.230958 -0.187613,0.419542 -0.42168,0.42168 -0.237929,-0.0024 -0.43214,-0.190722 -0.429948,-0.42168 -0.0022,-0.234217 0.192019,-0.422799 0.429948,-0.42168 z" id="permissions" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" class="sprite" />
<polygon points="12.5,50 12.5,87.5 43.75,87.5 43.75,62.5 56.25,62.5 56.25,87.5 87.5,87.5 87.5,50 100,50 50,0 0,50 " id="home" transform="matrix(0.0635,0,0,0.0635,30.162499,20.902083)" style="fill:#4d4d4d;fill-opacity:1" class="sprite" /> <polygon points="12.5,50 12.5,87.5 43.75,87.5 43.75,62.5 56.25,62.5 56.25,87.5 87.5,87.5 87.5,50 100,50 50,0 0,50 " id="home" transform="matrix(0.0635,0,0,0.0635,30.162499,20.902083)" style="fill:#4d4d4d;fill-opacity:1" class="sprite" />
<path inkscape:connector-curvature="0" d="m 7.937502,33.337505 c 0,-0.119238 -0.0078,-0.236713 -0.02082,-0.352777 h -0.356658 c -0.159103,-1.275998 -1.168753,-2.285648 -2.44475,-2.445102 v -0.356307 c -0.116064,-0.01304 -0.233539,-0.02082 -0.352778,-0.02082 -0.119239,0 -0.236714,0.0078 -0.352778,0.02082 v 0.356659 c -1.275997,0.159102 -2.285647,1.168752 -2.445103,2.44475 h -0.356305 c -0.01305,0.116064 -0.02081,0.233539 -0.02081,0.352777 0,0.119239 0.0078,0.236714 0.02081,0.352779 h 0.356658 c 0.159103,1.275996 1.168753,2.285659 2.44475,2.445123 v 0.356658 c 0.116064,0.0127 0.233539,0.02037 0.352778,0.02037 0.119239,0 0.236714,-0.0077 0.352778,-0.0209 v -0.356658 c 1.275644,-0.159438 2.285647,-1.168757 2.445102,-2.444753 h 0.356659 c 0.0127,-0.115712 0.02046,-0.233187 0.02046,-0.352779 z m -2.822223,2.084929 v -0.32104 c 0,-0.195085 -0.158044,-0.352777 -0.352777,-0.352777 -0.194734,0 -0.352778,0.157692 -0.352778,0.352777 v 0.32104 c -0.885472,-0.148883 -1.582914,-0.845973 -1.731786,-1.731798 l 0.320675,-2.65e-4 c 0.195086,0 0.352778,-0.158046 0.352778,-0.352779 0,-0.194733 -0.157692,-0.352777 -0.352778,-0.352777 h -0.321028 c 0.149225,-0.885473 0.846667,-1.582915 1.732139,-1.73214 v 0.32103 c 0,0.194733 0.158044,0.352777 0.352778,0.352777 0.194733,0 0.352777,-0.158044 0.352777,-0.352777 v -0.32103 c 0.885825,0.148873 1.583267,0.846315 1.732139,1.73214 h -0.321028 c -0.195086,0 -0.352777,0.158044 -0.352777,0.352777 0,0.194733 0.157691,0.352779 0.352777,0.352779 l 0.321028,2.65e-4 c -0.149225,0.885825 -0.846314,1.582915 -1.732139,1.731798 z" id="geolocation" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" class="sprite" /> <path inkscape:connector-curvature="0" d="m 7.937502,33.337505 c 0,-0.119238 -0.0078,-0.236713 -0.02082,-0.352777 h -0.356658 c -0.159103,-1.275998 -1.168753,-2.285648 -2.44475,-2.445102 v -0.356307 c -0.116064,-0.01304 -0.233539,-0.02082 -0.352778,-0.02082 -0.119239,0 -0.236714,0.0078 -0.352778,0.02082 v 0.356659 c -1.275997,0.159102 -2.285647,1.168752 -2.445103,2.44475 h -0.356305 c -0.01305,0.116064 -0.02081,0.233539 -0.02081,0.352777 0,0.119239 0.0078,0.236714 0.02081,0.352779 h 0.356658 c 0.159103,1.275996 1.168753,2.285659 2.44475,2.445123 v 0.356658 c 0.116064,0.0127 0.233539,0.02037 0.352778,0.02037 0.119239,0 0.236714,-0.0077 0.352778,-0.0209 v -0.356658 c 1.275644,-0.159438 2.285647,-1.168757 2.445102,-2.444753 h 0.356659 c 0.0127,-0.115712 0.02046,-0.233187 0.02046,-0.352779 z m -2.822223,2.084929 v -0.32104 c 0,-0.195085 -0.158044,-0.352777 -0.352777,-0.352777 -0.194734,0 -0.352778,0.157692 -0.352778,0.352777 v 0.32104 c -0.885472,-0.148883 -1.582914,-0.845973 -1.731786,-1.731798 l 0.320675,-2.65e-4 c 0.195086,0 0.352778,-0.158046 0.352778,-0.352779 0,-0.194733 -0.157692,-0.352777 -0.352778,-0.352777 h -0.321028 c 0.149225,-0.885473 0.846667,-1.582915 1.732139,-1.73214 v 0.32103 c 0,0.194733 0.158044,0.352777 0.352778,0.352777 0.194733,0 0.352777,-0.158044 0.352777,-0.352777 v -0.32103 c 0.885825,0.148873 1.583267,0.846315 1.732139,1.73214 h -0.321028 c -0.195086,0 -0.352777,0.158044 -0.352777,0.352777 0,0.194733 0.157691,0.352779 0.352777,0.352779 l 0.321028,2.65e-4 c -0.149225,0.885825 -0.846314,1.582915 -1.732139,1.731798 z" id="geolocation" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.264583" class="sprite" />
<g id="share" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,-2.6458336,-229.22505)"> <g id="share" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,-21.695832,-210.17502)">
<circle id="path4309" style="fill:none;stroke:#464646;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" cx="100" cy="992.3623" r="11" /> <circle id="path4309" style="fill:none;stroke:#464646;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" cx="100" cy="992.3623" r="11" />
<circle transform="rotate(-111.82202)" id="path4819" style="fill:#464646;fill-opacity:1;stroke:none;stroke-width:4.28879" cx="-963.88702" cy="-276.03735" r="2.5" /> <circle transform="rotate(-111.82202)" id="path4819" style="fill:#464646;fill-opacity:1;stroke:none;stroke-width:4.28879" cx="-963.88702" cy="-276.03735" r="2.5" />
<circle transform="rotate(-111.82202)" id="path4819-2" style="fill:#464646;fill-opacity:1;stroke:none;stroke-width:4.28879" cx="-956.38037" cy="-281.15619" r="2.5" /> <circle transform="rotate(-111.82202)" id="path4819-2" style="fill:#464646;fill-opacity:1;stroke:none;stroke-width:4.28879" cx="-956.38037" cy="-281.15619" r="2.5" />
@ -60,7 +60,7 @@
<path inkscape:export-ydpi="28.799999" inkscape:export-xdpi="28.799999" inkscape:export-filename="/home/ybon/Work/osmtouch64.png" d="m 36.286947,38.82145 c -0.457367,0.452579 -0.512559,0.504833 -0.938758,0.934524 l 1.311056,-0.309645 c 0.03951,-0.177773 0.08574,-0.397942 0.09827,-0.449622 -0.206968,-0.007 -0.324977,-0.0729 -0.470564,-0.175257 z m 1.416518,-0.515743 c -0.04859,0.578556 -0.300471,0.62169 -0.777745,0.697632 -0.034,0.152288 -0.05699,0.258181 -0.0969,0.437787 l 1.223994,0.303984 c 0.164208,-0.701576 0.296132,-1.269942 0.293248,-1.273096 -0.0043,-0.0046 -0.327631,-0.08748 -0.642597,-0.166307 z m -0.587772,-0.141586 c -0.0016,0.0027 -0.06999,0.304712 -0.158099,0.698899 0.559065,-0.08996 0.575972,-0.270987 0.592873,-0.594974 -0.229404,-0.05691 -0.432289,-0.106081 -0.434774,-0.103925 z m -0.164475,-0.0092 c -0.135978,0.01159 -0.204073,0.02561 -0.353171,0.06753 0.04792,0.09125 0.07023,0.278832 -0.200036,0.497924 0.141563,0.08791 0.265261,0.122014 0.390009,0.137353 0.114356,-0.532403 0.172961,-0.615354 0.163198,-0.702835 z m -2.677486,-0.0065 -0.237148,0.943143 0.805796,-0.798942 c -0.18084,-0.04602 -0.34599,-0.08797 -0.568648,-0.144201 z m 5.612522,-0.03249 c -0.750179,0.194829 -1.362065,0.355852 -1.364242,0.358548 -0.0019,0.0027 -0.137285,0.574647 -0.303451,1.280914 l 1.337469,-0.33256 z m -2.182789,-0.197471 v 0.211759 c 0.276503,0.0699 0.560065,0.139645 0.618371,0.140292 0,0 -0.03096,-0.126516 -0.06757,-0.283199 -7.93e-4,0 -0.0016,0 -0.0026,0 -0.238721,0.0062 -0.321882,-0.0081 -0.548246,-0.06885 z m -0.679572,-0.315683 -0.0026,0.0027 0.09817,0.38583 c 0.02307,-0.0027 0.214998,0.04675 0.430948,0.10131 2.4e-5,-0.0864 1.64e-4,-0.157114 0.0013,-0.219523 -0.185131,-0.06365 -0.363024,-0.153906 -0.527846,-0.270232 z m -2.866186,-0.12471 0.131326,0.50016 c 0,0 0.363977,0.08961 0.697421,0.171483 l 0.03825,-0.03769 c -0.494559,-0.17868 -0.501422,-0.552676 -0.866997,-0.633955 z m 5.579372,-0.111716 c -0.494358,0.418395 -0.758865,0.525016 -1.314519,0.614464 0.03396,0.138971 0.06369,0.258155 0.07268,0.285814 0.0076,0.02345 0.467328,-0.08354 1.388467,-0.320887 z m -3.207882,-0.254623 c -0.06109,-0.08511 -0.11524,-0.173667 -0.161925,-0.265029 -0.359863,0.0798 -0.952985,0.222488 -0.97027,0.237747 -0.0073,0.0065 0.04546,0.244648 0.118573,0.540437 0.178835,-0.168006 0.384271,-0.137731 0.520491,-0.04456 m 0.507283,0.496144 c 0.125,-0.04259 0.297064,-0.07581 0.406593,-0.08915 -0.01373,-0.100393 -0.0232,-0.163665 -0.06247,-0.267616 m -2.910811,-0.983419 0.131326,0.528737 c 0.662519,0.255998 0.711877,0.768478 1.067168,0.697631 l 0.228224,-0.226046 c -0.07081,-0.298943 -0.153485,-0.613683 -0.173397,-0.633956 -0.0046,-0.0046 -1.253321,-0.366366 -1.253321,-0.366366 z m 2.186615,-1.140587 -0.443699,0.111716 c -0.09333,0.398662 -0.219022,0.89726 -0.294523,1.192563 0.363871,-0.102631 0.462682,-0.124171 0.872095,-0.20785 -0.143711,-0.349112 -0.188886,-0.728445 -0.133873,-1.096429 z m -1.87424,-0.285813 -0.313648,1.249741 c 0.483029,0.139375 0.763559,0.218579 1.252043,0.335148 0.10314,-0.32458 0.219451,-0.683155 0.303448,-1.197766 -0.325758,-0.103251 -0.521049,-0.166792 -1.241843,-0.387123 z m 2.351088,-1.414701 -1.220169,0.30269 c 0.172125,0.761442 0.298183,1.305114 0.305999,1.313364 0.0075,0.0078 0.225253,-0.03952 0.473022,-0.09743 0.116554,-0.470022 0.217924,-0.632905 0.563546,-0.989889 -0.03709,-0.162128 -0.07823,-0.339596 -0.122398,-0.528737 z m 0.163197,-0.01698 c 0.05038,0.214994 0.05503,0.230495 0.09945,0.419609 0.140443,-0.115059 0.293208,-0.208632 0.452622,-0.281905 z m -2.852158,0 0.318746,1.249742 c 0.700001,0.21006 1.258697,0.375235 1.262245,0.371542 0.0038,-0.004 -0.123335,-0.586051 -0.283048,-1.309482 z m 5.60487,-0.01159 -0.493422,0.122095 c 0.227135,0.09573 0.440336,0.233245 0.628571,0.411818 z m -2.717445,2.334255 c 0.109487,0.68124 0.842335,1.193371 1.606491,1.108532 0.285036,-0.686201 0.484585,-0.652934 0.594535,-1.340268 0.0044,-0.611014 -0.784114,-0.234107 -1.142519,-0.214697 -0.615619,-0.01995 -0.584985,-0.758423 -0.651779,-0.867659 -0.190072,0.142368 -0.521817,0.587372 -0.406728,1.314092 z m 0.702955,-1.549601 c 0.200636,0.645656 0.243692,0.866311 0.883571,0.613171 0.481322,-0.142179 0.864986,0.05125 0.927298,0.283279 0.102087,0.345959 -0.06402,0.852913 -0.5091,1.641961 0.697153,-0.379441 0.91768,-1.209169 0.667258,-1.845956 -0.341146,-0.72645 -1.135436,-1.087828 -1.969027,-0.692455 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.264583" id="path5801" inkscape:connector-curvature="0" /> <path inkscape:export-ydpi="28.799999" inkscape:export-xdpi="28.799999" inkscape:export-filename="/home/ybon/Work/osmtouch64.png" d="m 36.286947,38.82145 c -0.457367,0.452579 -0.512559,0.504833 -0.938758,0.934524 l 1.311056,-0.309645 c 0.03951,-0.177773 0.08574,-0.397942 0.09827,-0.449622 -0.206968,-0.007 -0.324977,-0.0729 -0.470564,-0.175257 z m 1.416518,-0.515743 c -0.04859,0.578556 -0.300471,0.62169 -0.777745,0.697632 -0.034,0.152288 -0.05699,0.258181 -0.0969,0.437787 l 1.223994,0.303984 c 0.164208,-0.701576 0.296132,-1.269942 0.293248,-1.273096 -0.0043,-0.0046 -0.327631,-0.08748 -0.642597,-0.166307 z m -0.587772,-0.141586 c -0.0016,0.0027 -0.06999,0.304712 -0.158099,0.698899 0.559065,-0.08996 0.575972,-0.270987 0.592873,-0.594974 -0.229404,-0.05691 -0.432289,-0.106081 -0.434774,-0.103925 z m -0.164475,-0.0092 c -0.135978,0.01159 -0.204073,0.02561 -0.353171,0.06753 0.04792,0.09125 0.07023,0.278832 -0.200036,0.497924 0.141563,0.08791 0.265261,0.122014 0.390009,0.137353 0.114356,-0.532403 0.172961,-0.615354 0.163198,-0.702835 z m -2.677486,-0.0065 -0.237148,0.943143 0.805796,-0.798942 c -0.18084,-0.04602 -0.34599,-0.08797 -0.568648,-0.144201 z m 5.612522,-0.03249 c -0.750179,0.194829 -1.362065,0.355852 -1.364242,0.358548 -0.0019,0.0027 -0.137285,0.574647 -0.303451,1.280914 l 1.337469,-0.33256 z m -2.182789,-0.197471 v 0.211759 c 0.276503,0.0699 0.560065,0.139645 0.618371,0.140292 0,0 -0.03096,-0.126516 -0.06757,-0.283199 -7.93e-4,0 -0.0016,0 -0.0026,0 -0.238721,0.0062 -0.321882,-0.0081 -0.548246,-0.06885 z m -0.679572,-0.315683 -0.0026,0.0027 0.09817,0.38583 c 0.02307,-0.0027 0.214998,0.04675 0.430948,0.10131 2.4e-5,-0.0864 1.64e-4,-0.157114 0.0013,-0.219523 -0.185131,-0.06365 -0.363024,-0.153906 -0.527846,-0.270232 z m -2.866186,-0.12471 0.131326,0.50016 c 0,0 0.363977,0.08961 0.697421,0.171483 l 0.03825,-0.03769 c -0.494559,-0.17868 -0.501422,-0.552676 -0.866997,-0.633955 z m 5.579372,-0.111716 c -0.494358,0.418395 -0.758865,0.525016 -1.314519,0.614464 0.03396,0.138971 0.06369,0.258155 0.07268,0.285814 0.0076,0.02345 0.467328,-0.08354 1.388467,-0.320887 z m -3.207882,-0.254623 c -0.06109,-0.08511 -0.11524,-0.173667 -0.161925,-0.265029 -0.359863,0.0798 -0.952985,0.222488 -0.97027,0.237747 -0.0073,0.0065 0.04546,0.244648 0.118573,0.540437 0.178835,-0.168006 0.384271,-0.137731 0.520491,-0.04456 m 0.507283,0.496144 c 0.125,-0.04259 0.297064,-0.07581 0.406593,-0.08915 -0.01373,-0.100393 -0.0232,-0.163665 -0.06247,-0.267616 m -2.910811,-0.983419 0.131326,0.528737 c 0.662519,0.255998 0.711877,0.768478 1.067168,0.697631 l 0.228224,-0.226046 c -0.07081,-0.298943 -0.153485,-0.613683 -0.173397,-0.633956 -0.0046,-0.0046 -1.253321,-0.366366 -1.253321,-0.366366 z m 2.186615,-1.140587 -0.443699,0.111716 c -0.09333,0.398662 -0.219022,0.89726 -0.294523,1.192563 0.363871,-0.102631 0.462682,-0.124171 0.872095,-0.20785 -0.143711,-0.349112 -0.188886,-0.728445 -0.133873,-1.096429 z m -1.87424,-0.285813 -0.313648,1.249741 c 0.483029,0.139375 0.763559,0.218579 1.252043,0.335148 0.10314,-0.32458 0.219451,-0.683155 0.303448,-1.197766 -0.325758,-0.103251 -0.521049,-0.166792 -1.241843,-0.387123 z m 2.351088,-1.414701 -1.220169,0.30269 c 0.172125,0.761442 0.298183,1.305114 0.305999,1.313364 0.0075,0.0078 0.225253,-0.03952 0.473022,-0.09743 0.116554,-0.470022 0.217924,-0.632905 0.563546,-0.989889 -0.03709,-0.162128 -0.07823,-0.339596 -0.122398,-0.528737 z m 0.163197,-0.01698 c 0.05038,0.214994 0.05503,0.230495 0.09945,0.419609 0.140443,-0.115059 0.293208,-0.208632 0.452622,-0.281905 z m -2.852158,0 0.318746,1.249742 c 0.700001,0.21006 1.258697,0.375235 1.262245,0.371542 0.0038,-0.004 -0.123335,-0.586051 -0.283048,-1.309482 z m 5.60487,-0.01159 -0.493422,0.122095 c 0.227135,0.09573 0.440336,0.233245 0.628571,0.411818 z m -2.717445,2.334255 c 0.109487,0.68124 0.842335,1.193371 1.606491,1.108532 0.285036,-0.686201 0.484585,-0.652934 0.594535,-1.340268 0.0044,-0.611014 -0.784114,-0.234107 -1.142519,-0.214697 -0.615619,-0.01995 -0.584985,-0.758423 -0.651779,-0.867659 -0.190072,0.142368 -0.521817,0.587372 -0.406728,1.314092 z m 0.702955,-1.549601 c 0.200636,0.645656 0.243692,0.866311 0.883571,0.613171 0.481322,-0.142179 0.864986,0.05125 0.927298,0.283279 0.102087,0.345959 -0.06402,0.852913 -0.5091,1.641961 0.697153,-0.379441 0.91768,-1.209169 0.667258,-1.845956 -0.341146,-0.72645 -1.135436,-1.087828 -1.969027,-0.692455 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.264583" id="path5801" inkscape:connector-curvature="0" />
</g> </g>
<g id="delete-marker" transform="matrix(0.26458333,0,0,0.26458333,23.529017,-228.26118)" class="sprite"> <g id="delete-marker" transform="matrix(0.26458333,0,0,0.26458333,23.529017,-228.26118)" class="sprite">
<path id="path3378-6" d="m 178.57143,979.21934 c -3.0625,0 -6.125,2.1197 -7,6.375 0,2.5532 1.75,7.6676 7,13.625 3.4166,-3.877 5.31568,-7.3755 6.25,-10.0625 -1.31416,-0.1622 -2.497,-0.7235 -3.40625,-1.5938 -0.63462,0.8653 -1.6677,1.4375 -2.84375,1.4375 -1.933,0 -3.5,-1.5261 -3.5,-3.4062 0,-1.8801 1.567,-3.4063 3.5,-3.4063 0.36776,0 0.72951,0.085 1.0625,0.1875 0.14352,-1.0312 0.55799,-1.956 1.15625,-2.75 -0.72276,-0.259 -1.46314,-0.4062 -2.21875,-0.4062 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none" inkscape:connector-curvature="0" /> <path id="path3378-6" d="m 178.57143,979.21934 c -3.0625,0 -6.44624,2.06611 -7,6.375 -0.32545,2.53237 1.75,7.6676 7,13.625 3.4166,-3.877 5.31568,-7.3755 6.25,-10.0625 -1.31416,-0.1622 -2.497,-0.7235 -3.40625,-1.5938 -0.63462,0.8653 -1.6677,1.4375 -2.84375,1.4375 -1.933,0 -3.5,-1.5261 -3.5,-3.4062 0,-1.8801 1.567,-3.4063 3.5,-3.4063 0.36776,0 0.72951,0.085 1.0625,0.1875 0.14352,-1.0312 0.55799,-1.956 1.15625,-2.75 -0.72276,-0.259 -1.46314,-0.4062 -2.21875,-0.4062 z" style="fill:#4d4d4d;fill-opacity:1;stroke:none" inkscape:connector-curvature="0" sodipodi:nodetypes="sscccsssccs" />
<path inkscape:connector-curvature="0" id="path6764" d="m 185.57143,978.21934 c -2.76142,0 -5,2.2386 -5,5 0,2.7615 2.23858,5 5,5 2.76142,0 5,-2.2385 5,-5 0,-2.7614 -2.23858,-5 -5,-5 z m -1.81818,2.2727 1.81818,1.8182 1.81818,-1.8182 0.90909,0.9091 -1.81818,1.8182 1.81818,1.8182 -0.90909,0.9091 -1.81818,-1.8182 -1.81818,1.8182 -0.90909,-0.9091 1.81818,-1.8182 -1.81818,-1.8182 z" style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" /> <path inkscape:connector-curvature="0" id="path6764" d="m 185.57143,978.21934 c -2.76142,0 -5,2.2386 -5,5 0,2.7615 2.23858,5 5,5 2.76142,0 5,-2.2385 5,-5 0,-2.7614 -2.23858,-5 -5,-5 z m -1.81818,2.2727 1.81818,1.8182 1.81818,-1.8182 0.90909,0.9091 -1.81818,1.8182 1.81818,1.8182 -0.90909,0.9091 -1.81818,-1.8182 -1.81818,1.8182 -0.90909,-0.9091 1.81818,-1.8182 -1.81818,-1.8182 z" style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
</g> </g>
<g id="multipolygon" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,66.121027,-220.75833)"> <g id="multipolygon" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,66.121027,-220.75833)">
@ -77,7 +77,7 @@
</g> </g>
<path style="fill:#464646;fill-opacity:1;stroke:none;stroke-width:1.84551;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0017170804" inkscape:transform-center-y="-1.1593678" d="m 31.537126,45.771563 0.577355,-2.184903 -1.687401,-1.349931 h 2.154994 l 0.756436,-2.28465 0.754501,2.284227 h 2.154902 l -1.688682,1.351121 0.575368,2.185485 -1.798166,-1.252432 z" id="star" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" /> <path style="fill:#464646;fill-opacity:1;stroke:none;stroke-width:1.84551;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0017170804" inkscape:transform-center-y="-1.1593678" d="m 31.537126,45.771563 0.577355,-2.184903 -1.687401,-1.349931 h 2.154994 l 0.756436,-2.28465 0.754501,2.284227 h 2.154902 l -1.688682,1.351121 0.575368,2.185485 -1.798166,-1.252432 z" id="star" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" />
<path style="fill:none;fill-opacity:1;stroke:#464646;stroke-width:0.264583;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0017170804" inkscape:transform-center-y="-1.1593678" d="m 40.742193,45.771563 0.577355,-2.184903 -1.687401,-1.349931 h 2.154994 l 0.756436,-2.28465 0.754502,2.284227 h 2.154901 l -1.688682,1.351121 0.575368,2.185485 -1.798169,-1.252432 z" id="starred" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" /> <path style="fill:none;fill-opacity:1;stroke:#464646;stroke-width:0.264583;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" inkscape:transform-center-x="-0.0017170804" inkscape:transform-center-y="-1.1593678" d="m 40.742193,45.771563 0.577355,-2.184903 -1.687401,-1.349931 h 2.154994 l 0.756436,-2.28465 0.754502,2.284227 h 2.154901 l -1.688682,1.351121 0.575368,2.185485 -1.798169,-1.252432 z" id="starred" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" class="sprite" />
<path d="m 45.33157,52.032511 0.367177,0.21791 c 0.07232,0.04294 0.09577,0.135732 0.0524,0.207275 -0.01292,0.02122 -0.03092,0.03903 -0.0524,0.0518 l -2.836254,1.6832 -2.836235,-1.6832 c -0.07233,-0.04294 -0.09579,-0.135704 -0.05238,-0.207274 0.0129,-0.02125 0.03089,-0.03905 0.05238,-0.05181 l 0.367179,-0.21791 2.469056,1.465315 z m 0,1.419992 0.367177,0.217911 c 0.07232,0.04294 0.09577,0.135731 0.0524,0.207274 -0.01292,0.02125 -0.03092,0.03903 -0.0524,0.05181 l -2.679097,1.58996 c -0.09674,0.05739 -0.217576,0.05739 -0.314315,0 l -2.679077,-1.58996 c -0.07233,-0.04292 -0.09579,-0.135705 -0.05238,-0.207249 0.0129,-0.02127 0.03089,-0.03908 0.05238,-0.05183 l 0.367179,-0.217911 2.469056,1.465315 z m -2.31192,-4.196946 2.679097,1.589967 c 0.07232,0.04292 0.09577,0.135715 0.0524,0.207256 -0.01292,0.02126 -0.03092,0.03906 -0.0524,0.05182 l -2.836254,1.683221 -2.836235,-1.683221 c -0.07233,-0.04292 -0.09579,-0.135716 -0.05238,-0.207256 0.0129,-0.02126 0.03089,-0.03906 0.05238,-0.05182 l 2.679077,-1.589967 c 0.09674,-0.05741 0.217576,-0.05741 0.314315,0 z" fill="#4d4d4d" id="datalayers" style="stroke-width:0.264583" /> <path d="m 45.33157,52.032514 0.367177,0.21791 c 0.07232,0.04294 0.09577,0.135732 0.0524,0.207275 -0.01292,0.02122 -0.03092,0.03903 -0.0524,0.0518 l -2.836254,1.6832 -2.836235,-1.6832 c -0.07233,-0.04294 -0.09579,-0.135704 -0.05238,-0.207274 0.0129,-0.02125 0.03089,-0.03905 0.05238,-0.05181 l 0.367179,-0.21791 2.469056,1.465315 z m 0,1.419992 0.367177,0.217911 c 0.07232,0.04294 0.09577,0.135731 0.0524,0.207274 -0.01292,0.02125 -0.03092,0.03903 -0.0524,0.05181 l -2.679097,1.58996 c -0.09674,0.05739 -0.217576,0.05739 -0.314315,0 l -2.679077,-1.58996 c -0.07233,-0.04292 -0.09579,-0.135705 -0.05238,-0.207249 0.0129,-0.02127 0.03089,-0.03908 0.05238,-0.05183 l 0.367179,-0.217911 2.469056,1.465315 z m -2.31192,-4.196946 2.679097,1.589967 c 0.07232,0.04292 0.09577,0.135715 0.0524,0.207256 -0.01292,0.02126 -0.03092,0.03906 -0.0524,0.05182 l -2.836254,1.683221 -2.836235,-1.683221 c -0.07233,-0.04292 -0.09579,-0.135716 -0.05238,-0.207256 0.0129,-0.02126 0.03089,-0.03906 0.05238,-0.05182 l 2.679077,-1.589967 c 0.09674,-0.05741 0.217576,-0.05741 0.314315,0 z" fill="#4d4d4d" id="datalayers" style="stroke-width:0.264583" />
<g id="tilelayers" transform="translate(19.049999,56.885416)"> <g id="tilelayers" transform="translate(19.049999,56.885416)">
<path d="m 26.772659,3.4276506 h -4.243945 c -0.07035,0 -0.137814,0.027945 -0.187558,0.077687 -0.04974,0.049744 -0.07769,0.1172104 -0.07769,0.1875578 v 4.2439431 c 0,0.070353 0.02794,0.1378215 0.07769,0.1875631 0.04974,0.049742 0.11721,0.077682 0.187558,0.077682 h 4.243945 c 0.07035,0 0.137822,-0.02794 0.187563,-0.077682 0.04974,-0.049742 0.07768,-0.1172104 0.07768,-0.1875631 v -4.2439431 c 0,-0.070347 -0.02794,-0.1378135 -0.07768,-0.1875578 -0.04974,-0.049742 -0.11721,-0.077687 -0.187563,-0.077687 z m -0.265245,4.1590648 h -3.713453 v -3.546348 h 3.713453 z" fill="#464646" id="path2349" style="stroke-width:0.264583" /> <path d="m 26.772659,3.4276506 h -4.243945 c -0.07035,0 -0.137814,0.027945 -0.187558,0.077687 -0.04974,0.049744 -0.07769,0.1172104 -0.07769,0.1875578 v 4.2439431 c 0,0.070353 0.02794,0.1378215 0.07769,0.1875631 0.04974,0.049742 0.11721,0.077682 0.187558,0.077682 h 4.243945 c 0.07035,0 0.137822,-0.02794 0.187563,-0.077682 0.04974,-0.049742 0.07768,-0.1172104 0.07768,-0.1875631 v -4.2439431 c 0,-0.070347 -0.02794,-0.1378135 -0.07768,-0.1875578 -0.04974,-0.049742 -0.11721,-0.077687 -0.187563,-0.077687 z m -0.265245,4.1590648 h -3.713453 v -3.546348 h 3.713453 z" fill="#464646" id="path2349" style="stroke-width:0.264583" />
<g mask="url(#mask0_181_11898)" id="g2376" transform="matrix(0.26458333,0,0,0.26458333,20.637501,1.8520833)"> <g mask="url(#mask0_181_11898)" id="g2376" transform="matrix(0.26458333,0,0,0.26458333,20.637501,1.8520833)">
@ -110,5 +110,6 @@
<path inkscape:connector-curvature="0" id="path3789" style="font-weight:bold;font-size:12px;-inkscape-font-specification:'Sans Bold';fill:#4d4d4d;stroke-width:0.75" d="m 9,1046.0464 h -2.3698034 v -0.3223 c 0,-0.3596 0.072207,-0.6775 0.2166302,-0.9539 0.1444174,-0.2807 0.4485749,-0.636 0.9124728,-1.0658 l 0.4201314,-0.3816 c 0.249449,-0.228 0.4310681,-0.4429 0.5448577,-0.6446 0.1181576,-0.2019 0.1772384,-0.4036 0.177243,-0.6053 -4.6e-6,-0.3071 -0.1050376,-0.5462 -0.3150985,-0.7171 -0.2100697,-0.1756 -0.5032861,-0.2632 -0.87965,-0.2632 -0.3544889,0 -0.7374207,0.075 -1.1487968,0.2237 -0.4113804,0.1446 -0.840264,0.3618 -1.2866522,0.6513 v -2.0659 c 0.5295391,-0.184 1.0131273,-0.32 1.4507661,-0.4077 0.437634,-0.088 0.8599531,-0.1317 1.2669587,-0.1317 1.0678292,0 1.8818328,0.2194 2.442012,0.6579 0.560169,0.4341 0.840256,1.0702 0.840263,1.9078 -7e-6,0.4298 -0.08535,0.8159 -0.256017,1.158 -0.170685,0.3377 -0.461713,0.7017 -0.873085,1.092 l -0.4201313,0.375 c -0.297598,0.272 -0.4923463,0.4913 -0.5842451,0.658 -0.091909,0.1622 -0.1378603,0.342 -0.1378556,0.5394 v 0.296 m -2.3698034,0.9739 h 2.3698034 v 2.342 h -2.3698034 v -2.342" sodipodi:nodetypes="ccsccccccsccccsccccccccccccc" /> <path inkscape:connector-curvature="0" id="path3789" style="font-weight:bold;font-size:12px;-inkscape-font-specification:'Sans Bold';fill:#4d4d4d;stroke-width:0.75" d="m 9,1046.0464 h -2.3698034 v -0.3223 c 0,-0.3596 0.072207,-0.6775 0.2166302,-0.9539 0.1444174,-0.2807 0.4485749,-0.636 0.9124728,-1.0658 l 0.4201314,-0.3816 c 0.249449,-0.228 0.4310681,-0.4429 0.5448577,-0.6446 0.1181576,-0.2019 0.1772384,-0.4036 0.177243,-0.6053 -4.6e-6,-0.3071 -0.1050376,-0.5462 -0.3150985,-0.7171 -0.2100697,-0.1756 -0.5032861,-0.2632 -0.87965,-0.2632 -0.3544889,0 -0.7374207,0.075 -1.1487968,0.2237 -0.4113804,0.1446 -0.840264,0.3618 -1.2866522,0.6513 v -2.0659 c 0.5295391,-0.184 1.0131273,-0.32 1.4507661,-0.4077 0.437634,-0.088 0.8599531,-0.1317 1.2669587,-0.1317 1.0678292,0 1.8818328,0.2194 2.442012,0.6579 0.560169,0.4341 0.840256,1.0702 0.840263,1.9078 -7e-6,0.4298 -0.08535,0.8159 -0.256017,1.158 -0.170685,0.3377 -0.461713,0.7017 -0.873085,1.092 l -0.4201313,0.375 c -0.297598,0.272 -0.4923463,0.4913 -0.5842451,0.658 -0.091909,0.1622 -0.1378603,0.342 -0.1378556,0.5394 v 0.296 m -2.3698034,0.9739 h 2.3698034 v 2.342 h -2.3698034 v -2.342" sodipodi:nodetypes="ccsccccccsccccsccccccccccccc" />
</g> </g>
</g> </g>
<path id="copy" style="fill:#4d4d4d;stroke-width:0.264582;paint-order:fill markers stroke" d="m 42.218298,69.320832 v 1.288405 h 1.472463 v 1.472465 h 1.288405 v -2.76087 z m -1.472465,1.472463 v 2.760871 h 2.760869 v -2.760871 z" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><g filter="url(#a)"><circle cx="16" cy="12" r="6" fill="#2980B9"/></g><g filter="url(#b)"><circle cx="16" cy="12" r="11.5" stroke="#2980B9" shape-rendering="crispEdges"/></g><defs><filter id="a" width="20" height="20" x="6" y="6" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="4"/><feGaussianBlur stdDeviation="2"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2923_3333"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_2923_3333" result="shape"/></filter><filter id="b" width="32" height="32" x="0" y="0" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="4"/><feGaussianBlur stdDeviation="2"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2923_3333"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_2923_3333" result="shape"/></filter></defs></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -140,7 +140,6 @@ class uMapAlertConflict extends uMapAlert {
} }
onAlertConflict(event) { onAlertConflict(event) {
// biome-ignore lint/style/useNumberNamespace: Number.Infinity returns undefined by default
const { const {
level = 'info', level = 'info',
duration = Number.POSITIVE_INFINITY, duration = Number.POSITIVE_INFINITY,

View file

@ -7,6 +7,7 @@ import {
import { translate } from './i18n.js' import { translate } from './i18n.js'
import { Request, ServerRequest } from './request.js' import { Request, ServerRequest } from './request.js'
import { escapeHTML, generateId } from './utils.js' import { escapeHTML, generateId } from './utils.js'
import * as Utils from './utils.js'
export class BaseAutocomplete { export class BaseAutocomplete {
constructor(parent, options) { constructor(parent, options) {
@ -291,10 +292,9 @@ class BaseServerAjax extends BaseAjax {
export const SingleMixin = (Base) => export const SingleMixin = (Base) =>
class extends Base { class extends Base {
initSelectedContainer() { initSelectedContainer() {
return DomUtil.after( const el = Utils.loadTemplate('<div class="umap-singleresult"></div>')
this.input, this.input.parentNode.insertBefore(el, this.input.nextSibling)
DomUtil.element({ tagName: 'div', className: 'umap-singleresult' }) return el
)
} }
displaySelected(result) { displaySelected(result) {
@ -322,10 +322,9 @@ export const SingleMixin = (Base) =>
export const MultipleMixin = (Base) => export const MultipleMixin = (Base) =>
class extends Base { class extends Base {
initSelectedContainer() { initSelectedContainer() {
return DomUtil.after( const el = Utils.loadTemplate('<ul class="umap-multiresult"></ul>')
this.input, this.input.parentNode.insertBefore(el, this.input.nextSibling)
DomUtil.element({ tagName: 'ul', className: 'umap-multiresult' }) return el
)
} }
displaySelected(result) { displaySelected(result) {

View file

@ -1,10 +1,11 @@
import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js' import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
import { Form } from './form/builder.js'
import { EXPORT_FORMATS } from './formatter.js'
import { translate } from './i18n.js' import { translate } from './i18n.js'
import * as Icon from './rendering/icon.js' import * as Icon from './rendering/icon.js'
import * as Utils from './utils.js'
import { EXPORT_FORMATS } from './formatter.js'
import ContextMenu from './ui/contextmenu.js' import ContextMenu from './ui/contextmenu.js'
import { Form } from './form/builder.js' import * as Utils from './utils.js'
import { SCHEMA } from './schema.js'
export default class Browser { export default class Browser {
constructor(umap, leafletMap) { constructor(umap, leafletMap) {
@ -21,35 +22,24 @@ export default class Browser {
addFeature(feature, parent) { addFeature(feature, parent) {
if (feature.isFiltered()) return if (feature.isFiltered()) return
if (this.options.inBbox && !feature.isOnScreen(this.bounds)) return if (this.options.inBbox && !feature.isOnScreen(this.bounds)) return
const row = DomUtil.create('li', `${feature.getClassName()} feature`) const template = `
const zoom_to = DomUtil.createButtonIcon( <li class="feature ${feature.getClassName()}">
row, <button class="icon icon-16 icon-zoom" title="${translate('Bring feature to center')}" data-ref=zoom></button>
'icon-zoom', <button class="icon icon-16 show-on-edit icon-edit" title="${translate('Edit this feature')}" data-ref=edit></button>
translate('Bring feature to center') <button class="icon icon-16 show-on-edit icon-delete" title="${translate('Delete this feature')}" data-ref=remove></button>
) <i class="icon icon-16 icon-${feature.getClassName()} feature-color" data-ref=colorBox></i>
const edit = DomUtil.createButtonIcon( <span class="feature-title" data-ref=label></span>
row, </li>
'show-on-edit icon-edit', `
translate('Edit this feature') const [row, { zoom, edit, remove, colorBox, label }] =
) Utils.loadTemplateWithRefs(template)
const del = DomUtil.createButtonIcon( label.textContent = label.title = feature.getDisplayName() || '—'
row,
'show-on-edit icon-delete',
translate('Delete this feature')
)
const colorBox = DomUtil.create(
'i',
`icon icon-16 icon-${feature.getClassName()} feature-color`,
row
)
const title = DomUtil.create('span', 'feature-title', row)
const symbol = feature._getIconUrl const symbol = feature._getIconUrl
? Icon.formatUrl(feature._getIconUrl(), feature) ? Icon.formatUrl(feature._getIconUrl(), feature)
: null : null
title.textContent = title.title = feature.getDisplayName() || '—'
const bgcolor = feature.getPreviewColor() const bgcolor = feature.getPreviewColor()
colorBox.style.backgroundColor = bgcolor colorBox.style.backgroundColor = bgcolor
if (symbol && symbol !== U.SCHEMA.iconUrl.default) { if (symbol && symbol !== SCHEMA.iconUrl.default) {
const icon = Icon.makeElement(symbol, colorBox) const icon = Icon.makeElement(symbol, colorBox)
Icon.setContrast(icon, colorBox, symbol, bgcolor) Icon.setContrast(icon, colorBox, symbol, bgcolor)
} else if (DomUtil.contrastedColor(colorBox, bgcolor)) { } else if (DomUtil.contrastedColor(colorBox, bgcolor)) {
@ -58,10 +48,10 @@ export default class Browser {
const viewFeature = (e) => { const viewFeature = (e) => {
feature.zoomTo({ ...e, callback: () => feature.view() }) feature.zoomTo({ ...e, callback: () => feature.view() })
} }
DomEvent.on(zoom_to, 'click', viewFeature) zoom.addEventListener('click', viewFeature)
DomEvent.on(title, 'click', viewFeature) label.addEventListener('click', viewFeature)
DomEvent.on(edit, 'click', feature.edit, feature) edit.addEventListener('click', () => feature.edit())
DomEvent.on(del, 'click', feature.confirmDelete, feature) remove.addEventListener('click', () => feature.del())
// HOTFIX. Remove when this is released: // HOTFIX. Remove when this is released:
// https://github.com/Leaflet/Leaflet/pull/9052 // https://github.com/Leaflet/Leaflet/pull/9052
DomEvent.disableClickPropagation(row) DomEvent.disableClickPropagation(row)
@ -73,51 +63,51 @@ export default class Browser {
} }
addDataLayer(datalayer, parent) { addDataLayer(datalayer, parent) {
let className = `datalayer ${datalayer.getHidableClass()}` const open = this.mode !== 'layers' ? ' open' : ''
if (this.mode !== 'layers') className += ' show-list' const [container, { headline, toolbox, label }] = Utils.loadTemplateWithRefs(`
const container = DomUtil.create('div', className, parent) <details class="datalayer ${datalayer.getHidableClass()}" id="${this.datalayerId(datalayer)}"${open}>
const headline = DomUtil.create('h5', '', container) <summary data-ref=headline>
container.id = this.datalayerId(datalayer) <span data-ref=toolbox></span>
const ul = DomUtil.create('ul', '', container) <span class="datalayer-name" data-id="${datalayer.id}" data-ref=label></span>
<span class="datalayer-counter"></span>
</summary>
<ul></ul>
</details>
`)
datalayer.renderToolbox(toolbox)
parent.appendChild(container)
this.updateDatalayer(datalayer) this.updateDatalayer(datalayer)
} }
updateDatalayer(datalayer) { updateDatalayer(datalayer) {
// Compute once, but use it for each feature later. // Compute once, but use it for each feature later.
this.bounds = this._leafletMap.getBounds() this.bounds = this._leafletMap.getBounds()
const parent = DomUtil.get(this.datalayerId(datalayer)) const id = this.datalayerId(datalayer)
const parent = document.getElementById(id)
// Panel is not open // Panel is not open
if (!parent) return if (!parent) return
parent.classList.toggle('off', !datalayer.isVisible()) parent.classList.toggle('off', !datalayer.isVisible())
const label = parent.querySelector('.datalayer-name')
const container = parent.querySelector('ul') const container = parent.querySelector('ul')
const headline = parent.querySelector('h5')
const toggleList = () => parent.classList.toggle('show-list')
headline.innerHTML = ''
const toggle = DomUtil.create('i', 'icon icon-16 datalayer-toggle-list', headline)
DomEvent.on(toggle, 'click', toggleList)
datalayer.renderToolbox(headline)
const name = DomUtil.create('span', 'datalayer-name', headline)
name.textContent = name.title = datalayer.options.name
DomEvent.on(name, 'click', toggleList)
container.innerHTML = '' container.innerHTML = ''
datalayer.eachFeature((feature) => this.addFeature(feature, container)) datalayer.eachFeature((feature) => this.addFeature(feature, container))
datalayer.propagate(['properties.name'])
const total = datalayer.count() const total = datalayer.count()
if (!total) return if (!total) return
const current = container.querySelectorAll('li').length const current = container.querySelectorAll('li').length
const count = total === current ? total : `${current}/${total}` const count = total === current ? total : `${current}/${total}`
const counter = DomUtil.create('span', 'datalayer-counter', headline) const counter = parent.querySelector('.datalayer-counter')
counter.textContent = `(${count})` counter.textContent = `(${count})`
counter.title = translate(`Features in this layer: ${count}`) counter.title = translate(`Features in this layer: ${count}`)
} }
toggleBadge() { toggleBadge() {
U.Utils.toggleBadge(this.filtersTitle, this.hasFilters()) Utils.toggleBadge(this.filtersTitle, this.hasFilters())
U.Utils.toggleBadge('.umap-control-browse', this.hasFilters()) Utils.toggleBadge('.umap-control-browse', this.hasFilters())
} }
onFormChange() { onFormChange() {
this._umap.eachBrowsableDataLayer((datalayer) => { this._umap.datalayers.browsable().map((datalayer) => {
datalayer.resetLayer(true) datalayer.resetLayer(true)
this.updateDatalayer(datalayer) this.updateDatalayer(datalayer)
if (this._umap.fullPanel?.isOpen()) datalayer.tableEdit() if (this._umap.fullPanel?.isOpen()) datalayer.tableEdit()
@ -140,7 +130,7 @@ export default class Browser {
onMoveEnd() { onMoveEnd() {
if (!this.isOpen()) return if (!this.isOpen()) return
const isListDynamic = this.options.inBbox const isListDynamic = this.options.inBbox
this._umap.eachBrowsableDataLayer((datalayer) => { this._umap.datalayers.browsable().map((datalayer) => {
if (!isListDynamic && !datalayer.hasDynamicData()) return if (!isListDynamic && !datalayer.hasDynamicData()) return
this.updateDatalayer(datalayer) this.updateDatalayer(datalayer)
}) })
@ -149,7 +139,7 @@ export default class Browser {
update() { update() {
if (!this.isOpen()) return if (!this.isOpen()) return
this.dataContainer.innerHTML = '' this.dataContainer.innerHTML = ''
this._umap.eachBrowsableDataLayer((datalayer) => { this._umap.datalayers.browsable().map((datalayer) => {
this.addDataLayer(datalayer, this.dataContainer) this.addDataLayer(datalayer, this.dataContainer)
}) })
} }
@ -157,21 +147,51 @@ export default class Browser {
open(mode) { open(mode) {
// Force only if mode is known, otherwise keep current mode. // Force only if mode is known, otherwise keep current mode.
if (mode) this.mode = mode if (mode) this.mode = mode
const container = DomUtil.create('div') const template = `
<div>
<h3><i class="icon icon-16 icon-layers"></i>${translate('Data browser')}</h3>
<details class="filters" data-ref="details">
<summary data-ref=filtersTitle><i class="icon icon-16 icon-filters"></i>${translate('Filters')}</summary>
<fieldset>
<div data-ref=formContainer>
</div>
<button class="flat" type="button" data-ref=reset><i class="icon icon-16 icon-restore" title=""></i>${translate('Reset all')}</button>
</fieldset>
</details>
<div class="main-toolbox">
<i class="icon icon-16 icon-eye" title="${translate('show/hide all layers')}" data-ref="toggle"></i>
<i class="icon icon-16 icon-zoom" title="${translate('zoom to data extent')}" data-ref="fitBounds"></i>
<i class="icon icon-16 icon-download" title="${translate('download visible data')}" data-ref="download"></i>
</div>
<div data-ref=dataContainer></div>
</div>
`
const [
container,
{
details,
filtersTitle,
toggle,
fitBounds,
download,
dataContainer,
formContainer,
reset,
},
] = Utils.loadTemplateWithRefs(template)
// HOTFIX. Remove when this is released: // HOTFIX. Remove when this is released:
// https://github.com/Leaflet/Leaflet/pull/9052 // https://github.com/Leaflet/Leaflet/pull/9052
DomEvent.disableClickPropagation(container) DomEvent.disableClickPropagation(container)
details.open = this.mode === 'filters'
toggle.addEventListener('click', () => this.toggleLayers())
fitBounds.addEventListener('click', () => this._umap.fitDataBounds())
download.addEventListener('click', () => this.downloadVisible(download))
download.hidden = this._umap.getProperty('embedControl') === false
DomUtil.createTitle(container, translate('Data browser'), 'icon-layers') this.filtersTitle = filtersTitle
this.formContainer = DomUtil.createFieldset(container, L._('Filters'), { this.dataContainer = dataContainer
on: this.mode === 'filters', this.formContainer = formContainer
className: 'filters',
icon: 'icon-filters',
})
this.filtersTitle = container.querySelector('summary')
this.toggleBadge() this.toggleBadge()
this.addMainToolbox(container)
this.dataContainer = DomUtil.create('div', '', container)
let fields = [ let fields = [
[ [
@ -184,27 +204,19 @@ export default class Browser {
builder.on('set', () => this.onFormChange()) builder.on('set', () => this.onFormChange())
let filtersBuilder let filtersBuilder
this.formContainer.appendChild(builder.build()) this.formContainer.appendChild(builder.build())
DomEvent.on(builder.form, 'reset', () => { builder.form.addEventListener('reset', () => {
window.setTimeout(builder.syncAll.bind(builder)) window.setTimeout(builder.syncAll.bind(builder))
}) })
if (this._umap.properties.facetKey) { if (this._umap.properties.facetKey) {
fields = this._umap.facets.build() fields = this._umap.facets.build()
filtersBuilder = new Form(this._umap.facets, fields) filtersBuilder = new Form(this._umap.facets, fields)
filtersBuilder.on('set', () => this.onFormChange()) filtersBuilder.on('set', () => this.onFormChange())
DomEvent.on(filtersBuilder.form, 'reset', () => { filtersBuilder.form.addEventListener('reset', () => {
window.setTimeout(filtersBuilder.syncAll.bind(filtersBuilder)) window.setTimeout(filtersBuilder.syncAll.bind(filtersBuilder))
}) })
this.formContainer.appendChild(filtersBuilder.build()) this.formContainer.appendChild(filtersBuilder.build())
} }
const reset = DomUtil.createButton('flat', this.formContainer, '', () => reset.addEventListener('click', () => this.resetFilters())
this.resetFilters()
)
DomUtil.createIcon(reset, 'icon-restore')
DomUtil.element({
tagName: 'span',
parent: reset,
textContent: translate('Reset all'),
})
this._umap.panel.open({ this._umap.panel.open({
content: container, content: container,
@ -220,20 +232,6 @@ export default class Browser {
} }
} }
addMainToolbox(container) {
const [toolbox, { toggle, fitBounds, download }] = Utils.loadTemplateWithRefs(`
<div class="main-toolbox">
<i class="icon icon-16 icon-eye" title="${translate('show/hide all layers')}" data-ref="toggle"></i>
<i class="icon icon-16 icon-zoom" title="${translate('zoom to data extent')}" data-ref="fitBounds"></i>
<i class="icon icon-16 icon-download" title="${translate('download visible data')}" data-ref="download"></i>
</div>
`)
container.appendChild(toolbox)
toggle.addEventListener('click', () => this.toggleLayers())
fitBounds.addEventListener('click', () => this._umap.fitDataBounds())
download.addEventListener('click', () => this.downloadVisible(download))
}
downloadVisible(element) { downloadVisible(element) {
const menu = new ContextMenu({ fixed: true }) const menu = new ContextMenu({ fixed: true })
const items = [] const items = []
@ -250,10 +248,10 @@ export default class Browser {
// If at least one layer is shown, hide it // If at least one layer is shown, hide it
// otherwise show all // otherwise show all
let allHidden = true let allHidden = true
this._umap.eachBrowsableDataLayer((datalayer) => { this._umap.datalayers.browsable().map((datalayer) => {
if (datalayer.isVisible()) allHidden = false if (datalayer.isVisible()) allHidden = false
}) })
this._umap.eachBrowsableDataLayer((datalayer) => { this._umap.datalayers.browsable().map((datalayer) => {
datalayer._forcedVisibility = true datalayer._forcedVisibility = true
if (allHidden) { if (allHidden) {
datalayer.show() datalayer.show()
@ -264,15 +262,13 @@ export default class Browser {
} }
static backButton(umap) { static backButton(umap) {
const button = DomUtil.createButtonIcon( const button = Utils.loadTemplate(
DomUtil.create('li', '', undefined), `<button class="icon icon-16 icon-back" title="${translate('Back to browser')}"></button>`
'icon-back',
translate('Back to browser')
) )
// Fixme: remove me when this is merged and released // Fixme: remove me when this is merged and released
// https://github.com/Leaflet/Leaflet/pull/9052 // https://github.com/Leaflet/Leaflet/pull/9052
DomEvent.disableClickPropagation(button) DomEvent.disableClickPropagation(button)
DomEvent.on(button, 'click', () => umap.openBrowser()) button.addEventListener('click', () => umap.openBrowser())
return button return button
} }
} }

View file

@ -1,6 +1,6 @@
import { uMapAlert as Alert } from '../components/alerts/alert.js'
import { translate } from './i18n.js' import { translate } from './i18n.js'
import * as Utils from './utils.js' import * as Utils from './utils.js'
import { uMapAlert as Alert } from '../components/alerts/alert.js'
const TEMPLATE = ` const TEMPLATE = `
<div class="umap-caption"> <div class="umap-caption">
@ -68,16 +68,18 @@ export default class Caption extends Utils.WithTemplate {
this.elements.description.hidden = true this.elements.description.hidden = true
} }
this.elements.datalayersContainer.innerHTML = '' this.elements.datalayersContainer.innerHTML = ''
this._umap.eachDataLayerReverse((datalayer) => this._umap.datalayers
this.addDataLayer(datalayer, this.elements.datalayersContainer) .reverse()
) .map((datalayer) =>
this.addDataLayer(datalayer, this.elements.datalayersContainer)
)
this.addCredits() this.addCredits()
if (this._umap.properties.created_at) { if (this._umap.properties.created_at) {
const created_at = translate('created at {date}', { const created_at = translate('created at {date}', {
date: new Date(this._umap.properties.created_at).toLocaleDateString(), date: this._umap.createdAt.toLocaleDateString(),
}) })
const modified_at = translate('modified at {date}', { const modified_at = translate('modified at {date}', {
date: new Date(this._umap.properties.modified_at).toLocaleDateString(), date: this._umap.modifiedAt.toLocaleDateString(),
}) })
this.elements.dates.innerHTML = `${created_at} - ${modified_at}` this.elements.dates.innerHTML = `${created_at} - ${modified_at}`
} else { } else {
@ -85,7 +87,7 @@ export default class Caption extends Utils.WithTemplate {
} }
this._umap.panel.open({ content: this.element }).then(() => { this._umap.panel.open({ content: this.element }).then(() => {
// Create the legend when the panel is actually on the DOM // Create the legend when the panel is actually on the DOM
this._umap.eachDataLayerReverse((datalayer) => datalayer.renderLegend()) this._umap.datalayers.reverse().map((datalayer) => datalayer.renderLegend())
this._umap.propagate() this._umap.propagate()
}) })
} }

View file

@ -1,28 +1,27 @@
import { import {
DomUtil,
DomEvent, DomEvent,
stamp, DomUtil,
GeoJSON, GeoJSON,
LineUtil, LineUtil,
stamp,
} from '../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../vendors/leaflet/leaflet-src.esm.js'
import * as Utils from '../utils.js'
import { SCHEMA } from '../schema.js'
import { translate } from '../i18n.js'
import { uMapAlert as Alert } from '../../components/alerts/alert.js' import { uMapAlert as Alert } from '../../components/alerts/alert.js'
import { MutatingForm } from '../form/builder.js'
import { translate } from '../i18n.js'
import loadPopup from '../rendering/popup.js'
import { import {
LeafletMarker, LeafletMarker,
LeafletPolyline,
LeafletPolygon, LeafletPolygon,
LeafletPolyline,
MaskPolygon, MaskPolygon,
} from '../rendering/ui.js' } from '../rendering/ui.js'
import loadPopup from '../rendering/popup.js' import { SCHEMA } from '../schema.js'
import { MutatingForm } from '../form/builder.js' import * as Utils from '../utils.js'
class Feature { class Feature {
constructor(umap, datalayer, geojson = {}, id = null) { constructor(umap, datalayer, geojson = {}, id = null) {
this._umap = umap this._umap = umap
this.sync = umap.syncEngine.proxy(this) this.sync = umap.syncEngine.proxy(this)
this._isDirty = false
this._ui = null this._ui = null
// DataLayer the feature belongs to // DataLayer the feature belongs to
@ -54,17 +53,6 @@ class Feature {
} }
} }
set isDirty(status) {
this._isDirty = status
if (this.datalayer) {
this.datalayer.isDirty = status
}
}
get isDirty() {
return this._isDirty
}
get ui() { get ui() {
if (!this._ui) this.makeUI() if (!this._ui) this.makeUI()
return this._ui return this._ui
@ -91,6 +79,7 @@ class Feature {
} }
set geometry(value) { set geometry(value) {
this._geometry_bk = Utils.CopyJSON(this._geometry)
this._geometry = value this._geometry = value
this.pushGeometry() this.pushGeometry()
} }
@ -104,13 +93,15 @@ class Feature {
} }
pullGeometry(sync = true) { pullGeometry(sync = true) {
const oldGeometry = Utils.CopyJSON(this._geometry)
this.fromLatLngs(this._getLatLngs()) this.fromLatLngs(this._getLatLngs())
if (sync) { if (sync) {
this.sync.update('geometry', this.geometry) this.sync.update('geometry', this.geometry, oldGeometry)
} }
} }
fromLatLngs(latlngs) { fromLatLngs(latlngs) {
this._geometry_bk = Utils.CopyJSON(this._geometry)
this._geometry = this.convertLatLngs(latlngs) this._geometry = this.convertLatLngs(latlngs)
} }
@ -143,10 +134,16 @@ class Feature {
} }
onCommit() { onCommit() {
this.pullGeometry(false)
// When the layer is a remote layer, we don't want to sync the creation of the // When the layer is a remote layer, we don't want to sync the creation of the
// points via the websocket, as the other peers will get them themselves. // points via the websocket, as the other peers will get them themselves.
if (this.datalayer?.isRemoteLayer()) return if (this.datalayer?.isRemoteLayer()) return
this.sync.upsert(this.toGeoJSON()) if (this._needs_upsert) {
this.sync.upsert(this.toGeoJSON(), null)
this._needs_upsert = false
} else {
this.sync.update('geometry', this.geometry, this._geometry_bk)
}
} }
isReadOnly() { isReadOnly() {
@ -208,6 +205,7 @@ class Feature {
edit(event) { edit(event) {
if (!this._umap.editEnabled || this.isReadOnly()) return if (!this._umap.editEnabled || this.isReadOnly()) return
if (this._umap.editedFeature === this) return
const container = DomUtil.create('div', 'umap-feature-container') const container = DomUtil.create('div', 'umap-feature-container')
DomUtil.createTitle( DomUtil.createTitle(
container, container,
@ -268,7 +266,8 @@ class Feature {
<i class="icon icon-24 icon-delete"></i>${translate('Delete')} <i class="icon icon-24 icon-delete"></i>${translate('Delete')}
</button>`) </button>`)
button.addEventListener('click', () => { button.addEventListener('click', () => {
this.confirmDelete().then(() => this._umap.editPanel.close()) this.del()
this._umap.editPanel.close()
}) })
container.appendChild(button) container.appendChild(button)
} }
@ -315,7 +314,9 @@ class Feature {
] ]
} }
endEdit() {} endEdit() {
this.ui.disableEdit()
}
getDisplayName() { getDisplayName() {
const keys = U.LABEL_KEYS.slice() // Copy. const keys = U.LABEL_KEYS.slice() // Copy.
@ -329,7 +330,7 @@ class Feature {
} }
for (const key of keys) { for (const key of keys) {
const value = this.properties[key] const value = this.properties[key]
if (value) return value.trim() if (value) return String(value).trim()
} }
return this.datalayer.getName().trim() return this.datalayer.getName().trim()
} }
@ -353,19 +354,7 @@ class Feature {
return popup.loadContent() return popup.loadContent()
} }
async confirmDelete() {
const confirmed = await this._umap.dialog.confirm(
translate('Are you sure you want to delete the feature?')
)
if (confirmed) {
this.del()
return true
}
return false
}
del(sync) { del(sync) {
this.isDirty = true
this._umap._leafletMap.closePopup() this._umap._leafletMap.closePopup()
if (this.datalayer) { if (this.datalayer) {
this.datalayer.removeFeature(this, sync) this.datalayer.removeFeature(this, sync)
@ -410,13 +399,11 @@ class Feature {
changeDataLayer(datalayer) { changeDataLayer(datalayer) {
if (this.datalayer) { if (this.datalayer) {
this.datalayer.isDirty = true
this.datalayer.removeFeature(this) this.datalayer.removeFeature(this)
} }
datalayer.addFeature(this) datalayer.addFeature(this)
this.sync.upsert(this.toGeoJSON()) this.sync.upsert(this.toGeoJSON())
datalayer.isDirty = true
this.redraw() this.redraw()
} }
@ -483,7 +470,6 @@ class Feature {
deleteProperty(property) { deleteProperty(property) {
delete this.properties[property] delete this.properties[property]
this.isDirty = true
} }
renameProperty(from, to) { renameProperty(from, to) {
@ -508,7 +494,7 @@ class Feature {
icon: 'icon-edit', icon: 'icon-edit',
}, },
{ {
action: () => this.confirmDelete(), action: () => this.del(),
title: translate('Delete this feature'), title: translate('Delete this feature'),
icon: 'icon-delete', icon: 'icon-delete',
}, },
@ -576,7 +562,6 @@ class Feature {
delete geojson.id delete geojson.id
delete geojson.properties.id delete geojson.properties.id
const feature = this.datalayer.makeFeature(geojson) const feature = this.datalayer.makeFeature(geojson)
feature.isDirty = true
feature.edit() feature.edit()
return feature return feature
} }
@ -612,7 +597,7 @@ class Feature {
this.datalayer.hideFeature(this) this.datalayer.hideFeature(this)
this.makeUI() this.makeUI()
this.datalayer.showFeature(this) this.datalayer.showFeature(this)
} else { } else if (this.datalayer?.isBrowsable()) {
this.ui._redraw() this.ui._redraw()
} }
} }
@ -663,7 +648,7 @@ class Feature {
}, },
{ {
label: translate('Delete this feature'), label: translate('Delete this feature'),
action: () => this.confirmDelete(), action: () => this.del(),
}, },
{ {
label: translate('Clone this feature'), label: translate('Clone this feature'),
@ -828,11 +813,6 @@ class Path extends Feature {
) )
} }
endEdit() {
this.ui.disableEdit()
super.endEdit()
}
transferShape(at, to) { transferShape(at, to) {
const shape = this.ui.enableEdit().deleteShapeAt(at) const shape = this.ui.enableEdit().deleteShapeAt(at)
// FIXME: make Leaflet.Editable send an event instead // FIXME: make Leaflet.Editable send an event instead
@ -1056,7 +1036,6 @@ export class LineString extends Path {
this.pullGeometry() this.pullGeometry()
if (!this.ui.editEnabled()) this.edit() if (!this.ui.editEnabled()) this.edit()
this.ui.editor.reset() this.ui.editor.reset()
this.isDirty = true
} }
isMulti() { isMulti() {

View file

@ -1,26 +1,25 @@
// FIXME: this module should not depend on Leaflet // FIXME: this module should not depend on Leaflet
import { import {
DomUtil,
DomEvent, DomEvent,
stamp, DomUtil,
GeoJSON, GeoJSON,
stamp,
} from '../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../vendors/leaflet/leaflet-src.esm.js'
import * as Utils from '../utils.js'
import { Default as DefaultLayer } from '../rendering/layers/base.js'
import { Cluster } from '../rendering/layers/cluster.js'
import { Heat } from '../rendering/layers/heat.js'
import { Categorized, Choropleth, Circles } from '../rendering/layers/classified.js'
import { import {
uMapAlert as Alert, uMapAlert as Alert,
uMapAlertConflict as AlertConflict, uMapAlertConflict as AlertConflict,
} from '../../components/alerts/alert.js' } from '../../components/alerts/alert.js'
import { MutatingForm } from '../form/builder.js'
import { translate } from '../i18n.js' import { translate } from '../i18n.js'
import { DataLayerPermissions } from '../permissions.js' import { DataLayerPermissions } from '../permissions.js'
import { Point, LineString, Polygon } from './features.js' import { Default as DefaultLayer } from '../rendering/layers/base.js'
import TableEditor from '../tableeditor.js' import { Categorized, Choropleth, Circles } from '../rendering/layers/classified.js'
import { ServerStored } from '../saving.js' import { Cluster } from '../rendering/layers/cluster.js'
import { Heat } from '../rendering/layers/heat.js'
import * as Schema from '../schema.js' import * as Schema from '../schema.js'
import { MutatingForm } from '../form/builder.js' import TableEditor from '../tableeditor.js'
import * as Utils from '../utils.js'
import { LineString, Point, Polygon } from './features.js'
export const LAYER_TYPES = [ export const LAYER_TYPES = [
DefaultLayer, DefaultLayer,
@ -36,9 +35,8 @@ const LAYER_MAP = LAYER_TYPES.reduce((acc, klass) => {
return acc return acc
}, {}) }, {})
export class DataLayer extends ServerStored { export class DataLayer {
constructor(umap, leafletMap, data = {}) { constructor(umap, leafletMap, data = {}) {
super()
this._umap = umap this._umap = umap
this.sync = umap.syncEngine.proxy(this) this.sync = umap.syncEngine.proxy(this)
this._index = Array() this._index = Array()
@ -49,7 +47,6 @@ export class DataLayer extends ServerStored {
this._leafletMap = leafletMap this._leafletMap = leafletMap
this.parentPane = this._leafletMap.getPane('overlayPane') this.parentPane = this._leafletMap.getPane('overlayPane')
this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane) this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane)
this.pane.dataset.id = stamp(this)
// FIXME: should be on layer // FIXME: should be on layer
this.renderer = L.svg({ pane: this.pane }) this.renderer = L.svg({ pane: this.pane })
this.defaultOptions = { this.defaultOptions = {
@ -66,6 +63,10 @@ export class DataLayer extends ServerStored {
data.id = data.id || crypto.randomUUID() data.id = data.id || crypto.randomUUID()
this.setOptions(data) this.setOptions(data)
this.pane.dataset.id = this.id
if (this.options.rank === undefined) {
this.options.rank = this._umap.datalayers.count()
}
if (!Utils.isObject(this.options.remoteData)) { if (!Utils.isObject(this.options.remoteData)) {
this.options.remoteData = {} this.options.remoteData = {}
@ -83,7 +84,7 @@ export class DataLayer extends ServerStored {
this.connectToMap() this.connectToMap()
this.permissions = new DataLayerPermissions(this._umap, this) this.permissions = new DataLayerPermissions(this._umap, this)
this._needsFetch = this.createdOnServer this._needsFetch = this.createdOnServer || this.isRemoteLayer()
if (!this.createdOnServer) { if (!this.createdOnServer) {
if (this.showAtLoad()) this.show() if (this.showAtLoad()) this.show()
} }
@ -114,7 +115,6 @@ export class DataLayer extends ServerStored {
set isDeleted(status) { set isDeleted(status) {
this._isDeleted = status this._isDeleted = status
if (status) this.isDirty = status
} }
get isDeleted() { get isDeleted() {
@ -125,6 +125,20 @@ export class DataLayer extends ServerStored {
return `datalayer-${stamp(this)}` return `datalayer-${stamp(this)}`
} }
get rank() {
// Make sure we always have a valid rank. Undefined rank may happen
// after importing an old umap backup, and not touching the layers
// after that.
if (this.options.rank === undefined) {
this.options.rank = this.getDOMOrder()
}
return this.options.rank
}
set rank(value) {
this.options.rank = value
}
getSyncMetadata() { getSyncMetadata() {
return { return {
subject: 'datalayer', subject: 'datalayer',
@ -133,6 +147,10 @@ export class DataLayer extends ServerStored {
} }
render(fields, builder) { render(fields, builder) {
// Propagate will remove the fields it has already
// processed
fields = this.propagate(fields)
const impacts = Utils.getImpactsFromSchema(fields) const impacts = Utils.getImpactsFromSchema(fields)
for (const impact of impacts) { for (const impact of impacts) {
@ -144,19 +162,44 @@ export class DataLayer extends ServerStored {
if (fields.includes('options.type')) { if (fields.includes('options.type')) {
this.resetLayer() this.resetLayer()
} }
this.hide()
for (const field of fields) { for (const field of fields) {
this.layer.onEdit(field, builder) this.layer.onEdit(field, builder)
} }
this.show() this.redraw()
break break
case 'remote-data': case 'remote-data':
this.fetchRemoteData() this.fetchRemoteData()
break break
case 'datalayer-rank':
this._umap.reorderDataLayers()
break
} }
} }
} }
// This method does a targeted update of the UI,
// it whould be merged with `render`` method and the
// SCHEMA at some point
propagate(fields = []) {
const impacts = {
'properties.name': () => {
Utils.eachElement('.datalayer-name', (el) => {
if (el.dataset.id === this.id) {
el.textContent = this.getName()
el.title = this.getName()
}
})
},
}
for (const [field, impact] of Object.entries(impacts)) {
if (!fields.length || fields.includes(field)) {
impact()
fields = fields.filter((item) => item !== field)
}
}
return fields
}
showAtLoad() { showAtLoad() {
return this.autoLoaded() && this.showAtZoom() return this.autoLoaded() && this.showAtZoom()
} }
@ -224,17 +267,11 @@ export class DataLayer extends ServerStored {
this._loading = true this._loading = true
const [geojson, response, error] = await this._umap.server.get(this._dataUrl()) const [geojson, response, error] = await this._umap.server.get(this._dataUrl())
if (!error) { if (!error) {
this._umap.modifiedAt = response.headers.get('last-modified')
this.setReferenceVersion({ response, sync: false }) this.setReferenceVersion({ response, sync: false })
// FIXME: for now the _umap_options property is set dynamically from backend delete geojson._umap_options
// And thus it's not in the geojson file in the server
// So do not let all options to be reset
// Fix is a proper migration so all datalayers settings are
// in DB, and we remove it from geojson flat files.
if (geojson._umap_options) {
geojson._umap_options.editMode = this.options.editMode
}
// In case of maps pre 1.0 still around // In case of maps pre 1.0 still around
if (geojson._storage) geojson._storage.editMode = this.options.editMode delete geojson._storage
await this.fromUmapGeoJSON(geojson) await this.fromUmapGeoJSON(geojson)
this.backupOptions() this.backupOptions()
this._loading = false this._loading = false
@ -263,21 +300,12 @@ export class DataLayer extends ServerStored {
async fromUmapGeoJSON(geojson) { async fromUmapGeoJSON(geojson) {
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
geojson._umap_options.id = this.id
if (geojson._umap_options) this.setOptions(geojson._umap_options) if (geojson._umap_options) this.setOptions(geojson._umap_options)
if (this.isRemoteLayer()) await this.fetchRemoteData() if (this.isRemoteLayer()) {
else this.fromGeoJSON(geojson, false) await this.fetchRemoteData()
} } else {
this.fromGeoJSON(geojson, false)
clear() {
this.layer.clearLayers()
this._features = {}
this._index = Array()
if (this._geojson) {
this.backupData()
this._geojson = null
} }
this.dataChanged()
} }
backupData() { backupData() {
@ -306,7 +334,10 @@ export class DataLayer extends ServerStored {
async getUrl(url, initialUrl) { async getUrl(url, initialUrl) {
const response = await this._umap.request.get(url) const response = await this._umap.request.get(url)
return new Promise((resolve) => { return new Promise((resolve) => {
if (response?.ok) return resolve(response.text()) if (response?.ok) {
this._umap.modifiedAt = response.headers.get('last-modified')
return resolve(response.text())
}
Alert.error( Alert.error(
translate('Cannot load remote data for layer "{layer}" with url "{url}"', { translate('Cannot load remote data for layer "{layer}" with url "{url}"', {
layer: this.getName(), layer: this.getName(),
@ -327,11 +358,12 @@ export class DataLayer extends ServerStored {
url = this._umap.proxyUrl(url, this.options.remoteData.ttl) url = this._umap.proxyUrl(url, this.options.remoteData.ttl)
} }
return await this.getUrl(url, remoteUrl).then((raw) => { return await this.getUrl(url, remoteUrl).then((raw) => {
this.clear() this.clear(false)
return this._umap.formatter return this._umap.formatter
.parse(raw, this.options.remoteData.format) .parse(raw, this.options.remoteData.format)
.then((geojson) => this.fromGeoJSON(geojson)) .then((geojson) => this.fromGeoJSON(geojson, false))
.catch((error) => { .catch((error) => {
console.debug(error)
Alert.error( Alert.error(
translate('Cannot parse remote data for layer "{layer}" with url "{url}"', { translate('Cannot parse remote data for layer "{layer}" with url "{url}"', {
layer: this.getName(), layer: this.getName(),
@ -366,13 +398,7 @@ export class DataLayer extends ServerStored {
} }
connectToMap() { connectToMap() {
const id = stamp(this) this._umap.datalayers.add(this)
if (!this._umap.datalayers[id]) {
this._umap.datalayers[id] = this
}
if (!this._umap.datalayersIndex.includes(this)) {
this._umap.datalayersIndex.push(this)
}
this._umap.onDataLayersChanged() this._umap.onDataLayersChanged()
} }
@ -417,7 +443,14 @@ export class DataLayer extends ServerStored {
removeFeature(feature, sync) { removeFeature(feature, sync) {
const id = stamp(feature) const id = stamp(feature)
if (sync !== false) feature.sync.delete() // This feature was not yet added, may be after
// hitting Escape while drawing a new line or
// polygon, not yet valid (not enough points)
if (!this._index.includes(id)) return
if (sync !== false) {
const oldValue = feature.toGeoJSON()
feature.sync.delete(oldValue)
}
this.hideFeature(feature) this.hideFeature(feature)
delete this._umap.featuresIndex[feature.getSlug()] delete this._umap.featuresIndex[feature.getSlug()]
feature.disconnectFromDataLayer(this) feature.disconnectFromDataLayer(this)
@ -484,8 +517,19 @@ export class DataLayer extends ServerStored {
const features = [] const features = []
this.sortFeatures(collection) this.sortFeatures(collection)
for (const featureJson of collection) { for (const featureJson of collection) {
const feature = this.makeFeature(featureJson, sync) if (featureJson.geometry?.type === 'GeometryCollection') {
if (feature) features.push(feature) for (const geometry of featureJson.geometry.geometries) {
const feature = this.makeFeature({
type: 'Feature',
geometry,
properties: featureJson.properties,
})
if (feature) features.push(feature)
}
} else {
const feature = this.makeFeature(featureJson, sync)
if (feature) features.push(feature)
}
} }
return features return features
} }
@ -518,7 +562,7 @@ export class DataLayer extends ServerStored {
} }
if (feature && !feature.isEmpty()) { if (feature && !feature.isEmpty()) {
this.addFeature(feature) this.addFeature(feature)
if (sync) feature.onCommit() if (sync) feature.sync.upsert(feature.toGeoJSON(), null)
return feature return feature
} }
} }
@ -526,12 +570,14 @@ export class DataLayer extends ServerStored {
async importRaw(raw, format) { async importRaw(raw, format) {
return this._umap.formatter return this._umap.formatter
.parse(raw, format) .parse(raw, format)
.then((geojson) => this.addData(geojson)) .then((geojson) => {
.then((data) => { this.sync.startBatch()
if (data?.length) this.isDirty = true const data = this.addData(geojson)
this.sync.commitBatch()
return data return data
}) })
.catch((error) => { .catch((error) => {
console.debug(error)
Alert.error(translate('Import failed: invalid data')) Alert.error(translate('Import failed: invalid data'))
}) })
} }
@ -595,17 +641,34 @@ export class DataLayer extends ServerStored {
} }
del(sync = true) { del(sync = true) {
this.erase() const oldValue = Utils.CopyJSON(this.umapGeoJSON())
// TODO merge datalayer del and features del in same
// batch
this.clear()
if (sync) { if (sync) {
this.isDeleted = true this.isDeleted = true
this.sync.delete() this.sync.delete(oldValue)
} }
this.hide()
this.parentPane.removeChild(this.pane)
this._umap.onDataLayersChanged()
this.layer.onDelete(this._leafletMap)
this.propagateDelete()
this._leaflet_events_bk = this._leaflet_events
} }
empty() { empty() {
if (this.isRemoteLayer()) return if (this.isRemoteLayer()) return
this.sync.startBatch()
this.clear() this.clear()
this.isDirty = true this.sync.commitBatch()
}
clear(sync = true) {
for (const feature of Object.values(this._features)) {
feature.del(sync)
}
this.dataChanged()
} }
clone() { clone() {
@ -618,44 +681,13 @@ export class DataLayer extends ServerStored {
return datalayer return datalayer
} }
erase() {
this.hide()
this._umap.datalayersIndex.splice(this.getRank(), 1)
this.parentPane.removeChild(this.pane)
this._umap.onDataLayersChanged()
this.layer.onDelete(this._leafletMap)
this.propagateDelete()
this._leaflet_events_bk = this._leaflet_events
this.clear()
}
reset() {
if (!this.createdOnServer) {
this.erase()
return
}
this.resetOptions()
this.parentPane.appendChild(this.pane)
if (this._leaflet_events_bk && !this._leaflet_events) {
this._leaflet_events = this._leaflet_events_bk
}
this.clear()
this.hide()
if (this.isRemoteLayer()) this.fetchRemoteData()
else if (this._geojson_bk) this.fromGeoJSON(this._geojson_bk)
this.show()
this.isDirty = false
}
redraw() { redraw() {
if (!this.isVisible()) return if (!this.isVisible()) return
this.hide() this.eachFeature((feature) => feature.redraw())
this.show()
} }
edit() { edit() {
if (!this._umap.editEnabled || !this.isLoaded()) { if (!this._umap.editEnabled) {
return return
} }
const container = DomUtil.create('div', 'umap-layer-properties-container') const container = DomUtil.create('div', 'umap-layer-properties-container')
@ -831,8 +863,9 @@ export class DataLayer extends ServerStored {
this this
) )
if (this._umap.properties.urls.datalayer_versions) if (this._umap.properties.urls.datalayer_versions) {
this.buildVersionsFieldset(container) this.buildVersionsFieldset(container)
}
const advancedActions = DomUtil.createFieldset( const advancedActions = DomUtil.createFieldset(
container, container,
@ -907,10 +940,15 @@ export class DataLayer extends ServerStored {
const appendVersion = (data) => { const appendVersion = (data) => {
const date = new Date(Number.parseInt(data.at, 10)) const date = new Date(Number.parseInt(data.at, 10))
const content = `${date.toLocaleString(U.lang)} (${Number.parseInt(data.size) / 1000}Kb)` const content = `${date.toLocaleString(U.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
const el = DomUtil.create('div', 'umap-datalayer-version', versionsContainer) const [el, { button }] = Utils.loadTemplateWithRefs(
const button = DomUtil.createButton('', el, '', () => this.restore(data.ref)) `<div class="umap-datalayer-version">
button.title = translate('Restore this version') <button type="button" title="${translate('Restore this version')}" data-ref=button>
DomUtil.add('span', '', el, content) <i class="icon icon-16 icon-restore"></i> ${content}
</button>
</div>`
)
versionsContainer.appendChild(el)
button.addEventListener('click', () => this.restore(data.ref))
} }
const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), { const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), {
@ -934,11 +972,19 @@ export class DataLayer extends ServerStored {
) )
if (!error) { if (!error) {
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat. if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat.
if (geojson._umap_options) this.setOptions(geojson._umap_options) if (geojson._umap_options) {
const oldOptions = Utils.CopyJSON(this.options)
this.setOptions(geojson._umap_options)
this.sync.update('options', this.options, oldOptions)
}
this.empty() this.empty()
if (this.isRemoteLayer()) this.fetchRemoteData() if (this.isRemoteLayer()) {
else this.addData(geojson) this.fetchRemoteData()
this.isDirty = true } else {
this.sync.startBatch()
this.addData(geojson)
this.sync.commitBatch()
}
} }
}) })
} }
@ -960,12 +1006,18 @@ export class DataLayer extends ServerStored {
this.propagateHide() this.propagateHide()
} }
toggle() { toggle(force) {
// From now on, do not try to how/hidedataChanged // From now on, do not try to how/hidedataChanged
// automatically this layer. // automatically this layer.
let display = force
this._forcedVisibility = true this._forcedVisibility = true
if (!this.isVisible()) this.show() if (force === undefined) {
if (!this.isVisible()) display = true
else display = false
}
if (display) this.show()
else this.hide() else this.hide()
this._umap.bottomBar.redraw()
} }
zoomTo() { zoomTo() {
@ -1043,23 +1095,11 @@ export class DataLayer extends ServerStored {
} }
getPreviousBrowsable() { getPreviousBrowsable() {
let id = this.getRank() return this._umap.datalayers.prev(this)
let next
const index = this._umap.datalayersIndex
while (((id = index[++id] ? id : 0), (next = index[id]))) {
if (next === this || next.canBrowse()) break
}
return next
} }
getNextBrowsable() { getNextBrowsable() {
let id = this.getRank() return this._umap.datalayers.next(this)
let prev
const index = this._umap.datalayersIndex
while (((id = index[--id] ? id : index.length - 1), (prev = index[id]))) {
if (prev === this || prev.canBrowse()) break
}
return prev
} }
umapGeoJSON() { umapGeoJSON() {
@ -1070,8 +1110,8 @@ export class DataLayer extends ServerStored {
} }
} }
getRank() { getDOMOrder() {
return this._umap.datalayersIndex.indexOf(this) return Array.from(this.parentPane.children).indexOf(this.pane)
} }
isReadOnly() { isReadOnly() {
@ -1086,18 +1126,28 @@ export class DataLayer extends ServerStored {
setReferenceVersion({ response, sync }) { setReferenceVersion({ response, sync }) {
this._referenceVersion = response.headers.get('X-Datalayer-Version') this._referenceVersion = response.headers.get('X-Datalayer-Version')
if (sync) this.sync.update('_referenceVersion', this._referenceVersion) if (sync) {
this.sync.update('_referenceVersion', this._referenceVersion, null, {
undo: false,
})
}
}
prepareOptions() {
const options = Utils.CopyJSON(this.options)
delete options.permissions
return JSON.stringify(options)
} }
async save() { async save() {
if (this.isDeleted) return await this.saveDelete() if (this.isDeleted) return await this.saveDelete()
if (!this.isLoaded()) return if (!this.isRemoteLayer() && !this.isLoaded()) return
const geojson = this.umapGeoJSON() const geojson = this.umapGeoJSON()
const formData = new FormData() const formData = new FormData()
formData.append('name', this.options.name) formData.append('name', this.options.name)
formData.append('display_on_load', !!this.options.displayOnLoad) formData.append('display_on_load', !!this.options.displayOnLoad)
formData.append('rank', this.getRank()) formData.append('rank', this.rank)
formData.append('settings', JSON.stringify(this.options)) formData.append('settings', this.prepareOptions())
// Filename support is shaky, don't do it for now. // Filename support is shaky, don't do it for now.
const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' }) const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' })
formData.append('geojson', blob) formData.append('geojson', blob)
@ -1115,6 +1165,10 @@ export class DataLayer extends ServerStored {
} }
async _trySave(url, headers, formData) { async _trySave(url, headers, formData) {
if (this._forceSave) {
headers = {}
this._forceSave = false
}
const [data, response, error] = await this._umap.server.post(url, headers, formData) const [data, response, error] = await this._umap.server.post(url, headers, formData)
if (error) { if (error) {
if (response && response.status === 412) { if (response && response.status === 412) {
@ -1124,23 +1178,19 @@ export class DataLayer extends ServerStored {
'This situation is tricky, you have to choose carefully which version is pertinent.' 'This situation is tricky, you have to choose carefully which version is pertinent.'
), ),
async () => { async () => {
// Save again this layer this._forceSave = true
const status = await this._trySave(url, {}, formData) await this._umap.saveAll()
if (status) {
this.isDirty = false
// Call the main save, in case something else needs to be saved
// as the conflict stopped the saving flow
await this._umap.saveAll()
}
} }
) )
} else {
console.debug(error)
Alert.error(translate('Cannot save layer, please try again in a few minutes.'))
} }
} else { } else {
// Response contains geojson only if save has conflicted and conflicts have // Response contains geojson only if save has conflicted and conflicts have
// been resolved. So we need to reload to get extra data (added by someone else) // been resolved. So we need to reload to get extra data (added by someone else)
if (data.geojson) { if (data.geojson) {
this.clear() this.clear(false)
this.fromGeoJSON(data.geojson) this.fromGeoJSON(data.geojson)
delete data.geojson delete data.geojson
} }
@ -1167,7 +1217,7 @@ export class DataLayer extends ServerStored {
} }
commitDelete() { commitDelete() {
delete this._umap.datalayers[stamp(this)] delete this._umap.datalayers[this.id]
} }
getName() { getName() {
@ -1234,25 +1284,16 @@ export class DataLayer extends ServerStored {
translate('Delete layer') translate('Delete layer')
) )
if (this.isReadOnly()) { if (this.isReadOnly()) {
DomUtil.addClass(container, 'readonly') container.classList.add('readonly')
} else { } else {
DomEvent.on(edit, 'click', this.edit, this) edit.addEventListener('click', () => this.edit())
DomEvent.on(table, 'click', this.tableEdit, this) table.addEventListener('click', () => this.tableEdit())
DomEvent.on( remove.addEventListener('click', () => {
remove, if (!this.isVisible()) return
'click', this.del()
function () { })
if (!this.isVisible()) return
this._umap.dialog
.confirm(translate('Are you sure you want to delete this layer?'))
.then(() => {
this.del()
})
},
this
)
} }
DomEvent.on(toggle, 'click', this.toggle, this) DomEvent.on(toggle, 'click', () => this.toggle())
DomEvent.on(zoomTo, 'click', this.zoomTo, this) DomEvent.on(zoomTo, 'click', this.zoomTo, this)
container.classList.add(this.getHidableClass()) container.classList.add(this.getHidableClass())
container.classList.toggle('off', !this.isVisible()) container.classList.toggle('off', !this.isVisible())

View file

@ -24,7 +24,7 @@ export default class Facets {
this.selected[name] = selected this.selected[name] = selected
} }
this._umap.eachBrowsableDataLayer((datalayer) => { this._umap.datalayers.browsable().map((datalayer) => {
datalayer.eachFeature((feature) => { datalayer.eachFeature((feature) => {
for (const name of names) { for (const name of names) {
let value = feature.properties[name] let value = feature.properties[name]
@ -135,7 +135,13 @@ export default class Facets {
for (const [property, { label, type }] of parsed) { for (const [property, { label, type }] of parsed) {
dumped.push([property, label, type].filter(Boolean).join('|')) dumped.push([property, label, type].filter(Boolean).join('|'))
} }
return dumped.join(',') const oldValue = this._umap.properties.facetKey
this._umap.properties.facetKey = dumped.join(',')
this._umap.sync.update(
'properties.facetKey',
this._umap.properties.facetKey,
oldValue
)
} }
has(property) { has(property) {
@ -146,15 +152,13 @@ export default class Facets {
const defined = this.getDefined() const defined = this.getDefined()
if (!defined.has(property)) { if (!defined.has(property)) {
defined.set(property, { label, type }) defined.set(property, { label, type })
this._umap.properties.facetKey = this.dumps(defined) this.dumps(defined)
this._umap.isDirty = true
} }
} }
remove(property) { remove(property) {
const defined = this.getDefined() const defined = this.getDefined()
defined.delete(property) defined.delete(property)
this._umap.properties.facetKey = this.dumps(defined) this.dumps(defined)
this._umap.isDirty = true
} }
} }

View file

@ -1,7 +1,7 @@
import getClass from './fields.js'
import * as Utils from '../utils.js'
import { SCHEMA } from '../schema.js'
import { translate } from '../i18n.js' import { translate } from '../i18n.js'
import { SCHEMA } from '../schema.js'
import * as Utils from '../utils.js'
import getClass from './fields.js'
export class Form extends Utils.WithEvents { export class Form extends Utils.WithEvents {
constructor(obj, fields, properties) { constructor(obj, fields, properties) {
@ -70,21 +70,7 @@ export class Form extends Utils.WithEvents {
} }
setter(field, value) { setter(field, value) {
const path = field.split('.') Utils.setObjectValue(this.obj, field, value)
let obj = this.obj
let what
for (let i = 0, l = path.length; i < l; i++) {
what = path[i]
if (what === path[l - 1]) {
if (typeof value === 'undefined') {
delete obj[what]
} else {
obj[what] = value
}
} else {
obj = obj[what]
}
}
} }
restoreField(field) { restoreField(field) {
@ -144,14 +130,11 @@ export class MutatingForm extends Form {
} }
for (const [key, defaults] of Object.entries(SCHEMA)) { for (const [key, defaults] of Object.entries(SCHEMA)) {
const properties = Object.assign({}, defaults) const properties = Object.assign({}, defaults)
if (properties.type === Boolean) { if (properties.type === Array) {
properties.handler = 'CheckBoxes'
} else if (properties.type === Boolean) {
if (properties.nullable) properties.handler = 'NullableChoices' if (properties.nullable) properties.handler = 'NullableChoices'
else properties.handler = 'Switch' else properties.handler = 'Switch'
} else if (properties.type === 'Text') {
properties.handler = 'Textarea'
} else if (properties.type === Number) {
if (properties.step) properties.handler = 'Range'
else properties.handler = 'IntInput'
} else if (properties.choices) { } else if (properties.choices) {
const text_length = properties.choices.reduce( const text_length = properties.choices.reduce(
(acc, [_, label]) => acc + label.length, (acc, [_, label]) => acc + label.length,
@ -165,6 +148,11 @@ export class MutatingForm extends Form {
properties.handler = 'Select' properties.handler = 'Select'
properties.selectOptions = properties.choices properties.selectOptions = properties.choices
} }
} else if (properties.type === 'Text') {
properties.handler = 'Textarea'
} else if (properties.type === Number) {
if (properties.step) properties.handler = 'Range'
else properties.handler = 'IntInput'
} else { } else {
switch (key) { switch (key) {
case 'color': case 'color':
@ -190,13 +178,17 @@ export class MutatingForm extends Form {
} }
setter(field, value) { setter(field, value) {
super.setter(field, value) const oldValue = this.getter(field)
this.obj.isDirty = true if ('setter' in this.obj) {
this.obj.setter(field, value)
} else {
super.setter(field, value)
}
if ('render' in this.obj) { if ('render' in this.obj) {
this.obj.render([field], this) this.obj.render([field], this)
} }
if ('sync' in this.obj) { if ('sync' in this.obj) {
this.obj.sync.update(field, value) this.obj.sync.update(field, value, oldValue)
} }
} }

View file

@ -1,12 +1,12 @@
import * as Utils from '../utils.js'
import { translate } from '../i18n.js'
import { import {
AjaxAutocomplete, AjaxAutocomplete,
AjaxAutocompleteMultiple, AjaxAutocompleteMultiple,
AutocompleteDatalist, AutocompleteDatalist,
} from '../autocomplete.js' } from '../autocomplete.js'
import { SCHEMA } from '../schema.js' import { translate } from '../i18n.js'
import * as Icon from '../rendering/icon.js' import * as Icon from '../rendering/icon.js'
import { SCHEMA } from '../schema.js'
import * as Utils from '../utils.js'
const Fields = {} const Fields = {}
@ -152,7 +152,9 @@ Fields.Textarea = class extends BaseElement {
this.textarea.value = value this.textarea.value = value
} }
} }
clear() {
this.textarea.value = ''
}
value() { value() {
return this.textarea.value return this.textarea.value
} }
@ -254,8 +256,8 @@ Fields.BlurInput = class extends Fields.Input {
const IntegerMixin = (Base) => const IntegerMixin = (Base) =>
class extends Base { class extends Base {
value() { value() {
return !isNaN(this.input.value) && this.input.value !== '' return !Number.isNaN(this.input.value) && this.input.value !== ''
? parseInt(this.input.value, 10) ? Number.parseInt(this.input.value, 10)
: undefined : undefined
} }
@ -270,8 +272,8 @@ Fields.BlurIntInput = class extends IntegerMixin(Fields.BlurInput) {}
const FloatMixin = (Base) => const FloatMixin = (Base) =>
class extends Base { class extends Base {
value() { value() {
return !isNaN(this.input.value) && this.input.value !== '' return !Number.isNaN(this.input.value) && this.input.value !== ''
? parseFloat(this.input.value) ? Number.parseFloat(this.input.value)
: undefined : undefined
} }
@ -324,6 +326,29 @@ Fields.CheckBox = class extends BaseElement {
} }
} }
Fields.CheckBoxes = class extends BaseElement {
getInputTemplate(value, label) {
return `<label><input type=checkbox value="${value}" name="${this.name}" data-ref=input />${label}</label>`
}
build() {
const initial = this.get() || []
for (const [value, label] of this.properties.choices) {
const [root, { input }] = Utils.loadTemplateWithRefs(
this.getInputTemplate(value, label)
)
this.container.appendChild(root)
input.checked = initial.includes(value)
input.addEventListener('change', () => this.sync())
}
super.build()
}
value() {
return Array.from(this.root.querySelectorAll('input:checked')).map((el) => el.value)
}
}
Fields.Select = class extends BaseElement { Fields.Select = class extends BaseElement {
getTemplate() { getTemplate() {
return `<select name="${this.name}" data-ref=select></select>` return `<select name="${this.name}" data-ref=select></select>`
@ -390,7 +415,7 @@ Fields.Select = class extends BaseElement {
Fields.IntSelect = class extends Fields.Select { Fields.IntSelect = class extends Fields.Select {
value() { value() {
return parseInt(super.value(), 10) return Number.parseInt(super.value(), 10)
} }
} }
@ -535,20 +560,20 @@ Fields.SlideshowDelay = class extends Fields.IntSelect {
Fields.DataLayerSwitcher = class extends Fields.Select { Fields.DataLayerSwitcher = class extends Fields.Select {
getOptions() { getOptions() {
const options = [] const options = []
this.builder._umap.eachDataLayerReverse((datalayer) => { this.builder._umap.datalayers.reverse().map((datalayer) => {
if ( if (
datalayer.isLoaded() && datalayer.isLoaded() &&
!datalayer.isDataReadOnly() && !datalayer.isDataReadOnly() &&
datalayer.isBrowsable() datalayer.isBrowsable()
) { ) {
options.push([L.stamp(datalayer), datalayer.getName()]) options.push([datalayer.id, datalayer.getName()])
} }
}) })
return options return options
} }
toHTML() { toHTML() {
return L.stamp(this.obj.datalayer) return this.obj.datalayer.id
} }
toJS() { toJS() {
@ -783,9 +808,10 @@ Fields.IconUrl = class extends Fields.BlurInput {
} }
addCategory(items, name) { addCategory(items, name) {
const hidden = name ? '' : ' hidden'
const [parent, { grid }] = Utils.loadTemplateWithRefs(` const [parent, { grid }] = Utils.loadTemplateWithRefs(`
<div class="umap-pictogram-category"> <div class="umap-pictogram-category">
<h6 hidden=${!name}>${name}</h6> <h6${hidden}>${name}</h6>
<div class="umap-pictogram-grid" data-ref=grid></div> <div class="umap-pictogram-grid" data-ref=grid></div>
</div> </div>
`) `)
@ -805,7 +831,7 @@ Fields.IconUrl = class extends Fields.BlurInput {
categories[category] = categories[category] || [] categories[category] = categories[category] || []
categories[category].push(props) categories[category].push(props)
} }
const sorted = Object.entries(categories).toSorted(([a], [b]) => const sorted = Object.entries(categories).sort(([a], [b]) =>
Utils.naturalSort(a, b, U.lang) Utils.naturalSort(a, b, U.lang)
) )
for (const [name, items] of sorted) { for (const [name, items] of sorted) {
@ -899,7 +925,8 @@ Fields.Url = class extends Fields.Input {
Fields.Switch = class extends Fields.CheckBox { Fields.Switch = class extends Fields.CheckBox {
getTemplate() { getTemplate() {
const label = this.properties.label const label = this.properties.label
return `${super.getTemplate()}<label title="${label}" for="${this.id}" data-ref=customLabel>${label}</label>` const help = this.properties.helpEntries?.join() || ''
return `${super.getTemplate()}<label title="${label}" for="${this.id}" data-ref=customLabel data-help="${help}">${label}</label>`
} }
build() { build() {
@ -1296,12 +1323,13 @@ Fields.ManageEditors = class extends BaseElement {
placeholder: translate("Type editor's username"), placeholder: translate("Type editor's username"),
} }
this.autocomplete = new AjaxAutocompleteMultiple(this.container, options) this.autocomplete = new AjaxAutocompleteMultiple(this.container, options)
this._values = this.toHTML() this._values = this.toHTML() || []
if (this._values) if (this._values) {
for (let i = 0; i < this._values.length; i++) for (let i = 0; i < this._values.length; i++)
this.autocomplete.displaySelected({ this.autocomplete.displaySelected({
item: { value: this._values[i].id, label: this._values[i].name }, item: { value: this._values[i].id, label: this._values[i].name },
}) })
}
} }
value() { value() {

View file

@ -1,6 +1,6 @@
import { uMapAlert as Alert } from '../components/alerts/alert.js'
/* Uses globals for: csv2geojson, osmtogeojson (not available as ESM) */ /* Uses globals for: csv2geojson, osmtogeojson (not available as ESM) */
import { translate } from './i18n.js' import { translate } from './i18n.js'
import { uMapAlert as Alert } from '../components/alerts/alert.js'
export const EXPORT_FORMATS = { export const EXPORT_FORMATS = {
geojson: { geojson: {

View file

@ -1,13 +1,17 @@
import { uMapAlert as Alert } from '../components/alerts/alert.js' import { uMapAlert as Alert } from '../components/alerts/alert.js'
import { AjaxAutocomplete, AjaxAutocompleteMultiple, AutocompleteDatalist } from './autocomplete.js' import {
AjaxAutocomplete,
AjaxAutocompleteMultiple,
AutocompleteDatalist,
} from './autocomplete.js'
import { LineString, Point, Polygon } from './data/features.js'
import { LAYER_TYPES } from './data/layer.js'
import Help from './help.js' import Help from './help.js'
import * as Icon from './rendering/icon.js'
import { LeafletMarker, LeafletPolygon, LeafletPolyline } from './rendering/ui.js'
import { ServerRequest } from './request.js' import { ServerRequest } from './request.js'
import { SCHEMA } from './schema.js' import { SCHEMA } from './schema.js'
import * as Utils from './utils.js' import * as Utils from './utils.js'
import * as Icon from './rendering/icon.js'
import { LAYER_TYPES } from './data/layer.js'
import { Point, LineString, Polygon } from './data/features.js'
import { LeafletMarker, LeafletPolyline, LeafletPolygon } from './rendering/ui.js'
// Import modules and export them to the global scope. // Import modules and export them to the global scope.
// For the not yet module-compatible JS out there. // For the not yet module-compatible JS out there.

View file

@ -1,7 +1,7 @@
import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js' import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from './i18n.js' import { translate } from './i18n.js'
import * as Utils from './utils.js'
import Dialog from './ui/dialog.js' import Dialog from './ui/dialog.js'
import * as Utils from './utils.js'
const SHORTCUTS = { const SHORTCUTS = {
DRAW_MARKER: { DRAW_MARKER: {
@ -36,9 +36,13 @@ const SHORTCUTS = {
shortcut: 'Modifier+F', shortcut: 'Modifier+F',
label: translate('Search location'), label: translate('Search location'),
}, },
CANCEL: { UNDO: {
shortcut: 'Modifier+Z', shortcut: 'Modifier+Z',
label: translate('Cancel edits'), label: translate('Cancel last edit'),
},
REDO: {
shortcut: 'Modifier+Shift+Z',
label: translate('Redo last edit'),
}, },
PREVIEW: { PREVIEW: {
shortcut: 'Modifier+E', shortcut: 'Modifier+E',
@ -135,14 +139,23 @@ const ENTRIES = {
<li>${translate('# one hash for main heading')}</li> <li>${translate('# one hash for main heading')}</li>
<li>${translate('## two hashes for second heading')}</li> <li>${translate('## two hashes for second heading')}</li>
<li>${translate('### three hashes for third heading')}</li> <li>${translate('### three hashes for third heading')}</li>
<li>${translate('--- for a horizontal rule')}</li>
</ul>
<h4>${translate('Links')}</h4>
<ul>
<li>${translate('Simple link: [[https://example.com]]')}</li> <li>${translate('Simple link: [[https://example.com]]')}</li>
<li>${translate('Link with text: [[https://example.com|text of the link]]')}</li> <li>${translate('Link with text: [[https://example.com|text of the link]]')}</li>
</ul>
<h4>${translate('Images')}</h4>
<ul>
<li>${translate('Image: {{https://image.url.com}}')}</li> <li>${translate('Image: {{https://image.url.com}}')}</li>
<li>${translate('Image with custom width (in px): {{https://image.url.com|width}}')}</li> <li>${translate('Image with custom width (in px): {{https://image.url.com|width}}')}</li>
</ul>
<h4>${translate('Iframes')}</h4>
<ul>
<li>${translate('Iframe: {{{https://iframe.url.com}}}')}</li> <li>${translate('Iframe: {{{https://iframe.url.com}}}')}</li>
<li>${translate('Iframe with custom height (in px): {{{https://iframe.url.com|height}}}')}</li> <li>${translate('Iframe with custom height (in px): {{{https://iframe.url.com|height}}}')}</li>
<li>${translate('Iframe with custom height and width (in px): {{{https://iframe.url.com|height*width}}}')}</li> <li>${translate('Iframe with custom height and width (in px): {{{https://iframe.url.com|height*width}}}')}</li>
<li>${translate('--- for a horizontal rule')}</li>
</ul> </ul>
</div> </div>
`, `,
@ -183,7 +196,7 @@ export default class Help {
.split('+') .split('+')
.map((el) => `<kbd>${el}</kbd>`) .map((el) => `<kbd>${el}</kbd>`)
.join('+') .join('+')
label += ` ${shortcut}` label += ` <span class="nobr">${shortcut}</span>`
} else { } else {
label += ` (${shortcut})` label += ` (${shortcut})`
} }

View file

@ -94,6 +94,9 @@ export default class Importer extends Utils.WithTemplate {
case 'datasets': case 'datasets':
import('./importers/datasets.js').then(register) import('./importers/datasets.js').then(register)
break break
case 'banfr':
import('./importers/banfr.js').then(register)
break
} }
} }
} }
@ -173,7 +176,7 @@ export default class Importer extends Utils.WithTemplate {
showImporters() { showImporters() {
if (!this.IMPORTERS.length) return if (!this.IMPORTERS.length) return
const [element, { grid }] = Utils.loadTemplateWithRefs(GRID_TEMPLATE) const [element, { grid }] = Utils.loadTemplateWithRefs(GRID_TEMPLATE)
for (const plugin of this.IMPORTERS.sort((a, b) => (a.id > b.id ? 1 : -1))) { for (const plugin of this.IMPORTERS.sort((a, b) => (a.name > b.name ? 1 : -1))) {
const button = Utils.loadTemplate( const button = Utils.loadTemplate(
`<li><button type="button" class="${plugin.id}">${plugin.name}</button></li>` `<li><button type="button" class="${plugin.id}">${plugin.name}</button></li>`
) )
@ -240,13 +243,13 @@ export default class Importer extends Utils.WithTemplate {
this.raw = null this.raw = null
const layerSelect = this.qs('[name="layer-id"]') const layerSelect = this.qs('[name="layer-id"]')
layerSelect.innerHTML = '' layerSelect.innerHTML = ''
this._umap.eachDataLayerReverse((datalayer) => { this._umap.datalayers.reverse().map((datalayer) => {
if (datalayer.isLoaded() && !datalayer.isRemoteLayer()) { if (datalayer.isLoaded() && !datalayer.isRemoteLayer()) {
DomUtil.element({ DomUtil.element({
tagName: 'option', tagName: 'option',
parent: layerSelect, parent: layerSelect,
textContent: datalayer.options.name, textContent: datalayer.options.name,
value: L.stamp(datalayer), value: datalayer.id,
}) })
} }
}) })

View file

@ -0,0 +1,93 @@
import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
import { BaseAjax, SingleMixin } from '../autocomplete.js'
import { translate } from '../i18n.js'
import * as Utils from '../utils.js'
import { AutocompleteCommunes } from './communesfr.js'
const TEMPLATE = `
<div>
<h3>Géocodage dadresses en France</h3>
<p>Géocoder un fichier CSV avec la base adresse nationale.</p>
<fieldset class="formbox">
<legend>Choisir un fichier CSV (encodé en UTF-8)</legend>
<input type=file name=file data-ref=csvFile accept=".csv" />
</fieldset>
<fieldset class="formbox">
<legend>Aperçu des données</legend>
<table class="table-scrollable" data-ref=table></table>
</fieldset>
<fieldset class="formbox">
<legend>Sélectionner les colonnes à utiliser</legend>
<span data-ref="columns"></span>
</fieldset>
</div>
`
export class Importer {
constructor(umap, options) {
this._umap = umap
this.name = options.name || 'Géocodage FR'
this.id = 'banfr'
}
async open(importer) {
let data
const [container, { table, columns, csvFile }] =
Utils.loadTemplateWithRefs(TEMPLATE)
csvFile.addEventListener('change', () => {
const reader = new FileReader()
reader.onload = (evt) => {
data = evt.target.result
const rows = csv2geojson.auto(data).slice(0, 5)
const cols = Object.keys(rows[0])
table.innerHTML = ''
columns.innerHTML = ''
const tr = document.createElement('tr')
for (const column of cols) {
tr.appendChild(Utils.loadTemplate(`<th>${column}</th>`))
columns.appendChild(
Utils.loadTemplate(
`<label><input type="checkbox" value="${column}" /> ${column}</label>`
)
)
}
table.appendChild(tr)
for (const row of rows) {
const tr = document.createElement('tr')
for (const column of cols) {
tr.appendChild(Utils.loadTemplate(`<td>${row[column]}</td>`))
}
table.appendChild(tr)
}
}
reader.readAsText(csvFile.files[0])
})
const confirm = async (form) => {
const formData = new FormData()
formData.append('data', csvFile.files[0])
for (const option of columns.querySelectorAll('input:checked')) {
formData.append('columns', option.value)
}
const response = await this._umap.request.post(
'https://api-adresse.data.gouv.fr/search/csv/',
{},
formData
)
if (response?.ok) {
importer.raw = await response.text()
importer.format = 'csv'
}
}
importer.dialog
.open({
template: container,
className: `${this.id} importer dark`,
cancel: false,
accept: translate('Geocode'),
})
.then(confirm)
}
}

View file

@ -1,25 +1,27 @@
import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js' import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
import { BaseAjax, SingleMixin } from '../autocomplete.js' import { BaseAjax, SingleMixin } from '../autocomplete.js'
import { translate } from '../i18n.js'
import * as Util from '../utils.js' import * as Util from '../utils.js'
import { AutocompleteCommunes } from './communesfr.js' import { AutocompleteCommunes } from './communesfr.js'
import { translate } from '../i18n.js'
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
const TEMPLATE = ` const TEMPLATE = `
<h3>Cadastre</h3> <h3>Cadastre</h3>
<p>Importer les données cadastrales dune commune française.</p> <p>Importer les données cadastrales dune commune française.</p>
<select name="theme"> <div class="formbox">
<option value="batiments">Bâtiments</option> <select name="theme">
<option value="communes">Communes</option> <option value="batiments">Bâtiments</option>
<option value="feuilles">Feuilles</option> <option value="communes">Communes</option>
<option value="lieux_dits">Lieux dits</option> <option value="feuilles">Feuilles</option>
<option value="parcelles" selected>Parcelles</option> <option value="lieux_dits">Lieux dits</option>
<option value="prefixes_sections">Préfixes sections</option> <option value="parcelles" selected>Parcelles</option>
<option value="sections">Sections</option> <option value="prefixes_sections">Préfixes sections</option>
<option value="subdivisions_fiscales">Subdivisions fiscales</option> <option value="sections">Sections</option>
</select> <option value="subdivisions_fiscales">Subdivisions fiscales</option>
<label id="boundary"> </select>
</label> <label id="boundary">
</label>
</div>
` `
export class Importer { export class Importer {

View file

@ -15,7 +15,7 @@ export class AutocompleteCommunes extends SingleMixin(BaseAjax) {
let options = { q: encodeURIComponent(value) } let options = { q: encodeURIComponent(value) }
const re = /^(0[1-9]|[1-9][ABab\d])\d{3}$/gm const re = /^(0[1-9]|[1-9][ABab\d])\d{3}$/gm
if (re.test(value)) { if (re.test(value)) {
url = "https://geo.api.gouv.fr/communes?code={code}&limit=5" url = 'https://geo.api.gouv.fr/communes?code={code}&limit=5'
options = { code: encodeURIComponent(value) } options = { code: encodeURIComponent(value) }
} }
return Util.template(url, options) return Util.template(url, options)

View file

@ -16,15 +16,17 @@ const BOUNDARY_TYPES = {
const TEMPLATE = ` const TEMPLATE = `
<h3>GeoDataMine</h3> <h3>GeoDataMine</h3>
<p>${translate('GeoDataMine: thematic data from OpenStreetMap')}.</p> <p>${translate('GeoDataMine: thematic data from OpenStreetMap')}.</p>
<select name="theme"> <div class="formbox">
<option value="">${translate('Choose a theme')}</option> <select name="theme">
</select> <option value="">${translate('Choose a theme')}</option>
<label> </select>
<input type="checkbox" name="aspoint" /> <label>
${translate('Symplify all geometries to points')} <input type="checkbox" name="aspoint" />
</label> ${translate('Simplify all geometries to points')}
<label id="boundary"> </label>
</label> <label id="boundary">
</label>
</div>
` `
class Autocomplete extends SingleMixin(BaseAjax) { class Autocomplete extends SingleMixin(BaseAjax) {

View file

@ -0,0 +1,46 @@
export class DataLayerManager extends Object {
add(datalayer) {
this[datalayer.id] = datalayer
}
active() {
return Object.values(this)
.filter((datalayer) => !datalayer.isDeleted)
.sort((a, b) => a.rank > b.rank)
}
reverse() {
return this.active().reverse()
}
count() {
return this.active().length
}
find(func) {
for (const datalayer of this.reverse()) {
if (func.call(datalayer, datalayer)) {
return datalayer
}
}
}
filter(func) {
return this.active().filter(func)
}
visible() {
return this.filter((datalayer) => datalayer.isVisible())
}
browsable() {
return this.reverse().filter((datalayer) => datalayer.allowBrowse())
}
prev(datalayer) {
const browsable = this.browsable()
const current = browsable.indexOf(datalayer)
const prev = browsable[current - 1] || browsable[browsable.length - 1]
if (!prev.canBrowse()) return this.prev(prev)
return prev
}
next(datalayer) {
const browsable = this.browsable()
const current = browsable.indexOf(datalayer)
const next = browsable[current + 1] || browsable[0]
if (!next.canBrowse()) return this.next(next)
return next
}
}

View file

@ -1,18 +1,16 @@
import { DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js' import { DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from './i18n.js'
import { uMapAlert as Alert } from '../components/alerts/alert.js' import { uMapAlert as Alert } from '../components/alerts/alert.js'
import { ServerStored } from './saving.js'
import * as Utils from './utils.js'
import { MutatingForm } from './form/builder.js' import { MutatingForm } from './form/builder.js'
import { translate } from './i18n.js'
import * as Utils from './utils.js'
// Dedicated object so we can deal with a separate dirty status, and thus // Dedicated object so we can deal with a separate dirty status, and thus
// call the endpoint only when needed, saving one call at each save. // call the endpoint only when needed, saving one call at each save.
export class MapPermissions extends ServerStored { export class MapPermissions {
constructor(umap) { constructor(umap) {
super()
this.setProperties(umap.properties.permissions) this.setProperties(umap.properties.permissions)
this._umap = umap this._umap = umap
this._isDirty = false this.sync = umap.syncEngine.proxy(this)
} }
setProperties(properties) { setProperties(properties) {
@ -28,6 +26,13 @@ export class MapPermissions extends ServerStored {
) )
} }
getSyncMetadata() {
return {
subject: 'mappermissions',
metadata: {},
}
}
render() { render() {
this._umap.render(['properties.permissions']) this._umap.render(['properties.permissions'])
} }
@ -154,7 +159,7 @@ export class MapPermissions extends ServerStored {
`<fieldset class="separator"><legend>${translate('Datalayers')}</legend></fieldset>` `<fieldset class="separator"><legend>${translate('Datalayers')}</legend></fieldset>`
) )
container.appendChild(fieldset) container.appendChild(fieldset)
this._umap.eachDataLayer((datalayer) => { this._umap.datalayers.active().map((datalayer) => {
datalayer.permissions.edit(fieldset) datalayer.permissions.edit(fieldset)
}) })
} }
@ -188,7 +193,6 @@ export class MapPermissions extends ServerStored {
} }
async save() { async save() {
if (!this.isDirty) return
const formData = new FormData() const formData = new FormData()
if (!this.isAnonymousMap() && this.properties.editors) { if (!this.isAnonymousMap() && this.properties.editors) {
const editors = this.properties.editors.map((u) => u.id) const editors = this.properties.editors.map((u) => u.id)
@ -247,9 +251,8 @@ export class MapPermissions extends ServerStored {
} }
} }
export class DataLayerPermissions extends ServerStored { export class DataLayerPermissions {
constructor(umap, datalayer) { constructor(umap, datalayer) {
super()
this._umap = umap this._umap = umap
this.properties = Object.assign( this.properties = Object.assign(
{ {
@ -259,6 +262,14 @@ export class DataLayerPermissions extends ServerStored {
) )
this.datalayer = datalayer this.datalayer = datalayer
this.sync = umap.syncEngine.proxy(this)
}
getSyncMetadata() {
return {
subject: 'datalayerpermissions',
metadata: { id: this.datalayer.id },
}
} }
edit(container) { edit(container) {
@ -289,7 +300,6 @@ export class DataLayerPermissions extends ServerStored {
} }
async save() { async save() {
if (!this.isDirty) return
const formData = new FormData() const formData = new FormData()
formData.append('edit_status', this.properties.edit_status) formData.append('edit_status', this.properties.edit_status)
const [data, response, error] = await this._umap.server.post( const [data, response, error] = await this._umap.server.post(

View file

@ -0,0 +1,251 @@
import { Control } from '../../../vendors/leaflet/leaflet-src.esm.js'
import * as Utils from '../utils.js'
import { translate } from '../i18n.js'
export const HomeControl = Control.extend({
options: {
position: 'topleft',
},
onAdd: (map) => {
const path = map._umap.getStaticPathFor('home.svg')
const container = Utils.loadTemplate(
`<a href="/" class="home-button" title="${translate('Back to home')}"><img src="${path}" alt="${translate('Home logo')}" width="38px" height="38px" /></a>`
)
return container
},
})
export const EditControl = Control.extend({
options: {
position: 'topright',
},
onAdd: (map) => {
const template = `
<div class="edit-enable">
<button type="button" data-ref="button">${translate('Edit')}</button>
</div>
`
const [container, { button }] = Utils.loadTemplateWithRefs(template)
button.addEventListener('click', () => map._umap.enableEdit())
button.addEventListener('mouseover', () => {
map._umap.tooltip.open({
content: map._umap.help.displayLabel('TOGGLE_EDIT'),
anchor: button,
position: 'bottom',
delay: 750,
duration: 5000,
})
})
return container
},
})
export const MoreControl = Control.extend({
options: {
position: 'topleft',
},
onAdd: function (map) {
const pos = this.getPosition()
const corner = map._controlCorners[pos]
const className = 'umap-more-controls'
const template = `
<div class="umap-control-text">
<button class="umap-control-more" type="button" data-ref="button"></button>
</div>
`
const [container, { button }] = Utils.loadTemplateWithRefs(template)
button.addEventListener('click', () => corner.classList.toggle(className))
button.addEventListener('mouseover', () => {
const extended = corner.classList.contains(className)
map._umap.tooltip.open({
content: extended ? translate('Hide controls') : translate('More controls'),
anchor: button,
position: 'right',
delay: 750,
})
})
return container
},
})
export const PermanentCreditsControl = Control.extend({
options: {
position: 'bottomleft',
},
onAdd: (map) => {
const container = Utils.loadTemplate(
`<div class="umap-permanent-credits-container text">${Utils.toHTML(map.options.permanentCredit)}</div>`
)
const background = map.options.permanentCreditBackground ? '#FFFFFFB0' : ''
container.style.backgroundColor = background
return container
},
})
const BaseButton = Control.extend({
initialize: function (umap, options) {
this._umap = umap
Control.prototype.initialize.call(this, options)
},
onAdd: function (map) {
const template = `
<div class="${this.options.className} umap-control">
<button type="button" title="${this.options.title}" data-ref="button"></button>
</div>
`
const [container, { button }] = Utils.loadTemplateWithRefs(template)
button.addEventListener('click', (event) => {
event.stopPropagation()
this.onClick()
})
button.addEventListener('dblclick', (event) => {
event.stopPropagation()
})
this.afterAdd(container)
return container
},
afterAdd: (container) => {},
})
export const DataLayersControl = BaseButton.extend({
options: {
position: 'topleft',
className: 'umap-control-browse',
title: translate('Open browser'),
},
afterAdd: function (container) {
Utils.toggleBadge(container, this._umap.browser?.hasFilters())
},
onClick: function () {
this._umap.openBrowser()
},
})
export const CaptionControl = BaseButton.extend({
options: {
position: 'topleft',
className: 'umap-control-caption',
title: translate('About'),
},
onClick: function () {
this._umap.openCaption()
},
})
export const EmbedControl = BaseButton.extend({
options: {
position: 'topleft',
title: translate('Share and download'),
className: 'leaflet-control-embed',
},
onClick: function () {
this._umap.share.open()
},
})
export const AttributionControl = Control.Attribution.extend({
options: {
prefix: '',
},
_update: function () {
// Layer is no more on the map
if (!this._map) return
Control.Attribution.prototype._update.call(this)
const shortCredit = this._map._umap.getProperty('shortCredit')
const captionMenus = this._map._umap.getProperty('captionMenus')
// Use our own container, so we can hide/show on small screens
const originalCredits = this._container.innerHTML
this._container.innerHTML = ''
const template = `
<div class="attribution-container">
${originalCredits}
<span data-ref="short"> ${Utils.toHTML(shortCredit)}</span>
<a href="#" data-ref="caption"> ${translate('Open caption')}</a>
<a href="/" data-ref="home"> ${translate('Home')}</a>
<a href="https://umap-project.org/" data-ref="site"> ${translate('Powered by uMap')}</a>
<a href="#" class="attribution-toggle"></a>
</div>
`
const [container, { short, caption, home, site }] =
Utils.loadTemplateWithRefs(template)
caption.addEventListener('click', () => this._map._umap.openCaption())
this._container.appendChild(container)
short.hidden = !shortCredit
caption.hidden = !captionMenus
site.hidden = !captionMenus
home.hidden = this._map._umap.isEmbed || !captionMenus
},
})
/* Used in edit mode to define the default tilelayer */
export const TileLayerChooser = BaseButton.extend({
options: {
position: 'topleft',
},
onClick: function () {
this.openSwitcher({ edit: true })
},
openSwitcher: function (options = {}) {
const template = `
<div class="umap-edit-tilelayers">
<h3><i class="icon icon-16 icon-tilelayer" title=""></i><span class="">${translate('Change tilelayers')}</span></h3>
<ul data-ref="tileContainer"></ul>
</div>
`
const [container, { tileContainer }] = Utils.loadTemplateWithRefs(template)
this.buildList(tileContainer, options)
const panel = options.edit ? this._umap.editPanel : this._umap.panel
panel.open({ content: container, highlight: 'tilelayers' })
},
buildList: function (container, options) {
this._umap._leafletMap.eachTileLayer((tilelayer) => {
const browserIsHttps = window.location.protocol === 'https:'
const tileLayerIsHttp = tilelayer.options.url_template.indexOf('http:') === 0
if (browserIsHttps && tileLayerIsHttp) return
container.appendChild(this.addTileLayerElement(tilelayer, options))
})
},
addTileLayerElement: function (tilelayer, options) {
const selectedClass = this._umap._leafletMap.hasLayer(tilelayer) ? 'selected' : ''
const src = Utils.template(
tilelayer.options.url_template,
this._umap._leafletMap.options.demoTileInfos
)
const template = `
<li>
<img src="${src}" loading="lazy" />
<div>${tilelayer.options.name}</div>
</li>
`
const li = Utils.loadTemplate(template)
li.addEventListener('click', () => {
const oldTileLayer = this._umap.properties.tilelayer
this._umap._leafletMap.selectTileLayer(tilelayer)
this._umap._leafletMap._controls.tilelayers.setLayers()
if (options?.edit) {
this._umap.properties.tilelayer = tilelayer.toJSON()
this._umap.sync.update(
'properties.tilelayer',
this._umap.properties.tilelayer,
oldTileLayer
)
}
})
return li
},
})

View file

@ -1,11 +1,11 @@
import { import {
DivIcon,
DomEvent, DomEvent,
DomUtil, DomUtil,
DivIcon,
Icon, Icon,
} from '../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../vendors/leaflet/leaflet-src.esm.js'
import * as Utils from '../utils.js'
import { SCHEMA } from '../schema.js' import { SCHEMA } from '../schema.js'
import * as Utils from '../utils.js'
export function getClass(name) { export function getClass(name) {
switch (name) { switch (name) {
@ -15,6 +15,8 @@ export function getClass(name) {
return Ball return Ball
case 'Drop': case 'Drop':
return Drop return Drop
case 'Raw':
return Raw
default: default:
return DefaultIcon return DefaultIcon
} }
@ -152,6 +154,17 @@ const Circle = BaseIcon.extend({
}, },
}) })
const Raw = DefaultIcon.extend({
default_options: {
iconSize: new L.Point(48, 48),
popupAnchor: new L.Point(0, 0),
tooltipAnchor: new L.Point(0, 0),
className: 'umap-raw-icon',
},
_getColor: () => 'transparent',
})
const Drop = DefaultIcon.extend({ const Drop = DefaultIcon.extend({
default_options: { default_options: {
iconAnchor: new L.Point(16, 42), iconAnchor: new L.Point(16, 42),

View file

@ -1,9 +1,9 @@
import { FeatureGroup, DomUtil } from '../../../../vendors/leaflet/leaflet-src.esm.js' import colorbrewer from '../../../../vendors/colorbrewer/colorbrewer.js'
import { DomUtil, FeatureGroup } from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from '../../i18n.js' import { translate } from '../../i18n.js'
import { LayerMixin } from './base.js'
import * as Utils from '../../utils.js' import * as Utils from '../../utils.js'
import { CircleMarker } from '../ui.js' import { CircleMarker } from '../ui.js'
import colorbrewer from '../../../../vendors/colorbrewer/colorbrewer.js' import { LayerMixin } from './base.js'
// Layer where each feature color is relative to the others, // Layer where each feature color is relative to the others,
// so we need all features before behing able to set one // so we need all features before behing able to set one
@ -117,7 +117,7 @@ export const Choropleth = FeatureGroup.extend({
}, },
_getValue: function (feature) { _getValue: function (feature) {
const key = this.datalayer.options.choropleth.property || 'value' const key = this.datalayer.options.choropleth?.property || 'value'
const value = +feature.properties[key] const value = +feature.properties[key]
if (!Number.isNaN(value)) return value if (!Number.isNaN(value)) return value
}, },
@ -130,12 +130,12 @@ export const Choropleth = FeatureGroup.extend({
this.options.colors = [] this.options.colors = []
return return
} }
const mode = this.datalayer.options.choropleth.mode const mode = this.datalayer.options.choropleth?.mode
let classes = +this.datalayer.options.choropleth.classes || 5 let classes = +this.datalayer.options.choropleth?.classes || 5
let breaks let breaks
classes = Math.min(classes, values.length) classes = Math.min(classes, values.length)
if (mode === 'manual') { if (mode === 'manual') {
const manualBreaks = this.datalayer.options.choropleth.breaks const manualBreaks = this.datalayer.options.choropleth?.breaks
if (manualBreaks) { if (manualBreaks) {
breaks = manualBreaks breaks = manualBreaks
.split(',') .split(',')

View file

@ -1,10 +1,10 @@
import { Evented } from '../../../../vendors/leaflet/leaflet-src.esm.js'
// WARNING must be loaded dynamically, or at least after leaflet.markercluster // WARNING must be loaded dynamically, or at least after leaflet.markercluster
// Uses global L.MarkerCluster and L.MarkerClusterGroup, not exposed as ESM // Uses global L.MarkerCluster and L.MarkerClusterGroup, not exposed as ESM
import { translate } from '../../i18n.js' import { translate } from '../../i18n.js'
import { LayerMixin } from './base.js'
import * as Utils from '../../utils.js' import * as Utils from '../../utils.js'
import { Evented } from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { Cluster as ClusterIcon } from '../icon.js' import { Cluster as ClusterIcon } from '../icon.js'
import { LayerMixin } from './base.js'
const MarkerCluster = L.MarkerCluster.extend({ const MarkerCluster = L.MarkerCluster.extend({
// Custom class so we can call computeTextColor // Custom class so we can call computeTextColor

View file

@ -1,14 +1,14 @@
// Uses global L.HeatLayer, not exposed as ESM // Uses global L.HeatLayer, not exposed as ESM
import { import {
Marker,
LatLng,
latLngBounds,
Bounds, Bounds,
LatLng,
Marker,
latLngBounds,
point, point,
} from '../../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { LayerMixin } from './base.js'
import * as Utils from '../../utils.js'
import { translate } from '../../i18n.js' import { translate } from '../../i18n.js'
import * as Utils from '../../utils.js'
import { LayerMixin } from './base.js'
export const Heat = L.HeatLayer.extend({ export const Heat = L.HeatLayer.extend({
statics: { statics: {
@ -41,6 +41,11 @@ export const Heat = L.HeatLayer.extend({
} }
}, },
removeLayer: (layer) => {
// No op, there is no "removeLatLng" in Leaflet.heat
// but this method is expected by DataLayer
},
onAdd: function (map) { onAdd: function (map) {
LayerMixin.onAdd.call(this, map) LayerMixin.onAdd.call(this, map)
return L.HeatLayer.prototype.onAdd.call(this, map) return L.HeatLayer.prototype.onAdd.call(this, map)

View file

@ -1,18 +1,29 @@
// Goes here all code related to Leaflet, DOM and user interactions. // Goes here all code related to Leaflet, DOM and user interactions.
import { import {
Map as BaseMap, Map as BaseMap,
DomUtil,
DomEvent,
latLngBounds,
latLng,
Control, Control,
DomEvent,
DomUtil,
latLng,
latLngBounds,
setOptions, setOptions,
} from '../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from '../i18n.js'
import { uMapAlert as Alert } from '../../components/alerts/alert.js' import { uMapAlert as Alert } from '../../components/alerts/alert.js'
import DropControl from '../drop.js'
import { translate } from '../i18n.js'
import {
AttributionControl,
CaptionControl,
DataLayersControl,
EmbedControl,
EditControl,
HomeControl,
MoreControl,
PermanentCreditsControl,
TileLayerChooser,
} from './controls.js'
import * as Utils from '../utils.js' import * as Utils from '../utils.js'
import * as Icon from './icon.js' import * as Icon from './icon.js'
import DropControl from '../drop.js'
// Those options are not saved on the server, so they can live here // Those options are not saved on the server, so they can live here
// instead of in umap.properties // instead of in umap.properties
@ -23,6 +34,7 @@ BaseMap.mergeOptions({
const ControlsMixin = { const ControlsMixin = {
HIDDABLE_CONTROLS: [ HIDDABLE_CONTROLS: [
'home',
'zoom', 'zoom',
'search', 'search',
'fullscreen', 'fullscreen',
@ -39,14 +51,15 @@ const ControlsMixin = {
this._controls = {} this._controls = {}
if (this._umap.hasEditMode() && !this.options.noControl) { if (this._umap.hasEditMode() && !this.options.noControl) {
new U.EditControl(this).addTo(this) new EditControl(this).addTo(this)
} }
this._controls.home = new HomeControl(this._umap)
this._controls.zoom = new Control.Zoom({ this._controls.zoom = new Control.Zoom({
zoomInTitle: translate('Zoom in'), zoomInTitle: translate('Zoom in'),
zoomOutTitle: translate('Zoom out'), zoomOutTitle: translate('Zoom out'),
}) })
this._controls.datalayers = new U.DataLayersControl(this._umap) this._controls.datalayers = new DataLayersControl(this._umap)
this._controls.caption = new U.CaptionControl(this._umap) this._controls.caption = new CaptionControl(this._umap)
this._controls.locate = new U.Locate(this, { this._controls.locate = new U.Locate(this, {
strings: { strings: {
title: translate('Center map on your location'), title: translate('Center map on your location'),
@ -67,8 +80,8 @@ const ControlsMixin = {
}, },
}) })
this._controls.search = new U.SearchControl() this._controls.search = new U.SearchControl()
this._controls.embed = new Control.Embed(this._umap) this._controls.embed = new EmbedControl(this._umap)
this._controls.tilelayersChooser = new U.TileLayerChooser(this) this._controls.tilelayersChooser = new TileLayerChooser(this._umap)
this._controls.editinosm = new Control.EditInOSM({ this._controls.editinosm = new Control.EditInOSM({
position: 'topleft', position: 'topleft',
widgetOptions: { widgetOptions: {
@ -78,9 +91,9 @@ const ControlsMixin = {
}, },
}) })
this._controls.measure = new L.MeasureControl().initHandler(this) this._controls.measure = new L.MeasureControl().initHandler(this)
this._controls.more = new U.MoreControls() this._controls.more = new MoreControl()
this._controls.scale = L.control.scale() this._controls.scale = L.control.scale()
this._controls.permanentCredit = new U.PermanentCreditsControl(this) this._controls.permanentCredit = new PermanentCreditsControl(this)
this._umap.drop = new DropControl(this._umap, this, this._container) this._umap.drop = new DropControl(this._umap, this, this._container)
this._controls.tilelayers = new U.TileLayerControl(this) this._controls.tilelayers = new U.TileLayerControl(this)
}, },
@ -91,7 +104,7 @@ const ControlsMixin = {
} }
if (this.options.noControl) return if (this.options.noControl) return
this._controls.attribution = new U.AttributionControl().addTo(this) this._controls.attribution = new AttributionControl().addTo(this)
if (this.options.miniMap) { if (this.options.miniMap) {
this.whenReady(function () { this.whenReady(function () {
if (this.selectedTilelayer) { if (this.selectedTilelayer) {
@ -265,8 +278,12 @@ export const LeafletMap = BaseMap.extend({
this.renderUI() this.renderUI()
}, },
renderUI: function () { pullProperties() {
setOptions(this, this._umap.properties) setOptions(this, this._umap.properties)
},
renderUI: function () {
this.pullProperties()
if (this.options.scrollWheelZoom) { if (this.options.scrollWheelZoom) {
this.scrollWheelZoom.enable() this.scrollWheelZoom.enable()
this.dragging.enable() this.dragging.enable()
@ -310,7 +327,7 @@ export const LeafletMap = BaseMap.extend({
} else if (this.options.defaultView === 'latest') { } else if (this.options.defaultView === 'latest') {
this._umap.onceDataLoaded(() => { this._umap.onceDataLoaded(() => {
if (!this._umap.hasData()) return if (!this._umap.hasData()) return
const datalayer = this._umap.firstVisibleDatalayer() const datalayer = this._umap.datalayers.visible()[0]
let feature let feature
if (datalayer) { if (datalayer) {
const feature = datalayer.getFeatureByIndex(-1) const feature = datalayer.getFeatureByIndex(-1)

View file

@ -1,11 +1,11 @@
import { import {
Popup as BasePopup,
DomEvent, DomEvent,
DomUtil, DomUtil,
Path, Path,
Popup as BasePopup,
} from '../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../vendors/leaflet/leaflet-src.esm.js'
import loadTemplate from './template.js'
import Browser from '../browser.js' import Browser from '../browser.js'
import loadTemplate from './template.js'
export default function loadPopup(name) { export default function loadPopup(name) {
switch (name) { switch (name) {

View file

@ -1,8 +1,8 @@
import { DomUtil, DomEvent } from '../../../vendors/leaflet/leaflet-src.esm.js' import { DomEvent, DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
import { translate, getLocale } from '../i18n.js' import { getLocale, translate } from '../i18n.js'
import { Request } from '../request.js'
import * as Utils from '../utils.js' import * as Utils from '../utils.js'
import * as Icon from './icon.js' import * as Icon from './icon.js'
import { Request } from '../request.js'
export default async function loadTemplate(name, feature, container) { export default async function loadTemplate(name, feature, container) {
let klass = PopupTemplate let klass = PopupTemplate

View file

@ -1,18 +1,18 @@
// Goes here all code related to Leaflet, DOM and user interactions. // Goes here all code related to Leaflet, DOM and user interactions.
import { import {
Marker,
Polyline,
Polygon,
CircleMarker as BaseCircleMarker, CircleMarker as BaseCircleMarker,
DomEvent,
DomUtil, DomUtil,
LineUtil,
latLng,
LatLng, LatLng,
LatLngBounds, LatLngBounds,
DomEvent, LineUtil,
Marker,
Polygon,
Polyline,
latLng,
} from '../../../vendors/leaflet/leaflet-src.esm.js' } from '../../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from '../i18n.js'
import { uMapAlert as Alert } from '../../components/alerts/alert.js' import { uMapAlert as Alert } from '../../components/alerts/alert.js'
import { translate } from '../i18n.js'
import * as Utils from '../utils.js' import * as Utils from '../utils.js'
import * as Icon from './icon.js' import * as Icon from './icon.js'
@ -97,7 +97,6 @@ const FeatureMixin = {
}, },
onCommit: function () { onCommit: function () {
this.feature.pullGeometry(false)
this.feature.onCommit() this.feature.onCommit()
}, },
} }
@ -110,9 +109,7 @@ const PointMixin = {
addInteractions() { addInteractions() {
FeatureMixin.addInteractions.call(this) FeatureMixin.addInteractions.call(this)
this.on('dragend', (event) => { this.on('dragend', (event) => {
this.isDirty = true
this.feature.edit(event) this.feature.edit(event)
this.feature.pullGeometry(false)
}) })
if (!this.feature.isReadOnly()) this.on('mouseover', this._enableDragging) if (!this.feature.isReadOnly()) this.on('mouseover', this._enableDragging)
this.on('mouseout', this._onMouseOut) this.on('mouseout', this._onMouseOut)
@ -303,13 +300,13 @@ const PathMixin = {
this._container = null this._container = null
FeatureMixin.onAdd.call(this, map) FeatureMixin.onAdd.call(this, map)
this.setStyle() this.setStyle()
if (this.editing?.enabled()) this.editing.addHooks() if (this.editor?.enabled()) this.editor.addHooks()
this.resetTooltip() this.resetTooltip()
this._path.dataset.feature = this.feature.id this._path.dataset.feature = this.feature.id
}, },
onRemove: function (map) { onRemove: function (map) {
if (this.editing?.enabled()) this.editing.removeHooks() if (this.editor?.enabled()) this.editor.removeHooks()
FeatureMixin.onRemove.call(this, map) FeatureMixin.onRemove.call(this, map)
}, },
@ -362,6 +359,13 @@ const PathMixin = {
isOnScreen: function (bounds) { isOnScreen: function (bounds) {
return bounds.overlaps(this.getBounds()) return bounds.overlaps(this.getBounds())
}, },
_setLatLngs: function (latlngs) {
this.parentClass.prototype._setLatLngs.call(this, latlngs)
if (this.editor?.enabled()) {
this.editor.reset()
}
},
} }
export const LeafletPolyline = Polyline.extend({ export const LeafletPolyline = Polyline.extend({

View file

@ -1,9 +1,9 @@
import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js' import { stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from './i18n.js'
import * as Utils from './utils.js'
import { AutocompleteDatalist } from './autocomplete.js' import { AutocompleteDatalist } from './autocomplete.js'
import Orderable from './orderable.js'
import { MutatingForm } from './form/builder.js' import { MutatingForm } from './form/builder.js'
import { translate } from './i18n.js'
import Orderable from './orderable.js'
import * as Utils from './utils.js'
const EMPTY_VALUES = ['', undefined, null] const EMPTY_VALUES = ['', undefined, null]
@ -17,20 +17,10 @@ class Rule {
this.parse() this.parse()
} }
get isDirty() {
return this._isDirty
}
set isDirty(status) {
this._isDirty = status
if (status) this._umap.isDirty = status
}
constructor(umap, condition = '', options = {}) { constructor(umap, condition = '', options = {}) {
// TODO make this public properties when browser coverage is ok // TODO make this public properties when browser coverage is ok
// cf https://caniuse.com/?search=public%20class%20field // cf https://caniuse.com/?search=public%20class%20field
this._condition = null this._condition = null
this._isDirty = false
this.OPERATORS = [ this.OPERATORS = [
['>', this.gt], ['>', this.gt],
['<', this.lt], ['<', this.lt],
@ -129,10 +119,9 @@ class Rule {
'options.smoothFactor', 'options.smoothFactor',
'options.dashArray', 'options.dashArray',
] ]
const container = DomUtil.create('div')
const builder = new MutatingForm(this, options) const builder = new MutatingForm(this, options)
const defaultShapeProperties = DomUtil.add('div', '', container) const container = document.createElement('div')
defaultShapeProperties.appendChild(builder.build()) container.appendChild(builder.build())
const autocomplete = new AutocompleteDatalist(builder.helpers.condition.input) const autocomplete = new AutocompleteDatalist(builder.helpers.condition.input)
const properties = this._umap.allProperties() const properties = this._umap.allProperties()
autocomplete.suggestions = properties autocomplete.suggestions = properties
@ -147,60 +136,70 @@ class Rule {
.map((str) => `${value}${str || ''}`) .map((str) => `${value}${str || ''}`)
} }
}) })
this._umap.editPanel.open({ content: container, highlight: 'settings' }) const backButton = Utils.loadTemplate(`
<button class="flat" type="button" data-ref="add">
<i class="icon icon-16 icon-back" title="${translate('Back to list')}"></i>
</button>`)
backButton.addEventListener('click', () =>
this._umap.edit().then(() => {
this._umap.editPanel.container.querySelector('details#rules').open = true
})
)
this._umap.editPanel.open({
content: container,
highlight: 'settings',
actions: [backButton],
})
} }
renderToolbox(row) { renderToolbox(ul) {
row.classList.toggle('off', !this.active) const template = `
const toggle = DomUtil.createButtonIcon( <li data-id="${stamp(this)}" class="orderable">
row, <button class="icon icon-16 icon-eye" title="${translate('Toggle rule')}" data-ref=toggle></button>
'icon-eye', <button class="icon icon-16 icon-edit show-on-edit" title="${translate('Edit')}" data-ref=edit></button>
translate('Show/hide layer') <button class="icon icon-16 icon-delete show-on-edit" title="${translate('Delete rule')}" data-ref=remove></button>
) <span>${this.condition || translate('empty rule')}</span>
const edit = DomUtil.createButtonIcon( <i class="icon icon-16 icon-drag" title="${translate('Drag to reorder')}"></i>
row, </li>
'icon-edit show-on-edit', `
translate('Edit') const [li, { toggle, edit, remove }] = Utils.loadTemplateWithRefs(template)
) ul.appendChild(li)
const remove = DomUtil.createButtonIcon( li.classList.toggle('off', !this.active)
row, edit.addEventListener('click', () => this.edit())
'icon-delete show-on-edit', remove.addEventListener('click', () => {
translate('Delete layer') if (!confirm(translate('Are you sure you want to delete this rule?'))) return
) this._delete()
DomEvent.on(edit, 'click', this.edit, this) this._umap.editPanel.close()
DomEvent.on( })
remove, toggle.addEventListener('click', () => {
'click',
function () {
if (!confirm(translate('Are you sure you want to delete this rule?'))) return
this._delete()
this._umap.editPanel.close()
},
this
)
DomUtil.add('span', '', row, this.condition || translate('empty rule'))
DomUtil.createIcon(row, 'icon-drag', translate('Drag to reorder'))
row.dataset.id = stamp(this)
DomEvent.on(toggle, 'click', () => {
this.active = !this.active this.active = !this.active
row.classList.toggle('off', !this.active) li.classList.toggle('off', !this.active)
this._umap.render(['rules']) this._umap.render(['rules'])
}) })
} }
_delete() { _delete() {
this._umap.rules.rules = this._umap.rules.rules.filter((rule) => rule !== this) this._umap.rules.rules = this._umap.rules.rules.filter((rule) => rule !== this)
this._umap.rules.commit()
}
setter(key, value) {
const oldRules = Utils.CopyJSON(this._umap.properties.rules || {})
Utils.setObjectValue(this, key, value)
this._umap.rules.commit()
this._umap.sync.update('properties.rules', this._umap.properties.rules, oldRules)
} }
} }
export default class Rules { export default class Rules {
constructor(umap) { constructor(umap) {
this._umap = umap this._umap = umap
this.rules = []
this.load() this.load()
} }
load() { load() {
this.rules = []
if (!this._umap.properties.rules?.length) return if (!this._umap.properties.rules?.length) return
for (const { condition, options } of this._umap.properties.rules) { for (const { condition, options } of this._umap.properties.rules) {
if (!condition) continue if (!condition) continue
@ -209,8 +208,9 @@ export default class Rules {
} }
onReorder(src, dst, initialIndex, finalIndex) { onReorder(src, dst, initialIndex, finalIndex) {
const moved = this.rules.find((rule) => stamp(rule) === src.dataset.id) const oldRules = Utils.CopyJSON(this._umap.properties.rules || {})
const reference = this.rules.find((rule) => stamp(rule) === dst.dataset.id) const moved = this.rules.find((rule) => stamp(rule) === +src.dataset.id)
const reference = this.rules.find((rule) => stamp(rule) === +dst.dataset.id)
const movedIdx = this.rules.indexOf(moved) const movedIdx = this.rules.indexOf(moved)
let referenceIdx = this.rules.indexOf(reference) let referenceIdx = this.rules.indexOf(reference)
const minIndex = Math.min(movedIdx, referenceIdx) const minIndex = Math.min(movedIdx, referenceIdx)
@ -222,27 +222,34 @@ export default class Rules {
else if (finalIndex > initialIndex) newIdx = referenceIdx else if (finalIndex > initialIndex) newIdx = referenceIdx
else newIdx = referenceIdx + 1 else newIdx = referenceIdx + 1
this.rules.splice(newIdx, 0, moved) this.rules.splice(newIdx, 0, moved)
moved.isDirty = true
this._umap.render(['rules']) this._umap.render(['rules'])
this.commit()
this._umap.sync.update('properties.rules', this._umap.properties.rules, oldRules)
} }
edit(container) { edit(container) {
const body = DomUtil.createFieldset(container, translate('Conditional style rules')) const template = `
<details id="rules">
<summary>${translate('Conditional style rules')}</summary>
<fieldset>
<ul data-ref=ul></ul>
<button class="umap-add" type="button" data-ref=add>${translate('Add rule')}</button>
</fieldset>
</details>
`
const [body, { ul, add }] = Utils.loadTemplateWithRefs(template)
if (this.rules.length) { if (this.rules.length) {
const ul = DomUtil.create('ul', '', body)
for (const rule of this.rules) { for (const rule of this.rules) {
rule.renderToolbox(DomUtil.create('li', 'orderable', ul)) rule.renderToolbox(ul)
} }
const orderable = new Orderable(ul, this.onReorder.bind(this)) const orderable = new Orderable(ul, this.onReorder.bind(this))
} }
add.addEventListener('click', () => this.addRule())
DomUtil.createButton('umap-add', body, translate('Add rule'), this.addRule, this) container.appendChild(body)
} }
addRule() { addRule() {
const rule = new Rule(this._umap) const rule = new Rule(this._umap)
rule.isDirty = true
this.rules.push(rule) this.rules.push(rule)
rule.edit(map) rule.edit(map)
} }

Some files were not shown because too many files have changed in this diff Show more