Compare commits

..

No commits in common. "master" and "2.9.1" have entirely different histories.

270 changed files with 6318 additions and 10062 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -77,18 +77,11 @@ umap:
SECRET_KEY: CHANGE_ME
STATIC_ROOT: /srv/umap/static
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:
config: |
from umap.settings.base import *
# 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:
enabled: true

View file

@ -1,15 +1,5 @@
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:
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
@ -24,35 +14,18 @@ services:
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
image: umap/umap:3.0.2
image: umap/umap:2.0.2
ports:
- "${PORT-8000}:8000"
environment:
- STATIC_ROOT=/srv/umap/static
- MEDIA_ROOT=/srv/umap/uploads
- DATABASE_URL=postgis://postgres@db/postgres
- SECRET_KEY=some-long-and-weirdly-unrandom-secret-key
- SITE_URL=https://umap.local/
- UMAP_ALLOW_ANONYMOUS=True
- DEBUG=1
- REALTIME_ENABLED=1
- REDIS_URL=redis://redis:6379
volumes:
- 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:
data:
static:
db:

View file

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

View file

@ -1,111 +0,0 @@
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;
}
}
}

26
docker/uwsgi.ini Normal file
View file

@ -0,0 +1,26 @@
[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
mkdocs==1.6.1
pymdown-extensions==10.14.3
mkdocs-material==9.6.12
mkdocs-material==9.6.4
mkdocs-static-i18n==1.3.0

View file

@ -1,142 +1,5 @@
# 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
* be more persuasive in deprecating twitter login backend by @yohanboniface in #2538

View file

@ -88,19 +88,6 @@ Nginx configuration.
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
Must be defined to something unique and secret.
@ -134,13 +121,6 @@ The final URL of you instance, including the protocol:
`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
Where uMap should store static files (CSS, JS…), must be consistent with your
@ -343,10 +323,7 @@ CREATE EXTENSION btree_gin;
ALTER TEXT SEARCH CONFIGURATION umapdict ALTER MAPPING FOR hword, hword_part, word WITH unaccent, simple;
# 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, 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);
CREATE INDEX IF NOT EXISTS search_idx ON umap_map USING GIN(to_tsvector('umapdict', COALESCE(name, ''::character varying)::text), share_status);
```
Then set:
@ -368,3 +345,61 @@ 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.
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:
# Check https://hub.docker.com/r/umap/umap/tags to find the latest version
image: umap/umap:2.9.3
image: umap/umap:2.0.2
ports:
# modify the external port (8001, on the left) if desired, but make sure it matches SITE_URL, below
- "8001:8000"
@ -48,45 +48,3 @@ User accounts can be managed via the Django admin page ({SITE_URL}/admin). The r
```bash
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,10 +1,84 @@
# Configuring Nginx
See [WSGI](wsgi.md) or [ASGI](asgi.md) for a basic setup.
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.
Then consider adding this configuration
```nginx title="nginx.conf"
upstream umap {
server unix:///srv/umap/umap.sock;
}
## Static files and geojson
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;
}
}
```
## 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"
location /static {

View file

@ -1,37 +0,0 @@
# 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.

View file

@ -1,87 +0,0 @@
# 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
mkdocs==1.6.1
pymdown-extensions==10.14.3
mkdocs-material==9.6.12
mkdocs-material==9.6.4
mkdocs-static-i18n==1.3.0

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,6 @@ from agnocomplete.core import AgnocompleteModel
from agnocomplete.register import register
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.models.functions import Length
@register
@ -14,11 +13,3 @@ class AutocompleteUser(AgnocompleteModel):
data = super().item(current_item)
data["url"] = current_item.get_url()
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,7 +14,6 @@ def settings(request):
"UMAP_DEMO_SITE": djsettings.UMAP_DEMO_SITE,
"UMAP_HOST_INFOS": djsettings.UMAP_HOST_INFOS,
"UMAP_ALLOW_EDIT_PROFILE": djsettings.UMAP_ALLOW_EDIT_PROFILE,
"UMAP_TAGS": djsettings.UMAP_TAGS,
}

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

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

View file

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

Binary file not shown.

View file

@ -17,7 +17,7 @@ msgid ""
msgstr ""
"Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-11 15:30+0000\n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Ignacio L'Episcopo, 2024-2025\n"
"Language-Team: Spanish (http://app.transifex.com/openstreetmap/umap/language/es/)\n"
@ -44,205 +44,137 @@ msgstr "Sitio en modo solo lectura por mantenimiento"
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 "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."
" and maps."
msgstr ""
#: models.py:61 models.py:80
#: models.py:60 models.py:79
msgid "name"
msgstr "nombre"
#: models.py:63 models.py:493
#: models.py:62 models.py:485
msgid "description"
msgstr "descripción"
#: models.py:111
#: models.py:110
msgid "details"
msgstr "detalles"
#: models.py:112
#: models.py:111
msgid "Link to a page where the licence is detailed."
msgstr "Enlace a una página donde se detalla la licencia."
#: models.py:122
#: models.py:121
msgid "URL template using OSM tile format"
msgstr "Plantilla de URL usando el formato de teselas OSM"
#: models.py:128
#: models.py:127
msgid "Order of the tilelayers in the edit box"
msgstr "Orden de las capas de teselas en el cuadro de edición"
#: models.py:176 models.py:487
#: models.py:175 models.py:479
msgid "Only editable with secret edit link"
msgstr "Solo editable con enlace secreto de edición"
#: models.py:177 models.py:488
#: models.py:176 models.py:480
msgid "Everyone can edit"
msgstr "Todos pueden editar"
#: models.py:180 models.py:481
#: models.py:179 models.py:473
msgid "Everyone"
msgstr "Todos"
#: models.py:181 models.py:190 models.py:482
#: models.py:180 models.py:189 models.py:474
msgid "Editors and team only"
msgstr "Solo editores y equipo"
#: models.py:182 models.py:483
#: models.py:181 models.py:475
msgid "Owner only"
msgstr "Solo el propietario"
#: models.py:185
#: models.py:184
msgid "Draft (private)"
msgstr "Borrador (privado)"
#: models.py:186
#: models.py:185
msgid "Everyone (public)"
msgstr "Todos (público)"
#: models.py:189
#: models.py:188
msgid "Anyone with link"
msgstr "Cualquiera con el enlace"
#: models.py:191
#: models.py:190
msgid "Blocked"
msgstr "Bloqueado"
#: models.py:192 models.py:477
#: models.py:191 models.py:469
msgid "Deleted"
msgstr "Eliminado"
#: models.py:195
#: models.py:194
msgid "center"
msgstr "centro"
#: models.py:196
#: models.py:195
msgid "zoom"
msgstr "zoom"
#: models.py:198
#: models.py:197
msgid "locate"
msgstr "localizar"
#: models.py:198
#: models.py:197
msgid "Locate user on load?"
msgstr "¿Localizar al usuario al cargar?"
#: models.py:202
#: models.py:201
msgid "Choose the map licence."
msgstr "Elige la licencia del mapa."
#: models.py:203
#: models.py:202
msgid "licence"
msgstr "licencia"
#: models.py:214
#: models.py:213
msgid "owner"
msgstr "propietario"
#: models.py:218
#: models.py:217
msgid "editors"
msgstr "editores"
#: models.py:224
#: models.py:223
msgid "team"
msgstr "equipo"
#: models.py:230 models.py:509
#: models.py:229 models.py:501
msgid "edit status"
msgstr "estado de edición"
#: models.py:235 models.py:514
#: models.py:234 models.py:506
msgid "share status"
msgstr "estado de compartir"
#: models.py:238 models.py:504
#: models.py:237 models.py:496
msgid "settings"
msgstr "ajustes"
#: models.py:410
#: models.py:407
msgid "Clone of"
msgstr "Clon de"
#: models.py:476 models.py:480 models.py:486
#: models.py:468 models.py:472 models.py:478
msgid "Inherit"
msgstr "Heredar"
#: models.py:499
#: models.py:491
msgid "display on load"
msgstr "mostrar al cargar"
#: models.py:500
#: models.py:492
msgid "Display this layer on load."
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
msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -495,7 +427,7 @@ msgstr "Mis equipos"
msgid "Map of the uMaps"
msgstr "Mapa de los uMaps"
#: templates/umap/home.html:25
#: templates/umap/home.html:24
msgid "Get inspired, browse maps"
msgstr "Inspírate, navega por los mapas"
@ -503,15 +435,11 @@ msgstr "Inspírate, navega por los mapas"
msgid "You are logged in. Continuing..."
msgstr "Has iniciado sesión. Continuando..."
#: templates/umap/map_list.html:18 views.py:444
#: templates/umap/map_list.html:11 views.py:437
msgid "by"
msgstr "por"
#: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Ver el mapa"
#: templates/umap/map_list.html:28
#: templates/umap/map_list.html:20
msgid "More"
msgstr "Más"
@ -671,15 +599,11 @@ msgstr[0] "%(count)s mapa encontrado:"
msgstr[1] "%(count)s mapas encontrados:"
msgstr[2] "%(count)s mapas encontrados:"
#: templates/umap/search.html:30
#: templates/umap/search.html:28
msgid "No map found."
msgstr "No se ha encontrado ningún mapa."
#: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr "Últimos mapas creados en la categoría"
#: templates/umap/search.html:43
#: templates/umap/search.html:33
msgid "Latest created maps"
msgstr "Últimos mapas creados"
@ -687,11 +611,7 @@ msgstr "Últimos mapas creados"
msgid "Search maps"
msgstr "Buscar mapas"
#: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Cualquier categoría"
#: templates/umap/search_bar.html:19
#: templates/umap/search_bar.html:16
msgid "Search"
msgstr "Buscar"
@ -755,70 +675,70 @@ msgstr "Usuarios"
msgid "New team"
msgstr "Nuevo equipo"
#: views.py:235
#: views.py:234
msgid "Cannot delete a team with more than one member"
msgstr "No se puede eliminar un equipo con más de un miembro"
#: views.py:239
#: views.py:238
#, python-format
msgid "Team “%(name)s” has been deleted"
msgstr "El equipo “%(name)s” ha sido eliminado"
#: views.py:449
#: views.py:442
msgid "View the map"
msgstr "Ver el mapa"
#: views.py:845
#: views.py:838
msgid "See full screen"
msgstr "Ver en pantalla completa"
#: views.py:988
#: views.py:981
msgid "Map editors updated with success!"
msgstr "¡Los editores del mapas han sido actualizados con éxito!"
#: views.py:1024
#: views.py:1017
#, python-format
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"
#: views.py:1027
#: views.py:1020
#, python-format
msgid "Here is your secret edit link: %(link)s"
msgstr "Aquí está tu enlace secreto de edición: %(link)s"
#: views.py:1034
#: views.py:1027
#, python-format
msgid "Can't send email to %(email)s"
msgstr "No se puede enviar correo electrónico a %(email)s"
#: views.py:1037
#: views.py:1030
#, python-format
msgid "Email sent to %(email)s"
msgstr "Correo electrónico enviado a %(email)s"
#: views.py:1048
#: views.py:1041
msgid "Only its owner can delete the map."
msgstr "Sólo el propietario puede borrar el mapa."
#: views.py:1054
#: views.py:1044
msgid "Map successfully deleted."
msgstr "Mapa eliminado correctamente."
#: views.py:1080
#: views.py:1070
#, python-format
msgid ""
"Your map has been cloned! If you want to edit this map from another "
"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"
#: views.py:1085
#: views.py:1075
msgid "Congratulations, your map has been cloned!"
msgstr "¡Enhorabuena! ¡Tu mapa ha sido clonado!"
#: views.py:1339
#: views.py:1329
msgid "Layer successfully deleted."
msgstr "Se eliminó la capa con éxito."
#: views.py:1361
#: views.py:1351
msgid "Permissions updated with success!"
msgstr "¡Permisos actualizados con éxito!"

Binary file not shown.

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

@ -24,7 +24,7 @@ msgid ""
msgstr ""
"Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-11 15:30+0000\n"
"POT-Creation-Date: 2025-03-03 17:36+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"
"Language-Team: French (http://app.transifex.com/openstreetmap/umap/language/fr/)\n"
@ -51,205 +51,137 @@ msgstr "Le site est en lecture seule pour maintenance."
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 "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."
" and maps."
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."
#: models.py:61 models.py:80
#: models.py:60 models.py:79
msgid "name"
msgstr "nom"
#: models.py:63 models.py:493
#: models.py:62 models.py:485
msgid "description"
msgstr "description"
#: models.py:111
#: models.py:110
msgid "details"
msgstr "détails"
#: models.py:112
#: models.py:111
msgid "Link to a page where the licence is detailed."
msgstr "Lien vers une page détaillant la licence."
#: models.py:122
#: models.py:121
msgid "URL template using OSM tile format"
msgstr "Modèle d'URL au format des tuiles OSM"
#: models.py:128
#: models.py:127
msgid "Order of the tilelayers in the edit box"
msgstr "Ordre des calques de tuiles dans le panneau de modification"
#: models.py:176 models.py:487
#: models.py:175 models.py:479
msgid "Only editable with secret edit link"
msgstr "Modifiable seulement avec le lien de modification secret"
#: models.py:177 models.py:488
#: models.py:176 models.py:480
msgid "Everyone can edit"
msgstr "Tout le monde peut modifier"
#: models.py:180 models.py:481
#: models.py:179 models.py:473
msgid "Everyone"
msgstr "Tout le monde"
#: models.py:181 models.py:190 models.py:482
#: models.py:180 models.py:189 models.py:474
msgid "Editors and team only"
msgstr "Éditeurs et équipe seulement"
#: models.py:182 models.py:483
#: models.py:181 models.py:475
msgid "Owner only"
msgstr "Propriétaire uniquement"
#: models.py:185
#: models.py:184
msgid "Draft (private)"
msgstr "Brouillon (privé)"
#: models.py:186
#: models.py:185
msgid "Everyone (public)"
msgstr "Tout le monde (public)"
#: models.py:189
#: models.py:188
msgid "Anyone with link"
msgstr "Quiconque a le lien"
#: models.py:191
#: models.py:190
msgid "Blocked"
msgstr "Bloquée"
#: models.py:192 models.py:477
#: models.py:191 models.py:469
msgid "Deleted"
msgstr "Supprimé"
#: models.py:195
#: models.py:194
msgid "center"
msgstr "centre"
#: models.py:196
#: models.py:195
msgid "zoom"
msgstr "zoom"
#: models.py:198
#: models.py:197
msgid "locate"
msgstr "géolocaliser"
#: models.py:198
#: models.py:197
msgid "Locate user on load?"
msgstr "Géolocaliser l'utilisateur au chargement ?"
#: models.py:202
#: models.py:201
msgid "Choose the map licence."
msgstr "Choisir une licence pour la carte"
#: models.py:203
#: models.py:202
msgid "licence"
msgstr "licence"
#: models.py:214
#: models.py:213
msgid "owner"
msgstr "créateur"
#: models.py:218
#: models.py:217
msgid "editors"
msgstr "éditeurs"
#: models.py:224
#: models.py:223
msgid "team"
msgstr "équipe"
#: models.py:230 models.py:509
#: models.py:229 models.py:501
msgid "edit status"
msgstr "statut de modification"
#: models.py:235 models.py:514
#: models.py:234 models.py:506
msgid "share status"
msgstr "qui a accès"
#: models.py:238 models.py:504
#: models.py:237 models.py:496
msgid "settings"
msgstr "réglages"
#: models.py:410
#: models.py:407
msgid "Clone of"
msgstr "Clone de"
#: models.py:476 models.py:480 models.py:486
#: models.py:468 models.py:472 models.py:478
msgid "Inherit"
msgstr "Par défaut"
#: models.py:499
#: models.py:491
msgid "display on load"
msgstr "afficher au chargement."
#: models.py:500
#: models.py:492
msgid "Display this layer on load."
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
msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -502,7 +434,7 @@ msgstr "Mes équipes"
msgid "Map of the uMaps"
msgstr "La carte des uMaps"
#: templates/umap/home.html:25
#: templates/umap/home.html:24
msgid "Get inspired, browse maps"
msgstr "Naviguer dans les cartes"
@ -510,15 +442,11 @@ msgstr "Naviguer dans les cartes"
msgid "You are logged in. Continuing..."
msgstr "Vous êtes maintenant identifié. Merci de patienter..."
#: templates/umap/map_list.html:18 views.py:444
#: templates/umap/map_list.html:11 views.py:437
msgid "by"
msgstr "par"
#: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Voir la carte"
#: templates/umap/map_list.html:28
#: templates/umap/map_list.html:20
msgid "More"
msgstr "Plus"
@ -678,15 +606,11 @@ msgstr[0] "%(count)s carte trouvée:"
msgstr[1] "%(count)s cartes trouvées:"
msgstr[2] "%(count)s cartes trouvées :"
#: templates/umap/search.html:30
#: templates/umap/search.html:28
msgid "No map found."
msgstr "Aucune carte trouvée."
#: 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
#: templates/umap/search.html:33
msgid "Latest created maps"
msgstr "Dernières cartes créées."
@ -694,11 +618,7 @@ msgstr "Dernières cartes créées."
msgid "Search maps"
msgstr "Chercher des cartes"
#: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Toutes catégories"
#: templates/umap/search_bar.html:19
#: templates/umap/search_bar.html:16
msgid "Search"
msgstr "Chercher"
@ -762,70 +682,70 @@ msgstr "Membres"
msgid "New team"
msgstr "Nouvelle équipe"
#: views.py:235
#: views.py:234
msgid "Cannot delete a team with more than one member"
msgstr "Impossible de supprimer une équipe ayant plus d'un membre"
#: views.py:239
#: views.py:238
#, python-format
msgid "Team “%(name)s” has been deleted"
msgstr "L'équipe «%(name)s» a été supprimée"
#: views.py:449
#: views.py:442
msgid "View the map"
msgstr "Voir la carte"
#: views.py:845
#: views.py:838
msgid "See full screen"
msgstr "Plein écran"
#: views.py:988
#: views.py:981
msgid "Map editors updated with success!"
msgstr "Éditeurs de la carte mis à jour !"
#: views.py:1024
#: views.py:1017
#, python-format
msgid "The uMap edit link for your map: %(map_name)s"
msgstr "Le lien d'édition uMap pour votre carte : %(map_name)s"
#: views.py:1027
#: views.py:1020
#, python-format
msgid "Here is your secret edit link: %(link)s"
msgstr "Voici votre lien d'édition secret : %(link)s"
#: views.py:1034
#: views.py:1027
#, python-format
msgid "Can't send email to %(email)s"
msgstr "Impossible d'envoyer un courriel vers %(email)s"
#: views.py:1037
#: views.py:1030
#, python-format
msgid "Email sent to %(email)s"
msgstr "Courriel envoyé à %(email)s"
#: views.py:1048
#: views.py:1041
msgid "Only its owner can delete the map."
msgstr "Seul le créateur de la carte peut la supprimer."
#: views.py:1054
#: views.py:1044
msgid "Map successfully deleted."
msgstr "La carte a bien été supprimée."
#: views.py:1080
#: views.py:1070
#, python-format
msgid ""
"Your map has been cloned! If you want to edit this map from another "
"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"
#: views.py:1085
#: views.py:1075
msgid "Congratulations, your map has been cloned!"
msgstr "Votre carte a été dupliquée !"
#: views.py:1339
#: views.py:1329
msgid "Layer successfully deleted."
msgstr "Calque supprimé."
#: views.py:1361
#: views.py:1351
msgid "Permissions updated with success!"
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.
#
# Translators:
# Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2025
# Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2024
# Peter Velosy <peter.velosy@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-04 16:49+0000\n"
"POT-Creation-Date: 2024-12-24 08:39+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2025\n"
"Last-Translator: Gábor Babos <gabor.babos@gmail.com>, 2017-2019,2023-2024\n"
"Language-Team: Hungarian (http://app.transifex.com/openstreetmap/umap/language/hu/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -27,214 +27,138 @@ msgstr "CSV exportálás"
msgid "This map is not publicly available"
msgstr "Ez a térkép nem nyilvános"
#: middleware.py:19
#: middleware.py:13
msgid "Site is readonly for maintenance"
msgstr "Karbantartás miatt a webhely csak olvasható"
#: 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
#: models.py:60 models.py:79
msgid "name"
msgstr "név"
#: models.py:63 models.py:493
#: models.py:62 models.py:475
msgid "description"
msgstr "leírás"
#: models.py:111
#: models.py:110
msgid "details"
msgstr "részletek"
#: models.py:112
#: models.py:111
msgid "Link to a page where the licence is detailed."
msgstr "Link egy részletes licencinformációkat tartalmazó lapra."
#: models.py:122
#: models.py:121
msgid "URL template using OSM tile format"
msgstr "OSM-csempeformátumot használó URL-sablon"
#: models.py:128
#: models.py:127
msgid "Order of the tilelayers in the edit box"
msgstr "Csemperétegek sorrendje a szerkesztődobozban"
#: models.py:176 models.py:487
#: models.py:175 models.py:469
msgid "Only editable with secret edit link"
msgstr "Kizárólag titkos szerkesztési linkkel szerkeszthető"
#: models.py:177 models.py:488
#: models.py:176 models.py:470
msgid "Everyone can edit"
msgstr "Bárki szerkesztheti"
#: models.py:180 models.py:481
#: models.py:179 models.py:463
msgid "Everyone"
msgstr "Mindenki"
#: models.py:181 models.py:190 models.py:482
#: models.py:180 models.py:189 models.py:464
msgid "Editors and team only"
msgstr "Csak a szerkesztők és a csoport"
#: models.py:182 models.py:483
#: models.py:181 models.py:465
msgid "Owner only"
msgstr "Csak a tulajdonos"
#: models.py:185
#: models.py:184
msgid "Draft (private)"
msgstr "Piszkozat (privát)"
#: models.py:186
#: models.py:185
msgid "Everyone (public)"
msgstr "Mindenki (nyilvános)"
#: models.py:189
#: models.py:188
msgid "Anyone with link"
msgstr "A link birtokában bárki"
#: models.py:191
#: models.py:190
msgid "Blocked"
msgstr "Blokkolva"
#: models.py:192 models.py:477
#: models.py:191
msgid "Deleted"
msgstr "Törölve"
#: models.py:195
#: models.py:194
msgid "center"
msgstr "középpont"
#: models.py:196
#: models.py:195
msgid "zoom"
msgstr "nagyítás"
#: models.py:198
#: models.py:197
msgid "locate"
msgstr "helymeghatározás"
#: models.py:198
#: models.py:197
msgid "Locate user on load?"
msgstr "Bekérje a felhasználó pozícióját betöltéskor?"
#: models.py:202
#: models.py:201
msgid "Choose the map licence."
msgstr "Térképlicenc kiválasztása"
#: models.py:203
#: models.py:202
msgid "licence"
msgstr "licenc"
#: models.py:214
#: models.py:213
msgid "owner"
msgstr "tulajdonos"
#: models.py:218
#: models.py:217
msgid "editors"
msgstr "szerkesztők"
#: models.py:224
#: models.py:223
msgid "team"
msgstr "csoport"
#: models.py:230 models.py:509
#: models.py:229 models.py:491
msgid "edit status"
msgstr "szerkeszthetőség"
#: models.py:235 models.py:514
#: models.py:234
msgid "share status"
msgstr "megoszthatóság"
#: models.py:238 models.py:504
#: models.py:237 models.py:486
msgid "settings"
msgstr "beállítások"
#: models.py:410
#: models.py:402
msgid "Clone of"
msgstr "Másolat erről: "
#: models.py:476 models.py:480 models.py:486
#: models.py:462 models.py:468
msgid "Inherit"
msgstr "Öröklés"
#: models.py:499
#: models.py:481
msgid "display on load"
msgstr "megjelenítés betöltéskor"
#: models.py:500
#: models.py:482
msgid "Display this layer on load."
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
msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -250,54 +174,40 @@ msgstr "← Ugrás a főoldalra"
msgid "404 Page Not Found"
msgstr "404 hiba: ez az oldal nem található. Eltévedtél a térképek között"
#: 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
#: templates/auth/user_detail.html:8
#, python-format
msgid "Browse %(current_user)s's maps"
msgstr "%(current_user)s térképeinek böngészése"
#: templates/auth/user_detail.html:21
#: templates/auth/user_detail.html:17
#, python-format
msgid "%(current_user)s has no maps."
msgstr "%(current_user)s felhasználónak nincs térképe."
#: templates/auth/user_form.html:6
msgid "My Profile"
msgstr "Profilom"
#: templates/auth/user_form.html:24 templates/umap/team_form.html:25
#: templates/auth/user_form.html:21 templates/umap/team_form.html:21
msgid "Save"
msgstr "Mentés"
#: templates/auth/user_form.html:30
#: templates/auth/user_form.html:27
msgid "Your current providers"
msgstr "Jelenlegi szolgáltatói"
#: templates/auth/user_form.html:44
#: templates/auth/user_form.html:39
msgid "Connect to another provider"
msgstr "Újabb szolgáltató csatlakoztatása"
#: templates/auth/user_form.html:47
#: templates/auth/user_form.html:42
msgid ""
"It's a good habit to connect your account to more than one provider, in case"
" 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."
#: 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
#: templates/auth/user_stars.html:8
#, python-format
msgid "Browse %(current_user)s's starred maps"
msgstr "%(current_user)s megcsillagozott térképeinek böngészése"
#: templates/auth/user_stars.html:21
#: templates/auth/user_stars.html:17
#, python-format
msgid "%(current_user)s has no starred maps yet."
msgstr "%(current_user)s felhasználónak még nincs megcsillagozott térképe."
@ -332,10 +242,6 @@ msgstr "Jelszó"
msgid "Please choose a provider:"
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
#, python-format
msgid ""
@ -477,7 +383,7 @@ msgstr "Térképeim"
#: templates/umap/dashboard_menu.html:12
msgid "My profile"
msgstr "Profilom"
msgstr "Saját profil"
#: templates/umap/dashboard_menu.html:15
msgid "My teams"
@ -487,7 +393,7 @@ msgstr "Csoportjaim"
msgid "Map of the uMaps"
msgstr "uMap-térképek térképe"
#: templates/umap/home.html:25
#: templates/umap/home.html:24
msgid "Get inspired, browse maps"
msgstr "Szerezzen ihletet, böngésszen a térképek között!"
@ -495,19 +401,15 @@ msgstr "Szerezzen ihletet, böngésszen a térképek között!"
msgid "You are logged in. Continuing..."
msgstr "Be van jelentkezve. Továbblépés…"
#: templates/umap/map_list.html:18 views.py:444
#: templates/umap/map_list.html:11 views.py:437
msgid "by"
msgstr " készítette:"
#: templates/umap/map_list.html:22
msgid "See the map"
msgstr ""
#: templates/umap/map_list.html:28
#: templates/umap/map_list.html:20
msgid "More"
msgstr "Még több"
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:18
#: templates/umap/map_table.html:8 templates/umap/user_teams.html:14
msgid "Name"
msgstr "Név"
@ -531,7 +433,7 @@ msgstr "Utolsó mentés"
msgid "Owner"
msgstr "Tulajdonos"
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:24
#: templates/umap/map_table.html:26 templates/umap/user_teams.html:20
msgid "Actions"
msgstr "Műveletek"
@ -544,7 +446,7 @@ msgid "Share"
msgstr "Megosztás"
#: templates/umap/map_table.html:78 templates/umap/map_table.html:80
#: templates/umap/user_teams.html:42 templates/umap/user_teams.html:44
#: templates/umap/user_teams.html:38 templates/umap/user_teams.html:40
msgid "Edit"
msgstr "Szerkesztés"
@ -607,6 +509,10 @@ msgstr "Bejelentkezés"
msgid "Sign in"
msgstr "Regisztráció"
#: templates/umap/navigation.html:22
msgid "About"
msgstr "Névjegy"
#: templates/umap/navigation.html:30
msgid "Change password"
msgstr "Jelszó módosítása"
@ -615,58 +521,52 @@ msgstr "Jelszó módosítása"
msgid "Log out"
msgstr "Kijelentkezés"
#: templates/umap/password_change.html:6
#: templates/umap/password_change.html:11
#: templates/umap/password_change.html:7
msgid "Password change"
msgstr "Jelszó módosítása"
#: templates/umap/password_change.html:14
#: templates/umap/password_change.html:10
msgid ""
"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."
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:21
#: templates/umap/password_change.html:17
msgid "Old password"
msgstr "Régi jelszó"
#: templates/umap/password_change.html:26
#: templates/umap/password_change.html:22
msgid "New password"
msgstr "Új jelszó"
#: templates/umap/password_change.html:30
#: templates/umap/password_change.html:26
msgid "New password confirmation"
msgstr "Új jelszó ismét"
#: templates/umap/password_change.html:31
#: templates/umap/password_change.html:27
msgid "Change my password"
msgstr "Jelszavam módosítása"
#: templates/umap/password_change_done.html:6
#: templates/umap/password_change_done.html:11
#: templates/umap/password_change_done.html:7
msgid "Password change successful"
msgstr "A jelszómódosítás sikeres"
#: templates/umap/password_change_done.html:14
#: templates/umap/password_change_done.html:10
msgid "Your password was changed."
msgstr "A jelszava megváltozott."
#: templates/umap/search.html:6
msgid "Explore maps"
msgstr "Térképek felfedezése"
#: templates/umap/search.html:19
#: templates/umap/search.html:15
#, python-format
msgid "%(count)s map found:"
msgid_plural "%(count)s maps found:"
msgstr[0] "%(count)s térképet találtunk:"
msgstr[1] "%(count)s térképet találtunk:"
#: templates/umap/search.html:30
#: templates/umap/search.html:24
msgid "No map found."
msgstr "Nem található ilyen térkép."
#: templates/umap/search.html:35
#: templates/umap/search.html:29
msgid "Latest created maps"
msgstr "Legutóbb létrehozott térképek"
@ -674,42 +574,25 @@ msgstr "Legutóbb létrehozott térképek"
msgid "Search maps"
msgstr "Térképek keresése"
#: templates/umap/search_bar.html:14
msgid "Any category"
msgstr ""
#: templates/umap/search_bar.html:19
#: templates/umap/search_bar.html:15
msgid "Search"
msgstr "Keresés"
#: 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
#: templates/umap/team_detail.html:10
#, python-format
msgid "Browse %(current_team)s's maps"
msgstr "%(current_team)s csoport térképeinek böngészése"
#: templates/umap/team_detail.html:26
#: templates/umap/team_detail.html:22
#, python-format
msgid "%(current_team)s has no public maps."
msgstr "%(current_team)s csoportnak nincs nyilvános térképe."
#: 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
#: templates/umap/team_form.html:24
msgid "Delete this team"
msgstr "Csoport törlése"
#: templates/umap/team_form.html:51
#: templates/umap/team_form.html:47
msgid "Add user"
msgstr "Felhasználó hozzáadása"
@ -730,82 +613,78 @@ msgstr "%(count)s térkép letöltése"
msgid "You have no map yet."
msgstr "Önnek még nincs térképe."
#: templates/umap/user_teams.html:6
msgid "My Teams"
msgstr "Csoportjaim"
#: templates/umap/user_teams.html:21
#: templates/umap/user_teams.html:17
msgid "Users"
msgstr "Felhasználók"
#: templates/umap/user_teams.html:52
#: templates/umap/user_teams.html:48
msgid "New team"
msgstr "Új csoport"
#: views.py:235
#: views.py:234
msgid "Cannot delete a team with more than one member"
msgstr "Egynél több tagú csoport nem törölhető"
#: views.py:239
#: views.py:238
#, python-format
msgid "Team “%(name)s” has been deleted"
msgstr "%(name)s csoport törölve"
#: views.py:449
#: views.py:442
msgid "View the map"
msgstr "Térkép megtekintése"
#: views.py:845
#: views.py:825
msgid "See full screen"
msgstr "Teljes képernyős nézet megtekintése"
#: views.py:988
#: views.py:968
msgid "Map editors updated with success!"
msgstr "A térképszerkesztők sikeresen frissültek."
#: views.py:1024
#: views.py:1004
#, python-format
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"
#: views.py:1027
#: views.py:1007
#, python-format
msgid "Here is your secret edit link: %(link)s"
msgstr "Az Ön titkos szerkesztési linkje: %(link)s"
#: views.py:1034
#: views.py:1014
#, python-format
msgid "Can't send email to %(email)s"
msgstr "Nem sikerül e-mailt küldeni ide: %(email)s"
#: views.py:1037
#: views.py:1017
#, python-format
msgid "Email sent to %(email)s"
msgstr "E-mail elküldve ide: %(email)s"
#: views.py:1048
#: views.py:1028
msgid "Only its owner can delete the map."
msgstr "A térképet csak a tulajdonosa törölheti."
#: views.py:1051
#: views.py:1031
msgid "Map successfully deleted."
msgstr "Térkép sikeresen törölve."
#: views.py:1077
#: views.py:1057
#, python-format
msgid ""
"Your map has been cloned! If you want to edit this map from another "
"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"
#: views.py:1082
#: views.py:1062
msgid "Congratulations, your map has been cloned!"
msgstr "Gratulálunk, elkészült a térképe másolata!"
#: views.py:1336
#: views.py:1313
msgid "Layer successfully deleted."
msgstr "A réteg sikeresen törlődött."
#: views.py:1358
#: views.py:1335
msgid "Permissions updated with success!"
msgstr "Az engedélyek sikeresen frissültek!"

Binary file not shown.

View file

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

Binary file not shown.

View file

@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: uMap\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-11 15:30+0000\n"
"POT-Creation-Date: 2025-03-03 17:36+0000\n"
"PO-Revision-Date: 2013-11-22 14:00+0000\n"
"Last-Translator: Gideon van Melle <translations@gvmelle.com>, 2025\n"
"Language-Team: Dutch (http://app.transifex.com/openstreetmap/umap/language/nl/)\n"
@ -38,205 +38,137 @@ msgstr "Site is 'alleen lezen' wegens onderhoud"
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 "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."
" and maps."
msgstr ""
#: models.py:61 models.py:80
#: models.py:60 models.py:79
msgid "name"
msgstr "naam"
#: models.py:63 models.py:493
#: models.py:62 models.py:485
msgid "description"
msgstr "omschrijving"
#: models.py:111
#: models.py:110
msgid "details"
msgstr "details"
#: models.py:112
#: models.py:111
msgid "Link to a page where the licence is detailed."
msgstr "Link naar pagina waar de licentie details staan"
#: models.py:122
#: models.py:121
msgid "URL template using OSM tile format"
msgstr "URL-sjabloon met OSM tegel-formaat"
#: models.py:128
#: models.py:127
msgid "Order of the tilelayers in the edit box"
msgstr "Volgorde van de tegel-lagen in het bewerkingsvak."
#: models.py:176 models.py:487
#: models.py:175 models.py:479
msgid "Only editable with secret edit link"
msgstr "Alleen te bewerken met een geheime link"
#: models.py:177 models.py:488
#: models.py:176 models.py:480
msgid "Everyone can edit"
msgstr "Iedereen kan wijzigingen maken"
#: models.py:180 models.py:481
#: models.py:179 models.py:473
msgid "Everyone"
msgstr "Iedereen"
#: models.py:181 models.py:190 models.py:482
#: models.py:180 models.py:189 models.py:474
msgid "Editors and team only"
msgstr "Alleen redacteuren en team"
#: models.py:182 models.py:483
#: models.py:181 models.py:475
msgid "Owner only"
msgstr "Alleen eigenaar"
#: models.py:185
#: models.py:184
msgid "Draft (private)"
msgstr "Ontwerp (privé)"
#: models.py:186
#: models.py:185
msgid "Everyone (public)"
msgstr "Iedereen (openbaar)"
#: models.py:189
#: models.py:188
msgid "Anyone with link"
msgstr "Iedereen met een link"
#: models.py:191
#: models.py:190
msgid "Blocked"
msgstr "geblokkeerd"
#: models.py:192 models.py:477
#: models.py:191 models.py:469
msgid "Deleted"
msgstr "Verwijderd"
#: models.py:195
#: models.py:194
msgid "center"
msgstr "centreer"
#: models.py:196
#: models.py:195
msgid "zoom"
msgstr "zoom"
#: models.py:198
#: models.py:197
msgid "locate"
msgstr "zoek"
#: models.py:198
#: models.py:197
msgid "Locate user on load?"
msgstr "Gebruiker zoeken tijdens laden?"
#: models.py:202
#: models.py:201
msgid "Choose the map licence."
msgstr "Kies de kaartlicentie"
#: models.py:203
#: models.py:202
msgid "licence"
msgstr "Licentie"
#: models.py:214
#: models.py:213
msgid "owner"
msgstr "eigenaar"
#: models.py:218
#: models.py:217
msgid "editors"
msgstr "editors"
#: models.py:224
#: models.py:223
msgid "team"
msgstr "team"
#: models.py:230 models.py:509
#: models.py:229 models.py:501
msgid "edit status"
msgstr "wijzig status"
#: models.py:235 models.py:514
#: models.py:234 models.py:506
msgid "share status"
msgstr "deel status"
#: models.py:238 models.py:504
#: models.py:237 models.py:496
msgid "settings"
msgstr "instellingen"
#: models.py:410
#: models.py:407
msgid "Clone of"
msgstr "Kopie van"
#: models.py:476 models.py:480 models.py:486
#: models.py:468 models.py:472 models.py:478
msgid "Inherit"
msgstr "overerven"
#: models.py:499
#: models.py:491
msgid "display on load"
msgstr "toon tijdens laden"
#: models.py:500
#: models.py:492
msgid "Display this layer on load."
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
msgid ""
"<a href=\"https://discover.umap-project.org/support/faq/#map-statuses\" "
@ -489,7 +421,7 @@ msgstr "Mijn teams"
msgid "Map of the uMaps"
msgstr "Kaart van de uMaps"
#: templates/umap/home.html:25
#: templates/umap/home.html:24
msgid "Get inspired, browse maps"
msgstr "Laat u inspireren, blader door kaarten"
@ -497,15 +429,11 @@ msgstr "Laat u inspireren, blader door kaarten"
msgid "You are logged in. Continuing..."
msgstr "U bent ingelogd. Ga verder..."
#: templates/umap/map_list.html:18 views.py:444
#: templates/umap/map_list.html:11 views.py:437
msgid "by"
msgstr "door"
#: templates/umap/map_list.html:22
msgid "See the map"
msgstr "Zie de kaart"
#: templates/umap/map_list.html:28
#: templates/umap/map_list.html:20
msgid "More"
msgstr "Meer"
@ -664,15 +592,11 @@ msgid_plural "%(count)s maps found:"
msgstr[0] "%(count)s kaarten gevonden:"
msgstr[1] "%(count)s kaarten gevonden:"
#: templates/umap/search.html:30
#: templates/umap/search.html:28
msgid "No map found."
msgstr "Geen kaart gevonden."
#: templates/umap/search.html:36
msgid "Latest created maps in category"
msgstr "Laatst gemaakte kaarten in categorie"
#: templates/umap/search.html:43
#: templates/umap/search.html:33
msgid "Latest created maps"
msgstr "Laatste gemaakte kaarten"
@ -680,11 +604,7 @@ msgstr "Laatste gemaakte kaarten"
msgid "Search maps"
msgstr "Zoek kaarten"
#: templates/umap/search_bar.html:14
msgid "Any category"
msgstr "Elke categorie"
#: templates/umap/search_bar.html:19
#: templates/umap/search_bar.html:16
msgid "Search"
msgstr "Zoeken"
@ -748,70 +668,70 @@ msgstr "Gebruikers"
msgid "New team"
msgstr "Nieuw Team"
#: views.py:235
#: views.py:234
msgid "Cannot delete a team with more than one member"
msgstr "Kan een team met meer dan één lid niet verwijderen"
#: views.py:239
#: views.py:238
#, python-format
msgid "Team “%(name)s” has been deleted"
msgstr "Team “%(name)s” is verwijderd"
#: views.py:449
#: views.py:442
msgid "View the map"
msgstr "Bekijk de kaart"
#: views.py:845
#: views.py:838
msgid "See full screen"
msgstr "Volledig scherm weergeven"
#: views.py:988
#: views.py:981
msgid "Map editors updated with success!"
msgstr "Kaarteditors met succes bijgewerkt!"
#: views.py:1024
#: views.py:1017
#, python-format
msgid "The uMap edit link for your map: %(map_name)s"
msgstr "De uMap-bewerkingslink voor uw kaart: %(map_name)s"
#: views.py:1027
#: views.py:1020
#, python-format
msgid "Here is your secret edit link: %(link)s"
msgstr "Hier is je geheime bewerkingslink: %(link)s"
#: views.py:1034
#: views.py:1027
#, python-format
msgid "Can't send email to %(email)s"
msgstr "Kan geen e-mail verzenden naar %(email)s"
#: views.py:1037
#: views.py:1030
#, python-format
msgid "Email sent to %(email)s"
msgstr "E-mail verzonden naar %(email)s"
#: views.py:1048
#: views.py:1041
msgid "Only its owner can delete the map."
msgstr "Kaart kan alleen door eigenaar worden verwijderd."
#: views.py:1054
#: views.py:1044
msgid "Map successfully deleted."
msgstr "Kaart succesvol verwijderd."
#: views.py:1080
#: views.py:1070
#, python-format
msgid ""
"Your map has been cloned! If you want to edit this map from another "
"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"
#: views.py:1085
#: views.py:1075
msgid "Congratulations, your map has been cloned!"
msgstr "Gefeliciteerd, uw kaart is gekopieerd!"
#: views.py:1339
#: views.py:1329
msgid "Layer successfully deleted."
msgstr "Laag is verwijderd."
#: views.py:1361
#: views.py:1351
msgid "Permissions updated with success!"
msgstr "Machtigingen met succes bijgewerkt!"

View file

@ -34,8 +34,7 @@ def deprecated_auth_backend(get_response):
"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."
"to your account and maps."
)
% {"name": name},
)

View file

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

View file

@ -6,7 +6,6 @@ from email.utils import parseaddr
import environ
from django.conf.locale import LANG_INFO
from django.utils.translation import gettext_lazy as _
import umap as project_module
@ -19,7 +18,6 @@ env = environ.Env()
INTERNAL_IPS = env.list("INTERNAL_IPS", default=["127.0.0.1"])
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=[]))
ASGI_APPLICATION = "umap.asgi.application"
@ -165,8 +163,8 @@ LOGIN_REDIRECT_URL = "login_popup_end"
STATIC_URL = "/static/"
MEDIA_URL = "/uploads/"
STATIC_ROOT = env("STATIC_ROOT", default=os.path.join("static"))
MEDIA_ROOT = env("MEDIA_ROOT", default=os.path.join("uploads"))
STATIC_ROOT = os.path.join("static")
MEDIA_ROOT = os.path.join("uploads")
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
@ -292,25 +290,6 @@ UMAP_HOME_FEED = "latest"
UMAP_IMPORTERS = {}
UMAP_HOST_INFOS = {}
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_GZIP = True
@ -361,8 +340,10 @@ LOGGING = {
},
}
# Real-time editing configuration
# WebSocket configuration
REALTIME_ENABLED = env.bool("REALTIME_ENABLED", default=False)
WEBSOCKET_ENABLED = env.bool("WEBSOCKET_ENABLED", default=False)
WEBSOCKET_BACK_HOST = env("WEBSOCKET_BACK_HOST", default="localhost")
WEBSOCKET_BACK_PORT = env.int("WEBSOCKET_BACK_PORT", default=8001)
REDIS_URL = env("REDIS_URL", default="redis://localhost:6379")
REDIS_URL = "redis://localhost:6379"

View file

@ -3,7 +3,9 @@
*/
body, div, ul, ol, li, a, section, nav,
h1, h2, h3, h4, h5, h6, label,
hr, input, textarea, select {
hr, input, textarea {
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
@ -17,11 +19,7 @@ h1, h2, h3, h4, h5, h6, label, hr {
}
a {
text-decoration: none;
color: var(--link-color);
}
a.main {
font-weight: bold;
text-decoration: underline;
color: #1F5C39;
}
a[href^="http"]:not(nav.umap-nav a) {
text-decoration: underline;
@ -83,12 +81,10 @@ hgroup > * {
hgroup {
margin-bottom: var(--box-margin);
}
hgroup p,
hgroup button {
margin: 0;
hgroup > :not(:first-child):last-child {
font-weight: normal;
}
/*
* List
*/
@ -162,23 +158,10 @@ dt {
}
.grid-container {
display: grid;
--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-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-container.by4 {
--grid-column-count: 4;
--grid-item--min-width: 60px;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-container > * {
text-align: center;
@ -201,10 +184,6 @@ dt {
/* Various */
/* *********** */
.nobr {
white-space: nowrap;
}
.text {
word-break: break-word;
white-space: pre-line;
@ -223,19 +202,3 @@ dt {
height: 100vh;
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,21 +16,6 @@ input::-webkit-input-placeholder, ::-webkit-input-placeholder {
input:-moz-placeholder, :-moz-placeholder {
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;
}
/* **************** */
@ -71,12 +56,30 @@ body.login header {
.map_fragment {
width: 100%;
}
.map_fragment,
.map_list .map_fragment,
.demo_map .map_fragment {
height: var(--map-fragment-height);
height: 210px;
}
.grid-container hgroup {
text-align: left;
.map_list .legend {
padding-top: 7px;
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 {
margin-top: 14px;
@ -161,59 +164,13 @@ h2.tabs a:hover {
color: #efefef;
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 */
/* **************************** */
input[type="submit"],
.button {
background-color: var(--button-primary-background);
color: var(--button-primary-color);
@ -405,9 +362,22 @@ html[dir="rtl"] .content .icon-delete {
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"] {
width: 30ch;
}
.table-header form input[type="submit"] {
background-color: var(--color-darkBlue);
color: white;
font-weight: bold;
}
.table-header .button-download {
width: inherit;
@ -568,9 +538,4 @@ dialog::backdrop {
.mhide {
display: none;
}
.flex-break {
flex-direction: column;
align-items: center;
}
}

View file

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

View file

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

View file

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

View file

@ -55,10 +55,3 @@
.importers ul .datasets:before {
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,16 +59,3 @@
.tooltip-accent li:last-of-type {
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="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#">
<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#">
<defs id="defs4">
<clipPath id="clip0_241_10857">
<rect id="rect586" width="18.05" height="19.01" fill="#fff"/>
@ -15,12 +15,6 @@
<clipPath id="clip0_2695_1939">
<rect id="rect1" width="20" height="20" fill="#fff"/>
</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>
<metadata id="metadata7">
<rdf:RDF>
@ -70,12 +64,9 @@
</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"/>
<g id="g4244" transform="matrix(.51357 -.54309 .54309 .51357 -590.02 601.73)">
<g id="g4244" transform="matrix(.51357 -.54309 .54309 .51357 -518.02 506.23)">
<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 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)">
<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"/>
@ -149,10 +140,6 @@
<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"/>
</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">
<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"/>
@ -202,7 +189,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="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="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"/>
<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"/>
<g id="g1-5" transform="translate(.1 .1)">
<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"/>
@ -223,13 +210,5 @@
</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="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>
</svg>

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -62,6 +62,5 @@
</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="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>
</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>
</g>
<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.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.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"/>
<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="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"/>
</g>
<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="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="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"/>
<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"/>
<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"/>
<g id="share" class="sprite" transform="matrix(.26458 0 0 .26458 -21.696 -210.18)">
<g id="share" class="sprite" transform="matrix(.26458 0 0 .26458 -2.6458 -229.23)">
<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-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"/>
</g>
<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.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="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="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 id="multipolygon" class="sprite" transform="matrix(.26458 0 0 .26458 66.121 -220.76)" fill="#4d4d4d">
@ -97,6 +97,5 @@
<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>
<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>
</svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -1,7 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1,3 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15">
<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"/>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<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>

Before

Width:  |  Height:  |  Size: 199 B

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<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/">
<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/">
<defs id="defs4">
<clipPath id="clip0_241_10857">
<rect width="18.049999" height="19.01" fill="#ffffff" id="rect586" x="0" y="0" />
@ -18,14 +18,8 @@
<clipPath id="clip0_2695_1939">
<rect width="20" height="20" fill="#ffffff" id="rect1" x="0" y="0" />
</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>
<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">
<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">
<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" />
</sodipodi:namedview>
@ -81,12 +75,9 @@
</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" />
<g id="g4244" transform="matrix(0.51357238,-0.54309229,0.54309229,0.51357238,-590.0195,601.72586)">
<g id="g4244" transform="matrix(0.51357238,-0.54309229,0.54309229,0.51357238,-518.0199,506.22551)">
<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 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)">
<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" />
@ -160,10 +151,6 @@
<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" />
</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)">
<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" />
@ -213,7 +200,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 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 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" />
<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" />
<g id="g1-5" transform="translate(0.1,0.1)">
<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" />
@ -234,13 +221,5 @@
</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: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>
</svg>

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 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.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="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">
<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">
<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">
<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" />
</sodipodi:namedview>
@ -77,6 +77,5 @@
<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 " />
<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>
</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"?>
<!-- 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.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="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">
<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">
<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">
<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" />
</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>
</g>
<g id="markers" transform="matrix(0.26458333,0,0,0.26458333,42.862499,-225.92402)" class="sprite">
<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.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" />
<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 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" />
</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.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" 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" 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" />
<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" />
<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" />
<g id="share" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,-21.695832,-210.17502)">
<g id="share" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,-2.6458336,-229.22505)">
<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-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" />
</g>
<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.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 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 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 id="multipolygon" class="sprite" transform="matrix(0.26458333,0,0,0.26458333,66.121027,-220.75833)">
@ -77,7 +77,7 @@
</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: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.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" />
<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" />
<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" />
<g mask="url(#mask0_181_11898)" id="g2376" transform="matrix(0.26458333,0,0,0.26458333,20.637501,1.8520833)">
@ -110,6 +110,5 @@
<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>
<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>
</svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,25 +1,26 @@
// FIXME: this module should not depend on Leaflet
import {
DomEvent,
DomUtil,
GeoJSON,
DomEvent,
stamp,
GeoJSON,
} 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 {
uMapAlert as Alert,
uMapAlertConflict as AlertConflict,
} from '../../components/alerts/alert.js'
import { MutatingForm } from '../form/builder.js'
import { translate } from '../i18n.js'
import { DataLayerPermissions } from '../permissions.js'
import { Default as DefaultLayer } from '../rendering/layers/base.js'
import { Categorized, Choropleth, Circles } from '../rendering/layers/classified.js'
import { Cluster } from '../rendering/layers/cluster.js'
import { Heat } from '../rendering/layers/heat.js'
import * as Schema from '../schema.js'
import { Point, LineString, Polygon } from './features.js'
import TableEditor from '../tableeditor.js'
import * as Utils from '../utils.js'
import { LineString, Point, Polygon } from './features.js'
import { ServerStored } from '../saving.js'
import * as Schema from '../schema.js'
import { MutatingForm } from '../form/builder.js'
export const LAYER_TYPES = [
DefaultLayer,
@ -35,8 +36,9 @@ const LAYER_MAP = LAYER_TYPES.reduce((acc, klass) => {
return acc
}, {})
export class DataLayer {
export class DataLayer extends ServerStored {
constructor(umap, leafletMap, data = {}) {
super()
this._umap = umap
this.sync = umap.syncEngine.proxy(this)
this._index = Array()
@ -47,6 +49,7 @@ export class DataLayer {
this._leafletMap = leafletMap
this.parentPane = this._leafletMap.getPane('overlayPane')
this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane)
this.pane.dataset.id = stamp(this)
// FIXME: should be on layer
this.renderer = L.svg({ pane: this.pane })
this.defaultOptions = {
@ -63,10 +66,6 @@ export class DataLayer {
data.id = data.id || crypto.randomUUID()
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)) {
this.options.remoteData = {}
@ -84,7 +83,7 @@ export class DataLayer {
this.connectToMap()
this.permissions = new DataLayerPermissions(this._umap, this)
this._needsFetch = this.createdOnServer || this.isRemoteLayer()
this._needsFetch = this.createdOnServer
if (!this.createdOnServer) {
if (this.showAtLoad()) this.show()
}
@ -115,6 +114,7 @@ export class DataLayer {
set isDeleted(status) {
this._isDeleted = status
if (status) this.isDirty = status
}
get isDeleted() {
@ -125,20 +125,6 @@ export class DataLayer {
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() {
return {
subject: 'datalayer',
@ -147,10 +133,6 @@ export class DataLayer {
}
render(fields, builder) {
// Propagate will remove the fields it has already
// processed
fields = this.propagate(fields)
const impacts = Utils.getImpactsFromSchema(fields)
for (const impact of impacts) {
@ -162,44 +144,19 @@ export class DataLayer {
if (fields.includes('options.type')) {
this.resetLayer()
}
this.hide()
for (const field of fields) {
this.layer.onEdit(field, builder)
}
this.redraw()
this.show()
break
case 'remote-data':
this.fetchRemoteData()
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() {
return this.autoLoaded() && this.showAtZoom()
}
@ -267,11 +224,17 @@ export class DataLayer {
this._loading = true
const [geojson, response, error] = await this._umap.server.get(this._dataUrl())
if (!error) {
this._umap.modifiedAt = response.headers.get('last-modified')
this.setReferenceVersion({ response, sync: false })
delete geojson._umap_options
// FIXME: for now the _umap_options property is set dynamically from backend
// 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
delete geojson._storage
if (geojson._storage) geojson._storage.editMode = this.options.editMode
await this.fromUmapGeoJSON(geojson)
this.backupOptions()
this._loading = false
@ -300,12 +263,21 @@ export class DataLayer {
async fromUmapGeoJSON(geojson) {
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 (this.isRemoteLayer()) {
await this.fetchRemoteData()
} else {
this.fromGeoJSON(geojson, false)
if (this.isRemoteLayer()) 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() {
@ -334,10 +306,7 @@ export class DataLayer {
async getUrl(url, initialUrl) {
const response = await this._umap.request.get(url)
return new Promise((resolve) => {
if (response?.ok) {
this._umap.modifiedAt = response.headers.get('last-modified')
return resolve(response.text())
}
if (response?.ok) return resolve(response.text())
Alert.error(
translate('Cannot load remote data for layer "{layer}" with url "{url}"', {
layer: this.getName(),
@ -358,12 +327,11 @@ export class DataLayer {
url = this._umap.proxyUrl(url, this.options.remoteData.ttl)
}
return await this.getUrl(url, remoteUrl).then((raw) => {
this.clear(false)
this.clear()
return this._umap.formatter
.parse(raw, this.options.remoteData.format)
.then((geojson) => this.fromGeoJSON(geojson, false))
.then((geojson) => this.fromGeoJSON(geojson))
.catch((error) => {
console.debug(error)
Alert.error(
translate('Cannot parse remote data for layer "{layer}" with url "{url}"', {
layer: this.getName(),
@ -398,7 +366,13 @@ export class DataLayer {
}
connectToMap() {
this._umap.datalayers.add(this)
const id = stamp(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()
}
@ -443,14 +417,7 @@ export class DataLayer {
removeFeature(feature, sync) {
const id = stamp(feature)
// 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)
}
if (sync !== false) feature.sync.delete()
this.hideFeature(feature)
delete this._umap.featuresIndex[feature.getSlug()]
feature.disconnectFromDataLayer(this)
@ -517,19 +484,8 @@ export class DataLayer {
const features = []
this.sortFeatures(collection)
for (const featureJson of collection) {
if (featureJson.geometry?.type === 'GeometryCollection') {
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)
}
const feature = this.makeFeature(featureJson, sync)
if (feature) features.push(feature)
}
return features
}
@ -562,7 +518,7 @@ export class DataLayer {
}
if (feature && !feature.isEmpty()) {
this.addFeature(feature)
if (sync) feature.sync.upsert(feature.toGeoJSON(), null)
if (sync) feature.onCommit()
return feature
}
}
@ -570,14 +526,12 @@ export class DataLayer {
async importRaw(raw, format) {
return this._umap.formatter
.parse(raw, format)
.then((geojson) => {
this.sync.startBatch()
const data = this.addData(geojson)
this.sync.commitBatch()
.then((geojson) => this.addData(geojson))
.then((data) => {
if (data?.length) this.isDirty = true
return data
})
.catch((error) => {
console.debug(error)
Alert.error(translate('Import failed: invalid data'))
})
}
@ -641,34 +595,17 @@ export class DataLayer {
}
del(sync = true) {
const oldValue = Utils.CopyJSON(this.umapGeoJSON())
// TODO merge datalayer del and features del in same
// batch
this.clear()
this.erase()
if (sync) {
this.isDeleted = true
this.sync.delete(oldValue)
this.sync.delete()
}
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() {
if (this.isRemoteLayer()) return
this.sync.startBatch()
this.clear()
this.sync.commitBatch()
}
clear(sync = true) {
for (const feature of Object.values(this._features)) {
feature.del(sync)
}
this.dataChanged()
this.isDirty = true
}
clone() {
@ -681,13 +618,44 @@ export class 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() {
if (!this.isVisible()) return
this.eachFeature((feature) => feature.redraw())
this.hide()
this.show()
}
edit() {
if (!this._umap.editEnabled) {
if (!this._umap.editEnabled || !this.isLoaded()) {
return
}
const container = DomUtil.create('div', 'umap-layer-properties-container')
@ -863,9 +831,8 @@ export class DataLayer {
this
)
if (this._umap.properties.urls.datalayer_versions) {
if (this._umap.properties.urls.datalayer_versions)
this.buildVersionsFieldset(container)
}
const advancedActions = DomUtil.createFieldset(
container,
@ -940,15 +907,10 @@ export class DataLayer {
const appendVersion = (data) => {
const date = new Date(Number.parseInt(data.at, 10))
const content = `${date.toLocaleString(U.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
const [el, { button }] = Utils.loadTemplateWithRefs(
`<div class="umap-datalayer-version">
<button type="button" title="${translate('Restore this version')}" data-ref=button>
<i class="icon icon-16 icon-restore"></i> ${content}
</button>
</div>`
)
versionsContainer.appendChild(el)
button.addEventListener('click', () => this.restore(data.ref))
const el = DomUtil.create('div', 'umap-datalayer-version', versionsContainer)
const button = DomUtil.createButton('', el, '', () => this.restore(data.ref))
button.title = translate('Restore this version')
DomUtil.add('span', '', el, content)
}
const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), {
@ -972,19 +934,11 @@ export class DataLayer {
)
if (!error) {
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat.
if (geojson._umap_options) {
const oldOptions = Utils.CopyJSON(this.options)
this.setOptions(geojson._umap_options)
this.sync.update('options', this.options, oldOptions)
}
if (geojson._umap_options) this.setOptions(geojson._umap_options)
this.empty()
if (this.isRemoteLayer()) {
this.fetchRemoteData()
} else {
this.sync.startBatch()
this.addData(geojson)
this.sync.commitBatch()
}
if (this.isRemoteLayer()) this.fetchRemoteData()
else this.addData(geojson)
this.isDirty = true
}
})
}
@ -1006,18 +960,12 @@ export class DataLayer {
this.propagateHide()
}
toggle(force) {
toggle() {
// From now on, do not try to how/hidedataChanged
// automatically this layer.
let display = force
this._forcedVisibility = true
if (force === undefined) {
if (!this.isVisible()) display = true
else display = false
}
if (display) this.show()
if (!this.isVisible()) this.show()
else this.hide()
this._umap.bottomBar.redraw()
}
zoomTo() {
@ -1095,11 +1043,23 @@ export class DataLayer {
}
getPreviousBrowsable() {
return this._umap.datalayers.prev(this)
let id = this.getRank()
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() {
return this._umap.datalayers.next(this)
let id = this.getRank()
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() {
@ -1110,8 +1070,8 @@ export class DataLayer {
}
}
getDOMOrder() {
return Array.from(this.parentPane.children).indexOf(this.pane)
getRank() {
return this._umap.datalayersIndex.indexOf(this)
}
isReadOnly() {
@ -1126,28 +1086,18 @@ export class DataLayer {
setReferenceVersion({ response, sync }) {
this._referenceVersion = response.headers.get('X-Datalayer-Version')
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)
if (sync) this.sync.update('_referenceVersion', this._referenceVersion)
}
async save() {
if (this.isDeleted) return await this.saveDelete()
if (!this.isRemoteLayer() && !this.isLoaded()) return
if (!this.isLoaded()) return
const geojson = this.umapGeoJSON()
const formData = new FormData()
formData.append('name', this.options.name)
formData.append('display_on_load', !!this.options.displayOnLoad)
formData.append('rank', this.rank)
formData.append('settings', this.prepareOptions())
formData.append('rank', this.getRank())
formData.append('settings', JSON.stringify(this.options))
// Filename support is shaky, don't do it for now.
const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' })
formData.append('geojson', blob)
@ -1165,10 +1115,6 @@ export class DataLayer {
}
async _trySave(url, headers, formData) {
if (this._forceSave) {
headers = {}
this._forceSave = false
}
const [data, response, error] = await this._umap.server.post(url, headers, formData)
if (error) {
if (response && response.status === 412) {
@ -1178,19 +1124,23 @@ export class DataLayer {
'This situation is tricky, you have to choose carefully which version is pertinent.'
),
async () => {
this._forceSave = true
await this._umap.saveAll()
// Save again this layer
const status = await this._trySave(url, {}, formData)
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 {
// 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)
if (data.geojson) {
this.clear(false)
this.clear()
this.fromGeoJSON(data.geojson)
delete data.geojson
}
@ -1217,7 +1167,7 @@ export class DataLayer {
}
commitDelete() {
delete this._umap.datalayers[this.id]
delete this._umap.datalayers[stamp(this)]
}
getName() {
@ -1284,16 +1234,25 @@ export class DataLayer {
translate('Delete layer')
)
if (this.isReadOnly()) {
container.classList.add('readonly')
DomUtil.addClass(container, 'readonly')
} else {
edit.addEventListener('click', () => this.edit())
table.addEventListener('click', () => this.tableEdit())
remove.addEventListener('click', () => {
if (!this.isVisible()) return
this.del()
})
DomEvent.on(edit, 'click', this.edit, this)
DomEvent.on(table, 'click', this.tableEdit, this)
DomEvent.on(
remove,
'click',
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())
DomEvent.on(toggle, 'click', this.toggle, this)
DomEvent.on(zoomTo, 'click', this.zoomTo, this)
container.classList.add(this.getHidableClass())
container.classList.toggle('off', !this.isVisible())

View file

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

View file

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

View file

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

View file

@ -1,17 +1,13 @@
import { uMapAlert as Alert } from '../components/alerts/alert.js'
import {
AjaxAutocomplete,
AjaxAutocompleteMultiple,
AutocompleteDatalist,
} from './autocomplete.js'
import { LineString, Point, Polygon } from './data/features.js'
import { LAYER_TYPES } from './data/layer.js'
import { AjaxAutocomplete, AjaxAutocompleteMultiple, AutocompleteDatalist } from './autocomplete.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 { SCHEMA } from './schema.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.
// 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 { translate } from './i18n.js'
import Dialog from './ui/dialog.js'
import * as Utils from './utils.js'
import Dialog from './ui/dialog.js'
const SHORTCUTS = {
DRAW_MARKER: {
@ -36,13 +36,9 @@ const SHORTCUTS = {
shortcut: 'Modifier+F',
label: translate('Search location'),
},
UNDO: {
CANCEL: {
shortcut: 'Modifier+Z',
label: translate('Cancel last edit'),
},
REDO: {
shortcut: 'Modifier+Shift+Z',
label: translate('Redo last edit'),
label: translate('Cancel edits'),
},
PREVIEW: {
shortcut: 'Modifier+E',
@ -139,23 +135,14 @@ const ENTRIES = {
<li>${translate('# one hash for main heading')}</li>
<li>${translate('## two hashes for second 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('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 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 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('--- for a horizontal rule')}</li>
</ul>
</div>
`,
@ -196,7 +183,7 @@ export default class Help {
.split('+')
.map((el) => `<kbd>${el}</kbd>`)
.join('+')
label += ` <span class="nobr">${shortcut}</span>`
label += ` ${shortcut}`
} else {
label += ` (${shortcut})`
}

View file

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

View file

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

View file

@ -15,7 +15,7 @@ export class AutocompleteCommunes extends SingleMixin(BaseAjax) {
let options = { q: encodeURIComponent(value) }
const re = /^(0[1-9]|[1-9][ABab\d])\d{3}$/gm
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) }
}
return Util.template(url, options)

View file

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

View file

@ -1,46 +0,0 @@
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,16 +1,18 @@
import { DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
import { uMapAlert as Alert } from '../components/alerts/alert.js'
import { MutatingForm } from './form/builder.js'
import { translate } from './i18n.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'
// 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.
export class MapPermissions {
export class MapPermissions extends ServerStored {
constructor(umap) {
super()
this.setProperties(umap.properties.permissions)
this._umap = umap
this.sync = umap.syncEngine.proxy(this)
this._isDirty = false
}
setProperties(properties) {
@ -26,13 +28,6 @@ export class MapPermissions {
)
}
getSyncMetadata() {
return {
subject: 'mappermissions',
metadata: {},
}
}
render() {
this._umap.render(['properties.permissions'])
}
@ -159,7 +154,7 @@ export class MapPermissions {
`<fieldset class="separator"><legend>${translate('Datalayers')}</legend></fieldset>`
)
container.appendChild(fieldset)
this._umap.datalayers.active().map((datalayer) => {
this._umap.eachDataLayer((datalayer) => {
datalayer.permissions.edit(fieldset)
})
}
@ -193,6 +188,7 @@ export class MapPermissions {
}
async save() {
if (!this.isDirty) return
const formData = new FormData()
if (!this.isAnonymousMap() && this.properties.editors) {
const editors = this.properties.editors.map((u) => u.id)
@ -251,8 +247,9 @@ export class MapPermissions {
}
}
export class DataLayerPermissions {
export class DataLayerPermissions extends ServerStored {
constructor(umap, datalayer) {
super()
this._umap = umap
this.properties = Object.assign(
{
@ -262,14 +259,6 @@ export class DataLayerPermissions {
)
this.datalayer = datalayer
this.sync = umap.syncEngine.proxy(this)
}
getSyncMetadata() {
return {
subject: 'datalayerpermissions',
metadata: { id: this.datalayer.id },
}
}
edit(container) {
@ -300,6 +289,7 @@ export class DataLayerPermissions {
}
async save() {
if (!this.isDirty) return
const formData = new FormData()
formData.append('edit_status', this.properties.edit_status)
const [data, response, error] = await this._umap.server.post(

View file

@ -1,251 +0,0 @@
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 {
DivIcon,
DomEvent,
DomUtil,
DivIcon,
Icon,
} from '../../../vendors/leaflet/leaflet-src.esm.js'
import { SCHEMA } from '../schema.js'
import * as Utils from '../utils.js'
import { SCHEMA } from '../schema.js'
export function getClass(name) {
switch (name) {
@ -15,8 +15,6 @@ export function getClass(name) {
return Ball
case 'Drop':
return Drop
case 'Raw':
return Raw
default:
return DefaultIcon
}
@ -154,17 +152,6 @@ 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({
default_options: {
iconAnchor: new L.Point(16, 42),

View file

@ -1,9 +1,9 @@
import colorbrewer from '../../../../vendors/colorbrewer/colorbrewer.js'
import { DomUtil, FeatureGroup } from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { FeatureGroup, DomUtil } from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from '../../i18n.js'
import { LayerMixin } from './base.js'
import * as Utils from '../../utils.js'
import { CircleMarker } from '../ui.js'
import { LayerMixin } from './base.js'
import colorbrewer from '../../../../vendors/colorbrewer/colorbrewer.js'
// Layer where each feature color is relative to the others,
// so we need all features before behing able to set one
@ -117,7 +117,7 @@ export const Choropleth = FeatureGroup.extend({
},
_getValue: function (feature) {
const key = this.datalayer.options.choropleth?.property || 'value'
const key = this.datalayer.options.choropleth.property || 'value'
const value = +feature.properties[key]
if (!Number.isNaN(value)) return value
},
@ -130,12 +130,12 @@ export const Choropleth = FeatureGroup.extend({
this.options.colors = []
return
}
const mode = this.datalayer.options.choropleth?.mode
let classes = +this.datalayer.options.choropleth?.classes || 5
const mode = this.datalayer.options.choropleth.mode
let classes = +this.datalayer.options.choropleth.classes || 5
let breaks
classes = Math.min(classes, values.length)
if (mode === 'manual') {
const manualBreaks = this.datalayer.options.choropleth?.breaks
const manualBreaks = this.datalayer.options.choropleth.breaks
if (manualBreaks) {
breaks = manualBreaks
.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
// Uses global L.MarkerCluster and L.MarkerClusterGroup, not exposed as ESM
import { translate } from '../../i18n.js'
import * as Utils from '../../utils.js'
import { Cluster as ClusterIcon } from '../icon.js'
import { LayerMixin } from './base.js'
import * as Utils from '../../utils.js'
import { Evented } from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { Cluster as ClusterIcon } from '../icon.js'
const MarkerCluster = L.MarkerCluster.extend({
// Custom class so we can call computeTextColor

View file

@ -1,14 +1,14 @@
// Uses global L.HeatLayer, not exposed as ESM
import {
Bounds,
LatLng,
Marker,
LatLng,
latLngBounds,
Bounds,
point,
} from '../../../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from '../../i18n.js'
import * as Utils from '../../utils.js'
import { LayerMixin } from './base.js'
import * as Utils from '../../utils.js'
import { translate } from '../../i18n.js'
export const Heat = L.HeatLayer.extend({
statics: {
@ -41,11 +41,6 @@ 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) {
LayerMixin.onAdd.call(this, map)
return L.HeatLayer.prototype.onAdd.call(this, map)

View file

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

View file

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

View file

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

View file

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

View file

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

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