From c4f3be87bb928026f1235fe06e3854a2659328f5 Mon Sep 17 00:00:00 2001 From: michael spreng Date: Wed, 16 May 2018 15:11:08 +0200 Subject: [PATCH 001/239] bump social-auth to use https:// for osm.org oauth openstreetmap.org switched to https:// login with umap does not work anymore with old social-auth version. The new version now has the https:// urls. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6683a7eb..9c62a3eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,4 @@ Pillow==4.1.0 psycopg2==2.7.1 requests==2.13.0 social-auth-app-django==1.1.0 -social-auth-core==1.2.0 +social-auth-core==1.7.0 From e1b5c08c56b019615720aa9b6c565eb176cba87c Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 17 May 2018 09:55:51 +0200 Subject: [PATCH 002/239] Fix Travis failing to load gdal --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index cca3b66d..ed33d532 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,12 @@ python: - "3.6" services: - postgresql +addons: + postgresql: "9.6" + apt: + packages: + - libgdal-dev + - postgresql-9.6-postgis-2.3 env: - UMAP_SETTINGS=umap/tests/settings.py install: From e55d03bd5ec446d908da29bb67b7617a82e50d12 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Fri, 18 May 2018 21:40:38 +0200 Subject: [PATCH 003/239] Django 2.0 And update other deps --- Makefile | 3 + requirements.txt | 11 +- umap/admin.py | 13 + umap/decorators.py | 57 +++ umap/fields.py | 33 ++ umap/forms.py | 90 +++++ .../management/commands/anonymous_edit_url.py | 28 ++ .../management/commands/generate_js_locale.py | 42 +++ umap/management/commands/import_pictograms.py | 2 +- umap/managers.py | 8 + umap/models.py | 356 ++++++++++++++++++ umap/settings/base.py | 3 +- umap/templates/auth/user_detail.html | 2 +- umap/templates/umap/content.html | 6 +- umap/templates/umap/css.html | 10 + umap/templates/umap/home.html | 4 +- .../{leaflet_storage => umap}/js.html | 0 umap/templates/umap/login_popup_end.html | 19 + .../{leaflet_storage => umap}/map_detail.html | 10 +- umap/templates/umap/map_fragment.html | 5 + umap/templates/umap/map_init.html | 5 + .../{leaflet_storage => umap}/map_list.html | 2 +- umap/templates/umap/map_messages.html | 11 + .../umap/map_update_permissions.html | 7 + umap/templates/umap/search.html | 2 +- umap/templates/umap/success.html | 1 + umap/tests/test_views.py | 4 +- umap/urls.py | 2 +- umap/utils.py | 111 ++++++ umap/views.py | 2 +- 30 files changed, 824 insertions(+), 25 deletions(-) create mode 100644 umap/admin.py create mode 100644 umap/decorators.py create mode 100644 umap/fields.py create mode 100644 umap/forms.py create mode 100644 umap/management/commands/anonymous_edit_url.py create mode 100644 umap/management/commands/generate_js_locale.py create mode 100644 umap/managers.py create mode 100644 umap/models.py create mode 100644 umap/templates/umap/css.html rename umap/templates/{leaflet_storage => umap}/js.html (100%) create mode 100644 umap/templates/umap/login_popup_end.html rename umap/templates/{leaflet_storage => umap}/map_detail.html (77%) create mode 100644 umap/templates/umap/map_fragment.html create mode 100644 umap/templates/umap/map_init.html rename umap/templates/{leaflet_storage => umap}/map_list.html (92%) create mode 100644 umap/templates/umap/map_messages.html create mode 100644 umap/templates/umap/map_update_permissions.html create mode 100644 umap/templates/umap/success.html create mode 100644 umap/utils.py diff --git a/Makefile b/Makefile index 09c76e57..b2245e16 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ test: py.test + +develop: + python setup.py develop diff --git a/requirements.txt b/requirements.txt index 9c62a3eb..f75f92f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,7 @@ -Django==1.11 +Django==2.0.5 django-compressor==2.1.1 -django-leaflet-storage==0.8.2 -Pillow==4.1.0 -psycopg2==2.7.1 -requests==2.13.0 -social-auth-app-django==1.1.0 +Pillow==5.1.0 +psycopg2==2.7.4 +requests==2.18.4 +social-auth-app-django==2.1.0 social-auth-core==1.7.0 diff --git a/umap/admin.py b/umap/admin.py new file mode 100644 index 00000000..74193e3b --- /dev/null +++ b/umap/admin.py @@ -0,0 +1,13 @@ +from django.contrib.gis import admin +from .models import Map, DataLayer, Pictogram, TileLayer, Licence + + +class TileLayerAdmin(admin.ModelAdmin): + list_display = ('name', 'rank', ) + list_editable = ('rank', ) + +admin.site.register(Map, admin.OSMGeoAdmin) +admin.site.register(DataLayer) +admin.site.register(Pictogram) +admin.site.register(TileLayer, TileLayerAdmin) +admin.site.register(Licence) diff --git a/umap/decorators.py b/umap/decorators.py new file mode 100644 index 00000000..a6f27134 --- /dev/null +++ b/umap/decorators.py @@ -0,0 +1,57 @@ +from functools import wraps + +from django.urls import reverse_lazy +from django.shortcuts import get_object_or_404 +from django.http import HttpResponseForbidden +from django.conf import settings + +from .views import simple_json_response +from .models import Map + + +LOGIN_URL = getattr(settings, "LOGIN_URL", "login") +LOGIN_URL = (reverse_lazy(LOGIN_URL) if not LOGIN_URL.startswith("/") + else LOGIN_URL) + + +def login_required_if_not_anonymous_allowed(view_func): + @wraps(view_func) + def wrapper(request, *args, **kwargs): + if (not getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False) + and not request.user.is_authenticated): + return simple_json_response(login_required=str(LOGIN_URL)) + return view_func(request, *args, **kwargs) + return wrapper + + +def map_permissions_check(view_func): + """ + Used for URLs dealing with the map. + """ + @wraps(view_func) + def wrapper(request, *args, **kwargs): + map_inst = get_object_or_404(Map, pk=kwargs['map_id']) + user = request.user + kwargs['map_inst'] = map_inst # Avoid rerequesting the map in the view + if map_inst.edit_status >= map_inst.EDITORS: + can_edit = map_inst.can_edit(user=user, request=request) + if not can_edit: + if map_inst.owner and not user.is_authenticated: + return simple_json_response(login_required=str(LOGIN_URL)) + else: + return HttpResponseForbidden('Action not allowed for user.') + return view_func(request, *args, **kwargs) + return wrapper + + +def jsonize_view(view_func): + @wraps(view_func) + def wrapper(request, *args, **kwargs): + response = view_func(request, *args, **kwargs) + response_kwargs = {} + if hasattr(response, 'rendered_content'): + response_kwargs['html'] = response.rendered_content + if response.has_header('location'): + response_kwargs['redirect'] = response['location'] + return simple_json_response(**response_kwargs) + return wrapper diff --git a/umap/fields.py b/umap/fields.py new file mode 100644 index 00000000..f60a62fa --- /dev/null +++ b/umap/fields.py @@ -0,0 +1,33 @@ +import json + +from django.utils import six +from django.db import models +from django.utils.encoding import smart_text + + +class DictField(models.TextField): + """ + A very simple field to store JSON in db. + """ + + def get_prep_value(self, value): + if not value: + value = {} + if not isinstance(value, six.string_types): + value = json.dumps(value) + return value + + def from_db_value(self, value, expression, connection, context): + return self.to_python(value) + + def to_python(self, value): + if not value: + value = {} + if isinstance(value, six.string_types): + return json.loads(value) + else: + return value + + def value_to_string(self, obj): + """Return value from object converted to string properly""" + return smart_text(self.get_prep_value(self.value_from_object(obj))) diff --git a/umap/forms.py b/umap/forms.py new file mode 100644 index 00000000..136cbba0 --- /dev/null +++ b/umap/forms.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- + +from django import forms +from django.contrib.gis.geos import Point +from django.contrib.auth import get_user_model +from django.utils.translation import ugettext_lazy as _ +from django.template.defaultfilters import slugify +from django.conf import settings +from django.forms.utils import ErrorList + +from .models import Map, DataLayer + +DEFAULT_LATITUDE = settings.LEAFLET_LATITUDE if hasattr(settings, "LEAFLET_LATITUDE") else 51 +DEFAULT_LONGITUDE = settings.LEAFLET_LONGITUDE if hasattr(settings, "LEAFLET_LONGITUDE") else 2 +DEFAULT_CENTER = Point(DEFAULT_LONGITUDE, DEFAULT_LATITUDE) + +User = get_user_model() + + +class FlatErrorList(ErrorList): + def __unicode__(self): + return self.flat() + + def flat(self): + if not self: + return u'' + return u' — '.join([e for e in self]) + + +class UpdateMapPermissionsForm(forms.ModelForm): + owner = forms.ModelChoiceField(User.objects, required=True) + + class Meta: + model = Map + fields = ('edit_status', 'editors', 'share_status', 'owner') + + +class AnonymousMapPermissionsForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + super(AnonymousMapPermissionsForm, self).__init__(*args, **kwargs) + full_secret_link = "%s%s" % (settings.SITE_URL, self.instance.get_anonymous_edit_url()) + help_text = _('Secret edit link is %s') % full_secret_link + self.fields['edit_status'].help_text = _(help_text) + + STATUS = ( + (Map.ANONYMOUS, _('Everyone can edit')), + (Map.OWNER, _('Only editable with secret edit link')) + ) + + edit_status = forms.ChoiceField(choices=STATUS) + + class Meta: + model = Map + fields = ('edit_status', ) + + +class DataLayerForm(forms.ModelForm): + + class Meta: + model = DataLayer + fields = ('geojson', 'name', 'display_on_load', 'rank') + + +class MapSettingsForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + super(MapSettingsForm, self).__init__(*args, **kwargs) + self.fields["slug"].required = False + + def clean_slug(self): + slug = self.cleaned_data.get('slug', None) + name = self.cleaned_data.get('name', None) + if not slug and name: + # If name is empty, don't do nothing, validation will raise + # later on the process because name is required + self.cleaned_data['slug'] = slugify(name) or "map" + return self.cleaned_data['slug'][:50] + else: + return "" + + def clean_center(self): + if not self.cleaned_data['center']: + point = DEFAULT_CENTER + self.cleaned_data['center'] = point + return self.cleaned_data['center'] + + class Meta: + fields = ('settings', 'name', 'center', 'slug') + model = Map diff --git a/umap/management/commands/anonymous_edit_url.py b/umap/management/commands/anonymous_edit_url.py new file mode 100644 index 00000000..f23d0f56 --- /dev/null +++ b/umap/management/commands/anonymous_edit_url.py @@ -0,0 +1,28 @@ +import sys + +from django.core.management.base import BaseCommand +from django.conf import settings + +from umap.models import Map + + +class Command(BaseCommand): + help = ('Retrieve anonymous edit url of a map. ' + 'Eg.: python manage.py anonymous_edit_url 1234') + + def add_arguments(self, parser): + parser.add_argument('pk', help='PK of the map to retrieve.') + + def abort(self, msg): + self.stderr.write(msg) + sys.exit(1) + + def handle(self, *args, **options): + pk = options['pk'] + try: + map_ = Map.objects.get(pk=pk) + except Map.DoesNotExist: + self.abort('Map with pk {} not found'.format(pk)) + if map_.owner: + self.abort('Map is not anonymous (owner: {})'.format(map_.owner)) + print(settings.SITE_URL + map_.get_anonymous_edit_url()) diff --git a/umap/management/commands/generate_js_locale.py b/umap/management/commands/generate_js_locale.py new file mode 100644 index 00000000..533035c0 --- /dev/null +++ b/umap/management/commands/generate_js_locale.py @@ -0,0 +1,42 @@ +import io +import os + +from django.core.management.base import BaseCommand +from django.conf import settings +from django.contrib.staticfiles import finders +from django.template.loader import render_to_string +from django.utils.translation import to_locale + + +class Command(BaseCommand): + + def handle(self, *args, **options): + self.verbosity = options['verbosity'] + for code, name in settings.LANGUAGES: + code = to_locale(code) + if self.verbosity > 0: + print("Processing", name) + path = finders.find('storage/src/locale/{code}.json'.format( + code=code)) + if not path: + print("No file for", code, "Skipping") + else: + with io.open(path, "r", encoding="utf-8") as f: + if self.verbosity > 1: + print("Found file", path) + self.render(code, f.read()) + + def render(self, code, json): + path = os.path.join( + settings.STATIC_ROOT, + "storage/src/locale/", + "{code}.js".format(code=code) + ) + with io.open(path, "w", encoding="utf-8") as f: + content = render_to_string('umap/locale.js', { + "locale": json, + "locale_code": code + }) + if self.verbosity > 1: + print("Exporting to", path) + f.write(content) diff --git a/umap/management/commands/import_pictograms.py b/umap/management/commands/import_pictograms.py index 11cae597..fe3b05c0 100644 --- a/umap/management/commands/import_pictograms.py +++ b/umap/management/commands/import_pictograms.py @@ -3,7 +3,7 @@ import os from django.core.files import File from django.core.management.base import BaseCommand -from leaflet_storage.models import Pictogram +from umap.models import Pictogram class Command(BaseCommand): diff --git a/umap/managers.py b/umap/managers.py new file mode 100644 index 00000000..d1728890 --- /dev/null +++ b/umap/managers.py @@ -0,0 +1,8 @@ +from django.db.models import Manager + + +class PublicManager(Manager): + + def get_queryset(self): + return super(PublicManager, self).get_queryset().filter( + share_status=self.model.PUBLIC) diff --git a/umap/models.py b/umap/models.py new file mode 100644 index 00000000..b2909820 --- /dev/null +++ b/umap/models.py @@ -0,0 +1,356 @@ +# -*- coding: utf-8 -*- + +import os +import time + +from django.contrib.gis.db import models +from django.conf import settings +from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ +from django.core.signing import Signer +from django.contrib import messages +from django.template.defaultfilters import slugify +from django.core.files.base import File + +from .fields import DictField +from .managers import PublicManager + + +class NamedModel(models.Model): + name = models.CharField(max_length=200, verbose_name=_("name")) + + class Meta: + abstract = True + ordering = ('name', ) + + def __unicode__(self): + return self.name + + def __str__(self): + return self.name + + +def get_default_licence(): + """ + Returns a default Licence, creates it if it doesn't exist. + Needed to prevent a licence deletion from deleting all the linked + maps. + """ + return Licence.objects.get_or_create( + # can't use ugettext_lazy for database storage, see #13965 + name=getattr(settings, "LEAFLET_STORAGE_DEFAULT_LICENCE_NAME", + 'No licence set') + )[0] + + +class Licence(NamedModel): + """ + The licence one map is published on. + """ + details = models.URLField( + verbose_name=_('details'), + help_text=_('Link to a page where the licence is detailed.') + ) + + @property + def json(self): + return { + 'name': self.name, + 'url': self.details + } + + +class TileLayer(NamedModel): + url_template = models.CharField( + max_length=200, + help_text=_("URL template using OSM tile format") + ) + minZoom = models.IntegerField(default=0) + maxZoom = models.IntegerField(default=18) + attribution = models.CharField(max_length=300) + rank = models.SmallIntegerField( + blank=True, + null=True, + help_text=_('Order of the tilelayers in the edit box') + ) + # See https://wiki.openstreetmap.org/wiki/TMS#The_Y_coordinate + tms = models.BooleanField(default=False) + + @property + def json(self): + return dict((field.name, getattr(self, field.name)) + for field in self._meta.fields) + + @classmethod + def get_default(cls): + """ + Returns the default tile layer (used for a map when no layer is set). + """ + return cls.objects.order_by('rank')[0] # FIXME, make it administrable + + @classmethod + def get_list(cls, selected=None): + l = [] + for t in cls.objects.all(): + fields = t.json + if selected and selected.pk == t.pk: + fields['selected'] = True + l.append(fields) + return l + + class Meta: + ordering = ('rank', 'name', ) + + +class Map(NamedModel): + """ + A single thematical map. + """ + ANONYMOUS = 1 + EDITORS = 2 + OWNER = 3 + PUBLIC = 1 + OPEN = 2 + PRIVATE = 3 + EDIT_STATUS = ( + (ANONYMOUS, _('Everyone can edit')), + (EDITORS, _('Only editors can edit')), + (OWNER, _('Only owner can edit')), + ) + SHARE_STATUS = ( + (PUBLIC, _('everyone (public)')), + (OPEN, _('anyone with link')), + (PRIVATE, _('editors only')), + ) + slug = models.SlugField(db_index=True) + description = models.TextField(blank=True, null=True, verbose_name=_("description")) + center = models.PointField(geography=True, verbose_name=_("center")) + zoom = models.IntegerField(default=7, verbose_name=_("zoom")) + locate = models.BooleanField(default=False, verbose_name=_("locate"), help_text=_("Locate user on load?")) + licence = models.ForeignKey( + Licence, + help_text=_("Choose the map licence."), + verbose_name=_('licence'), + on_delete=models.SET_DEFAULT, + default=get_default_licence + ) + modified_at = models.DateTimeField(auto_now=True) + tilelayer = models.ForeignKey(TileLayer, blank=True, null=True, related_name="maps", verbose_name=_("background"), on_delete=models.PROTECT) + owner = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name="owned_maps", verbose_name=_("owner"), on_delete=models.PROTECT) + editors = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_("editors")) + edit_status = models.SmallIntegerField(choices=EDIT_STATUS, default=OWNER, verbose_name=_("edit status")) + share_status = models.SmallIntegerField(choices=SHARE_STATUS, default=PUBLIC, verbose_name=_("share status")) + settings = DictField(blank=True, null=True, verbose_name=_("settings")) + + objects = models.Manager() + public = PublicManager() + + def get_absolute_url(self): + return reverse("map", kwargs={'slug': self.slug or "map", 'pk': self.pk}) + + def get_anonymous_edit_url(self): + signer = Signer() + signature = signer.sign(self.pk) + return reverse('map_anonymous_edit_url', kwargs={'signature': signature}) + + def is_anonymous_owner(self, request): + if self.owner: + # edit cookies are only valid while map hasn't owner + return False + key, value = self.signed_cookie_elements + try: + has_anonymous_cookie = int(request.get_signed_cookie(key, False)) == value + except ValueError: + has_anonymous_cookie = False + return has_anonymous_cookie + + def can_edit(self, user=None, request=None): + """ + Define if a user can edit or not the instance, according to his account + or the request. + """ + can = False + if request and not self.owner: + if (getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False) + and self.is_anonymous_owner(request)): + can = True + if user and user.is_authenticated: + # if user is authenticated, attach as owner + self.owner = user + self.save() + msg = _("Your anonymous map has been attached to your account %s" % user) + messages.info(request, msg) + if self.edit_status == self.ANONYMOUS: + can = True + elif not user.is_authenticated: + pass + elif user == self.owner: + can = True + elif self.edit_status == self.EDITORS and user in self.editors.all(): + can = True + return can + + def can_view(self, request): + if self.owner is None: + can = True + elif self.share_status in [self.PUBLIC, self.OPEN]: + can = True + elif request.user == self.owner: + can = True + else: + can = not (self.share_status == self.PRIVATE and request.user not in self.editors.all()) + return can + + @property + def signed_cookie_elements(self): + return ('anonymous_owner|%s' % self.pk, self.pk) + + def get_tilelayer(self): + return self.tilelayer or TileLayer.get_default() + + def clone(self, **kwargs): + new = self.__class__.objects.get(pk=self.pk) + new.pk = None + new.name = u"%s %s" % (_("Clone of"), self.name) + if "owner" in kwargs: + # can be None in case of anonymous cloning + new.owner = kwargs["owner"] + new.save() + for editor in self.editors.all(): + new.editors.add(editor) + for datalayer in self.datalayer_set.all(): + datalayer.clone(map_inst=new) + return new + + +class Pictogram(NamedModel): + """ + An image added to an icon of the map. + """ + attribution = models.CharField(max_length=300) + pictogram = models.ImageField(upload_to="pictogram") + + @property + def json(self): + return { + "id": self.pk, + "attribution": self.attribution, + "name": self.name, + "src": self.pictogram.url + } + + +# Must be out of Datalayer for Django migration to run, because of python 2 +# serialize limitations. +def upload_to(instance, filename): + if instance.pk: + return instance.upload_to() + name = "%s.geojson" % slugify(instance.name)[:50] or "untitled" + return os.path.join(instance.storage_root(), name) + + +class DataLayer(NamedModel): + """ + Layer to store Features in. + """ + map = models.ForeignKey(Map, on_delete=models.CASCADE) + description = models.TextField( + blank=True, + null=True, + verbose_name=_("description") + ) + geojson = models.FileField(upload_to=upload_to, blank=True, null=True) + display_on_load = models.BooleanField( + default=False, + verbose_name=_("display on load"), + help_text=_("Display this layer on load.") + ) + rank = models.SmallIntegerField(default=0) + + class Meta: + ordering = ('rank',) + + def save(self, force_insert=False, force_update=False, **kwargs): + is_new = not bool(self.pk) + super(DataLayer, self).save(force_insert, force_update, **kwargs) + + if is_new: + force_insert, force_update = False, True + filename = self.upload_to() + old_name = self.geojson.name + new_name = self.geojson.storage.save(filename, self.geojson) + self.geojson.storage.delete(old_name) + self.geojson.name = new_name + super(DataLayer, self).save(force_insert, force_update, **kwargs) + self.purge_old_versions() + + def upload_to(self): + root = self.storage_root() + name = '%s_%s.geojson' % (self.pk, int(time.time() * 1000)) + return os.path.join(root, name) + + def storage_root(self): + path = ["datalayer", str(self.map.pk)[-1]] + if len(str(self.map.pk)) > 1: + path.append(str(self.map.pk)[-2]) + path.append(str(self.map.pk)) + return os.path.join(*path) + + @property + def metadata(self): + return { + "name": self.name, + "id": self.pk, + "displayOnLoad": self.display_on_load + } + + def clone(self, map_inst=None): + new = self.__class__.objects.get(pk=self.pk) + new.pk = None + if map_inst: + new.map = map_inst + new.geojson = File(new.geojson.file.file) + new.save() + return new + + def is_valid_version(self, name): + return name.startswith('%s_' % self.pk) and name.endswith('.geojson') + + def version_metadata(self, name): + els = name.split('.')[0].split('_') + return { + "name": name, + "at": els[1], + "size": self.geojson.storage.size(self.get_version_path(name)) + } + + def get_versions(self): + root = self.storage_root() + names = self.geojson.storage.listdir(root)[1] + names = [name for name in names if self.is_valid_version(name)] + names.sort(reverse=True) # Recent first. + return names + + @property + def versions(self): + names = self.get_versions() + return [self.version_metadata(name) for name in names] + + def get_version(self, name): + path = self.get_version_path(name) + with self.geojson.storage.open(path, 'r') as f: + return f.read() + + def get_version_path(self, name): + return '{root}/{name}'.format(root=self.storage_root(), name=name) + + def purge_old_versions(self): + root = self.storage_root() + names = self.get_versions()[settings.LEAFLET_STORAGE_KEEP_VERSIONS:] + for name in names: + for ext in ['', '.gz']: + path = os.path.join(root, name + ext) + try: + self.geojson.storage.delete(path) + except FileNotFoundError: + pass diff --git a/umap/settings/base.py b/umap/settings/base.py index 9c9c1166..05cdc25a 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -132,7 +132,7 @@ TEMPLATES = [ # Middleware # ============================================================================= -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', @@ -141,6 +141,7 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.messages.middleware.MessageMiddleware', ) + # ============================================================================= # Auth / security # ============================================================================= diff --git a/umap/templates/auth/user_detail.html b/umap/templates/auth/user_detail.html index 51374464..363b1529 100644 --- a/umap/templates/auth/user_detail.html +++ b/umap/templates/auth/user_detail.html @@ -9,7 +9,7 @@
{% if maps %} - {% include "leaflet_storage/map_list.html" %} + {% include "umap/map_list.html" %} {% else %}
{% blocktrans %}{{ current_user }} has no maps.{% endblocktrans %} diff --git a/umap/templates/umap/content.html b/umap/templates/umap/content.html index 8435d7fd..7d807abe 100644 --- a/umap/templates/umap/content.html +++ b/umap/templates/umap/content.html @@ -1,14 +1,14 @@ {% extends "base.html" %} -{% load leaflet_storage_tags compress i18n %} +{% load umap_tags compress i18n %} {% block body_class %}content{% endblock %} {% block extra_head %} {% compress css %} - {% leaflet_storage_css %} + {% umap_css %} {% endcompress css %} - {% leaflet_storage_js %} + {% umap_js %} {% endblock %} {% block header %} diff --git a/umap/templates/umap/css.html b/umap/templates/umap/css.html new file mode 100644 index 00000000..5ff289d7 --- /dev/null +++ b/umap/templates/umap/css.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/umap/templates/umap/home.html b/umap/templates/umap/home.html index 42663513..b405786e 100644 --- a/umap/templates/umap/home.html +++ b/umap/templates/umap/home.html @@ -1,6 +1,6 @@ {% extends "umap/content.html" %} -{% load leaflet_storage_tags i18n %} +{% load umap_tags i18n %} {% block maincontent %} {% if DEMO_SITE %} @@ -23,7 +23,7 @@

{% blocktrans %}Get inspired, browse maps{% endblocktrans %}

- {% include "leaflet_storage/map_list.html" %} + {% include "umap/map_list.html" %}
diff --git a/umap/templates/leaflet_storage/js.html b/umap/templates/umap/js.html similarity index 100% rename from umap/templates/leaflet_storage/js.html rename to umap/templates/umap/js.html diff --git a/umap/templates/umap/login_popup_end.html b/umap/templates/umap/login_popup_end.html new file mode 100644 index 00000000..7873be76 --- /dev/null +++ b/umap/templates/umap/login_popup_end.html @@ -0,0 +1,19 @@ +{% load i18n %} +

{% trans "You are logged in. Continuing..." %}

+ + \ No newline at end of file diff --git a/umap/templates/leaflet_storage/map_detail.html b/umap/templates/umap/map_detail.html similarity index 77% rename from umap/templates/leaflet_storage/map_detail.html rename to umap/templates/umap/map_detail.html index 07c629ef..0d8ce992 100644 --- a/umap/templates/leaflet_storage/map_detail.html +++ b/umap/templates/umap/map_detail.html @@ -1,13 +1,13 @@ {% extends "base.html" %} -{% load leaflet_storage_tags compress i18n %} +{% load umap_tags compress i18n %} {% block head_title %}{{ map.name }} - {{ SITE_NAME }}{% endblock %} {% block body_class %}map_detail{% endblock %} {% block extra_head %} {% compress css %} - {% leaflet_storage_css %} + {% umap_css %} {% endcompress %} - {% leaflet_storage_js locale=locale %} + {% umap_js locale=locale %} {% if object.share_status != object.PUBLIC %} {% endif %} @@ -15,9 +15,9 @@ {% block content %} {% block map_init %} - {% include "leaflet_storage/map_init.html" %} + {% include "umap/map_init.html" %} {% endblock %} - {% include "leaflet_storage/map_messages.html" %} + {% include "umap/map_messages.html" %} diff --git a/umap/templates/umap/map_init.html b/umap/templates/umap/map_init.html new file mode 100644 index 00000000..f0f8142e --- /dev/null +++ b/umap/templates/umap/map_init.html @@ -0,0 +1,5 @@ +{% load umap_tags %} +
+ diff --git a/umap/templates/leaflet_storage/map_list.html b/umap/templates/umap/map_list.html similarity index 92% rename from umap/templates/leaflet_storage/map_list.html rename to umap/templates/umap/map_list.html index 73d9b607..926bcdd3 100644 --- a/umap/templates/leaflet_storage/map_list.html +++ b/umap/templates/umap/map_list.html @@ -1,4 +1,4 @@ -{% load leaflet_storage_tags umap_tags i18n %} +{% load umap_tags umap_tags i18n %} {% for map_inst in maps %}
diff --git a/umap/templates/umap/map_messages.html b/umap/templates/umap/map_messages.html new file mode 100644 index 00000000..0ce6adf7 --- /dev/null +++ b/umap/templates/umap/map_messages.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/umap/templates/umap/map_update_permissions.html b/umap/templates/umap/map_update_permissions.html new file mode 100644 index 00000000..3b39af87 --- /dev/null +++ b/umap/templates/umap/map_update_permissions.html @@ -0,0 +1,7 @@ +{% load i18n %} +

{% trans "Map permissions" %}

+
+ {% csrf_token %} + {{ form }} + +
\ No newline at end of file diff --git a/umap/templates/umap/search.html b/umap/templates/umap/search.html index da860da7..51c37a17 100644 --- a/umap/templates/umap/search.html +++ b/umap/templates/umap/search.html @@ -8,7 +8,7 @@
{% if maps %} - {% include "leaflet_storage/map_list.html" with prefix='search_map_' %} + {% include "umap/map_list.html" with prefix='search_map_' %} {% else %} {% trans "Not map found." %} {% endif %} diff --git a/umap/templates/umap/success.html b/umap/templates/umap/success.html new file mode 100644 index 00000000..b5754e20 --- /dev/null +++ b/umap/templates/umap/success.html @@ -0,0 +1 @@ +ok \ No newline at end of file diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index 5c65844a..b53360f4 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -3,7 +3,7 @@ import socket import pytest from django.conf import settings from django.contrib.auth import get_user, get_user_model -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import RequestFactory from umap.views import validate_url @@ -105,4 +105,4 @@ def test_can_login_with_username_and_password_if_enabled(client, settings): user.save() client.post(reverse('login'), {'username': 'test', 'password': 'test'}) user = get_user(client) - assert user.is_authenticated() + assert user.is_authenticated diff --git a/umap/urls.py b/umap/urls.py index 5bcb6d85..590c050e 100644 --- a/umap/urls.py +++ b/umap/urls.py @@ -14,7 +14,7 @@ from . import views admin.autodiscover() urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), url('', include('social_django.urls', namespace='social')), url(r'^m/(?P\d+)/$', MapShortUrl.as_view(), name='umap_short_url'), url(r'^ajax-proxy/$', cache_page(180)(views.ajax_proxy), diff --git a/umap/utils.py b/umap/utils.py new file mode 100644 index 00000000..57d4ce30 --- /dev/null +++ b/umap/utils.py @@ -0,0 +1,111 @@ +import gzip + +from django.urls import get_resolver +from django.urls import URLPattern, URLResolver + + +def get_uri_template(urlname, args=None, prefix=""): + ''' + Utility function to return an URI Template from a named URL in django + Copied from django-digitalpaper. + + Restrictions: + - Only supports named urls! i.e. url(... name="toto") + - Only support one namespace level + - Only returns the first URL possibility. + - Supports multiple pattern possibilities (i.e., patterns with + non-capturing parenthesis in them) by trying to find a pattern + whose optional parameters match those you specified (a parameter + is considered optional if it doesn't appear in every pattern possibility) + ''' + def _convert(template, args=None): + """URI template converter""" + if not args: + args = [] + paths = template % dict([p, "{%s}" % p] for p in args) + return u'%s/%s' % (prefix, paths) + + resolver = get_resolver(None) + parts = urlname.split(':') + if len(parts) > 1 and parts[0] in resolver.namespace_dict: + namespace = parts[0] + urlname = parts[1] + nprefix, resolver = resolver.namespace_dict[namespace] + prefix = prefix + '/' + nprefix.rstrip('/') + possibilities = resolver.reverse_dict.getlist(urlname) + for tmp in possibilities: + possibility, pattern = tmp[:2] + if not args: + # If not args are specified, we only consider the first pattern + # django gives us + result, params = possibility[0] + return _convert(result, params) + else: + # If there are optionnal arguments passed, use them to try to find + # the correct pattern. + # First, we need to build a list with all the arguments + seen_params = [] + for result, params in possibility: + seen_params.append(params) + # Then build a set to find the common ones, and use it to build the + # list of all the expected params + common_params = reduce(lambda x, y: set(x) & set(y), seen_params) + expected_params = sorted(common_params.union(args)) + # Then loop again over the pattern possibilities and return + # the first one that strictly match expected params + for result, params in possibility: + if sorted(params) == expected_params: + return _convert(result, params) + return None + + +class DecoratedURLPattern(URLPattern): + + def resolve(self, *args, **kwargs): + result = URLPattern.resolve(self, *args, **kwargs) + if result: + for func in self._decorate_with: + result.func = func(result.func) + return result + + +def decorated_patterns(func, *urls): + """ + Utility function to decorate a group of url in urls.py + + Taken from http://djangosnippets.org/snippets/532/ + comments + See also http://friendpaste.com/6afByRiBB9CMwPft3a6lym + + Example: + urlpatterns = [ + url(r'^language/(?P[a-z]+)$', views.MyView, name='name'), + ] + decorated_patterns(login_required, url(r'^', include('cms.urls')), + """ + + def decorate(urls, func): + for url in urls: + if isinstance(url, URLPattern): + url.__class__ = DecoratedURLPattern + if not hasattr(url, "_decorate_with"): + setattr(url, "_decorate_with", []) + url._decorate_with.append(func) + elif isinstance(url, URLResolver): + for pp in url.url_patterns: + if isinstance(pp, URLPattern): + pp.__class__ = DecoratedURLPattern + if not hasattr(pp, "_decorate_with"): + setattr(pp, "_decorate_with", []) + pp._decorate_with.append(func) + if func: + if not isinstance(func, (list, tuple)): + func = [func] + for f in func: + decorate(urls, f) + + return urls + + +def gzip_file(from_path, to_path): + with open(from_path, 'rb') as f_in: + with gzip.open(to_path, 'wb') as f_out: + f_out.writelines(f_in) diff --git a/umap/views.py b/umap/views.py index bfc98ab0..b0415cba 100644 --- a/umap/views.py +++ b/umap/views.py @@ -22,7 +22,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.http import HttpResponse, HttpResponseBadRequest from django.utils.translation import ugettext as _ from django.utils.encoding import smart_bytes -from django.core.urlresolvers import reverse +from django.urls import reverse from django.core.validators import URLValidator, ValidationError from leaflet_storage.models import Map From cb470198e697afa9b2d16944b6426da956fc3239 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 11:12:19 +0200 Subject: [PATCH 004/239] Merge leaflet_storage locales --- Makefile | 5 +- umap/context_processors.py | 1 - umap/locale/am_ET/LC_MESSAGES/django.mo | Bin 3675 -> 7748 bytes umap/locale/am_ET/LC_MESSAGES/django.po | 213 ++++++++- umap/locale/bg/LC_MESSAGES/django.mo | Bin 3729 -> 8203 bytes umap/locale/bg/LC_MESSAGES/django.po | 213 ++++++++- umap/locale/ca/LC_MESSAGES/django.mo | Bin 3105 -> 6519 bytes umap/locale/ca/LC_MESSAGES/django.po | 220 +++++++-- umap/locale/cs_CZ/LC_MESSAGES/django.mo | Bin 3230 -> 6717 bytes umap/locale/cs_CZ/LC_MESSAGES/django.po | 219 +++++++-- umap/locale/da/LC_MESSAGES/django.mo | Bin 3070 -> 6364 bytes umap/locale/da/LC_MESSAGES/django.po | 218 +++++++-- umap/locale/de/LC_MESSAGES/django.mo | Bin 3262 -> 7950 bytes umap/locale/de/LC_MESSAGES/django.po | 259 +++++++++-- umap/locale/en/LC_MESSAGES/django.po | 180 ++++++++ umap/locale/es/LC_MESSAGES/django.mo | Bin 4315 -> 7778 bytes umap/locale/es/LC_MESSAGES/django.po | 184 +++++++- umap/locale/fi/LC_MESSAGES/django.mo | Bin 3289 -> 6765 bytes umap/locale/fi/LC_MESSAGES/django.po | 225 +++++++-- umap/locale/fr/LC_MESSAGES/django.mo | Bin 4320 -> 7868 bytes umap/locale/fr/LC_MESSAGES/django.po | 199 +++++++- umap/locale/it/LC_MESSAGES/django.mo | Bin 3211 -> 7877 bytes umap/locale/it/LC_MESSAGES/django.po | 247 ++++++++-- umap/locale/ja/LC_MESSAGES/django.mo | Bin 4613 -> 8260 bytes umap/locale/ja/LC_MESSAGES/django.po | 184 +++++++- umap/locale/lt/LC_MESSAGES/django.mo | Bin 2815 -> 7949 bytes umap/locale/lt/LC_MESSAGES/django.po | 262 +++++++++-- umap/locale/nl/LC_MESSAGES/django.mo | Bin 465 -> 499 bytes umap/locale/nl/LC_MESSAGES/django.po | 180 ++++++++ umap/locale/pl/LC_MESSAGES/django.po | 190 +++++++- umap/locale/pt/LC_MESSAGES/django.mo | Bin 4397 -> 7774 bytes umap/locale/pt/LC_MESSAGES/django.po | 184 +++++++- umap/locale/ru/LC_MESSAGES/django.mo | Bin 5526 -> 9994 bytes umap/locale/ru/LC_MESSAGES/django.po | 184 +++++++- umap/locale/sk_SK/LC_MESSAGES/django.po | 186 +++++++- umap/locale/uk_UA/LC_MESSAGES/django.mo | Bin 4122 -> 10184 bytes umap/locale/uk_UA/LC_MESSAGES/django.po | 249 ++++++++-- umap/locale/vi/LC_MESSAGES/django.mo | Bin 3291 -> 7111 bytes umap/locale/vi/LC_MESSAGES/django.po | 218 +++++++-- umap/locale/zh/LC_MESSAGES/django.mo | Bin 1807 -> 1819 bytes umap/locale/zh/LC_MESSAGES/django.po | 24 +- umap/locale/zh_TW/LC_MESSAGES/django.mo | Bin 4111 -> 7326 bytes umap/locale/zh_TW/LC_MESSAGES/django.po | 186 +++++++- umap/migrations/0001_add_tilelayer.py | 29 -- umap/migrations/0002_add_licence.py | 25 - umap/settings/base.py | 5 +- umap/templatetags/umap_tags.py | 70 +++ umap/urls.py | 68 ++- umap/views.py | 587 +++++++++++++++++++++++- 49 files changed, 4730 insertions(+), 484 deletions(-) delete mode 100644 umap/migrations/0001_add_tilelayer.py delete mode 100644 umap/migrations/0002_add_licence.py diff --git a/Makefile b/Makefile index b2245e16..6d0d58cb 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ test: py.test - develop: python setup.py develop +compilemessages: + django-admin.py compilemessages +makemessages: + django-admin.py makemessages -a diff --git a/umap/context_processors.py b/umap/context_processors.py index f50e6212..03253b24 100644 --- a/umap/context_processors.py +++ b/umap/context_processors.py @@ -15,4 +15,3 @@ def version(request): return { 'UMAP_VERSION': __version__ } - diff --git a/umap/locale/am_ET/LC_MESSAGES/django.mo b/umap/locale/am_ET/LC_MESSAGES/django.mo index e66689624dcde5870294733dbac14b6593a82c4b..119056d1cb6d19e7c96c0a05e8f6e6d815436cd9 100644 GIT binary patch literal 7748 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 diff --git a/umap/locale/am_ET/LC_MESSAGES/django.po b/umap/locale/am_ET/LC_MESSAGES/django.po index c8306d32..6d04e10e 100644 --- a/umap/locale/am_ET/LC_MESSAGES/django.po +++ b/umap/locale/am_ET/LC_MESSAGES/django.po @@ -9,14 +9,13 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2015-11-15 14:24+0000\n" -"Last-Translator: Alazar Tekle \n" -"Language-Team: Amharic (Ethiopia) (http://www.transifex.com/yohanboniface/" -"umap/language/am_ET/)\n" -"Language: am_ET\n" +"PO-Revision-Date: 2017-09-22 17:21+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Amharic (Ethiopia) (http://www.transifex.com/yohanboniface/umap/language/am_ET/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: am_ET\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 @@ -33,10 +32,8 @@ msgid "Type editors nick to add…" msgstr "የአራሚዎችን ኒክ በመፃፍ ጨምር" #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "የአራሚዎችን ኒክ በመፃፍ ጨምር" +msgstr "" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -71,9 +68,7 @@ msgstr "እባክዎ አቅራቢ ይምረጡ" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"ዩማፕ በ ኦፕን ስትሪት ማፕ ሌየሮች ካርታዎችን በደቂቃ ውስጥ ሰርተን " -"በገፃችን ማካተት እንድንችል ያደርገናል" +msgstr "ዩማፕ በ ኦፕን ስትሪት ማፕ ሌየሮች ካርታዎችን በደቂቃ ውስጥ ሰርተን በገፃችን ማካተት እንድንችል ያደርገናል" #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -120,13 +115,10 @@ msgstr "በማሳያው ተለማመድ" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"ይህ ለሙከራ እና ፕሪ-ሮሊግ ሪሊዞች የሚያገለግል ማሳያ ነው። ቋሚ የሆነ ማሳያ ከፈለጉ እባክዎ %(stable_url)s ይጠቀሙ። እንዲሁም የራስዎን ማስቀመጥ ይችላሉ፣ ነፃ እና ክፍት ነው!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "ይህ ለሙከራ እና ፕሪ-ሮሊግ ሪሊዞች የሚያገለግል ማሳያ ነው። ቋሚ የሆነ ማሳያ ከፈለጉ እባክዎ %(stable_url)s ይጠቀሙ። እንዲሁም የራስዎን ማስቀመጥ ይችላሉ፣ ነፃ እና ክፍት ነው!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -170,8 +162,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -214,5 +206,182 @@ msgstr "ፈልግ" msgid "View the map" msgstr "ካርታውን አሳይ" -#~ msgid "Map settings" -#~ msgstr "የካርታዎች ሁኔታ" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "የሚስጥር የማረሚያ መስመሩ %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "ሁሉም ማረም ይችላል" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "በሚስጥር የመረሚያ መስመሩ ብቻ የሚታረም" + +#: models.py:20 +msgid "name" +msgstr "ስም" + +#: models.py:42 +msgid "No licence set" +msgstr "ምንም ፈቃድ አልተሰጠም" + +#: models.py:51 +msgid "details" +msgstr "ዝርዝሮች" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "ፈቃዱ በዝርዝር ከተቀመጠ ገፅ ጛር አገናኝ" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "የድረ-ገፅ አድራሻ ተምሳሌ በኦ.ኤስ.ኤም. የታይል ፎርማት" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "በማረሚያ ሳጥኑ ውስጥ የታይል ሌየሮቹ ቅደም ተከተል" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "አራሚዎች ብቻ ማረም ይችላሉ" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "ባለቤት ብቻ ማረም ይችላል" + +#: models.py:118 +msgid "everyone (public)" +msgstr "ሁሉም (የህዝብ)" + +#: models.py:119 +msgid "anyone with link" +msgstr "አድራሻው ያለው ሁሉ" + +#: models.py:120 +msgid "editors only" +msgstr "አራሚዎች ብቻ" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "መገለጫ" + +#: models.py:124 +msgid "center" +msgstr "መሀከል" + +#: models.py:125 +msgid "zoom" +msgstr "ዙም" + +#: models.py:126 +msgid "locate" +msgstr "ጠቁም" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "በመጫን ላይ ያለውን ተጠቃሚ ጠቁም?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "የካርታውን ፈቃድ ከልስ" + +#: models.py:130 +msgid "licence" +msgstr "ፈቃድ" + +#: models.py:135 +msgid "background" +msgstr "ጀርባ" + +#: models.py:136 +msgid "owner" +msgstr "ባለቤት" + +#: models.py:137 +msgid "editors" +msgstr "አራሚዎች" + +#: models.py:138 +msgid "edit status" +msgstr "ያለበትን ሁኔታ አርም" + +#: models.py:139 +msgid "share status" +msgstr "ያለበትን ሁኔታ አጋራ" + +#: models.py:140 +msgid "settings" +msgstr "ሁኔታዎች" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "በግልፅ ያልተቀመጠው ካርታዎ ከ %s አካውንትዎ ጋር ተያይዟል" + +#: models.py:211 +msgid "Clone of" +msgstr "ድቃይ" + +#: models.py:262 +msgid "display on load" +msgstr "በመጫን ላይ አሳይ" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "ሌየሩ በመጫን ላይ አሳይ" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "ገብተዋል። በመቀጠል ላይ ..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "የካርታ ፍቃዶች" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "እባክዎ ለመቀጠል ይግቡ" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "የተገልጋይ ስምዎ እና የይለፍ ቃልዎ አልተዛመደም። እባክዎ እንደገና ይሞክሩ።" + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "ካርታዎ ተፈጥሯል! ይህንን ካርታ ከሌላ ኮምፒውተር ላይ ሆነው ለማረም ከፈለጉ የሚከተለውን አድራሻ ይጠቀሙ %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "እንኳን ደስ አለዎ ካርታዎ ተፈጥሯል!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "ካርታው ታድሷል!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "የካርታ አራሚዎች በትክክል ታድሰዋል!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "ካርታውን የሚሰርዘው ባለቤቱ ብቻ ነው።" + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "እንኳን ደስ አለዎ ካርታዎ ተዳቅሏል!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "ሌየሩ በትክክል ተሰርዟ" diff --git a/umap/locale/bg/LC_MESSAGES/django.mo b/umap/locale/bg/LC_MESSAGES/django.mo index 3399a0d933704e3093e1d6cf354d093178ebb204..f47568a701daf3bf682a6676703e0ba4ac0edfd5 100644 GIT binary patch literal 8203 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 K{W1nGxc>${N^2$n delta 963 zcmYk)-AmI^7{KvkIp0c`^R=bZ2j0dme2eYqEmf)xPoW=2P!5{IZoGrC z?Wm3@w# z7#LRT9fws=zA$_kR?u#d4=beF6 zG7t}>nH;!aM\n" -"Language-Team: Bulgarian (http://www.transifex.com/projects/p/umap/language/" -"bg/)\n" -"Language: bg\n" +"Language-Team: Bulgarian (http://www.transifex.com/yohanboniface/umap/language/bg/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 @@ -70,10 +69,7 @@ msgstr "Моля изберете провайдер" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"uMap ви позволява да създавате карти базирани върху слоевете на OpenStreetMap само за минути и да ги вградите в " -"сайта си." +msgstr "uMap ви позволява да създавате карти базирани върху слоевете на OpenStreetMap само за минути и да ги вградите в сайта си." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -89,9 +85,7 @@ msgstr "Промени POIs цветове и икони" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Играй с опциите на картата: покажи миникарта, локализирай потребителя при " -"зареждане ..." +msgstr "Играй с опциите на картата: покажи миникарта, локализирай потребителя при зареждане ..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -122,14 +116,10 @@ msgstr "Играй си с демото" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Това е само демо пример, използван за тестове и предварителни издания. Ако " -"имате нужда от стабилна версия, моля използвайте " -"%(stable_url)s. Можете също така да бъде хост на вашата собствена " -"версия, това е отворен код !" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Това е само демо пример, използван за тестове и предварителни издания. Ако имате нужда от стабилна версия, моля използвайте %(stable_url)s. Можете също така да бъде хост на вашата собствена версия, това е отворен код !" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -173,8 +163,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -217,5 +207,182 @@ msgstr "Търсене" msgid "View the map" msgstr "Виж картата" -#~ msgid "Map settings" -#~ msgstr "Настройки на картата" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Тайно редактиране на линк е %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Всеки може да редактира" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Само може да се редактира с тайно редактиран линк" + +#: models.py:20 +msgid "name" +msgstr "име" + +#: models.py:42 +msgid "No licence set" +msgstr "Няма избран лиценз" + +#: models.py:51 +msgid "details" +msgstr "детайли" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Линк към страницата с подробно описание за лиценза." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "URL шаблон, използван формат OSM плочи" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Поръчка на tilelayers в полето за редактиране" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Само редактори могат да редактират" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Само притежателят може да редактира" + +#: models.py:118 +msgid "everyone (public)" +msgstr "всеки (публично)" + +#: models.py:119 +msgid "anyone with link" +msgstr "всеки които има линк" + +#: models.py:120 +msgid "editors only" +msgstr "само редакторите" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "описание" + +#: models.py:124 +msgid "center" +msgstr "център" + +#: models.py:125 +msgid "zoom" +msgstr "мащаб" + +#: models.py:126 +msgid "locate" +msgstr "локализирай" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Локализирай потребител при зареждане?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Избери лиценз за картата." + +#: models.py:130 +msgid "licence" +msgstr "лиценз" + +#: models.py:135 +msgid "background" +msgstr "фон" + +#: models.py:136 +msgid "owner" +msgstr "притежател" + +#: models.py:137 +msgid "editors" +msgstr "редактори" + +#: models.py:138 +msgid "edit status" +msgstr "статус на редактиране" + +#: models.py:139 +msgid "share status" +msgstr "сподели статус" + +#: models.py:140 +msgid "settings" +msgstr "настройки" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Вашата анонимна карта е прикрепена към вашия акаунт %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Клониране на" + +#: models.py:262 +msgid "display on load" +msgstr "покажи при зареждане" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Покажи този слой при зареждане" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "В процес на включване. Продължение..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Разрешения за картата" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Моля, включете се за да осъществите тази процедура" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Вашето потребителско име и парола не съвпадат. Моля, опитайте отново." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Вашата карта е създадена! Ако искате да редактирате тази карта от друг компютър, моля използвайте този линк : %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Поздравления, вашата карта е създадена!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Карта е актуализирана!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Редакторите на картата актуализират с успех!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Само собственикът може да изтрие картата." + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Поздравления, вашата карта е клонирана!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Слоят е изтрит успешно." diff --git a/umap/locale/ca/LC_MESSAGES/django.mo b/umap/locale/ca/LC_MESSAGES/django.mo index 498932e7c1e4e5ec89ca62bb93882dcb96ef5702..54786006562daa1357aec18004b6799a1abe6217 100644 GIT binary patch literal 6519 zcmcJTU2G*~8OL9~M2n)}2jUlR!KLlebK32)EPIySWk0%0NlWXtEb)S@@0odf&aiW4 zhIeM#EvO+ekQj(}CSpj~#6$!kCKyAML?YD-Nw_j0h6|#2g?eSU(D)I5&pUI@X<=94 zf=Q>po|*UadH&DyKBsS7ed%`<*Btj3xWkK;GVs|;`NcK;A*C*ZyWkGE7f!=_;ePlX z_$BxX{33h{YIynON?ilT;fLYva3`FDH^Bma6rO{hhtI*!!r#KH;G0nTy$!F0|Ax}; z8Xh*_Zulu^AXBO}NE7u9DC>9_9)Lf9qwtUL)9{jyDD??=E&Mp#31zD-DE$w?E8&Tn zr{E2Iwov+i8(t5egr9^j!!h_8yc+%o%08|dskjr$`i{aY;GOU@@D!B!dhpM%gtEV{ z(MZPsIu!dn2{n8c?uD*wEsGVh~M{P4Z{`7=<)c^-P{Rk|m*EqT zAN4DKi9LP?Mc;2g@#jC`47?7fiM>xk*-r^&-4DW@@FBPYe++Mi;&jpD9w_!(gbbxl zL+N)v6#cBh&%uYG`1>5(4PSuQ!M{Km{|ZDbpKpPC;3+8m9)mPdPeF;V7on{0btr!P z1002ag)-lji1Xr$uoax*vu0A!#S)bFk3yO6`)~&S28xdU4hxtNtP(GOg8ZmaoFMzz z2QPsKq4@s@l=}RNBM{fA$D#P)87TYs8I*Bfte?LGW!zVw zjQ1LR1il4j-VCF&J%15mgNyB}gY~BqP}<5RwicbpC3cic<`dh9Uc}}{xJ4^_xo_p3 zTQ2dT=u~Vh_7jcBC9xs?+$SHn?%xcbc^{>P2v@F!&Fw{$nb9qbmj5}jpKB?mz1 zjZT{6&1O>_PC^|OW4XS~=&rM?2d>{S?rfHxE?qp4Uw<&oY@+kDbb-BX${ZY3M@$iP zb=1pJSLlvS^TL%uQ92vy&=f|G^X$GnO(u0GJ3Fb*^x{dK<~`<`P)A(4o?E?RJSd&B zNpZT&t((Z1y=Ssq9qpzmuZynLvDsk7I$hNp%q_3Cy^R8!&~i0()q9zFYXjP|SsDel zsgA~JVi`&uO_Po@MH!nSV*8VWv31wvx^3BMAZ^3Z_tex`Q~0+24{iJ^k41UL;@L!$ zSG&+@qT|$rO*PwVVYs0n)&ZrZ%&{2|S5eA;r z?aF}OTJvHeotHsi^L(|8;|(3!*s`Rinvaq*x=2}5W;#}{cP-O-yH-ZgEH1Q#iDKV6 z4cLhmXY?0)NX@4mCiW0DEto_`5<%%8jd4oucM=6yvj0}ho@U;-EgjaDz%Ee|@e2LD zd!jcV`XRkDzw4AS%M4#)rS+)j_BS``TMT?uH>sYY5ZPDB7_y8^XV&$iJQoM6h16NK zuu-Y&uCy-+o!dg)l@{_G4V4KNTTHN@nBKHw4CZIIfy4UpP$K8du#GHq;40rUDiG^> zf&t}u{0Q;_{}R^RcTF=4TYTi(!Z3WYs1ZZfokPn)Q>8XG|0(V-mTXLQP#qLg6;F=@_i7OyU!% z4;UY`l0`dCf?TyX6h{IEP@&BO7x_%Z-;xJ&)z4RTx>nwh=&vYq|2IM3Cs{JyP`017 z$Fs7{X)~efBS%$vPRZ((4|_$%K?I##RhhpYR zse_9g$;*YawxGKNMgO!Ub@*h9kG;{XKW}h-4_K7dB3D z){-z=K8=o?-=$T!u z-Ft7Eo|&GeVdJD-i)6%MyS>tGX1Ct8uXXdDo2I!&=1pESR-8$4qAPVRR@gO3J58ch z6Oa|QeY|~@4L4WaLAoWKlC!9>Vok55k8KOM-S*- z6Z=QhS4s(IqYkgyj*UvabZpMoae)cZAt&kPb4gU!a+}Zfi@7)HNinQ`573wsZOOaQ8=QSpHHS?(<<3+WHe!iH8Ett_{_k9VoB8bxPpr79Yie8HFwM^Xz! zk(w1z+vYYvNp{PFzjXK`? zkx8n{a~r?>g1FDb`u@`RR{eFVJIju^%5S484JANi3w5;OSt&>D=1)jeh@0)vo`Nu! zZBm@0Q(u*a5n*6m!1p%!T?>Bxg0}IgZ3kZx>-dynrm*U89hzcl(LZOhpNWl0t=wOo z)U76DYQF$7b+t;-F=>x-h-j|*BG{&0j%ZJq$D-8!kdgwZVSNc)zQ3Y%1%quq?R{DL zqSX}lN$9cOD#K)M^ZAVY7kEtm-#m`|_{v=+@>!{6)_mH@`KsRLn|0dravrLP9L7l! zIf#n^5P zLv5ZT9(~=*L^A2@wros!viUq;3agl^!+}9Cc;#3BRpi3STpYCKlUSwZIzxNuOCG~( zCYIDs$w)RtinZ6OOimM@GtXD@`jksBR*}5*1o;3bo$seUIYlJ%<~G?dI!XB$aWIB9 zI&1kZv64FSaHA{V>?2>I$RR|O#<|5F+tZ6$mG8hP-dDYR6RxXXAFWdL##Fskh-}UM z%9~WOlvJty6M0CXDWA@UsYw;pxi+3{{-Umbhe^>NF49R2GnLAW+dS8^I3`!(XHH8t zHkb;H_==d&W7V|tHL?HikEA0~=O9nTWAD8>uJpipQ}VAA%;ryQ;~FtJAHmfwjw#yp Ox@|WV-wmiJ)qer7)k~uQ delta 1037 zcmXxiO=uHA6bJB^+HaF=lYUq~s-v{hR?|&C1dUqMwg;ingT*2uI7z0hG2IROLC7f= zQNeT_z&`bQ`?BT;3X(v35MYV*a??lBYXvS z!WCFgRG}}pX+Xz1Y=L!Mv(A|Wlo?eGQU@h{1LeLexUzupjf&S=>xP4;t{@=73emD_w&f@CV!lYmv1T?t`3g z81jmbK^{K=Yp{?hXySPqFS-8~#OBg{coRN^6^x?@8c)E%TaI~xLbyskk{xKgwH#ak zuaYB%#tFHYt>ABnj|HDa@Lg~}pEnn<6{ssHxQ*yQu!Z~ryA_;IJ3k=!2sr9=qJE>> zQPNXFig{V2iTRAm32EhoJ0~3_%C_(D3;nyHN0%C{UVBD(b4vJWS#&9FJBrd}9^leB z+v6KCWBXQaK>uw@#4af5Wap>~zg)iF919s2uc=ay1wE80>(xkEPe-lMkwkJNF*Ga& zkEV_!4hiuiSl*meb)wsO;)))+h$FKpyx41s3AH@#p53yeD$L|, 2014 +# jmontane, 2014 msgid "" msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-04-23 18:50+0000\n" -"Last-Translator: jmontane \n" -"Language-Team: Catalan (http://www.transifex.com/projects/p/umap/language/" -"ca/)\n" -"Language: ca\n" +"PO-Revision-Date: 2017-09-23 19:45+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Catalan (http://www.transifex.com/yohanboniface/umap/language/ca/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 @@ -33,10 +32,8 @@ msgid "Type editors nick to add…" msgstr "Escriviu els sobrenoms dels editors a afegir..." #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Escriviu els sobrenoms dels editors a afegir..." +msgstr "" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -71,9 +68,7 @@ msgstr "Trieu un proveïdor" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"El uMap us permet crear mapes amb capes de l'OpenStreetMap en un minut i incrustar-los al vostre lloc web." +msgstr "El uMap us permet crear mapes amb capes de l'OpenStreetMap en un minut i incrustar-los al vostre lloc web." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -89,9 +84,7 @@ msgstr "Gestioneu els colors i les icones dels PDI" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Gestioneu les opcions del mapa: mostreu un minimapa, ubiqueu l'usuari en " -"carregar..." +msgstr "Gestioneu les opcions del mapa: mostreu un minimapa, ubiqueu l'usuari en carregar..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -122,14 +115,10 @@ msgstr "Jugueu amb la demostració" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Aquesta és una versió de demostració, usada per a fer proves i desplegar " -"versions. Si us cal un versió estable, useu " -"%(stable_url)s. També podeu hostatjar la vostra pròpia còpia, és codi lliure!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Aquesta és una versió de demostració, usada per a fer proves i desplegar versions. Si us cal un versió estable, useu %(stable_url)s. També podeu hostatjar la vostra pròpia còpia, és codi lliure!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -173,8 +162,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -217,5 +206,182 @@ msgstr "Cerca" msgid "View the map" msgstr "Mostra el mapa" -#~ msgid "Map settings" -#~ msgstr "Paràmetres del mapa" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "L'enllaç d'edició secret és %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Tothom pot editar" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Només es pot editar amb l'enllaç d'edició secret" + +#: models.py:20 +msgid "name" +msgstr "nom" + +#: models.py:42 +msgid "No licence set" +msgstr "No s'ha indicat llicència" + +#: models.py:51 +msgid "details" +msgstr "detalls" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Enllaç a una pàgina on es detalla la llicència." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "La plantilla de l'URL usa el format de tesel·les de l'OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Ordre de les capes de tessel·les al quadre d'edició" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Només els editors poden editar" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Només el propietari pot editar" + +#: models.py:118 +msgid "everyone (public)" +msgstr "tothom (públic)" + +#: models.py:119 +msgid "anyone with link" +msgstr "qualsevol amb l'enllaç" + +#: models.py:120 +msgid "editors only" +msgstr "només els editors" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "descripció" + +#: models.py:124 +msgid "center" +msgstr "centre" + +#: models.py:125 +msgid "zoom" +msgstr "escala" + +#: models.py:126 +msgid "locate" +msgstr "ubica" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Voleu ubicar l'usuari en carregar?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Trieu la llicència del mapa." + +#: models.py:130 +msgid "licence" +msgstr "llicència" + +#: models.py:135 +msgid "background" +msgstr "fons" + +#: models.py:136 +msgid "owner" +msgstr "propietari" + +#: models.py:137 +msgid "editors" +msgstr "editors" + +#: models.py:138 +msgid "edit status" +msgstr "edita l'estat" + +#: models.py:139 +msgid "share status" +msgstr "comparteix l'estat" + +#: models.py:140 +msgid "settings" +msgstr "paràmetres" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "El vostre mapa anònim s'ha enllaçat al compte %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Clon de" + +#: models.py:262 +msgid "display on load" +msgstr "mostra en carregar" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Mostra aquesta capa en carregar." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Heu iniciat sessió. S'està continuant..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Permisos del mapa" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Inicieu sessió per a procedir" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "L'usuari i contrasenya no coincideixen. Torneu-ho a intentar." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "S'ha creat el vostre mapa! Si voleu editar aquest mapa en un altre ordinador, useu aquest enllaç: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Enhorabona, s'ha creat el vostre mapa!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "S'ha actualitzat el mapa!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "S'han actualitzat els editors del mapa correctament!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Només el propietari pot suprimir el mapa." + +#: views.py:335 +#, 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 "S'ha clonat el vostre mapa! Si voleu editar aquest mapa en un altre ordinador, useu aquest enllaç: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Enhorabona, s'ha clonat el vostre mapa!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "S'ha suprimit la capa correctament." diff --git a/umap/locale/cs_CZ/LC_MESSAGES/django.mo b/umap/locale/cs_CZ/LC_MESSAGES/django.mo index 23782defba698556f049ce5b058d869cb8f67840..10e40bd3b5de0701dbd8c555954ef59b846ad567 100644 GIT binary patch literal 6717 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 EKgas+{r~^~ delta 1056 zcmXxiO-vI(6bJAr@=+>up@0?Y$7qBUvDihBxL6G_UW96l1fxdHv<$RRcAMQU&6=3T z#GBqGBzjRe5D#cLaN&T)#1Ia~n~CwD#+xxAG4Tq<|6BB>+u!cYcHVn4eck`8z4A3u zJ$a5MZnuZbOQND#mKyBJ6}OU=n_SL+}rz-x_-uI|y$;4$H6sK7sq;5)8sO zupMr~TE;5uJ8tSQ@B`8UzhDZ6s~Ky8qYxi<8(;KZ28Q7@j6e@kg2xaGvL(0|zJ&Dt z8vF_0!WdjeH&oartU`YF5jSNFe1dD}`U+N|g@P#eIMm<(G~fssel!D6#3aYZieAEsKFzl-7VK4hS(sa@nIN+S78UtLn`zk zY=Ms;b^aV4MkC8m$Mbs((w6T))XJjBejjpJ!Fzs{`yd5vIVGip*fIY|C@CePpu|)? zMKdm(mYlGCJDQ-%=zQAf0YPU+QKJ&I+sAAv zN|FmcD~jymY(`FSVNP%-Cv3?*%e84j{jTd&<)9h2CV43*xtkV6hovoBvb0ApIP9`j zq8mPGx#mQ#+Nn=8Uz5Vl=GZPYxjGYS4rt?fS@u`K2+MftbEBuOhs}Y3gq}?3r@5Xq z^fNt4L}*kvrNo#mOs619mTmA$V#dwz;a)x_oxJJHcq*((ZB&?3u9%Vr&pLN6+*G!9 zOMTIziBm(oSa5AoNX5-mO7G_9d6FAEZk|i^@vbgzo=x@BppL=5)$yiyprJHpZ9L8U zt+*-{NvdpQP&KtYIGGkj!RIy>vpK(eHvaBa7TsIZk~;I4KW|D?6y!a8tF6|4HPRMa Woo~AnP_bx7@B|kw^`KVTD}MoXwyd`R diff --git a/umap/locale/cs_CZ/LC_MESSAGES/django.po b/umap/locale/cs_CZ/LC_MESSAGES/django.po index 738b95ab..247c0c7d 100644 --- a/umap/locale/cs_CZ/LC_MESSAGES/django.po +++ b/umap/locale/cs_CZ/LC_MESSAGES/django.po @@ -9,15 +9,14 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2015-10-16 10:19+0000\n" -"Last-Translator: Jakub A. Tesinsky\n" -"Language-Team: Czech (Czech Republic) (http://www.transifex.com/" -"yohanboniface/umap/language/cs_CZ/)\n" -"Language: cs_CZ\n" +"PO-Revision-Date: 2017-09-19 23:03+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Czech (Czech Republic) (http://www.transifex.com/yohanboniface/umap/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"Language: cs_CZ\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" #: templates/404.html:7 msgid "Take me to the home page" @@ -33,10 +32,8 @@ msgid "Type editors nick to add…" msgstr "Vložte přezdívku přispěvovatele k přidání" #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Vložte přezdívku přispěvovatele k přidání" +msgstr "" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -71,9 +68,7 @@ msgstr "Vyberte poskytovatele mapy" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"Vytvářejte a sdílejte vlastní OpenStreet mapy " -"a během pár minut je použijte na svém webu." +msgstr "Vytvářejte a sdílejte vlastní OpenStreet mapy a během pár minut je použijte na svém webu." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -93,8 +88,7 @@ msgstr "Nastavte další možnosti - minimapu, lokalizaci uživatele, ..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" -msgstr "" -"Import existujících geodat v mnoha formátech (geojson, gpx, kml, osm...)" +msgstr "Import existujících geodat v mnoha formátech (geojson, gpx, kml, osm...)" #: templates/umap/about_summary.html:16 msgid "Choose the license for your data" @@ -121,14 +115,10 @@ msgstr "Vyzkoušejte si to hned" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Toto je ukázková verze, používaná na testování nových vydání uMap. Pokud " -"potřebujete stabilní verzi, použijte " -"%(stable_url)s. Můžete si taky stáhnout celý projekt a nainstalovat na " -"svém serveru, je to open source!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Toto je ukázková verze, používaná na testování nových vydání uMap. Pokud potřebujete stabilní verzi, použijte %(stable_url)s. Můžete si taky stáhnout celý projekt a nainstalovat na svém serveru, je to open source!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -172,8 +162,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -216,5 +206,182 @@ msgstr "Hledej" msgid "View the map" msgstr "Prohlídnout si tuto mapu" -#~ msgid "Map settings" -#~ msgstr "Nastavení mapy" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Tajný odkaz umožňující úpravu mapy je %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Kdokoli může editovat" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Lze upravovat jen pomocí tajného odkazu" + +#: models.py:20 +msgid "name" +msgstr "název" + +#: models.py:42 +msgid "No licence set" +msgstr "Licence nenastavena." + +#: models.py:51 +msgid "details" +msgstr "podrobnosti" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Odkaz na stránku s podrobnějším popisem licence." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Vzor URL ve formátu pro dlaždice OSM " + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Pořadí vrstev při editaci" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Jen přispěvovatelé mohou editovat" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Jen vlastník může editovat" + +#: models.py:118 +msgid "everyone (public)" +msgstr "kdokoli (veřejná)" + +#: models.py:119 +msgid "anyone with link" +msgstr "kdokoli kdo má odkaz" + +#: models.py:120 +msgid "editors only" +msgstr "jen připěvovatelé" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "popis" + +#: models.py:124 +msgid "center" +msgstr "střed" + +#: models.py:125 +msgid "zoom" +msgstr "přiblížení" + +#: models.py:126 +msgid "locate" +msgstr "lokalizuj" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Najdi poluhu uživatele na startu?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Vyberte si licenci mapy." + +#: models.py:130 +msgid "licence" +msgstr "licence" + +#: models.py:135 +msgid "background" +msgstr "pozadí" + +#: models.py:136 +msgid "owner" +msgstr "vlastník" + +#: models.py:137 +msgid "editors" +msgstr "přispěvovatelé" + +#: models.py:138 +msgid "edit status" +msgstr "kdo může provádět úpravy" + +#: models.py:139 +msgid "share status" +msgstr "nastavení sdílení" + +#: models.py:140 +msgid "settings" +msgstr "nastavení" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Vaše anonymní mapa byla připojena k vašemů účtu %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Kopie" + +#: models.py:262 +msgid "display on load" +msgstr "zbraz na startu" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Zobrazit tuto vrstvu na startu." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Jste přihlášeni. Jedeme dál ..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Přístupová oprávnění" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Pro pokračování se musíte přihlásit" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Jméno či heslo nesouhlasí. Zkuste to prosím znovu." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Vaše mapa byla vytvořena! Pokud chcete upravovat tuto mapu z jiného počítače, použijte tento odkaz: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Gratulujeme, vaše mapa byla vytvořena!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Mapa byla aktualizována!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Seznam přispěvovatelů byl úspěšně upraven!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Jen vlastník může vymzat tuto mapu." + +#: views.py:335 +#, 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 "Byla vytvořena kopie mapy! Pokud chcete upravovat tuto mapu z jiného počítače, použijte tento odkaz: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Gratulujeme, byla vytvořena kopie mapy!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Vrstva úspěšně vymazána." diff --git a/umap/locale/da/LC_MESSAGES/django.mo b/umap/locale/da/LC_MESSAGES/django.mo index 18ecf3c97198d8341c90e0ce4f75b6490b4c1a64..c7674b83efb983298e7002426b91fc9413030031 100644 GIT binary patch literal 6364 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 U(^wtVLW@l&T<=}z`rDrp zVg%(BN}rEt6z)Ne7i~lx@Ffhx*Dwx0!7Fed^0%o&M5p0A6tD*S;4?T3S7A4N50Aqp z>?CT?cT~F2unl>DU3d)!+KG<9G{i*@aN~Yi7=T6C59^R8cnmQht-{0bE#&?i@F)BL zPr^6Y4KJ(-+b}HFC78IDDrcs%PCLDwxAr?zp5EuQxjd!{OdFRyI%1jV)KLNQt z40!?L@E4qfNq7m3sL}%DjTPYvEW-vLvmb?b!oex$NrNanI3LLn3a6Ii1PZ5*BZPv} zq5*z52>yq7u{;s~7aW`oZ{glkYcZIcH+$AQJ8tJx@%bF(2LzuTM~55f+&gC}=_nyZ zSypJOoK>2Th9>O1w3MiuRf}J^zq`V2t=qU@=7f`1qMDHvn=+=QC{yPSHcgujS47UN z8d}u-+Y<@RDrqg|sRh4WU+N9{f^!8`^F~1nW$W%&f8D(oFf!wj_(UY06p72JMDk)B z(VLdG6S-?i!!Ak3v{GVPnK~{@=9D3>+E{=QEt+|07|OPlF{zhjp%h&-%dS6|9IIGn zQ7t-ltP-nYvRFwPdR6KwrpeeS25&v3geKjE;QjSx@VqaamdippV#%}|x@~ABRYV?4 zU1+MLgjQ(1ao0iu)nkt*h zpt;RgC0(FXRm;{jWzp>BhVI=&!TV4die@U7w85gUUdrNc*53^d`22GPyVcVn KnRBOxpZo)^s@FgO diff --git a/umap/locale/da/LC_MESSAGES/django.po b/umap/locale/da/LC_MESSAGES/django.po index 7ef85014..7d654af4 100644 --- a/umap/locale/da/LC_MESSAGES/django.po +++ b/umap/locale/da/LC_MESSAGES/django.po @@ -9,14 +9,13 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-06-02 15:12+0000\n" -"Last-Translator: Neogeografen \n" -"Language-Team: Danish (http://www.transifex.com/projects/p/umap/language/" -"da/)\n" -"Language: da\n" +"PO-Revision-Date: 2017-09-19 22:28+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Danish (http://www.transifex.com/yohanboniface/umap/language/da/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: da\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 @@ -33,10 +32,8 @@ msgid "Type editors nick to add…" msgstr "Indtast redaktørernes nickname for tilføjelse..." #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Indtast redaktørernes nickname for tilføjelse..." +msgstr "" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -71,9 +68,7 @@ msgstr "Vælg en udbyder" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"Med uMap kan du lave kort med OpenStreetMap " -"lag og på et minuts arbejde kan du indlejre disse på dit eget websted." +msgstr "Med uMap kan du lave kort med OpenStreetMap lag og på et minuts arbejde kan du indlejre disse på dit eget websted." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -89,9 +84,7 @@ msgstr "Håndterer POIs farver og ikoner" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Håndterer kortindstillinger: vis et miniaturekort, lokaliser brugeren ved " -"indlæsning..." +msgstr "Håndterer kortindstillinger: vis et miniaturekort, lokaliser brugeren ved indlæsning..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -122,14 +115,10 @@ msgstr "Leg med demoen" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Dette er en demo som bruges til test og forhåndstesting. Hvis du har brug " -"for en stabil testdemo, så brug %(stable_url)s. Du kan webhoste din egen testdemo. det er open " -"source!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Dette er en demo som bruges til test og forhåndstesting. Hvis du har brug for en stabil testdemo, så brug %(stable_url)s. Du kan webhoste din egen testdemo. det er open source!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -173,8 +162,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -217,5 +206,182 @@ msgstr "Søg" msgid "View the map" msgstr "Vis kortet" -#~ msgid "Map settings" -#~ msgstr "Kortindstillinger" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Hemmeligt redigeringslink er %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Alle kan redigere" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Er kun redigerbart med et hemmeligt link" + +#: models.py:20 +msgid "name" +msgstr "navn" + +#: models.py:42 +msgid "No licence set" +msgstr "Ingen licens angivet" + +#: models.py:51 +msgid "details" +msgstr "detaljer" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Link til siden hvor der er flere detaljer om licensen." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "URL skabelon bruger OSMs tile format" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Rækkefølge af tile-lag i redigeringsboksen" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Kun redaktører kan redigere" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Kun ejeren kan redigere" + +#: models.py:118 +msgid "everyone (public)" +msgstr "alle (fuldt offentlig)" + +#: models.py:119 +msgid "anyone with link" +msgstr "alle med et link" + +#: models.py:120 +msgid "editors only" +msgstr "kun redaktører " + +#: models.py:123 models.py:257 +msgid "description" +msgstr "beskrivelse" + +#: models.py:124 +msgid "center" +msgstr "center" + +#: models.py:125 +msgid "zoom" +msgstr "zoom" + +#: models.py:126 +msgid "locate" +msgstr "lokalisere" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Lokaliserer brugeren ved indlæsning?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Vælg kortlicensen." + +#: models.py:130 +msgid "licence" +msgstr "licens" + +#: models.py:135 +msgid "background" +msgstr "baggrund" + +#: models.py:136 +msgid "owner" +msgstr "ejer" + +#: models.py:137 +msgid "editors" +msgstr "redaktører" + +#: models.py:138 +msgid "edit status" +msgstr "ret status" + +#: models.py:139 +msgid "share status" +msgstr "Delestatus" + +#: models.py:140 +msgid "settings" +msgstr "indstillinger" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Dit anonyme kort er blevet tilføjet til din konto %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Klonet kopi af" + +#: models.py:262 +msgid "display on load" +msgstr "vis ved indlæsning" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Vis dette lag ved indlæsning" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Du er logget ind. Fortsætter..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Kortindstillinger" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Login ind for at fortsætte" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Dit brugernavn og adgangskode passer ikke. Prøv igen." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Dit kort er blevet lavet! Hvis du ønsker at rette dette kort fra en anden computer, så brug dette link: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Tillykke dit kort er nu blevet lavet!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Kortet er blevet opdateret!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Kortredaktører blev opdateret med succes!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Kun ejer kan slettet kortet." + +#: views.py:335 +#, 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 "Dit kort er blevet klonet! Hvis du ønsker at rette dette kort fra en anden computer, så brug dette link: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Tillykke dit kort er blevet klonet!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Lag blev slettet med succes." diff --git a/umap/locale/de/LC_MESSAGES/django.mo b/umap/locale/de/LC_MESSAGES/django.mo index 32b751c2d7a53be67426cbac1d1b182e7b6bb3ad..0e7b7465039e06e5541cf4ceb280811bbf8758fd 100644 GIT binary patch literal 7950 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 diff --git a/umap/locale/de/LC_MESSAGES/django.po b/umap/locale/de/LC_MESSAGES/django.po index bea9e4e9..93c3f0a3 100644 --- a/umap/locale/de/LC_MESSAGES/django.po +++ b/umap/locale/de/LC_MESSAGES/django.po @@ -3,25 +3,26 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# Klumbumbus , 2013-2014 +# Ettore Atalan , 2016 +# Jannis Leidel , 2016 +# Klumbumbus, 2013-2014,2016 msgid "" msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-03-01 23:34+0000\n" -"Last-Translator: Klumbumbus \n" -"Language-Team: German (http://www.transifex.com/projects/p/umap/language/" -"de/)\n" -"Language: de\n" +"PO-Revision-Date: 2017-09-19 22:04+0000\n" +"Last-Translator: Klumbumbus\n" +"Language-Team: German (http://www.transifex.com/yohanboniface/umap/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 msgid "Take me to the home page" -msgstr "" +msgstr "Zur Startseite zurückkehren" #: templates/auth/user_detail.html:7 #, python-format @@ -33,10 +34,8 @@ msgid "Type editors nick to add…" msgstr "Zum Hinzufügen von Bearbeitern, Benutzernamen hier eingeben..." #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Zum Hinzufügen von Bearbeitern, Benutzernamen hier eingeben..." +msgstr "Benutzernamen des neuen Besitzers eingeben..." #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -48,19 +47,19 @@ msgstr "Mehr" #: templates/registration/login.html:4 msgid "Please log in with your account" -msgstr "" +msgstr "Bitte melden Sie sich mit Ihrem Konto an" #: templates/registration/login.html:18 msgid "Username" -msgstr "" +msgstr "Benutzername" #: templates/registration/login.html:20 msgid "Password" -msgstr "" +msgstr "Passwort" #: templates/registration/login.html:21 msgid "Login" -msgstr "" +msgstr "Anmeldung" #: templates/registration/login.html:27 msgid "Please choose a provider" @@ -71,10 +70,7 @@ msgstr "Bitte wähle einen Anbieter" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"Mit uMap kannst du in einer Minute Karten mit OpenStreetMap-Hintergrund erstellen und sie in deine eigene " -"Internetseite einbinden." +msgstr "Mit uMap kannst du in einer Minute Karten mit OpenStreetMap-Hintergrund erstellen und sie in deine eigene Internetseite einbinden." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -90,15 +86,11 @@ msgstr "Verwalte Farben und Icons der POIs" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Verwalte Karteneinstellungen: eine Übersichtskarte anzeigen, den Nutzer beim " -"Seitenaufruf lokalisieren,..." +msgstr "Verwalte Karteneinstellungen: eine Übersichtskarte anzeigen, den Nutzer beim Seitenaufruf lokalisieren,..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" -msgstr "" -"Stapelverarbeitung beim Importieren von geotechnischen Daten (geojson, gpx, " -"kml, osm...)" +msgstr "Stapelverarbeitung beim Importieren von geotechnischen Daten (geojson, gpx, kml, osm...)" #: templates/umap/about_summary.html:16 msgid "Choose the license for your data" @@ -111,7 +103,7 @@ msgstr "Teile und binde deine Karte ein" #: templates/umap/about_summary.html:23 #, python-format msgid "And it's open source!" -msgstr "Und es ist open source!" +msgstr "Und es ist Open Source!" #: templates/umap/about_summary.html:32 templates/umap/navigation.html:31 msgid "Create a map" @@ -125,18 +117,14 @@ msgstr "Spiele mit der Demo" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Dies ist eine Demo-Instanz und wird benutzt für Tests und " -"Vorveröffentlichungen. Wenn du eine stabile Instanz benötigst, benutze bitte " -"%(stable_url)s. Du kannst auch deine eigene " -"Instanz hosten, es ist open source!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Dies ist eine Demo-Instanz und wird für Tests und Vorveröffentlichungen benutzt. Wenn du eine stabile Instanz benötigst, benutze bitte %(stable_url)s. Du kannst auch deine eigene Instanz hosten, uMap ist Open Source!" #: templates/umap/home.html:17 msgid "Map of the uMaps" -msgstr "Karte aller \"uMap\"-Karten" +msgstr "Karte aller „uMap“-Karten" #: templates/umap/home.html:24 msgid "Get inspired, browse maps" @@ -164,7 +152,7 @@ msgstr "Feedback" #: templates/umap/navigation.html:20 msgid "Change password" -msgstr "" +msgstr "Passwort ändern" #: templates/umap/navigation.html:22 msgid "Log out" @@ -172,37 +160,37 @@ msgstr "Ausloggen" #: templates/umap/password_change.html:6 msgid "Password change" -msgstr "" +msgstr "Passwortänderung" #: templates/umap/password_change.html:7 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 "" +"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:12 msgid "Old password" -msgstr "" +msgstr "Altes Passwort" #: templates/umap/password_change.html:14 msgid "New password" -msgstr "" +msgstr "Neues Passwort" #: templates/umap/password_change.html:16 msgid "New password confirmation" -msgstr "" +msgstr "Neues Passwort bestätigen" #: templates/umap/password_change.html:18 msgid "Change my password" -msgstr "" +msgstr "Mein Passwort ändern" #: templates/umap/password_change_done.html:6 msgid "Password change successful" -msgstr "" +msgstr "Passwortänderung erfolgreich" #: templates/umap/password_change_done.html:7 msgid "Your password was changed." -msgstr "" +msgstr "Ihr Passwort wurde geändert." #: templates/umap/search.html:13 msgid "Not map found." @@ -220,5 +208,182 @@ msgstr "Suchen" msgid "View the map" msgstr "Diese Karte anzeigen" -#~ msgid "Map settings" -#~ msgstr "Karteneinstellungen" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Geheimer Bearbeitungslink ist %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Jeder kann bearbeiten" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Nur mit geheimen Bearbeitungslink zu bearbeiten" + +#: models.py:20 +msgid "name" +msgstr "Name" + +#: models.py:42 +msgid "No licence set" +msgstr "Keine Lizenz ausgewählt" + +#: models.py:51 +msgid "details" +msgstr "Details" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Verlinke auf eine Seite mit der Lizenz." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Das URL-Template nutzt das OSM Tile Format" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Reihenfolge der Karten-Ebenen in der Bearbeiten-Box" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Nur Bearbeiter können bearbeiten" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Nur der Ersteller kann bearbeiten" + +#: models.py:118 +msgid "everyone (public)" +msgstr "Jeder (Öffentlich)" + +#: models.py:119 +msgid "anyone with link" +msgstr "Jeder mit Link" + +#: models.py:120 +msgid "editors only" +msgstr "Nur Bearbeiter " + +#: models.py:123 models.py:257 +msgid "description" +msgstr "Beschreibung" + +#: models.py:124 +msgid "center" +msgstr "Mittelpunkt" + +#: models.py:125 +msgid "zoom" +msgstr "Zoom" + +#: models.py:126 +msgid "locate" +msgstr "lokalisiere" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Standort des Benutzers beim Seitenaufruf bestimmen?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Kartenlizenz auswählen" + +#: models.py:130 +msgid "licence" +msgstr "Lizenz" + +#: models.py:135 +msgid "background" +msgstr "Hintergrund" + +#: models.py:136 +msgid "owner" +msgstr "Ersteller" + +#: models.py:137 +msgid "editors" +msgstr "Bearbeiter" + +#: models.py:138 +msgid "edit status" +msgstr "Bearbeitungsstatus" + +#: models.py:139 +msgid "share status" +msgstr "Teilen-Status" + +#: models.py:140 +msgid "settings" +msgstr "Einstellungen" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Deine anonyme Karte wurde deinem Account %s zugeordnet." + +#: models.py:211 +msgid "Clone of" +msgstr "Duplicat von" + +#: models.py:262 +msgid "display on load" +msgstr "Beim Seitenaufruf einblenden" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Diese Ebene beim Seitenaufruf einblenden." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Du bist eingeloggt. Weiterleitung..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Kartenberechtigungen" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Bitte logge dich ein, um fortzufahren." + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Dein Benutzername und Password stimmen nicht überein. Bitte versuche es noch einmal." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Deine Karte wurde erstellt! Wenn du diese Karte von einem anderen Computer aus bearbeiten möchtest, benutze bitte diesen Link: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Glückwunsch, deine Karte wurde erstellt!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Karte wurde aktualisiert!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Bearbeiter erfolgreich geändert" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Nur der Ersteller kann die Karte löschen." + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Glückwunsch, deine Karte wurde kopiert!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Ebene erfolgreich gelöscht." diff --git a/umap/locale/en/LC_MESSAGES/django.po b/umap/locale/en/LC_MESSAGES/django.po index 9c54f1a1..5a040279 100644 --- a/umap/locale/en/LC_MESSAGES/django.po +++ b/umap/locale/en/LC_MESSAGES/django.po @@ -204,3 +204,183 @@ msgstr "" #: views.py:190 msgid "View the map" msgstr "" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "" + +#: models.py:20 +msgid "name" +msgstr "" + +#: models.py:42 +msgid "No licence set" +msgstr "" + +#: models.py:51 +msgid "details" +msgstr "" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "" + +#: models.py:118 +msgid "everyone (public)" +msgstr "" + +#: models.py:119 +msgid "anyone with link" +msgstr "" + +#: models.py:120 +msgid "editors only" +msgstr "" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "" + +#: models.py:124 +msgid "center" +msgstr "" + +#: models.py:125 +msgid "zoom" +msgstr "" + +#: models.py:126 +msgid "locate" +msgstr "" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "" + +#: models.py:130 +msgid "licence" +msgstr "" + +#: models.py:135 +msgid "background" +msgstr "" + +#: models.py:136 +msgid "owner" +msgstr "" + +#: models.py:137 +msgid "editors" +msgstr "" + +#: models.py:138 +msgid "edit status" +msgstr "" + +#: models.py:139 +msgid "share status" +msgstr "" + +#: models.py:140 +msgid "settings" +msgstr "" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "" + +#: models.py:211 +msgid "Clone of" +msgstr "" + +#: models.py:262 +msgid "display on load" +msgstr "" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "" + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "" + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "" diff --git a/umap/locale/es/LC_MESSAGES/django.mo b/umap/locale/es/LC_MESSAGES/django.mo index f030120e1aed099d3d20080c3d299798999cd7c9..558a2c141643067fb250ec7e4db29a16f62d91a7 100644 GIT binary patch literal 7778 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 Bx2pgE delta 1230 zcmXxiOGs2v9LMo9K2k@=SH7Rua;(fDA6RN>h(?sXutm6#8krHnbZlnSY@sc(w$VYT zT=bx2Q8cs*Tu6mP1x1?#v04Ptwjg`Z_c!U`p8GlXIG+Fi{LlHcZ@Fq_B{yl#(0ueV z`X!e!?f5N$7i~4sm}LBjUi^af=t(kWFLq!BUcg+ufmwJT%ke2X_yIHU7ZzbEi>4Yg zW2zVwGf|71up3jb2YJj%URtORmDnU^;}c{p^Bnd2m#6^mQ0uK?Ca$f|r?EHzO#v#w zN-QD1*~LJaA4X-?k5_O4EAcP#meTV{n(Um!%oQV;0;bg-h6kKd~EqME7DC72rB<#)qhd7g0yCf(rNtRS7pA zgfP|Upl|*A7|u`~bBcj>)Q`0o#9q9LIrte>>hGuo*VgBgJpXrGfT~0zDxn@EwmFS? zIE<>~Mbvt?Q5Apeq5ks>o-v`z=jXsw>S-i~nO*l9YJpprPo)-6iN5C`t5Fw13wu$4 z_n_A6Lhh?MgA*7){yknL;9jZzw4HR7utp!W?R1rFqix+7phH(RbQIdP&Qi(w=xRzt zO_z*)#ha?Drs}C8JLtMAZpDx90F^Nti#L@~l~5H(I=+j1+(Orp>0DL9jizc8(seJk z(d+1{gj$teodcoqsOby@oD;_nMcSMZe|R_;j>I0NB)O`?L4P#p_?a9t2Sx^h0mnZY za3VwgaL}0wjfeFIJDujW3GQfmXwZoc1)cGu%q_WFY<7ByT}=OB-)7XrvON1;_FQI> zeUnv`Ffe6bXHVH9IisH4zWP>QV~bPY)YjY(dyzAkkkLg@XM9vk`|Yc|Qu{lv*3Re8 z<*=^b2?U+9p-4PP#6BqKu*rqKn7b&&Wt)rZVzb58We=8C*qdeLiDRL#T`oWW5AM8> A@Bjb+ diff --git a/umap/locale/es/LC_MESSAGES/django.po b/umap/locale/es/LC_MESSAGES/django.po index f7b75419..1c0586bb 100644 --- a/umap/locale/es/LC_MESSAGES/django.po +++ b/umap/locale/es/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Igor Támara , 2013 # Marco Antonio , 2014 @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-09-28 03:51+0000\n" +"PO-Revision-Date: 2017-09-19 22:04+0000\n" "Last-Translator: Marco Antonio \n" "Language-Team: Spanish (http://www.transifex.com/yohanboniface/umap/language/es/)\n" "MIME-Version: 1.0\n" @@ -208,3 +208,183 @@ msgstr "Buscar" #: views.py:190 msgid "View the map" msgstr "Ver el mapa" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "El enlace secreto de edición es %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Todos pueden editar" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Sólo puede editarse con el enlace secreto de edición" + +#: models.py:20 +msgid "name" +msgstr "nombre" + +#: models.py:42 +msgid "No licence set" +msgstr "Sin conjunto de licencias" + +#: models.py:51 +msgid "details" +msgstr "detalles" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Enlace a una página donde se detalla la licencia." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Plantilla URL usando el formato de teselas OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Orden de las capas de teselas en la caja de edición" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Solo los editores pueden editar" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Solo el propietario puede editar" + +#: models.py:118 +msgid "everyone (public)" +msgstr "todo el mundo (público)" + +#: models.py:119 +msgid "anyone with link" +msgstr "cualquiera que tenga el enlace" + +#: models.py:120 +msgid "editors only" +msgstr "sólo editores" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "descripción" + +#: models.py:124 +msgid "center" +msgstr "centrar" + +#: models.py:125 +msgid "zoom" +msgstr "acercar/alejar" + +#: models.py:126 +msgid "locate" +msgstr "localizar" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "¿Al cargar localizar el usuario?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Elija la licencia del mapa." + +#: models.py:130 +msgid "licence" +msgstr "licencia" + +#: models.py:135 +msgid "background" +msgstr "fondo" + +#: models.py:136 +msgid "owner" +msgstr "propietario" + +#: models.py:137 +msgid "editors" +msgstr "editores" + +#: models.py:138 +msgid "edit status" +msgstr "estado de la edición" + +#: models.py:139 +msgid "share status" +msgstr "compartir estado" + +#: models.py:140 +msgid "settings" +msgstr "ajustes" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Tu mapa anónimo se ha adjuntado a tu cuenta %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Clon de" + +#: models.py:262 +msgid "display on load" +msgstr "mostrar al cargar" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Mostrar esta capa al cargar." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Has iniciado sesión. Continuando..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Permisos del mapa" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Inicia sesión para poder continuar" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Tu nombre de usuario y contraseña no coinciden. Inténtalo de nuevo." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "¡Tu mapa ha sido creado! Si deseas editarlo desde otro ordenador, por favor usa este enlace: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "¡Enhorabuena! ¡Tu mapa ha sido creado!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "¡El mapa ha sido actualizado!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "¡Los editores del mapas han sido actualizados con éxito!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Sólo el propietario puede borrar el mapa." + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "¡Enhorabuena! ¡Tu mapa ha sido clonado!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Se eliminó la capa con éxito." diff --git a/umap/locale/fi/LC_MESSAGES/django.mo b/umap/locale/fi/LC_MESSAGES/django.mo index d52aa379e41f9e1f18634f09c9ef7e6f4f47f92a..ad9da68e2d745cb2530dca1b5c16666b0f0267c6 100644 GIT binary patch literal 6765 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, 2013 -# jaakkoh , 2013 +# Antti Castrén, 2014 +# Jaakko Helleranta , 2013 +# Jaakko Helleranta , 2013 msgid "" msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-03-04 21:50+0000\n" -"Last-Translator: acastren\n" -"Language-Team: Finnish (http://www.transifex.com/projects/p/umap/language/" -"fi/)\n" -"Language: fi\n" +"PO-Revision-Date: 2017-09-23 19:23+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Finnish (http://www.transifex.com/yohanboniface/umap/language/fi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 @@ -35,10 +34,8 @@ msgid "Type editors nick to add…" msgstr "Kirjoita muokkaajan nimi lisätäksesi..." #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Kirjoita muokkaajan nimi lisätäksesi..." +msgstr "" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -73,10 +70,7 @@ msgstr "Valitse mieleisesi palveluntarjoaja" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"uMap mahdollistaa OpenStreetMap-pohjaisten " -"räätälöityjen karttojen luomisen ja liittämisen verkkosivuusi muutamassa " -"minuutissa." +msgstr "uMap mahdollistaa OpenStreetMap-pohjaisten räätälöityjen karttojen luomisen ja liittämisen verkkosivuusi muutamassa minuutissa." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -92,9 +86,7 @@ msgstr "Valitse ja hallinnoi POI-merkintöjen värit ja karttakuvakkeet" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Hallitse kartta-optiot: näytä mini-kartta, paikanna käyttäjä sivun " -"latauksessa, ..." +msgstr "Hallitse kartta-optiot: näytä mini-kartta, paikanna käyttäjä sivun latauksessa, ..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -125,14 +117,10 @@ msgstr "Tongi demoa sielusi kyllyydestä!" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Tämä on uMapin demo-instanssi, jota käytetään testaamiseen ja " -"väliversioille. Jos tarvitset vakaan version, niin käytäthän %(stable_url)s :a. Voit myös tarjota oman instanssin " -"- avoin lähdekoodi rulettaa!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Tämä on uMapin demo-instanssi, jota käytetään testaamiseen ja väliversioille. Jos tarvitset vakaan version, niin käytäthän %(stable_url)s :a. Voit myös tarjota oman instanssin - avoin lähdekoodi rulettaa!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -176,8 +164,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -220,5 +208,182 @@ msgstr "Etsi" msgid "View the map" msgstr "Katso karttaa" -#~ msgid "Map settings" -#~ msgstr "Kartan asetukset" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Salainen muokkauslinkki on %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Kuka tahansa saa muokata" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Muokattavissa vain salaisella muokkauslinkillä" + +#: models.py:20 +msgid "name" +msgstr "nimi" + +#: models.py:42 +msgid "No licence set" +msgstr "Määrittämätön lisenssi" + +#: models.py:51 +msgid "details" +msgstr "tarkemmat tiedot" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Linkki sivulle, jossa lisenssi on määritetty yksityiskohtaisesti." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "OSM-karttatiiliformaattia mukaileva URL-sapluuna" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Taustakarttojen järjestys muokkauslaatikossa" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Vain julkaisijat saavat muokata" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Vain omistaja saa muokata" + +#: models.py:118 +msgid "everyone (public)" +msgstr "kaikille (julkinen)" + +#: models.py:119 +msgid "anyone with link" +msgstr "linkinhaltijoille" + +#: models.py:120 +msgid "editors only" +msgstr "vain muokkaajille" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "kuvaus" + +#: models.py:124 +msgid "center" +msgstr "keskitä" + +#: models.py:125 +msgid "zoom" +msgstr "zoomaa" + +#: models.py:126 +msgid "locate" +msgstr "paikanna" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Paikanna käyttäjä sivua ladattaessa?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Valitse kartan lisenssi" + +#: models.py:130 +msgid "licence" +msgstr "lisenssi" + +#: models.py:135 +msgid "background" +msgstr "tausta" + +#: models.py:136 +msgid "owner" +msgstr "omistaja" + +#: models.py:137 +msgid "editors" +msgstr "julkaisija" + +#: models.py:138 +msgid "edit status" +msgstr "muokkaa tilaa" + +#: models.py:139 +msgid "share status" +msgstr "jaa status" + +#: models.py:140 +msgid "settings" +msgstr "asetukset" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Anonyymi karttasi on liitetty tiliisi %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Kloonattu kartasta" + +#: models.py:262 +msgid "display on load" +msgstr "näytä ladattaessa" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Näytä tämä kerros ladattaessa." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Sisäänkirjautumisesi onnistui. Jatketahan..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Kartan oikeudet" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Rekisteröidythän jatkaaksesi, jooko?" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Käyttäjätunnuksesi ja salasanasi eivät täsmänneet. Yritä uudestaan ole hyvä." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Karttasi on luotu! Jos haluat muokata tätä karttaa joltain muulta tietokoneelta, käytä tätä linkkiä: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Onneksi olkoon! Uusi karttasi on luotu!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Kartta on päivitetty!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Kartan toimittajat päivitetty onnistuneesti!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Vain kartan omistaja voi poistaa kartan." + +#: views.py:335 +#, 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 "Karttasi on kloonattu! Jos haluat muokata tätä karttaa joltain muulta tietokoneelta, käytä tätä linkkiä: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Onneksi olkoon! Karttasi on kloonattu!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Kerros onnistuneesti poistettu. Pysyvästi." diff --git a/umap/locale/fr/LC_MESSAGES/django.mo b/umap/locale/fr/LC_MESSAGES/django.mo index f2c2f5d6fc764395efbcc17a5fe01aa3027bdc9b..34fd05dd4ab7d66d508db9b31c2558d06c59845a 100644 GIT binary patch literal 7868 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 diff --git a/umap/locale/fr/LC_MESSAGES/django.po b/umap/locale/fr/LC_MESSAGES/django.po index 68e441fb..3c4ec38c 100644 --- a/umap/locale/fr/LC_MESSAGES/django.po +++ b/umap/locale/fr/LC_MESSAGES/django.po @@ -1,10 +1,11 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Buggi, 2013 # Buggi, 2013 +# Philippe Verdy, 2017 # yohanboniface , 2014,2016 # YOHAN BONIFACE , 2012 msgid "" @@ -12,8 +13,8 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-09-09 19:41+0000\n" -"Last-Translator: yohanboniface \n" +"PO-Revision-Date: 2017-09-19 22:04+0000\n" +"Last-Translator: Philippe Verdy\n" "Language-Team: French (http://www.transifex.com/yohanboniface/umap/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -32,11 +33,11 @@ msgstr "Consulter les cartes de %(current_user)s" #: templates/leaflet_storage/map_detail.html:24 msgid "Type editors nick to add…" -msgstr "Taper le nom d'un éditeur…" +msgstr "Entrez le nom d'un modificateur…" #: templates/leaflet_storage/map_detail.html:27 msgid "Type new owner nick…" -msgstr "Nouveau du nouveau propriétaire…" +msgstr "Entrez le nom du nouveau propriétaire…" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -75,11 +76,11 @@ msgstr "uMap permet de créer des cartes personnalisées sur des fonds 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 xv%h=XNk?rdTuZ~wIdM0WP1{*_qr!ixtbNAK, 2013-2015 +# idetao , 2017 +# Maurizio Napolitano , 2013-2015,2018 # claudiamocci , 2013 # YOHAN BONIFACE , 2012 msgid "" @@ -11,19 +12,18 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2015-11-02 09:15+0000\n" +"PO-Revision-Date: 2018-02-22 11:08+0000\n" "Last-Translator: Maurizio Napolitano \n" -"Language-Team: Italian (http://www.transifex.com/yohanboniface/umap/language/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.com/yohanboniface/umap/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: templates/404.html:7 msgid "Take me to the home page" -msgstr "" +msgstr "Vai alla pagina principale" #: templates/auth/user_detail.html:7 #, python-format @@ -35,10 +35,8 @@ msgid "Type editors nick to add…" msgstr "Inserire nick degli editor d'aggiungere..." #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Inserire nick degli editor d'aggiungere..." +msgstr "Inserisci il nome del nuovo proprietario..." #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -50,19 +48,19 @@ msgstr "Altre mappe" #: templates/registration/login.html:4 msgid "Please log in with your account" -msgstr "" +msgstr "Accedi con il tuo account" #: templates/registration/login.html:18 msgid "Username" -msgstr "" +msgstr "Nome utente" #: templates/registration/login.html:20 msgid "Password" -msgstr "" +msgstr "Password" #: templates/registration/login.html:21 msgid "Login" -msgstr "" +msgstr "Login" #: templates/registration/login.html:27 msgid "Please choose a provider" @@ -73,9 +71,7 @@ msgstr "Seleziona un fornitore" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"uMap permette di creare mappe, che fanno uso di OpenStreetMap come sfondo, da inserire nel proprio sito in un minuto." +msgstr "uMap permette di creare mappe, che fanno uso di OpenStreetMap come sfondo, da inserire nel proprio sito in un minuto." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -91,9 +87,7 @@ msgstr "Scegli colori ed icone dei POI" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Aggiungi opzioni alla mappa: mappa panoramica, geolocalizzazione di un " -"utente al caricamento ..." +msgstr "Aggiungi opzioni alla mappa: mappa panoramica, geolocalizzazione di un utente al caricamento ..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -124,14 +118,10 @@ msgstr "Gioca con la demo" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Questa è una demo da utilizzare solo per test e prototipi. Qualora sia " -"necessaria una versione stabile si deve utilizzare l'indirizzo a href=" -"\"%(stable_url)s\">%(stable_url)s. Chiunque inoltre può crearsi una " -"propria istanza, uMap è software libero!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Questa è una demo da utilizzare solo per test e prototipi. Qualora sia necessaria una versione stabile si deve utilizzare l'indirizzo a href=\"%(stable_url)s\">%(stable_url)s. Chiunque inoltre può crearsi una propria istanza, uMap è software libero!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -163,7 +153,7 @@ msgstr "Feedback" #: templates/umap/navigation.html:20 msgid "Change password" -msgstr "" +msgstr "Cambia password" #: templates/umap/navigation.html:22 msgid "Log out" @@ -171,37 +161,37 @@ msgstr "Esci" #: templates/umap/password_change.html:6 msgid "Password change" -msgstr "" +msgstr "Cambia password" #: templates/umap/password_change.html:7 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 "" +"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 "Per motivi di sicurezza inserire la vecchia password, poi inserire quella nuova due volte così da verificare che sia stata scritta correttamente" #: templates/umap/password_change.html:12 msgid "Old password" -msgstr "" +msgstr "Password vecchia" #: templates/umap/password_change.html:14 msgid "New password" -msgstr "" +msgstr "Nuova password" #: templates/umap/password_change.html:16 msgid "New password confirmation" -msgstr "" +msgstr "Conferma della nuova password" #: templates/umap/password_change.html:18 msgid "Change my password" -msgstr "" +msgstr "Cambia la mia password" #: templates/umap/password_change_done.html:6 msgid "Password change successful" -msgstr "" +msgstr "Cambio della password effettuato con successo!" #: templates/umap/password_change_done.html:7 msgid "Your password was changed." -msgstr "" +msgstr "La tua password è stata cambiata." #: templates/umap/search.html:13 msgid "Not map found." @@ -219,5 +209,182 @@ msgstr "Cerca" msgid "View the map" msgstr "Visualizza la mappa" -#~ msgid "Map settings" -#~ msgstr "Impostazioni mappa" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Il link segreto per la modifica %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Chiunque può modificare" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Modificabile solo con il link segreto" + +#: models.py:20 +msgid "name" +msgstr "nome" + +#: models.py:42 +msgid "No licence set" +msgstr "Nessuna licenza definita" + +#: models.py:51 +msgid "details" +msgstr "dettagli" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Link alla pagina con i dettagli della licenza" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Modello dell'URL usando il formato delle tile OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Ordine degli sfondi (tilelayers) nel box di modifica" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Solo gli editor possono fare modifiche" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Solo il proprietario può effettuare modifiche" + +#: models.py:118 +msgid "everyone (public)" +msgstr "chiunque (pubblico)" + +#: models.py:119 +msgid "anyone with link" +msgstr "chiunque abbia il ilnk" + +#: models.py:120 +msgid "editors only" +msgstr "solo autori" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "descrizione" + +#: models.py:124 +msgid "center" +msgstr "centra" + +#: models.py:125 +msgid "zoom" +msgstr "zoom" + +#: models.py:126 +msgid "locate" +msgstr "localizza" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Geolocalizzare l'utente al caricamento?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Scegliere una licenza per la mappa." + +#: models.py:130 +msgid "licence" +msgstr "licenza" + +#: models.py:135 +msgid "background" +msgstr "sfondo" + +#: models.py:136 +msgid "owner" +msgstr "proprietario" + +#: models.py:137 +msgid "editors" +msgstr "editor" + +#: models.py:138 +msgid "edit status" +msgstr "stato della modifica" + +#: models.py:139 +msgid "share status" +msgstr "stato condivisione" + +#: models.py:140 +msgid "settings" +msgstr "impostazioni" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "La mappa anonima è stata associata all'account %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Duplicata da " + +#: models.py:262 +msgid "display on load" +msgstr "mostra al caricamento" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Visualizza questo layer al caricamento." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Utente loggato. Continuare..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Permessi della mappa" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Effettuare il login per continuare" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Username e password non corrispondono. Riprovare." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "La mappa è stata creata! Per modificarla da un altro computer, si deve utilizzare questo link: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Congratulazioni, la mappa è stata creata!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "La mappa è stata aggiornata!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Aggiornato l'elenco degli editor abilitati alla modifica della mappa!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Solo il proprietario può eliminare la mappa." + +#: views.py:335 +#, 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 "La mappa è stata clonata! Per modificarla usando un altro computer, si deve utilizzare questo link: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Perfetto, la tua mappa è stata clonata!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Layer eliminato correttamente" diff --git a/umap/locale/ja/LC_MESSAGES/django.mo b/umap/locale/ja/LC_MESSAGES/django.mo index 9998dc0cddfb2eae1ac6a30ed38f9fb41e4457f2..79c26bdde5923df241374f2686c79e0476308b6e 100644 GIT binary patch literal 8260 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 delta 1227 zcmYk*Ur19?9Ki9jHPdbCrlqcBdR=a%HJUWckFp+;!u~-I z)uD%|9*jzgqF@9?^`saQRMcBU7)e3&)I(4~^!?o}>Bl|ybMLu#=XdV!oK0;$SwH%r z+;&M3L0UC!%%W5~ezS5SW)~<`fFIG1UoeCvHl^BdBi7(iEXT{}!n?Q(pQ3^9uo!=% z2a6cANU2d($Hfvl8gU_R!9v`H9O@t^8K?_oVk79rhsaoJ8s+^LC<)%8j5mv=_$%LU zXK)g#N|XuKqL=(?4Hq)=ohUQw!P7X5wfF})R1I02=toJ|#7W-YfM4+dF2#1TRALuO z!a+_lu?%|g6iRW&afJNp1{YT-d$m3HWse-W(#~KD&kM-94cpO=V-!X}G+`q;Men%KZn3 z|CreYaSrKHWB=aQ>r5xHTLh@k!&^M;lzkJPR^UdW}?H%t-H{Z^p4+yPaM= z>HMMJ6bG`dl1&ypRO->MTpnvAqhGo+dUsiW@w#ABC>UxsLM^S$+3B+T)}j*^=bl~t zeCE8at7z2GiY9HTyys>}h1zpL<-{X^+pMZQkwKxOd#5JF9&, 2013-2014 # tomoya muramoto , 2016 @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-10-02 07:23+0000\n" +"PO-Revision-Date: 2017-09-19 22:33+0000\n" "Last-Translator: tomoya muramoto \n" "Language-Team: Japanese (http://www.transifex.com/yohanboniface/umap/language/ja/)\n" "MIME-Version: 1.0\n" @@ -206,3 +206,183 @@ msgstr "検索" #: views.py:190 msgid "View the map" msgstr "マップ表示" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "非公開の編集用リンク %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "だれでも編集可能" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "非公開の編集リンクからのみ編集可能" + +#: models.py:20 +msgid "name" +msgstr "名称" + +#: models.py:42 +msgid "No licence set" +msgstr "ライセンス未設定" + +#: models.py:51 +msgid "details" +msgstr "詳細" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "ライセンス詳細ページへのリンク" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "OSMタイルフォーマットを利用したURLテンプレート" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "編集ボックス内のタイルレイヤ並び順" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "指定ユーザのみ編集可能" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "所有者のみ編集可能" + +#: models.py:118 +msgid "everyone (public)" +msgstr "制限なし (公開)" + +#: models.py:119 +msgid "anyone with link" +msgstr "リンクを知っている人全員" + +#: models.py:120 +msgid "editors only" +msgstr "編集者のみ" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "概要" + +#: models.py:124 +msgid "center" +msgstr "中心点" + +#: models.py:125 +msgid "zoom" +msgstr "ズーム" + +#: models.py:126 +msgid "locate" +msgstr "現在地" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "読み込み時に現在地を表示?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "マップのライセンスを選択" + +#: models.py:130 +msgid "licence" +msgstr "ライセンス" + +#: models.py:135 +msgid "background" +msgstr "背景地図" + +#: models.py:136 +msgid "owner" +msgstr "所有者" + +#: models.py:137 +msgid "editors" +msgstr "編集者" + +#: models.py:138 +msgid "edit status" +msgstr "編集ステータス" + +#: models.py:139 +msgid "share status" +msgstr "共有状況" + +#: models.py:140 +msgid "settings" +msgstr "設定" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "所有者不明のマップがアカウント %s と関連付けられました" + +#: models.py:211 +msgid "Clone of" +msgstr "複製元" + +#: models.py:262 +msgid "display on load" +msgstr "読み込み時に表示" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "読み込み時にこのレイヤを表示" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "ログインしました" + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "マップ編集許可" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "ログインが必要です" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "ユーザ名とパスワードが不一致です。もう一度入力してください。" + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "マップの作成が完了しました! このマップを他の端末から編集する場合、いかのリンクを使用してください: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "マップ作成完了です!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "マップが更新されました!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "マップ編集者の更新が完了しました!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "マップを削除できるのは所有者だけです" + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "マップの複製が完了しました!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "レイヤ削除完了" diff --git a/umap/locale/lt/LC_MESSAGES/django.mo b/umap/locale/lt/LC_MESSAGES/django.mo index da0cb847f7c463ebeda42ae0d3c82be486ea654c..9dab2005f88c90af16305aed0b327a287d237ccb 100644 GIT binary patch literal 7949 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 delta 1021 zcmY+>OK1~87zgmFt$nw)Y18y!>$K3?hiP_O@ez|g4wZ^ggsLD#VUkRet()Dj54BL~ z%}c2Vha!q6@8UtkTR~_~f_hL;6v3mVH$l;h{=bbq_>tM)%CWuurRabq4m8@vhMq1Y#EB8Bd$ z?l6+ZU=-@`O0ZsKYz>os+;{&o}LU>M(L1DLeH6R-yzpMejsmiP*mLC{}7L5CtSom6!jXL0_MPCtX(_X5k-5%NcAgtnfbDxKTz{?Gb|gEuOldAV zZ+kT1Ior3glR6(7;xyIzle*5QxyIwc zdMY_VkAgHUp=*3)rJRQc+6WSLBu*%!Ew3W&M^veOruD4vcn06zl*O(4rYLPaRfX{3 z##zrbOhcB8qA=8SN2khk+*Y%Zo@(h}<3hdc99HXHhgvReZ@Pvf^M>m=zU>*$es}d& JsHMJ#e*vIYyyyS` diff --git a/umap/locale/lt/LC_MESSAGES/django.po b/umap/locale/lt/LC_MESSAGES/django.po index 95242114..383be1ea 100644 --- a/umap/locale/lt/LC_MESSAGES/django.po +++ b/umap/locale/lt/LC_MESSAGES/django.po @@ -3,26 +3,25 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# ramunasd , 2014 +# Ramūnas D. , 2014 +# Ugne Urbelyte , 2017 msgid "" msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-03-01 00:29+0000\n" -"Last-Translator: yohanboniface \n" -"Language-Team: Lithuanian (http://www.transifex.com/projects/p/umap/language/" -"lt/)\n" -"Language: lt\n" +"PO-Revision-Date: 2017-09-19 23:05+0000\n" +"Last-Translator: Ugne Urbelyte \n" +"Language-Team: Lithuanian (http://www.transifex.com/yohanboniface/umap/language/lt/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" -"%100<10 || n%100>=20) ? 1 : 2);\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\n" #: templates/404.html:7 msgid "Take me to the home page" -msgstr "" +msgstr "Grįžti į pagrindinį puslapį" #: templates/auth/user_detail.html:7 #, python-format @@ -31,15 +30,15 @@ msgstr "Peržiūrėti %(current_user)s žemėlapius" #: templates/leaflet_storage/map_detail.html:24 msgid "Type editors nick to add…" -msgstr "" +msgstr "Įveskite redaguotojų pseudonimus, kad pridėtu..." #: templates/leaflet_storage/map_detail.html:27 msgid "Type new owner nick…" -msgstr "" +msgstr "Įveskite naują vartotojo vardą" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" -msgstr "" +msgstr "pagal" #: templates/leaflet_storage/map_list.html:11 msgid "More" @@ -47,19 +46,19 @@ msgstr "Daugiau" #: templates/registration/login.html:4 msgid "Please log in with your account" -msgstr "" +msgstr "Prisijungti prie savo paskyros" #: templates/registration/login.html:18 msgid "Username" -msgstr "" +msgstr "Vartotojo vardas" #: templates/registration/login.html:20 msgid "Password" -msgstr "" +msgstr "Slaptažodis" #: templates/registration/login.html:21 msgid "Login" -msgstr "" +msgstr "Prisijungti" #: templates/registration/login.html:27 msgid "Please choose a provider" @@ -70,9 +69,7 @@ msgstr "Pasirinkite teikėją" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"uMap leidžia susikurti savo žemėlapį naudojant OpenStreetMap sluoksnius vos per minutę ir įterpti jį į savo puslapį." +msgstr "uMap leidžia susikurti savo žemėlapį naudojant OpenStreetMap sluoksnius vos per minutę ir įterpti jį į savo puslapį." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -88,13 +85,11 @@ msgstr "Valdyti POI spalvas ir ikonėles" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Valdyti žemėlapio nustatymus: rodyti mini žemėlapį, automatiškai nustatyti " -"padėtį.." +msgstr "Valdyti žemėlapio nustatymus: rodyti mini žemėlapį, automatiškai nustatyti padėtį.." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" -msgstr "" +msgstr "Masiškai importuoti geografinius duomenis (geojson, gpx, kml, osm...)" #: templates/umap/about_summary.html:16 msgid "Choose the license for your data" @@ -121,22 +116,18 @@ msgstr "Išbandyti demo" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Tai demonstracinė versija, naudojama testavimui ir naujų versijų " -"demonstravimui. Jei Jums reikia stabilios versijos, tada geriau naudokitės " -"%(stable_url)s. Jūs taip pat gali pasileisti " -"savo puslapį, juk tai atviras kodas!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Tai demonstracinė versija, naudojama testavimui ir naujų versijų demonstravimui. Jei Jums reikia stabilios versijos, tada geriau naudokitės %(stable_url)s. Jūs taip pat gali pasileisti savo puslapį, juk tai atviras kodas!" #: templates/umap/home.html:17 msgid "Map of the uMaps" -msgstr "" +msgstr "uMap žemėlapis" #: templates/umap/home.html:24 msgid "Get inspired, browse maps" -msgstr "" +msgstr "Peržiūrėkite žemėlapius, raskite įkvėpimą" #: templates/umap/navigation.html:12 msgid "My maps" @@ -160,7 +151,7 @@ msgstr "Atsiliepimai" #: templates/umap/navigation.html:20 msgid "Change password" -msgstr "" +msgstr "Keisti slaptažodį" #: templates/umap/navigation.html:22 msgid "Log out" @@ -168,37 +159,37 @@ msgstr "Atsijungti" #: templates/umap/password_change.html:6 msgid "Password change" -msgstr "" +msgstr "Slaptažodžio keitimas" #: templates/umap/password_change.html:7 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 "" +"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 "Saugumo sumetimais, įveskite savo dabartinį slaptažodį. Tuomet įveskite naują slaptažodį du kartus." #: templates/umap/password_change.html:12 msgid "Old password" -msgstr "" +msgstr "Senas slaptažodis" #: templates/umap/password_change.html:14 msgid "New password" -msgstr "" +msgstr "Naujas slaptažodis" #: templates/umap/password_change.html:16 msgid "New password confirmation" -msgstr "" +msgstr "Naujo slaptažodžio patvirtinimas" #: templates/umap/password_change.html:18 msgid "Change my password" -msgstr "" +msgstr "Keisti mano slaptažodį" #: templates/umap/password_change_done.html:6 msgid "Password change successful" -msgstr "" +msgstr "Slaptažodžio pakeitimas sėkmingas." #: templates/umap/password_change_done.html:7 msgid "Your password was changed." -msgstr "" +msgstr "Jūsų slaptažodis buvo pakeistas." #: templates/umap/search.html:13 msgid "Not map found." @@ -214,7 +205,184 @@ msgstr "Ieškoti" #: views.py:190 msgid "View the map" -msgstr "" +msgstr "Peržiūrėti žemėlapį" -#~ msgid "Map settings" -#~ msgstr "Žemėlapio nustatymai" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Slapta redagavimo nuoroda %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Visi gali redaguoti" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Redaguojamas tik su slapta nuoroda" + +#: models.py:20 +msgid "name" +msgstr "vardas" + +#: models.py:42 +msgid "No licence set" +msgstr "Nenustatyta licenzija" + +#: models.py:51 +msgid "details" +msgstr "išsamiau" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Licenzijos aprašymo nuoroda." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "URL šablonas OSM kaladėlių formatui" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Žemėlapio sluoksnių tvarka redagavimo lange" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Tik redaktoriai gali keisti" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Tik savininkas gali keisti" + +#: models.py:118 +msgid "everyone (public)" +msgstr "visi (viešai)" + +#: models.py:119 +msgid "anyone with link" +msgstr "visi su nuoroda" + +#: models.py:120 +msgid "editors only" +msgstr "tik keitėjai" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "aprašymas" + +#: models.py:124 +msgid "center" +msgstr "centras" + +#: models.py:125 +msgid "zoom" +msgstr "mastelis" + +#: models.py:126 +msgid "locate" +msgstr "nustatyti padėtį" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Nustatyti padėti užsikrovus?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Pasirinkite žemėlapio licenziją." + +#: models.py:130 +msgid "licence" +msgstr "licenzija" + +#: models.py:135 +msgid "background" +msgstr "fonas" + +#: models.py:136 +msgid "owner" +msgstr "savininkas" + +#: models.py:137 +msgid "editors" +msgstr "redaktoriai" + +#: models.py:138 +msgid "edit status" +msgstr "keisti būseną" + +#: models.py:139 +msgid "share status" +msgstr "pasidalinti būsena" + +#: models.py:140 +msgid "settings" +msgstr "nustatymai" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Jūsų anoniminis žemėlapis prijungtas prie Jūsų paskyros %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Kopija" + +#: models.py:262 +msgid "display on load" +msgstr "rodyti pasikrovus" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Rodyti šį sluoksnį pasrikrovus." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Sėkmingai prisijungėte. Kraunasi..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Žemėlapio leidimai" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Prisijunkite, kad tęsti" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Jūsų vardas ir slaptažodis yra neteisingi. Prašom pabandyti iš naujo." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Jūsų žemėlapis sėkmingai sukurtas! Jei norite redaguoti jį iš kito kompiuterio, pasinaudokite šia nuoroda: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Sveikinam, Jūsų žemėlapis sukurtas!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Žemėlapis atnaujintas!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Žemėlapio keitėjai atnaujinti!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Tik savininkas gali ištrinti žemėlapį." + +#: views.py:335 +#, 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 "Jūsų žemėlapis nukopijuotas! Jei norite redaguoti jį iš kito kompiuterio, pasinaudokite šia nuoroda: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Sveikinam, Jūsų žemėlapis buvo nukopijuotas!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Sluoksnis sėkmingai ištrintas." diff --git a/umap/locale/nl/LC_MESSAGES/django.mo b/umap/locale/nl/LC_MESSAGES/django.mo index 9e6b85ca7237c72872ab8b3f808907696184a67b..d260e00bb9856093b28c86ef6ca7d905937c2fa7 100644 GIT binary patch delta 100 zcmcb}{FyoQo)F7a1|VPpVi_RT0b*7lwgF-g2moRhAPxlL>5L2vVNm`%ARCCl0HhZV T@)C1XH(JbOWX(%V%w+%oEFueo delta 65 xcmey&e39AWo)F7a1|VPrVi_P-0b*t#)&XJ=umIxeKuJp=4N?OG8$)L@0ssoE2BrW2 diff --git a/umap/locale/nl/LC_MESSAGES/django.po b/umap/locale/nl/LC_MESSAGES/django.po index 6ca1c454..107b432a 100644 --- a/umap/locale/nl/LC_MESSAGES/django.po +++ b/umap/locale/nl/LC_MESSAGES/django.po @@ -205,3 +205,183 @@ msgstr "" #: views.py:190 msgid "View the map" msgstr "" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "" + +#: models.py:20 +msgid "name" +msgstr "naam" + +#: models.py:42 +msgid "No licence set" +msgstr "" + +#: models.py:51 +msgid "details" +msgstr "" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "" + +#: models.py:118 +msgid "everyone (public)" +msgstr "" + +#: models.py:119 +msgid "anyone with link" +msgstr "" + +#: models.py:120 +msgid "editors only" +msgstr "" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "" + +#: models.py:124 +msgid "center" +msgstr "" + +#: models.py:125 +msgid "zoom" +msgstr "" + +#: models.py:126 +msgid "locate" +msgstr "" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "" + +#: models.py:130 +msgid "licence" +msgstr "" + +#: models.py:135 +msgid "background" +msgstr "" + +#: models.py:136 +msgid "owner" +msgstr "" + +#: models.py:137 +msgid "editors" +msgstr "" + +#: models.py:138 +msgid "edit status" +msgstr "" + +#: models.py:139 +msgid "share status" +msgstr "" + +#: models.py:140 +msgid "settings" +msgstr "" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "" + +#: models.py:211 +msgid "Clone of" +msgstr "" + +#: models.py:262 +msgid "display on load" +msgstr "" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "" + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "" + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "" + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "" diff --git a/umap/locale/pl/LC_MESSAGES/django.po b/umap/locale/pl/LC_MESSAGES/django.po index 5999965e..09d71416 100644 --- a/umap/locale/pl/LC_MESSAGES/django.po +++ b/umap/locale/pl/LC_MESSAGES/django.po @@ -1,24 +1,24 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Daniel Koć , 2015 # endro, 2015 -# Teiron , 2016 +# Teiron, 2016 msgid "" msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-09-16 17:30+0000\n" -"Last-Translator: Teiron \n" +"PO-Revision-Date: 2017-09-22 02:09+0000\n" +"Last-Translator: Teiron\n" "Language-Team: Polish (http://www.transifex.com/yohanboniface/umap/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" #: templates/404.html:7 msgid "Take me to the home page" @@ -207,3 +207,183 @@ msgstr "Szukaj" #: views.py:190 msgid "View the map" msgstr "Zobacz mapę" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Sekretnym odnośnikiem do edycji jest %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Wszyscy mogą edytować" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Edycja możliwa tylko z sekretnym odnośnikiem" + +#: models.py:20 +msgid "name" +msgstr "nazwa" + +#: models.py:42 +msgid "No licence set" +msgstr "Brak ustawionej licencji" + +#: models.py:51 +msgid "details" +msgstr "szczegóły" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Odnośnik do strony ze szczegółowym opisem licencji." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Szablon URL używający formatu kafelków OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Kolejność podkładów w oknie edycji" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Tylko edytorzy mogą edytować" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Tylko właściciel może edytować" + +#: models.py:118 +msgid "everyone (public)" +msgstr "wszyscy (publiczne)" + +#: models.py:119 +msgid "anyone with link" +msgstr "każdy z linkiem" + +#: models.py:120 +msgid "editors only" +msgstr "tylko edytorzy" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "opis" + +#: models.py:124 +msgid "center" +msgstr "środek" + +#: models.py:125 +msgid "zoom" +msgstr "przybliżenie" + +#: models.py:126 +msgid "locate" +msgstr "lokalizuj" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Lokalizować użytkownika po załadowaniu?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Wybierz licencję mapy." + +#: models.py:130 +msgid "licence" +msgstr "licencja" + +#: models.py:135 +msgid "background" +msgstr "tło" + +#: models.py:136 +msgid "owner" +msgstr "właściciel" + +#: models.py:137 +msgid "editors" +msgstr "edytorzy" + +#: models.py:138 +msgid "edit status" +msgstr "status edycji" + +#: models.py:139 +msgid "share status" +msgstr "udostępnij status" + +#: models.py:140 +msgid "settings" +msgstr "ustawienia" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Twoja anonimowa mapa została dołączona do twojego konta %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Kopia" + +#: models.py:262 +msgid "display on load" +msgstr "wyświetl po załadowaniu" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Wyświetl tę warstwę po załadowaniu." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Jesteś zalogowany. Kontynuowanie..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Uprawnienia mapy" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Proszę się zalogować by kontynuować" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Twoja nazwa użytkownika i hasło nie pasują. Proszę spróbować ponownie." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Twoja mapa została utworzona! Jeśli chcesz edytować ją z innego komputera, użyj odnośnika: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Gratulacje, twoja mapa została utworzona!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Mapa została zaktualizowana!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Edytorzy mapy zaktualizowani pomyślnie!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Tylko właściciel może usunąć mapę." + +#: views.py:335 +#, 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 "Twoja mapa została skopiowana! Jeśli chcesz edytować ją z innego komputera, użyj odnośnika: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Gratulacje, twoja mapa została skopiowana!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Warstwa usunięta pomyślnie." diff --git a/umap/locale/pt/LC_MESSAGES/django.mo b/umap/locale/pt/LC_MESSAGES/django.mo index 74bffddd6862505f078c08d637d93d8d15f4e275..061bb4fc957668dbcb6f9f2e20afccf4a8ab6b01 100644 GIT binary patch literal 7774 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 delta 1228 zcmXxiUr19?9Ki9jX{npr)aG>ly)&m}jnp8@GLs6aEF)j?p@%D5STeWnwroX75anwe z3Vn*89)bj8=u5sug%kzVL-b(l$qJu)$f&-*tNys>eD03d^E>Bv&eDOIrirDB!h4E{ z(CTQn97=WLij$7W7bvv}zhM}cu^l~yO6|vk*nn5D0;kc3Pq7{s(7-QPimO`gjSGlTZav z7TAb2>7dVYE;xGKG~mk23LFY{g~tppUGw zfqG;)IlNbbTO+2EWH~5T{T|xPtQCD$2ytNyWSVc)O9p)61lJH2}-4Bkbk!q4OCG^i5)a4VT=4Aw$WrE8?klc1r3^1LykhuU(Ql? z6QN0zuVG&@_GJfG!wxwHsgP7dHsq50%`^$A02{Mo3%#5X6}NA@>_SS}MB_r+H(YkS z5mE&?0=al{2X@k=auOlwdWRF4wCasUjnf0iQe8&ev_@lADmPnH=xDZLW;$k=3?|jl z_;4(0m}5~RHDX#ZBb&%r@&|pRB&?mTv^#O$NRPyf%t^);U3+zzyGFlo|I!~yTXH^6 zk3(PbR_ph^YUglPzbnh?{_-);o=8V$q_flLXzyy@oqJt=#pyY0T`(;p6PLM7o%e^d zzp_<7uAKBTv1vpTDLX|, 2014 # Rui , 2016 @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-12-22 10:03+0000\n" +"PO-Revision-Date: 2017-09-19 22:04+0000\n" "Last-Translator: Rui \n" "Language-Team: Portuguese (http://www.transifex.com/yohanboniface/umap/language/pt/)\n" "MIME-Version: 1.0\n" @@ -206,3 +206,183 @@ msgstr "Procurar" #: views.py:190 msgid "View the map" msgstr "Ver o mapa" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Link secreto para edição é %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Todos podem editar" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Unicamente editável através de link secreto" + +#: models.py:20 +msgid "name" +msgstr "nome" + +#: models.py:42 +msgid "No licence set" +msgstr "Nenhuma licença definida" + +#: models.py:51 +msgid "details" +msgstr "detalhes" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Link para uma página detalhando a licença." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Modelo de URL no formato de telas OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Ordem das camadas na caixa de edição" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Só editores podem editar" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Só o proprietário pode editar" + +#: models.py:118 +msgid "everyone (public)" +msgstr "todos (público)" + +#: models.py:119 +msgid "anyone with link" +msgstr "qualquer um com o link" + +#: models.py:120 +msgid "editors only" +msgstr "só editores" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "descrição" + +#: models.py:124 +msgid "center" +msgstr "centro" + +#: models.py:125 +msgid "zoom" +msgstr "zoom" + +#: models.py:126 +msgid "locate" +msgstr "localizar" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Localizar usuário no início?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Escolha uma licença para o mapa." + +#: models.py:130 +msgid "licence" +msgstr "licença" + +#: models.py:135 +msgid "background" +msgstr "fundo" + +#: models.py:136 +msgid "owner" +msgstr "proprietário" + +#: models.py:137 +msgid "editors" +msgstr "editores" + +#: models.py:138 +msgid "edit status" +msgstr "editar estado" + +#: models.py:139 +msgid "share status" +msgstr "partilhar estado" + +#: models.py:140 +msgid "settings" +msgstr "parâmetros" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "O seu mapa anónimo foi anexado à sua conta %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Clone de" + +#: models.py:262 +msgid "display on load" +msgstr "mostrar no início" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Apresentar esta camada ao carregar." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Sucesso na identificação. Continuando..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Permissões do mapa" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Por favor entre na sua conta para continuar" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "O nome de usuário e senha não correspondem. Tente novamente." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "O seu mapa foi criado! Se quiser editar este mapa noutro computador, por favor utilize este link: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Parabéns, o seu mapa foi criado!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "O mapa foi atualizado!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Os editores do mapa foram atualizados com sucesso!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Só o proprietário pode eliminar o mapa." + +#: views.py:335 +#, 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 "O seu mapa foi clonado! Se quiser editar este mapa noutro computador, por favor utilize este link: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Parabéns, o seu mapa foi clonado!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Camada eliminada com sucesso." diff --git a/umap/locale/ru/LC_MESSAGES/django.mo b/umap/locale/ru/LC_MESSAGES/django.mo index 919eb1df059a69318f09d5ac03ecb4d65c08efb0..97c25ed3f1c87401307844cb7307b428da66c1d5 100644 GIT binary patch literal 9994 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 Q&Jb92eWrQZNk3=)2N5l!p8x;= delta 1223 zcmX}rTS(JU9Ki82U8$S8X*K7({k=?UI-Egy2`$Sm+RX|AyF5&{lEO<7yi#lM3%cX22?(cOgcQc78@`D_ah&5j7lbILD^V8+HnS%OT9!H{|04&4=D4^V=De$=}%&E z7E}(D4d$VX^;J0y*?AMn&Q9Y^yohT(9vsj0w zl;sTUKpB4mW!yd7gOAW6<4DhdG?HnE8F&f{@HP&hq{>bu88A>bSb`Z?jpcX*B~w>X zQa_IDMLk~WpGDcgx0UbBoZn8KbM55+BMmz8dp56|aN?#L)E;u!Mt*o6hMDETK!DRMT&@<42)a4M@&xY}C2%`&N* zBIhq>DT{k466`G&ysRSAvEXXNf)iHkL2aT)Ml7$JI7#;r5`CzCgGM!*H z6@`NS-k{;9vs>-%XblDoe`mnxY4?YMM!2glBwy$&Np2ly>9uy9F?!pBM&CjDUR$cP z-RjcMtqb~na&g3#vfZRFq&oFGn=`I8tl!$h`aoJ|%2scM&%4=Y_$q6*R7PH diff --git a/umap/locale/ru/LC_MESSAGES/django.po b/umap/locale/ru/LC_MESSAGES/django.po index 1ba5919c..21b58c65 100644 --- a/umap/locale/ru/LC_MESSAGES/django.po +++ b/umap/locale/ru/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Кругликов Илья , 2014 # Кругликов Илья , 2016 @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-10-20 07:57+0000\n" +"PO-Revision-Date: 2017-09-20 07:08+0000\n" "Last-Translator: Кругликов Илья \n" "Language-Team: Russian (http://www.transifex.com/yohanboniface/umap/language/ru/)\n" "MIME-Version: 1.0\n" @@ -206,3 +206,183 @@ msgstr "Найти" #: views.py:190 msgid "View the map" msgstr "Посмотреть карту" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Секретная ссылка для редактирования: %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Все могут редактировать" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Редактирование возможно только при наличии секретной ссылки" + +#: models.py:20 +msgid "name" +msgstr "название" + +#: models.py:42 +msgid "No licence set" +msgstr "Лицензия не задана" + +#: models.py:51 +msgid "details" +msgstr "подробности" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Ссылка на страницу с описанием лицензии" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "шаблон ссылки использует формат слоя OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Расположите слои карт в окне редактирования" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Только редакторы могут редактировать" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Только владелец может редактировать" + +#: models.py:118 +msgid "everyone (public)" +msgstr "все (без ограничений)" + +#: models.py:119 +msgid "anyone with link" +msgstr "все, у кого есть ссылка" + +#: models.py:120 +msgid "editors only" +msgstr "только редакторы" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "описание" + +#: models.py:124 +msgid "center" +msgstr "центр" + +#: models.py:125 +msgid "zoom" +msgstr "масштаб" + +#: models.py:126 +msgid "locate" +msgstr "геолокация" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Использовать геолокацию при загрузке?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Выберите лицензию для карты." + +#: models.py:130 +msgid "licence" +msgstr "лицензия" + +#: models.py:135 +msgid "background" +msgstr "фоновый слой" + +#: models.py:136 +msgid "owner" +msgstr "владелец" + +#: models.py:137 +msgid "editors" +msgstr "редакторы" + +#: models.py:138 +msgid "edit status" +msgstr "статус редактирования" + +#: models.py:139 +msgid "share status" +msgstr "статус совместного использования" + +#: models.py:140 +msgid "settings" +msgstr "настройки" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Ваша анонимная карта была присоединена к вашей учётной записи %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Копия" + +#: models.py:262 +msgid "display on load" +msgstr "показывать при загрузке" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Показать этот слой при загрузке." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Вы вошли. Продолжим..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Разрешения для карты" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Чтобы продолжить, выполните вход" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Имя пользователя или пароль неверные. Попробуйте ещё раз." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Ваша карта готова! Если вы хотите редактировать её на другом компьютере, используйте эту ссылку:: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Поздравляем, ваша карта готова!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Карта обновлена!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Редакторы карты успешно обновлены!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Только владелец карты может удалить её." + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Поздравляем, ваша карта скопирована!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Слой удалён." diff --git a/umap/locale/sk_SK/LC_MESSAGES/django.po b/umap/locale/sk_SK/LC_MESSAGES/django.po index cd4e7a8c..ea6c245e 100644 --- a/umap/locale/sk_SK/LC_MESSAGES/django.po +++ b/umap/locale/sk_SK/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Martin , 2016 # Martin , 2016 @@ -11,14 +11,14 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-10-09 11:19+0000\n" +"PO-Revision-Date: 2017-09-21 14:34+0000\n" "Last-Translator: Martin \n" "Language-Team: Slovak (Slovakia) (http://www.transifex.com/yohanboniface/umap/language/sk_SK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sk_SK\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" #: templates/404.html:7 msgid "Take me to the home page" @@ -207,3 +207,183 @@ msgstr "Hľadať" #: views.py:190 msgid "View the map" msgstr "Prezrieť si túto mapu" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Tajný odkaz umožňujúci úpravu mapy je %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Hocikto môže upravovať" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Možné upravovať iba pomocou tajného odkazu" + +#: models.py:20 +msgid "name" +msgstr "názov" + +#: models.py:42 +msgid "No licence set" +msgstr "Žiadná licencia nie je nastavená" + +#: models.py:51 +msgid "details" +msgstr "podrobnosti" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Odkaz na stránku s podrobnejším popisom licencie." + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Vzor URL vo formáte pre dlaždice OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Poradie vrstiev pri úprave" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Upravovať môžu iba prispievatelia" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Upravovať môže iba vlastník" + +#: models.py:118 +msgid "everyone (public)" +msgstr "hocikto (verejná)" + +#: models.py:119 +msgid "anyone with link" +msgstr "hocikto pomocou odkazu" + +#: models.py:120 +msgid "editors only" +msgstr "iba prispievatelia" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "popis" + +#: models.py:124 +msgid "center" +msgstr "stred" + +#: models.py:125 +msgid "zoom" +msgstr "priblíženie" + +#: models.py:126 +msgid "locate" +msgstr "lokalizovať" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Nájsť polohu používateľa pri štarte?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Vyberte si licenciu mapy." + +#: models.py:130 +msgid "licence" +msgstr "licencia" + +#: models.py:135 +msgid "background" +msgstr "pozadie" + +#: models.py:136 +msgid "owner" +msgstr "vlastník" + +#: models.py:137 +msgid "editors" +msgstr "prispievatelia" + +#: models.py:138 +msgid "edit status" +msgstr "kto môže vykonávať úpravy" + +#: models.py:139 +msgid "share status" +msgstr "nastavenie zdieľania" + +#: models.py:140 +msgid "settings" +msgstr "nastavenia" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Vaša anonymná mapa bola pripojená k vašemu účtu %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Kópia" + +#: models.py:262 +msgid "display on load" +msgstr "zobraziť pri štarte" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Zobraziť túto vrstvu pri štarte." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Ste prihláseni. Pokračujeme ďalej…" + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Prístupové práva" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Pre pokračovanie sa musíte prihlásiť" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Používateľské meno a heslo sa nezhodujú. Prosím, skúste to znova." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Vaša mapa bola vytvorená! Ak chcete upravovať túto mapu z iného počítača, použite tento odkaz: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Gratulujeme, vaša mapa bola vytvorená!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Mapa bola aktualizována!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Zoznam prispievovateľov bol úspešne upravený!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Iba vlastník môže vymazať túto mapu." + +#: views.py:335 +#, 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 "Bola vytvorená kópia mapy! Ak chcete upravovať túto mapu z iného počítača, použite tento odkaz: %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Gratulujeme, bola vytvorená kópia mapy!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Vrstva bola úspešne vymazaná." diff --git a/umap/locale/uk_UA/LC_MESSAGES/django.mo b/umap/locale/uk_UA/LC_MESSAGES/django.mo index 0626adfcd6e97805392f64adbfef638f65f799dd..90c615fe60f88dc30808955639bb49d48cf4588f 100644 GIT binary patch literal 10184 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 diff --git a/umap/locale/uk_UA/LC_MESSAGES/django.po b/umap/locale/uk_UA/LC_MESSAGES/django.po index 314911cd..349777a0 100644 --- a/umap/locale/uk_UA/LC_MESSAGES/django.po +++ b/umap/locale/uk_UA/LC_MESSAGES/django.po @@ -3,26 +3,24 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# Сергій Дубик , 2014 +# Сергій Дубик , 2014,2017 msgid "" msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-09-15 16:05+0000\n" +"PO-Revision-Date: 2017-09-20 04:50+0000\n" "Last-Translator: Сергій Дубик \n" -"Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/umap/" -"language/uk_UA/)\n" -"Language: uk_UA\n" +"Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/yohanboniface/umap/language/uk_UA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Language: uk_UA\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" #: templates/404.html:7 msgid "Take me to the home page" -msgstr "" +msgstr "Перемістіть мене на головну сторінку" #: templates/auth/user_detail.html:7 #, python-format @@ -34,10 +32,8 @@ msgid "Type editors nick to add…" msgstr "Введіть ім’я редактора, щоб додати…" #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Введіть ім’я редактора, щоб додати…" +msgstr "Введіть нік нового власника..." #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -49,19 +45,19 @@ msgstr "Ще" #: templates/registration/login.html:4 msgid "Please log in with your account" -msgstr "" +msgstr "Будь ласка, увійдіть за обліковим записом" #: templates/registration/login.html:18 msgid "Username" -msgstr "" +msgstr "Ім’я користувача" #: templates/registration/login.html:20 msgid "Password" -msgstr "" +msgstr "Пароль" #: templates/registration/login.html:21 msgid "Login" -msgstr "" +msgstr "Логін" #: templates/registration/login.html:27 msgid "Please choose a provider" @@ -72,9 +68,7 @@ msgstr "Виберіть провайдера автентифікації" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"uMap дає Вам можливість за лічені хвилини створювати мапи на основі даних OpenStreetMap та публікувати їх на своєму сайті." +msgstr "uMap дає Вам можливість за лічені хвилини створювати мапи на основі даних OpenStreetMap та публікувати їх на своєму сайті." #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -90,9 +84,7 @@ msgstr "Вибирайте потрібні кольори та значки д #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Змінюйте параметри мапи: відображення мінімапи, встановлення місця " -"користувача при завантаженні …" +msgstr "Змінюйте параметри мапи: відображення мінімапи, встановлення місця користувача при завантаженні …" #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -123,14 +115,10 @@ msgstr "Погратися з демо-версією" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Це демонстраційний сайт, що використовується для тестів та підготовки " -"стабільних випусків. Якщо Вам потрібна стабільна версія, перейдіть на %(stable_url)s. Ви також можете створити свою " -"інсталяцію, оскільки це відкрите ПЗ!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Це демонстраційний сайт, що використовується для тестів та підготовки стабільних випусків. Якщо Вам потрібна стабільна версія, перейдіть на %(stable_url)s. Ви також можете створити свою інсталяцію, оскільки це відкрите ПЗ!" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -162,7 +150,7 @@ msgstr "Зворотній зв’язок" #: templates/umap/navigation.html:20 msgid "Change password" -msgstr "" +msgstr "Зміна паролю" #: templates/umap/navigation.html:22 msgid "Log out" @@ -170,37 +158,37 @@ msgstr "Вийти" #: templates/umap/password_change.html:6 msgid "Password change" -msgstr "" +msgstr "Зміна паролю" #: templates/umap/password_change.html:7 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 "" +"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 "Будь ласка, введіть свій старий пароль, для надійності, а потім введіть новий пароль двічі, щоб ми могли переконатися, що Ви ввели його правильно." #: templates/umap/password_change.html:12 msgid "Old password" -msgstr "" +msgstr "Старий пароль" #: templates/umap/password_change.html:14 msgid "New password" -msgstr "" +msgstr "Новий пароль" #: templates/umap/password_change.html:16 msgid "New password confirmation" -msgstr "" +msgstr "Підтвердження для нового паролю" #: templates/umap/password_change.html:18 msgid "Change my password" -msgstr "" +msgstr "Змінити мій пароль" #: templates/umap/password_change_done.html:6 msgid "Password change successful" -msgstr "" +msgstr "Зміна паролю успішна." #: templates/umap/password_change_done.html:7 msgid "Your password was changed." -msgstr "" +msgstr "Ваш пароль змінено." #: templates/umap/search.html:13 msgid "Not map found." @@ -218,5 +206,182 @@ msgstr "Шукати" msgid "View the map" msgstr "Переглянути мапу" -#~ msgid "Map settings" -#~ msgstr "Налаштування мапи" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Секретне посилання для редагування: %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Кожен може редагувати" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Редагування можливе лише за наявності секретного посилання" + +#: models.py:20 +msgid "name" +msgstr "назва" + +#: models.py:42 +msgid "No licence set" +msgstr "Ліцензія не задана" + +#: models.py:51 +msgid "details" +msgstr "подробиці" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Посилання на сторінку з описом ліцензії" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "шаблон посилання використовує формат шару OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Розташуйте шари мап у вікні редагування" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Лише редактори можуть редагувати" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Лише власник може редагувати" + +#: models.py:118 +msgid "everyone (public)" +msgstr "усі (відкритий доступ)" + +#: models.py:119 +msgid "anyone with link" +msgstr "усі, у кого є посилання" + +#: models.py:120 +msgid "editors only" +msgstr "лише редактори" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "опис" + +#: models.py:124 +msgid "center" +msgstr "центр" + +#: models.py:125 +msgid "zoom" +msgstr "масштаб" + +#: models.py:126 +msgid "locate" +msgstr "геолокація" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Використовувати геолокацію при завантаженні?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Виберіть ліцензію для мапи." + +#: models.py:130 +msgid "licence" +msgstr "ліцензія" + +#: models.py:135 +msgid "background" +msgstr "фоновий шар" + +#: models.py:136 +msgid "owner" +msgstr "власник" + +#: models.py:137 +msgid "editors" +msgstr "редактори" + +#: models.py:138 +msgid "edit status" +msgstr "статус редагування" + +#: models.py:139 +msgid "share status" +msgstr "статус спільного використання" + +#: models.py:140 +msgid "settings" +msgstr "налаштування" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Ваша анонімна мапа була приєднана до Вашого облікового запису %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Копія " + +#: models.py:262 +msgid "display on load" +msgstr "показувати при завантаженні" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Показати цей шар при завантаженні." + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Ви увійшли. Продовжимо …" + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Дозволи для мапи" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Щоб продовжити, виконайте вхід" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Ім’я користувача або пароль невірні. Спробуйте ще раз." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Ваша мапа готова! Якщо Ви хочете редагувати її на іншому комп’ютері, використовуйте це посилання: %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Вітаємо, Ваша мапа готова!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Мапа оновлена!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Редактори мапи успішно оновлені!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Лише власник мапи може вилучити її." + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Вітаємо, Ваша мапа скопійована!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Шар вилучено." diff --git a/umap/locale/vi/LC_MESSAGES/django.mo b/umap/locale/vi/LC_MESSAGES/django.mo index 1ae04e617604386158ff169a1f8b73ca4881dce4..de82ae4546e13106bde429a44208285371f861ae 100644 GIT binary patch literal 7111 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\n" -"Language-Team: Vietnamese (http://www.transifex.com/projects/p/umap/language/" -"vi/)\n" -"Language: vi\n" +"PO-Revision-Date: 2017-09-20 09:39+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Vietnamese (http://www.transifex.com/yohanboniface/umap/language/vi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" "Plural-Forms: nplurals=1; plural=0;\n" #: templates/404.html:7 @@ -33,10 +32,8 @@ msgid "Type editors nick to add…" msgstr "Nhập nick thành viên để thêm vào..." #: templates/leaflet_storage/map_detail.html:27 -#, fuzzy -#| msgid "Type editors nick to add…" msgid "Type new owner nick…" -msgstr "Nhập nick thành viên để thêm vào..." +msgstr "" #: templates/leaflet_storage/map_list.html:7 views.py:184 msgid "by" @@ -71,9 +68,7 @@ msgstr "Hãy chọn một nhà cung cấp" msgid "" "uMap let you create maps with OpenStreetMap " "layers in a minute and embed them in your site." -msgstr "" -"uMap cho phép bạn tạo bản đồ với các layer của OpenStreetMap trong vài phút và chèn nó vào trong website của bạn" +msgstr "uMap cho phép bạn tạo bản đồ với các layer của OpenStreetMap trong vài phút và chèn nó vào trong website của bạn" #: templates/umap/about_summary.html:11 msgid "Choose the layers of your map" @@ -89,9 +84,7 @@ msgstr "Quản lý màu và biểu tượng POI" #: templates/umap/about_summary.html:14 msgid "Manage map options: display a minimap, locate user on load…" -msgstr "" -"Quản lý thiết lập bản đồ: hiển thị bản đồ con, xác định vị trí người dùng " -"khi tải bản đồ..." +msgstr "Quản lý thiết lập bản đồ: hiển thị bản đồ con, xác định vị trí người dùng khi tải bản đồ..." #: templates/umap/about_summary.html:15 msgid "Batch import geostructured data (geojson, gpx, kml, osm...)" @@ -122,14 +115,10 @@ msgstr "Xem thử demo" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" -msgstr "" -"Đây là một bản demo được dùng để kiểm tra và xuất bản thử. Nếu bạn cần một " -"bản ổ định, hãy sử dụng %(stable_url)s. Bạn " -"cũng có thể chạy nó trên máy tính của mình vì nó là phần mềm nguồn mở" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" +msgstr "Đây là một bản demo được dùng để kiểm tra và xuất bản thử. Nếu bạn cần một bản ổ định, hãy sử dụng %(stable_url)s. Bạn cũng có thể chạy nó trên máy tính của mình vì nó là phần mềm nguồn mở" #: templates/umap/home.html:17 msgid "Map of the uMaps" @@ -173,8 +162,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -217,5 +206,182 @@ msgstr "Tìm" msgid "View the map" msgstr "Xem bản đồ" -#~ msgid "Map settings" -#~ msgstr "Thiết lập bản đồ" +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "Link chỉnh sửa bí mật là %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "Ai cũng có thể chỉnh sửa" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "Chỉ có thể sửa với liên kết chỉnh sửa bí mật" + +#: models.py:20 +msgid "name" +msgstr "tên" + +#: models.py:42 +msgid "No licence set" +msgstr "Bản quyền không được đặt" + +#: models.py:51 +msgid "details" +msgstr "chi tiết" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "Liên kết đến trang có chi tiết về bản quyền" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "Mẫu URL sử dụng định dạng tile của OSM" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "Thứ tự các titlelayer trong hộp chỉnh sửa" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "Chỉ chỉnh sửa bởi người có quyền" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "Chỉ người sở hữu có thể chỉnh sửa" + +#: models.py:118 +msgid "everyone (public)" +msgstr "mọi người" + +#: models.py:119 +msgid "anyone with link" +msgstr "bất kì ai với liên kết" + +#: models.py:120 +msgid "editors only" +msgstr "chỉ người có quyền" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "mô tả" + +#: models.py:124 +msgid "center" +msgstr "trung tâm" + +#: models.py:125 +msgid "zoom" +msgstr "thu phóng" + +#: models.py:126 +msgid "locate" +msgstr "xác định" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "Xác định người dùng khi tải trang?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "Chọn bản quyền cho bản đồ" + +#: models.py:130 +msgid "licence" +msgstr "bản quyền" + +#: models.py:135 +msgid "background" +msgstr "nền" + +#: models.py:136 +msgid "owner" +msgstr "chủ nhân" + +#: models.py:137 +msgid "editors" +msgstr "người chỉnh sửa" + +#: models.py:138 +msgid "edit status" +msgstr "trạng thái chỉnh sửa" + +#: models.py:139 +msgid "share status" +msgstr "chia sẻ trạng thái" + +#: models.py:140 +msgid "settings" +msgstr "thiết lập" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "Bản đồ chưa đặt tên của bản đã được đính kèm vào tài khoản của bạn %s" + +#: models.py:211 +msgid "Clone of" +msgstr "Sao chép của" + +#: models.py:262 +msgid "display on load" +msgstr "hiển thị khi tải trang" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "Hiển thị layer này khi tải trang" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "Bạn đã đăng nhập, Đang tiếp tục..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "Quyền hạn" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "Vui lòng đăng nhập để thực thi" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "Tên truy cập hoặc mật khẩu không đúng. Vui lòng thử lại." + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "Bản đồ của bạn đã được tạo! Nếu bạn muốn chỉnh sửa bản đồ từ máy tính khác, vui lòng sử dụng liên kết này %(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "Chúc mừng, bản đồ của bạn đã được tạo!" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "Bản đồ đã được cập nhật!" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "Bản đồ được cập nhật thành công!" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "Chỉ chủ nhân của bản đồ mới có quyền xóa." + +#: views.py:335 +#, 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 "Bản đồ của bạn đã được sao chép. Nếu bạn muốn chỉnh sửa bản đồ từ máy tính khác, vui lòng sử dụng liên kết này %(anonymous_url)s" + +#: views.py:340 +msgid "Congratulations, your map has been cloned!" +msgstr "Chúc mừng, bản đồ của bạn đã được sao chép!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "Đã xóa layer" diff --git a/umap/locale/zh/LC_MESSAGES/django.mo b/umap/locale/zh/LC_MESSAGES/django.mo index 2d4e4752d58d3f0317d8d63c919f851120adaf96..9d53af5aa0e3d2f735e59b7e54ebb14a90c337c8 100644 GIT binary patch delta 334 zcmeC@o6R@jPW@Cy28LJ63=C`x3=9pd3=B#@x*bTX0_jyiS`IJ zY68j218It|2}tt;CGJBN zzK4o`gYuc#AsV@WG|38x*cXT2X4MURu%Q=`6;m3iV5K6AScn67$ka6Vp@m at1|R8Cx2my=JA1wSSeIxZ1!V4$Or&7L_)6s delta 307 zcmbQu*UvZMPJJgM1H&t31_m|;28I$=1_mV{T@9pFf%H5eEefQMK, 2014 msgid "" @@ -9,14 +9,13 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2014-06-23 01:07+0000\n" -"Last-Translator: sun wei \n" -"Language-Team: Chinese (http://www.transifex.com/projects/p/umap/language/" -"zh/)\n" -"Language: zh\n" +"PO-Revision-Date: 2017-09-20 05:52+0000\n" +"Last-Translator: yohanboniface \n" +"Language-Team: Chinese (http://www.transifex.com/yohanboniface/umap/language/zh/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: zh\n" "Plural-Forms: nplurals=1; plural=0;\n" #: templates/404.html:7 @@ -116,9 +115,9 @@ msgstr "试用示例" #, python-format msgid "" "This is a demo instance, used for tests and pre-rolling releases. If you " -"need a stable instance, please use " -"%(stable_url)s. You can also host your own instance, it's open source!" +"need a stable instance, please use %(stable_url)s. You can also host your own " +"instance, it's open source!" msgstr "" #: templates/umap/home.html:17 @@ -163,8 +162,8 @@ msgstr "" #: templates/umap/password_change.html:7 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." +"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 "" #: templates/umap/password_change.html:12 @@ -206,6 +205,3 @@ msgstr "搜索" #: views.py:190 msgid "View the map" msgstr "浏览地图" - -#~ msgid "Map settings" -#~ msgstr "地图设置" diff --git a/umap/locale/zh_TW/LC_MESSAGES/django.mo b/umap/locale/zh_TW/LC_MESSAGES/django.mo index f9b9c015c15392803d24ce18b59e4c8aabc4046a..32b7b9dd9b6aa9fd8642edc129fec6f8e3cf9308 100644 GIT binary patch literal 7326 zcmcJRdu$ZP9mgk+wyBdQX`0eDX`6wR0>O7SkOX2L2@ptVF(zR0P%B02yS2UHZuhji zhq+W$Y>1!Ou^Yf(V=%9PG1x#T#BZd&{s~p{N2R7xno7y--d-CCwN(@KA*J8n%-s13 zRh3rC%Hz-NJbv?=-)r{WyKdgg@H~t5b+mVGWb7rd?=$#^XaDCIqn|zCY_K0J1%D1M z1wRD82`;>avAe*hz&pSw_zlnnIru9074QOxKlUd6Jple1oDY5s-UiP9JY)BQOTe#! zmEae_I7sVW0>1{ffHdzY7y_rjyTK2@&w@7;F$UGxEgh%E_x3Ny`7^*j z;JpMSd)))2Y2L#i=~WJr9tjXjSqkJ}6Sx>W2`0hcgWJF@P?q$(0+xXpknA=K|6mHX z2t)|66(H%i5+wbe1WB(-kk0#k)gM#++dxv6>HQu^`~Ow(MmU+|+yPSm3=pZo?guf2g%nqVwEj6Y9s^14HZ}e# zNaq|-@4o~oe%}X4{;f!Al7AOSa_&>_3qd;Hqu>v~3f2Fn;@cpt_tg6bAlcz>s{dXX zk=D-w{|+t$NskbckL-K>NUsi#JkQP3t`dj!=KGB1t2pLaA!)dp`JG zG>%q`Mlrk|Z7~`>O#J8}Wo? zySzrX9M?`p+@!5Xc~o;XJ{Ns2IF?z=YZBXw`PO)>m|IR9d(C63Y^%=E`Ruuoq;2b_ z`+U;T?RgG%k825st*+I~8lA^eJfS&Gon=RJT?Ox!1qp7g&SP2%hvHT>PeDDBfZ5Zd zMnpF;v)Z!dI4M^+0rO!GOp54XwmN2+Iz+M6mRVzKZZf911}s#Zm(6Q6hgaz^Mug@@ zXMUoowywEiuK2+!RU3hI<^ybl}6!EE~>kl5fihm2u{MuUpZwTW$UdPY%D+lhgZCnYbME~ z$m0yt=d;0hcsk-ilasT1bTn%ahZzsu)ZyG}a?F{6?LWmRnhV4jnGQXT4uG_?xsQY^C5(NPTyH-#$T zXj}DS5iJmnFrQv#7Wjm_bqG-uC0-}f0jXhBr$|0`QwhWbY>JacEEJiD8%u?Adc;J) zQq)7k2=eEe0dXp!rWT37k1pG+Yj&hoL59cXYdlAZGTULBjT)1(p%Q1{aio$ZOkHc? zH)R;Bq;$uhCTvC->uM-I#gtT0VF_1v;Au+!gsq2cD~7jw0?FW)d>!hQkCKMzzdT+)9d@X1bPZuB%0Au?*fS^gB6JtfP$1 z*ArFwbAG7POqUjlY!bzsW>?!*oVJ60$X6?#NFw%e=T19E)_vrB8E(S7V$wtZX;*cL zeEQqwZdqQ3yG|AYR5D=)D*R-78J((XpmImeIaK!WNf73$3b=NPYc(1i!8B7`St6}O zk)!*n#-<9%s!|M>FKol2x)ZStaU0+_-8c@*-3jVqWWvUXMK|e)-zbtf;y#L{n4Y^I z=O&U>xYy?~b-6QnmoO1IBIX#%HR7YjVe*buV(Dh!xEw_tL2;%)ghL%!>k2-P@HL~- ziI=RX!1vK+*Vc6x%PF67-z6wO;zEP_h0%0zvm+|vh*24Aj^X0l<3-DgvyHa(0%}!g zT{QGGzG`qOm5HmWXcNB0Y&TTy)ELpws$`85sOON&@`U!UJS!Tj!X-qAyT&)MwwA^OC* zI??M7^aKO@->+}TywU3qU&IgZcyD$`n>Trss!vego*vob?>}2ulM6qvv)#M=JyYH* z{ocu4nWGaTgfhJ^U!7=Re(R`z=7`sR)@yvt>pPd}Y6>ni2Lo;Y9}8z0M@-lfhGOtiu}{?KufcK*2Evm<-tZ07hF^BPZj7h(GoUQ1JY z>~x__7`EQ;YfX=hWqO;u&a;^}27-yR%sX(%JAB^T+nGJmjww^{u{YEOjip7s#!Kn( zZndr44eEO>gV`Qfrv6ywVpq_7A#V-;%v3Nq=QS zlO0}Lf3S1%>O?=w^o-*i0?lLjx8Wmj`gFLF53@%)gVxuBmS(6x=gf#XQZ4u=d$+}vOLtP#13I>L-tJiW6k%ql9lfx9Ca-}puP~S+gfgo3w7V&~pk_*HD6W`A~ zZv}E9yr1pqq7XvlGZj`U(jZC(nAg;SSPmve$Xoedzi-fQZ-!QdW+U6DM>@O~2q*dP z*Y99KOIuFR&PJFlv*&!~WCOaS;d36`*(iTyrj8f*wQ~^O_IEenKTe2&^!RJiZz67J z59aM`ES#YPO8DKQ-jTNS$dIztv0f3t6mQwXP2N~1%jqW08Vt9=7BEB?+)HNLGpfe@ zSBEIq&+jG2sbuQw@OJfhdz)Bh$5`g*So-q8;KCWdWyBjsU=JYr0>pY_i?m#N@-ViB zF>n+q6UNEBe94B9)MZEx20QYGSCfa1p%Zm3@Tu0HSF zE+(PePR?mOgTe(}q!*-}q%Y{(DHs^{n%bB*atYypyh@LZXAd_ZOL|ZVGiP5$sqn?Y z5te>uS9;nVyN@NW0hCkv+997;2Si17*DvJN!d^$meWd zeQ=^7bLtf02bw5>!eDZ8VaYB0?47mZ`p;kphRF12zYLF{c@UfXhb|#$@|q$m;FABZ zmP?CEJ0S>3-`?|?f%6oKZHJK*;N9tp^#nw zfqc!@>M{`Z>eJp@nL#8u%p+5q(kE~B^!PED$ZzSE$%&IAoRMQPjkC>^fie=rvhnfs zRg#osHAiiMsBjRWrNl{l;A^ zA7;!GwJ-nfH8unk7PO_moB2(4qAEafncv>%6t>KE?f1@|SEXAxn{M`t$j8^@Lfo>bFl5!t J$S{g5`xn}wz=Hq) delta 1249 zcmX|=TS$~a6oALoyzY8yy|k|STdtWYxlyKunP5a0%Publ1uJd|;iX+oHX(cHLPQjd z3V{_xgk2uArI#{<1S5))dYCB_DLrOD zA!Vo&Js+i14g6+dKxU(rS^+;p7YxI4Xp2#5E8GV2;2D?>Z@?7z80Nw;Xuyxq3je@t z7|*5gO7*D%CaW-%z*txhw&58Dda9S3FZ77C=RBf+&2r8;i73z z;Bp+QOeg{7LkIrV1||~uZYYr*g_q!Im=FI#K9z@;BA zC=NRrB(MN83ldk6O5U)^JJo3uLGayj-1C@KC4H$ykx3*ZST0bho4@eq_i z9+>+tP5T^_fELWPjl)tZ2b2d@!9JO6Hw`=C8rJ(@E%ZS?^@KsrjhpL9NUUlaX22OJ z0sS!Tv9_i2sSuOOg0f#|uD3ubLA{Oq_cA$bZcIUOG-Iyk%=H44AN+=kFrLB|!f1^0 z@?t3abqwP0fN4Jl=~vYQHSC2XI+6uIUrGLv^{CXQNES#jN>%=gWMx?lCenB=RGdpK zrBBLGk+da50wUgsNWX|k*6ipyR7#U5{^cbi^7oUD6uT$7tsbA(2y}G&WJ8}#aA`|oS5n7uqpQ_xbT?poomi<;lN@>?>6iXs zEefXCYNPb2|FQvIldr8>5_aFUG_D!}I4Zgsxu= a509!Z5AV+3A2fgQ-QkE1_m66ebKoEQ6{m0j diff --git a/umap/locale/zh_TW/LC_MESSAGES/django.po b/umap/locale/zh_TW/LC_MESSAGES/django.po index 94927669..359d4ad3 100644 --- a/umap/locale/zh_TW/LC_MESSAGES/django.po +++ b/umap/locale/zh_TW/LC_MESSAGES/django.po @@ -1,10 +1,10 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Supaplex , 2014 -# Hsin-lin Cheng , 2014 +# Hsin-lin Cheng (lancetw) , 2014 # Sean Young , 2016 # Yuan CHAO , 2014 msgid "" @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: uMap\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-09 21:37+0200\n" -"PO-Revision-Date: 2016-12-04 11:18+0000\n" +"PO-Revision-Date: 2017-09-23 20:04+0000\n" "Last-Translator: Sean Young \n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/yohanboniface/umap/language/zh_TW/)\n" "MIME-Version: 1.0\n" @@ -208,3 +208,183 @@ msgstr "搜尋" #: views.py:190 msgid "View the map" msgstr "檢視地圖" + +#: forms.py:43 +#, python-format +msgid "Secret edit link is %s" +msgstr "不公開的私密編輯連結 %s" + +#: forms.py:47 models.py:113 +msgid "Everyone can edit" +msgstr "所有人皆可編輯" + +#: forms.py:48 +msgid "Only editable with secret edit link" +msgstr "僅能由私密連結編輯" + +#: models.py:20 +msgid "name" +msgstr "名稱" + +#: models.py:42 +msgid "No licence set" +msgstr "未指定授權條款" + +#: models.py:51 +msgid "details" +msgstr "詳情" + +#: models.py:52 +msgid "Link to a page where the licence is detailed." +msgstr "連結至授權條款說明網址" + +#: models.py:66 +msgid "URL template using OSM tile format" +msgstr "URL 樣板,使用 OSM 地圖磚格式" + +#: models.py:74 +msgid "Order of the tilelayers in the edit box" +msgstr "編輯方塊中地圖磚的圖層順序" + +#: models.py:114 +msgid "Only editors can edit" +msgstr "僅編輯群可編輯" + +#: models.py:115 +msgid "Only owner can edit" +msgstr "僅擁有者可編輯" + +#: models.py:118 +msgid "everyone (public)" +msgstr "所有人(公開)" + +#: models.py:119 +msgid "anyone with link" +msgstr "任何有連結的人" + +#: models.py:120 +msgid "editors only" +msgstr "只有編輯者允許" + +#: models.py:123 models.py:257 +msgid "description" +msgstr "描述" + +#: models.py:124 +msgid "center" +msgstr "中心" + +#: models.py:125 +msgid "zoom" +msgstr "縮放" + +#: models.py:126 +msgid "locate" +msgstr "定位" + +#: models.py:126 +msgid "Locate user on load?" +msgstr "載入時使用定位功能?" + +#: models.py:129 +msgid "Choose the map licence." +msgstr "選擇地圖授權" + +#: models.py:130 +msgid "licence" +msgstr "授權" + +#: models.py:135 +msgid "background" +msgstr "地圖背景" + +#: models.py:136 +msgid "owner" +msgstr "擁有者" + +#: models.py:137 +msgid "editors" +msgstr "編輯者" + +#: models.py:138 +msgid "edit status" +msgstr "編輯狀態" + +#: models.py:139 +msgid "share status" +msgstr "分享狀態" + +#: models.py:140 +msgid "settings" +msgstr "設定" + +#: models.py:178 +#, python-format +msgid "Your anonymous map has been attached to your account %s" +msgstr "你的匿名地圖已經加入你的帳號 %s " + +#: models.py:211 +msgid "Clone of" +msgstr "複製" + +#: models.py:262 +msgid "display on load" +msgstr "載入時顯示" + +#: models.py:263 +msgid "Display this layer on load." +msgstr "載入此圖層時顯示" + +#: templates/leaflet_storage/login_popup_end.html:2 +msgid "You are logged in. Continuing..." +msgstr "您已登入,繼續中..." + +#: templates/leaflet_storage/map_update_permissions.html:2 +msgid "Map permissions" +msgstr "地圖權限" + +#: templates/registration/login.html:2 +msgid "Please log in to proceed" +msgstr "請先登入" + +#: templates/registration/login.html:4 +msgid "Your username and password didn't match. Please try again." +msgstr "使用者代號或密碼不正確,請重新輸入。" + +#: views.py:232 +#, python-format +msgid "" +"Your map has been created! If you want to edit this map from another " +"computer, please use this link: %(anonymous_url)s" +msgstr "您的地圖已建立完成!如果您想在不同的機器編輯這個地圖,請使用這個連結:%(anonymous_url)s" + +#: views.py:237 +msgid "Congratulations, your map has been created!" +msgstr "恭喜您的地圖已經新增完成" + +#: views.py:264 +msgid "Map has been updated!" +msgstr "地圖已經更新" + +#: views.py:291 +msgid "Map editors updated with success!" +msgstr "地圖編輯者更新完成" + +#: views.py:306 +msgid "Only its owner can delete the map." +msgstr "只有擁有者可以刪除此地圖" + +#: views.py:335 +#, 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:340 +msgid "Congratulations, your map has been cloned!" +msgstr "恭喜,您的地圖已被複製!" + +#: views.py:526 +msgid "Layer successfully deleted." +msgstr "圖層已刪除" diff --git a/umap/migrations/0001_add_tilelayer.py b/umap/migrations/0001_add_tilelayer.py deleted file mode 100644 index 6f1281ad..00000000 --- a/umap/migrations/0001_add_tilelayer.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.3 on 2016-11-26 16:02 -from __future__ import unicode_literals - -from django.db import migrations - - -def add_tilelayer(apps, *args): - TileLayer = apps.get_model('leaflet_storage', 'TileLayer') - if TileLayer.objects.count(): - return - TileLayer( - name='Positron', - url_template=('https://cartodb-basemaps-{s}.global.ssl.fastly.net/' - 'light_all/{z}/{x}/{y}.png'), - attribution=('© [[http://www.openstreetmap.org/copyright|' - 'OpenStreetMap]] contributors, © ' - '[[https://carto.com/attributions|CARTO]]')).save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('leaflet_storage', '0001_initial'), - ] - - operations = [ - migrations.RunPython(add_tilelayer), - ] diff --git a/umap/migrations/0002_add_licence.py b/umap/migrations/0002_add_licence.py deleted file mode 100644 index 3edfb73d..00000000 --- a/umap/migrations/0002_add_licence.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.3 on 2016-11-26 16:11 -from __future__ import unicode_literals - -from django.db import migrations - - -def add_licence(apps, *args): - Licence = apps.get_model('leaflet_storage', 'Licence') - if Licence.objects.count(): - return - Licence( - name='ODbL', - details='http://opendatacommons.org/licenses/odbl/').save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('umap', '0001_add_tilelayer'), - ] - - operations = [ - migrations.RunPython(add_licence), - ] diff --git a/umap/settings/base.py b/umap/settings/base.py index 05cdc25a..e6490bc5 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -5,9 +5,9 @@ from django.conf.global_settings import * # pylint: disable=W0614,W0401 from django.template.defaultfilters import slugify -#============================================================================== +# ============================================================================= # Generic Django project settings -#============================================================================== +# ============================================================================= DEBUG = True @@ -56,7 +56,6 @@ INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.gis', - 'leaflet_storage', 'umap', 'compressor', 'social_django', diff --git a/umap/templatetags/umap_tags.py b/umap/templatetags/umap_tags.py index b86c8a62..22764199 100644 --- a/umap/templatetags/umap_tags.py +++ b/umap/templatetags/umap_tags.py @@ -1,10 +1,80 @@ +import json from copy import copy from django import template +from django.conf import settings + +from ..models import DataLayer, TileLayer +from ..views import _urls_for_js register = template.Library() +@register.inclusion_tag('umap/css.html') +def umap_css(): + return { + "STATIC_URL": settings.STATIC_URL + } + + +@register.inclusion_tag('umap/js.html') +def umap_js(locale=None): + return { + "STATIC_URL": settings.STATIC_URL, + "locale": locale + } + + +@register.inclusion_tag('umap/map_fragment.html') +def map_fragment(map_instance, **kwargs): + layers = DataLayer.objects.filter(map=map_instance) + datalayer_data = [c.metadata for c in layers] + tilelayers = TileLayer.get_list() # TODO: no need to all + map_settings = map_instance.settings + if "properties" not in map_settings: + map_settings['properties'] = {} + map_settings['properties'].update({ + 'tilelayers': tilelayers, + 'datalayers': datalayer_data, + 'urls': _urls_for_js(), + 'STATIC_URL': settings.STATIC_URL, + "allowEdit": False, + 'hash': False, + 'attributionControl': False, + 'scrollWheelZoom': False, + 'storageAttributionControl': False, + 'noControl': True, + 'storage_id': map_instance.pk, + 'onLoadPanel': "none", + 'captionBar': False, + 'default_iconUrl': "%sstorage/src/img/marker.png" % settings.STATIC_URL, + 'slideshow': {} + }) + map_settings['properties'].update(kwargs) + prefix = kwargs.pop('prefix', None) or 'map_' + return { + "map_settings": json.dumps(map_settings), + "map": map_instance, + "prefix": prefix + } + + +@register.simple_tag +def tilelayer_preview(tilelayer): + """ + Return an tag with a tile of the tilelayer. + """ + output = '{alt}' + url = tilelayer.url_template.format(s="a", z=9, x=265, y=181) + output = output.format(src=url, alt=tilelayer.name, title=tilelayer.name) + return output + + +@register.filter +def notag(s): + return s.replace('<', '<') + + @register.simple_tag(takes_context=True) def paginate_querystring(context, page): qs = copy(context["request"].GET) diff --git a/umap/urls.py b/umap/urls.py index 590c050e..5b735b87 100644 --- a/umap/urls.py +++ b/umap/urls.py @@ -1,22 +1,27 @@ from django.conf import settings -from django.conf.urls.static import static +from django.conf.urls import include, url +from django.urls import path from django.conf.urls.i18n import i18n_patterns -from django.conf.urls import url, include -from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.conf.urls.static import static from django.contrib import admin -from django.views.decorators.cache import cache_page from django.contrib.auth import views as auth_views - -from leaflet_storage.views import MapShortUrl +from django.contrib.auth.views import login +from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.views.decorators.cache import (cache_control, cache_page, + never_cache) +from django.views.decorators.csrf import ensure_csrf_cookie from . import views +from .decorators import (jsonize_view, login_required_if_not_anonymous_allowed, + map_permissions_check) +from .utils import decorated_patterns admin.autodiscover() urlpatterns = [ url(r'^admin/', admin.site.urls), url('', include('social_django.urls', namespace='social')), - url(r'^m/(?P\d+)/$', MapShortUrl.as_view(), name='umap_short_url'), + url(r'^m/(?P\d+)/$', views.MapShortUrl.as_view(), name='umap_short_url'), url(r'^ajax-proxy/$', cache_page(180)(views.ajax_proxy), name='ajax-proxy'), url(r'^change-password/', auth_views.password_change, @@ -26,6 +31,53 @@ urlpatterns = [ {'template_name': 'umap/password_change_done.html'}, name='password_change_done'), ] + +i18n_urls = [ + url(r'^login/$', jsonize_view(login), name='login'), # noqa + url(r'^login/popup/end/$', views.LoginPopupEnd.as_view(), + name='login_popup_end'), + url(r'^logout/$', views.logout, name='logout'), + url(r'^map/(?P\d+)/geojson/$', views.MapViewGeoJSON.as_view(), + name='map_geojson'), + url(r'^map/(?P[-_\w]+)/(?P[-_\w]+)/$', + views.MapOldUrl.as_view(), name='map_old_url'), + url(r'^map/anonymous-edit/(?P.+)$', + views.MapAnonymousEditUrl.as_view(), name='map_anonymous_edit_url'), + url(r'^m/(?P\d+)/$', views.MapShortUrl.as_view(), + name='map_short_url'), + url(r'^pictogram/json/$', views.PictogramJSONList.as_view(), + name='pictogram_list_json'), +] +i18n_urls += decorated_patterns(cache_control(must_revalidate=True), + url(r'^datalayer/(?P[\d]+)/$', views.DataLayerView.as_view(), name='datalayer_view'), # noqa + url(r'^datalayer/(?P[\d]+)/versions/$', views.DataLayerVersions.as_view(), name='datalayer_versions'), # noqa + url(r'^datalayer/(?P[\d]+)/(?P[_\w]+.geojson)$', views.DataLayerVersion.as_view(), name='datalayer_version'), # noqa +) +i18n_urls += decorated_patterns([ensure_csrf_cookie], + url(r'^map/(?P[-_\w]+)_(?P\d+)$', views.MapView.as_view(), name='map'), # noqa + url(r'^map/new/$', views.MapNew.as_view(), name='map_new'), +) +i18n_urls += decorated_patterns( + [login_required_if_not_anonymous_allowed, never_cache], + url(r'^map/create/$', views.MapCreate.as_view(), name='map_create'), +) +i18n_urls += decorated_patterns( + [map_permissions_check, never_cache], + url(r'^map/(?P[\d]+)/update/settings/$', views.MapUpdate.as_view(), + name='map_update'), + url(r'^map/(?P[\d]+)/update/permissions/$', + views.UpdateMapPermissions.as_view(), name='map_update_permissions'), + url(r'^map/(?P[\d]+)/update/delete/$', + views.MapDelete.as_view(), name='map_delete'), + url(r'^map/(?P[\d]+)/update/clone/$', + views.MapClone.as_view(), name='map_clone'), + url(r'^map/(?P[\d]+)/datalayer/create/$', + views.DataLayerCreate.as_view(), name='datalayer_create'), + url(r'^map/(?P[\d]+)/datalayer/update/(?P\d+)/$', + views.DataLayerUpdate.as_view(), name='datalayer_update'), + url(r'^map/(?P[\d]+)/datalayer/delete/(?P\d+)/$', + views.DataLayerDelete.as_view(), name='datalayer_delete'), +) urlpatterns += i18n_patterns( url(r'^$', views.home, name="home"), url(r'^showcase/$', cache_page(24 * 60 * 60)(views.showcase), @@ -33,7 +85,7 @@ urlpatterns += i18n_patterns( url(r'^search/$', views.search, name="search"), url(r'^about/$', views.about, name="about"), url(r'^user/(?P[-_\w@]+)/$', views.user_maps, name='user_maps'), - url(r'', include('leaflet_storage.urls')), + url(r'', include(i18n_urls)), ) if settings.DEBUG and settings.MEDIA_ROOT: diff --git a/umap/views.py b/umap/views.py index b0415cba..bac84e58 100644 --- a/umap/views.py +++ b/umap/views.py @@ -1,8 +1,42 @@ +import hashlib import json -import mimetypes +import os import re import socket +import mimetypes +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import logout as do_logout +from django.contrib.auth import get_user_model +from django.contrib.gis.measure import D +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.core.signing import BadSignature, Signer +from django.core.validators import URLValidator, ValidationError +from django.db.models import Q +from django.http import (HttpResponse, HttpResponseBadRequest, + HttpResponseForbidden, HttpResponsePermanentRedirect, + HttpResponseRedirect) +from django.middleware.gzip import re_accepts_gzip +from django.shortcuts import get_object_or_404 +from django.template.loader import render_to_string +from django.urls import reverse, reverse_lazy +from django.utils.encoding import force_bytes, smart_bytes +from django.utils.http import http_date +from django.utils.translation import ugettext as _ +from django.utils.translation import to_locale +from django.views.generic import DetailView, TemplateView, View +from django.views.generic.base import RedirectView +from django.views.generic.detail import BaseDetailView +from django.views.generic.edit import CreateView, DeleteView, UpdateView +from django.views.generic.list import ListView + +from .forms import (DEFAULT_LATITUDE, DEFAULT_LONGITUDE, DEFAULT_CENTER, + AnonymousMapPermissionsForm, DataLayerForm, FlatErrorList, + MapSettingsForm, UpdateMapPermissionsForm) +from .models import DataLayer, Licence, Map, Pictogram, TileLayer +from .utils import get_uri_template, gzip_file + try: # python3 from urllib.parse import urlparse @@ -12,21 +46,6 @@ except ImportError: from urlparse import urlparse from urllib2 import Request, HTTPError, build_opener -from django.views.generic import TemplateView -from django.contrib.auth import get_user_model -from django.views.generic import DetailView, View -from django.db.models import Q -from django.contrib.gis.measure import D -from django.conf import settings -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from django.http import HttpResponse, HttpResponseBadRequest -from django.utils.translation import ugettext as _ -from django.utils.encoding import smart_bytes -from django.urls import reverse -from django.core.validators import URLValidator, ValidationError - -from leaflet_storage.models import Map -from leaflet_storage.forms import DEFAULT_CENTER User = get_user_model() @@ -36,6 +55,7 @@ PRIVATE_IP = re.compile(r'((^127\.)|(^10\.)' r'|(^172\.2[0-9]\.)' r'|(^172\.3[0-1]\.)' r'|(^192\.168\.))') +ANONYMOUS_COOKIE_MAX_AGE = 60 * 60 * 24 * 30 # One month class PaginatorMixin(object): @@ -58,7 +78,7 @@ class PaginatorMixin(object): class Home(TemplateView, PaginatorMixin): template_name = "umap/home.html" - list_template_name = "leaflet_storage/map_list.html" + list_template_name = "umap/map_list.html" def get_context_data(self, **kwargs): qs = Map.public @@ -115,7 +135,7 @@ class UserMaps(DetailView, PaginatorMixin): model = User slug_url_kwarg = 'username' slug_field = 'username' - list_template_name = "leaflet_storage/map_list.html" + list_template_name = "umap/map_list.html" context_object_name = "current_user" def get_context_data(self, **kwargs): @@ -147,7 +167,7 @@ user_maps = UserMaps.as_view() class Search(TemplateView, PaginatorMixin): template_name = "umap/search.html" - list_template_name = "leaflet_storage/map_list.html" + list_template_name = "umap/map_list.html" def get_context_data(self, **kwargs): q = self.request.GET.get('q') @@ -268,3 +288,532 @@ class AjaxProxy(View): return HttpResponse(content, status=status_code, content_type=mimetype) ajax_proxy = AjaxProxy.as_view() + + +# ############## # +# Utils # +# ############## # + +def _urls_for_js(urls=None): + """ + Return templated URLs prepared for javascript. + """ + if urls is None: + # prevent circular import + from .urls import urlpatterns, i18n_urls + urls = [url.name for url in urlpatterns + i18n_urls + if getattr(url, 'name', None)] + urls = dict(zip(urls, [get_uri_template(url) for url in urls])) + urls.update(getattr(settings, 'LEAFLET_STORAGE_EXTRA_URLS', {})) + return urls + + +def render_to_json(templates, context, request): + """ + Generate a JSON HttpResponse with rendered template HTML. + """ + html = render_to_string( + templates, + context=context, + request=request + ) + _json = json.dumps({ + "html": html + }) + return HttpResponse(_json) + + +def simple_json_response(**kwargs): + return HttpResponse(json.dumps(kwargs)) + + +# ############## # +# Map # +# ############## # + + +class FormLessEditMixin(object): + http_method_names = [u'post', ] + + def form_invalid(self, form): + return simple_json_response(errors=form.errors, + error=str(form.errors)) + + def get_form(self): + kwargs = self.get_form_kwargs() + kwargs['error_class'] = FlatErrorList + return self.get_form_class()(**kwargs) + + +class MapDetailMixin(object): + + model = Map + + def get_context_data(self, **kwargs): + context = super(MapDetailMixin, self).get_context_data(**kwargs) + properties = { + 'urls': _urls_for_js(), + 'tilelayers': self.get_tilelayers(), + 'allowEdit': self.is_edit_allowed(), + 'default_iconUrl': "%sstorage/src/img/marker.png" % settings.STATIC_URL, # noqa + 'storage_id': self.get_storage_id(), + 'licences': dict((l.name, l.json) for l in Licence.objects.all()), + } + if self.get_short_url(): + properties['shortUrl'] = self.get_short_url() + + if settings.USE_I18N: + locale = settings.LANGUAGE_CODE + # Check attr in case the middleware is not active + if hasattr(self.request, "LANGUAGE_CODE"): + locale = self.request.LANGUAGE_CODE + locale = to_locale(locale) + properties['locale'] = locale + context['locale'] = locale + map_settings = self.get_geojson() + if "properties" not in map_settings: + map_settings['properties'] = {} + map_settings['properties'].update(properties) + map_settings['properties']['datalayers'] = self.get_datalayers() + context['map_settings'] = json.dumps(map_settings, + indent=settings.DEBUG) + return context + + def get_tilelayers(self): + return TileLayer.get_list(selected=TileLayer.get_default()) + + def get_datalayers(self): + return [] + + def is_edit_allowed(self): + return True + + def get_storage_id(self): + return None + + def get_geojson(self): + return { + "geometry": { + "coordinates": [DEFAULT_LONGITUDE, DEFAULT_LATITUDE], + "type": "Point" + }, + "properties": { + "zoom": getattr(settings, 'LEAFLET_ZOOM', 6), + "datalayers": [], + } + } + + def get_short_url(self): + return None + + +class MapView(MapDetailMixin, DetailView): + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + canonical = self.get_canonical_url() + if not request.path == canonical: + if request.META.get('QUERY_STRING'): + canonical = "?".join([canonical, request.META['QUERY_STRING']]) + return HttpResponsePermanentRedirect(canonical) + if not self.object.can_view(request): + return HttpResponseForbidden('Forbidden') + return super(MapView, self).get(request, *args, **kwargs) + + def get_canonical_url(self): + return self.object.get_absolute_url() + + def get_datalayers(self): + datalayers = DataLayer.objects.filter(map=self.object) + return [l.metadata for l in datalayers] + + def get_tilelayers(self): + return TileLayer.get_list(selected=self.object.get_tilelayer()) + + def is_edit_allowed(self): + return self.object.can_edit(self.request.user, self.request) + + def get_storage_id(self): + return self.object.pk + + def get_short_url(self): + shortUrl = None + if hasattr(settings, 'SHORT_SITE_URL'): + short_url_name = getattr(settings, 'MAP_SHORT_URL_NAME', + 'map_short_url') + short_path = reverse_lazy(short_url_name, + kwargs={'pk': self.object.pk}) + shortUrl = "%s%s" % (settings.SHORT_SITE_URL, short_path) + return shortUrl + + def get_geojson(self): + map_settings = self.object.settings + if "properties" not in map_settings: + map_settings['properties'] = {} + if self.object.owner and hasattr(settings, 'USER_MAPS_URL'): + map_settings['properties']['author'] = { + 'name': self.object.owner.get_username(), + 'link': reverse(settings.USER_MAPS_URL, + args=(self.object.owner.get_username(), )) + } + return map_settings + + +class MapViewGeoJSON(MapView): + + def get_canonical_url(self): + return reverse('map_geojson', args=(self.object.pk, )) + + def render_to_response(self, context, *args, **kwargs): + return HttpResponse(context['map_settings']) + + +class MapNew(MapDetailMixin, TemplateView): + template_name = "umap/map_detail.html" + + +class MapCreate(FormLessEditMixin, CreateView): + model = Map + form_class = MapSettingsForm + + def form_valid(self, form): + if self.request.user.is_authenticated: + form.instance.owner = self.request.user + self.object = form.save() + if not self.request.user.is_authenticated: + anonymous_url = "%s%s" % ( + settings.SITE_URL, + self.object.get_anonymous_edit_url() + ) + msg = _( + "Your map has been created! If you want to edit this map from " + "another computer, please use this link: %(anonymous_url)s" + % {"anonymous_url": anonymous_url} + ) + else: + msg = _("Congratulations, your map has been created!") + response = simple_json_response( + id=self.object.pk, + url=self.object.get_absolute_url(), + info=msg + ) + if not self.request.user.is_authenticated: + key, value = self.object.signed_cookie_elements + response.set_signed_cookie( + key=key, + value=value, + max_age=ANONYMOUS_COOKIE_MAX_AGE + ) + return response + + +class MapUpdate(FormLessEditMixin, UpdateView): + model = Map + form_class = MapSettingsForm + pk_url_kwarg = 'map_id' + + def form_valid(self, form): + self.object.settings = form.cleaned_data["settings"] + self.object.save() + return simple_json_response( + id=self.object.pk, + url=self.object.get_absolute_url(), + info=_("Map has been updated!") + ) + + +class UpdateMapPermissions(UpdateView): + template_name = "umap/map_update_permissions.html" + model = Map + pk_url_kwarg = 'map_id' + + def get_form_class(self): + if self.object.owner: + return UpdateMapPermissionsForm + else: + return AnonymousMapPermissionsForm + + def get_form(self, form_class=None): + form = super(UpdateMapPermissions, self).get_form(form_class) + user = self.request.user + if self.object.owner and not user == self.object.owner: + del form.fields['edit_status'] + del form.fields['share_status'] + del form.fields['owner'] + return form + + def form_valid(self, form): + self.object = form.save() + return simple_json_response( + info=_("Map editors updated with success!")) + + def render_to_response(self, context, **response_kwargs): + context.update(response_kwargs) + return render_to_json(self.get_template_names(), context, self.request) + + +class MapDelete(DeleteView): + model = Map + pk_url_kwarg = "map_id" + + def delete(self, *args, **kwargs): + self.object = self.get_object() + if self.object.owner and self.request.user != self.object.owner: + return HttpResponseForbidden( + _('Only its owner can delete the map.')) + if not self.object.owner\ + and not self.object.is_anonymous_owner(self.request): + return HttpResponseForbidden('Forbidden.') + self.object.delete() + return simple_json_response(redirect="/") + + +class MapClone(View): + + def post(self, *args, **kwargs): + if not getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False) \ + and not self.request.user.is_authenticated: + return HttpResponseForbidden('Forbidden') + owner = self.request.user if self.request.user.is_authenticated else None + self.object = kwargs['map_inst'].clone(owner=owner) + response = simple_json_response(redirect=self.object.get_absolute_url()) + if not self.request.user.is_authenticated: + key, value = self.object.signed_cookie_elements + response.set_signed_cookie( + key=key, + value=value, + max_age=ANONYMOUS_COOKIE_MAX_AGE + ) + anonymous_url = "%s%s" % ( + settings.SITE_URL, + self.object.get_anonymous_edit_url() + ) + msg = _( + "Your map has been cloned! If you want to edit this map from " + "another computer, please use this link: %(anonymous_url)s" + % {"anonymous_url": anonymous_url} + ) + else: + msg = _("Congratulations, your map has been cloned!") + messages.info(self.request, msg) + return response + + +class MapShortUrl(RedirectView): + query_string = True + permanent = True + + def get_redirect_url(self, **kwargs): + map_inst = get_object_or_404(Map, pk=kwargs['pk']) + url = map_inst.get_absolute_url() + if self.query_string: + args = self.request.META.get('QUERY_STRING', '') + if args: + url = "%s?%s" % (url, args) + return url + + +class MapOldUrl(RedirectView): + """ + Handle map URLs from before anonymous allowing. + """ + query_string = True + permanent = True + + def get_redirect_url(self, **kwargs): + owner = get_object_or_404(User, username=self.kwargs['username']) + map_inst = get_object_or_404(Map, slug=self.kwargs['slug'], + owner=owner) + url = map_inst.get_absolute_url() + if self.query_string: + args = self.request.META.get('QUERY_STRING', '') + if args: + url = "%s?%s" % (url, args) + return url + + +class MapAnonymousEditUrl(RedirectView): + + permanent = False + + def get(self, request, *args, **kwargs): + signer = Signer() + try: + pk = signer.unsign(self.kwargs['signature']) + except BadSignature: + return HttpResponseForbidden('Bad Signature') + else: + map_inst = get_object_or_404(Map, pk=pk) + url = map_inst.get_absolute_url() + response = HttpResponseRedirect(url) + if not map_inst.owner: + key, value = map_inst.signed_cookie_elements + response.set_signed_cookie( + key=key, + value=value, + max_age=ANONYMOUS_COOKIE_MAX_AGE + ) + return response + + +# ############## # +# DataLayer # +# ############## # + + +class GZipMixin(object): + + EXT = '.gz' + + def _path(self): + return self.object.geojson.path + + def path(self): + """ + Serve gzip file if client accept it. + Generate or update the gzip file if needed. + """ + path = self._path() + statobj = os.stat(path) + ae = self.request.META.get('HTTP_ACCEPT_ENCODING', '') + if re_accepts_gzip.search(ae) and getattr(settings, 'LEAFLET_STORAGE_GZIP', True): + gzip_path = "{path}{ext}".format(path=path, ext=self.EXT) + up_to_date = True + if not os.path.exists(gzip_path): + up_to_date = False + else: + gzip_statobj = os.stat(gzip_path) + if statobj.st_mtime > gzip_statobj.st_mtime: + up_to_date = False + if not up_to_date: + gzip_file(path, gzip_path) + path = gzip_path + return path + + def etag(self): + path = self.path() + with open(path, mode='rb') as f: + return hashlib.md5(f.read()).hexdigest() + + +class DataLayerView(GZipMixin, BaseDetailView): + model = DataLayer + + def render_to_response(self, context, **response_kwargs): + response = None + path = self.path() + + if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None): + response = HttpResponse() + path = path.replace(settings.MEDIA_ROOT, '/internal') + response[settings.LEAFLET_STORAGE_XSENDFILE_HEADER] = path + else: + # TODO IMS + statobj = os.stat(path) + with open(path, 'rb') as f: + response = HttpResponse( + f.read(), # should not be used in production! + content_type='application/json' + ) + response["Last-Modified"] = http_date(statobj.st_mtime) + response['ETag'] = '%s' % hashlib.md5(force_bytes(response.content)).hexdigest() # noqa + response['Content-Length'] = len(response.content) + if path.endswith(self.EXT): + response['Content-Encoding'] = 'gzip' + return response + + +class DataLayerVersion(DataLayerView): + + def _path(self): + return '{root}/{path}'.format( + root=settings.MEDIA_ROOT, + path=self.object.get_version_path(self.kwargs['name'])) + + +class DataLayerCreate(FormLessEditMixin, GZipMixin, CreateView): + model = DataLayer + form_class = DataLayerForm + + def form_valid(self, form): + form.instance.map = self.kwargs['map_inst'] + self.object = form.save() + response = simple_json_response(**self.object.metadata) + response['ETag'] = self.etag() + return response + + +class DataLayerUpdate(FormLessEditMixin, GZipMixin, UpdateView): + model = DataLayer + form_class = DataLayerForm + + def form_valid(self, form): + self.object = form.save() + response = simple_json_response(**self.object.metadata) + response['ETag'] = self.etag() + return response + + def if_match(self): + """Optimistic concurrency control.""" + match = True + if_match = self.request.META.get('HTTP_IF_MATCH') + if if_match: + etag = self.etag() + if etag != if_match: + match = False + return match + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + if self.object.map != self.kwargs['map_inst']: + return HttpResponseForbidden('Route to nowhere') + if not self.if_match(): + return HttpResponse(status=412) + return super(DataLayerUpdate, self).post(request, *args, **kwargs) + + +class DataLayerDelete(DeleteView): + model = DataLayer + + def delete(self, *args, **kwargs): + self.object = self.get_object() + if self.object.map != self.kwargs['map_inst']: + return HttpResponseForbidden('Route to nowhere') + self.object.delete() + return simple_json_response(info=_("Layer successfully deleted.")) + + +class DataLayerVersions(BaseDetailView): + model = DataLayer + + def render_to_response(self, context, **response_kwargs): + return simple_json_response(versions=self.object.versions) + + +# ############## # +# Picto # +# ############## # + +class PictogramJSONList(ListView): + model = Pictogram + + def render_to_response(self, context, **response_kwargs): + content = [p.json for p in Pictogram.objects.all()] + return simple_json_response(pictogram_list=content) + + +# ############## # +# Generic # +# ############## # + +def logout(request): + do_logout(request) + return simple_json_response(redirect="/") + + +class LoginPopupEnd(TemplateView): + """ + End of a loggin process in popup. + Basically close the popup. + """ + template_name = "umap/login_popup_end.html" From 65e939c4ee11d70cc24a8ba7b3ca369a7ededd8e Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 11:29:30 +0200 Subject: [PATCH 005/239] Reset migrations There are two files: - the initial one that create everyting, but TileLayer.tms - one for TileLayer.tms, because it was not released so people upgrading will need to fake the first, but really run the second --- umap/migrations/0001_initial.py | 107 ++++++++++++++++++++++++++ umap/migrations/0002_tilelayer_tms.py | 18 +++++ 2 files changed, 125 insertions(+) create mode 100644 umap/migrations/0001_initial.py create mode 100644 umap/migrations/0002_tilelayer_tms.py diff --git a/umap/migrations/0001_initial.py b/umap/migrations/0001_initial.py new file mode 100644 index 00000000..fff32572 --- /dev/null +++ b/umap/migrations/0001_initial.py @@ -0,0 +1,107 @@ +# Generated by Django 2.0.5 on 2018-05-19 09:27 + +from django.conf import settings +import django.contrib.gis.db.models.fields +from django.db import migrations, models +import django.db.models.deletion +import umap.fields +import umap.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='DataLayer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='name')), + ('description', models.TextField(blank=True, null=True, verbose_name='description')), + ('geojson', models.FileField(blank=True, null=True, upload_to=umap.models.upload_to)), + ('display_on_load', models.BooleanField(default=False, help_text='Display this layer on load.', verbose_name='display on load')), + ('rank', models.SmallIntegerField(default=0)), + ], + options={ + 'ordering': ('rank',), + }, + ), + migrations.CreateModel( + name='Licence', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='name')), + ('details', models.URLField(help_text='Link to a page where the licence is detailed.', verbose_name='details')), + ], + options={ + 'ordering': ('name',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Map', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='name')), + ('slug', models.SlugField()), + ('description', models.TextField(blank=True, null=True, verbose_name='description')), + ('center', django.contrib.gis.db.models.fields.PointField(geography=True, srid=4326, verbose_name='center')), + ('zoom', models.IntegerField(default=7, verbose_name='zoom')), + ('locate', models.BooleanField(default=False, help_text='Locate user on load?', verbose_name='locate')), + ('modified_at', models.DateTimeField(auto_now=True)), + ('edit_status', models.SmallIntegerField(choices=[(1, 'Everyone can edit'), (2, 'Only editors can edit'), (3, 'Only owner can edit')], default=3, verbose_name='edit status')), + ('share_status', models.SmallIntegerField(choices=[(1, 'everyone (public)'), (2, 'anyone with link'), (3, 'editors only')], default=1, verbose_name='share status')), + ('settings', umap.fields.DictField(blank=True, null=True, verbose_name='settings')), + ('editors', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='editors')), + ('licence', models.ForeignKey(default=umap.models.get_default_licence, help_text='Choose the map licence.', on_delete=django.db.models.deletion.SET_DEFAULT, to='umap.Licence', verbose_name='licence')), + ('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='owned_maps', to=settings.AUTH_USER_MODEL, verbose_name='owner')), + ], + options={ + 'ordering': ('name',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Pictogram', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='name')), + ('attribution', models.CharField(max_length=300)), + ('pictogram', models.ImageField(upload_to='pictogram')), + ], + options={ + 'ordering': ('name',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TileLayer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='name')), + ('url_template', models.CharField(help_text='URL template using OSM tile format', max_length=200)), + ('minZoom', models.IntegerField(default=0)), + ('maxZoom', models.IntegerField(default=18)), + ('attribution', models.CharField(max_length=300)), + ('rank', models.SmallIntegerField(blank=True, help_text='Order of the tilelayers in the edit box', null=True)), + ], + options={ + 'ordering': ('rank', 'name'), + }, + ), + migrations.AddField( + model_name='map', + name='tilelayer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='maps', to='umap.TileLayer', verbose_name='background'), + ), + migrations.AddField( + model_name='datalayer', + name='map', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='umap.Map'), + ), + ] diff --git a/umap/migrations/0002_tilelayer_tms.py b/umap/migrations/0002_tilelayer_tms.py new file mode 100644 index 00000000..9b966815 --- /dev/null +++ b/umap/migrations/0002_tilelayer_tms.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.5 on 2018-05-19 09:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('umap', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='tilelayer', + name='tms', + field=models.BooleanField(default=False), + ), + ] From 53c738abaf233f13a8d30d750a40405a07ec6bf3 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 11:54:08 +0200 Subject: [PATCH 006/239] Merge leaflet_storage tests --- .gitignore | 1 + Makefile | 2 +- umap/tests/__init__.py | 1 - umap/tests/base.py | 96 ++++ umap/tests/conftest.py | 64 +++ umap/tests/fixtures/test_upload_data.csv | 2 + umap/tests/fixtures/test_upload_data.gpx | 17 + umap/tests/fixtures/test_upload_data.json | 188 ++++++++ umap/tests/fixtures/test_upload_data.kml | 33 ++ .../test_upload_empty_coordinates.json | 36 ++ .../fixtures/test_upload_missing_name.json | 153 ++++++ .../fixtures/test_upload_non_linear_ring.json | 51 ++ umap/tests/test_datalayer.py | 81 ++++ umap/tests/test_datalayer_views.py | 162 +++++++ umap/tests/test_fields.py | 43 ++ umap/tests/test_licence.py | 12 + umap/tests/test_map.py | 109 +++++ umap/tests/test_map_views.py | 449 ++++++++++++++++++ umap/tests/test_tilelayer.py | 21 + 19 files changed, 1519 insertions(+), 2 deletions(-) create mode 100644 umap/tests/base.py create mode 100644 umap/tests/conftest.py create mode 100644 umap/tests/fixtures/test_upload_data.csv create mode 100644 umap/tests/fixtures/test_upload_data.gpx create mode 100644 umap/tests/fixtures/test_upload_data.json create mode 100644 umap/tests/fixtures/test_upload_data.kml create mode 100644 umap/tests/fixtures/test_upload_empty_coordinates.json create mode 100644 umap/tests/fixtures/test_upload_missing_name.json create mode 100644 umap/tests/fixtures/test_upload_non_linear_ring.json create mode 100644 umap/tests/test_datalayer.py create mode 100644 umap/tests/test_datalayer_views.py create mode 100644 umap/tests/test_fields.py create mode 100644 umap/tests/test_licence.py create mode 100644 umap/tests/test_map.py create mode 100644 umap/tests/test_map_views.py create mode 100644 umap/tests/test_tilelayer.py diff --git a/.gitignore b/.gitignore index 60d85dc4..a9a3b7a9 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ nosetests.xml coverage.xml *,cover .hypothesis/ +.pytest_cache/ # Translations *.mo diff --git a/Makefile b/Makefile index 6d0d58cb..c02b8c8e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ test: - py.test + py.test -xv develop: python setup.py develop compilemessages: diff --git a/umap/tests/__init__.py b/umap/tests/__init__.py index 92018579..e69de29b 100644 --- a/umap/tests/__init__.py +++ b/umap/tests/__init__.py @@ -1 +0,0 @@ -from .test_views import * diff --git a/umap/tests/base.py b/umap/tests/base.py new file mode 100644 index 00000000..820425e6 --- /dev/null +++ b/umap/tests/base.py @@ -0,0 +1,96 @@ +import json + +import factory +from django.contrib.auth import get_user_model +from django.urls import reverse + +from umap.forms import DEFAULT_CENTER +from umap.models import DataLayer, Licence, Map, TileLayer + +User = get_user_model() + + +class LicenceFactory(factory.DjangoModelFactory): + name = "WTFPL" + + class Meta: + model = Licence + + +class TileLayerFactory(factory.DjangoModelFactory): + name = "Test zoom layer" + url_template = "http://{s}.test.org/{z}/{x}/{y}.png" + attribution = "Test layer attribution" + + class Meta: + model = TileLayer + + +class UserFactory(factory.DjangoModelFactory): + username = 'Joe' + email = factory.LazyAttribute( + lambda a: '{0}@example.com'.format(a.username).lower()) + password = factory.PostGenerationMethodCall('set_password', '123123') + + class Meta: + model = User + + +class MapFactory(factory.DjangoModelFactory): + name = "test map" + slug = "test-map" + center = DEFAULT_CENTER + settings = { + 'geometry': { + 'coordinates': [13.447265624999998, 48.94415123418794], + 'type': 'Point' + }, + 'properties': { + 'datalayersControl': True, + 'description': 'Which is just the Danube, at the end', + 'displayCaptionOnLoad': False, + 'displayDataBrowserOnLoad': False, + 'displayPopupFooter': False, + 'licence': '', + 'miniMap': False, + 'moreControl': True, + 'name': 'Cruising on the Donau', + 'scaleControl': True, + 'tilelayer': { + 'attribution': u'\xa9 OSM Contributors', + 'maxZoom': 18, + 'minZoom': 0, + 'url_template': 'http://{s}.osm.fr/{z}/{x}/{y}.png' + }, + 'tilelayersControl': True, + 'zoom': 7, + 'zoomControl': True + }, + 'type': 'Feature' + } + + licence = factory.SubFactory(LicenceFactory) + owner = factory.SubFactory(UserFactory) + + class Meta: + model = Map + + +class DataLayerFactory(factory.DjangoModelFactory): + map = factory.SubFactory(MapFactory) + name = "test datalayer" + description = "test description" + display_on_load = True + geojson = factory.django.FileField(data="""{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[13.68896484375,48.55297816440071]},"properties":{"_storage_options":{"color":"DarkCyan","iconClass":"Ball"},"name":"Here","description":"Da place anonymous again 755"}}],"_storage":{"displayOnLoad":true,"name":"Donau","id":926}}""") # noqa + + class Meta: + model = DataLayer + + +def login_required(response): + assert response.status_code == 200 + j = json.loads(response.content.decode()) + assert 'login_required' in j + redirect_url = reverse('login') + assert j['login_required'] == redirect_url + return True diff --git a/umap/tests/conftest.py b/umap/tests/conftest.py new file mode 100644 index 00000000..441513f7 --- /dev/null +++ b/umap/tests/conftest.py @@ -0,0 +1,64 @@ +import shutil +import tempfile + +import pytest +from django.core.signing import get_cookie_signer + +from .base import (DataLayerFactory, LicenceFactory, MapFactory, + TileLayerFactory, UserFactory) + +TMP_ROOT = tempfile.mkdtemp() + + +def pytest_configure(config): + from django.conf import settings + settings.MEDIA_ROOT = TMP_ROOT + + +def pytest_unconfigure(config): + shutil.rmtree(TMP_ROOT, ignore_errors=True) + + +@pytest.fixture +def user(): + return UserFactory(password="123123") + + +@pytest.fixture +def licence(): + return LicenceFactory() + + +@pytest.fixture +def map(licence, tilelayer): + user = UserFactory(username="Gabriel", password="123123") + return MapFactory(owner=user, licence=licence) + + +@pytest.fixture +def anonymap(map): + map.owner = None + map.save() + return map + + +@pytest.fixture +def cookieclient(client, anonymap): + key, value = anonymap.signed_cookie_elements + client.cookies[key] = get_cookie_signer(salt=key).sign(value) + return client + + +@pytest.fixture +def allow_anonymous(settings): + settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = True + + +@pytest.fixture +def datalayer(map): + return DataLayerFactory(map=map, name="Default Datalayer") + + +@pytest.fixture +def tilelayer(): + return TileLayerFactory() diff --git a/umap/tests/fixtures/test_upload_data.csv b/umap/tests/fixtures/test_upload_data.csv new file mode 100644 index 00000000..107f2510 --- /dev/null +++ b/umap/tests/fixtures/test_upload_data.csv @@ -0,0 +1,2 @@ +Foo,Latitude,geo_Longitude,title,description +bar,41.34,122.86,a point somewhere,the description of this point \ No newline at end of file diff --git a/umap/tests/fixtures/test_upload_data.gpx b/umap/tests/fixtures/test_upload_data.gpx new file mode 100644 index 00000000..ea7e1080 --- /dev/null +++ b/umap/tests/fixtures/test_upload_data.gpx @@ -0,0 +1,17 @@ + + 1374Simple PointSimple description + + Simple path + Simple description + + + + + + + \ No newline at end of file diff --git a/umap/tests/fixtures/test_upload_data.json b/umap/tests/fixtures/test_upload_data.json new file mode 100644 index 00000000..8d7fc002 --- /dev/null +++ b/umap/tests/fixtures/test_upload_data.json @@ -0,0 +1,188 @@ +{ + "crs": null, + "type": "FeatureCollection", + "features": [ + { + "geometry": { + "type": "Point", + "coordinates": [ + -0.1318359375, + 51.474540439419755 + ] + }, + "type": "Feature", + "properties": { + "name": "London", + "description": "London description", + "color": "Pink" + } + }, + { + "geometry": { + "type": "Point", + "coordinates": [ + 4.350585937499999, + 51.26878915771344 + ] + }, + "type": "Feature", + "properties": { + "name": "Antwerpen", + "description": "" + } + }, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 2.4005126953125, + 48.81228985866255 + ], + [ + 2.78228759765625, + 48.89903236496008 + ], + [ + 2.845458984375, + 48.89903236496008 + ], + [ + 2.86468505859375, + 48.96218736991556 + ], + [ + 2.9278564453125, + 48.93693495409401 + ], + [ + 2.93060302734375, + 48.99283383694349 + ], + [ + 3.04046630859375, + 49.01085236926211 + ], + [ + 3.0157470703125, + 48.96038404976431 + ], + [ + 3.12286376953125, + 48.94415123418794 + ], + [ + 3.1805419921874996, + 48.99824008113872 + ], + [ + 3.2684326171875, + 48.95497369808868 + ], + [ + 3.53759765625, + 49.0900564769189 + ], + [ + 3.57330322265625, + 49.057670047140604 + ], + [ + 3.72161865234375, + 49.095452162534826 + ], + [ + 3.9578247070312496, + 49.06486885623368 + ] + ] + }, + "type": "Feature", + "properties": { + "name": "2011" + } + }, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 10.04150390625, + 52.70967533219883 + ], + [ + 8.800048828125, + 51.80182150078305 + ], + [ + 11.271972656249998, + 51.12421275782688 + ], + [ + 12.689208984375, + 52.214338608258196 + ], + [ + 10.04150390625, + 52.70967533219883 + ] + ] + ] + }, + "type": "Feature", + "properties": { + "name": "test" + } + }, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 7.327880859374999, + 50.52041218671901 + ], + [ + 6.064453125, + 49.6462914122132 + ], + [ + 7.503662109375, + 49.54659778073743 + ], + [ + 6.8115234375, + 49.167338606291075 + ], + [ + 9.635009765625, + 48.99463598353408 + ], + [ + 10.557861328125, + 49.937079756975294 + ], + [ + 8.4814453125, + 49.688954878870305 + ], + [ + 9.173583984375, + 51.04830113331224 + ], + [ + 7.327880859374999, + 50.52041218671901 + ] + ] + ] + }, + "type": "Feature", + "properties": { + "name": "test polygon 2" + } + } + ] +} \ No newline at end of file diff --git a/umap/tests/fixtures/test_upload_data.kml b/umap/tests/fixtures/test_upload_data.kml new file mode 100644 index 00000000..af857078 --- /dev/null +++ b/umap/tests/fixtures/test_upload_data.kml @@ -0,0 +1,33 @@ + + + + Simple point + Here is a simple description. + + -122.0822035425683,37.42228990140251,0 + + + + Simple path + Simple description + + -112.2550785337791,36.07954952145647,2357 -112.2549277039738,36.08117083492122,2357 -112.2552505069063,36.08260761307279,2357 + + + + Simple polygon + A description. + + + + + -77.05788457660967,38.87253259892824,100 + -77.05465973756702,38.87291016281703,100 + -77.05315536854791,38.87053267794386,100 + -77.05788457660967,38.87253259892824,100 + + + + + + \ No newline at end of file diff --git a/umap/tests/fixtures/test_upload_empty_coordinates.json b/umap/tests/fixtures/test_upload_empty_coordinates.json new file mode 100644 index 00000000..65f8dd16 --- /dev/null +++ b/umap/tests/fixtures/test_upload_empty_coordinates.json @@ -0,0 +1,36 @@ +{ + "crs": null, + "type": "FeatureCollection", + "features": [ + { + "geometry": { + "type": "Point", + "coordinates": [] + }, + "type": "Feature", + "properties": { + "name": "London" + } + }, + { + "geometry": { + "type": "LineString", + "coordinates": [] + }, + "type": "Feature", + "properties": { + "name": "2011" + } + }, + { + "geometry": { + "type": "Polygon", + "coordinates": [[]] + }, + "type": "Feature", + "properties": { + "name": "test" + } + } + ] +} \ No newline at end of file diff --git a/umap/tests/fixtures/test_upload_missing_name.json b/umap/tests/fixtures/test_upload_missing_name.json new file mode 100644 index 00000000..e4e4acbf --- /dev/null +++ b/umap/tests/fixtures/test_upload_missing_name.json @@ -0,0 +1,153 @@ +{ + "crs": null, + "type": "FeatureCollection", + "features": [ + { + "geometry": { + "type": "Point", + "coordinates": [ + -0.1318359375, + 51.474540439419755 + ] + }, + "type": "Feature", + "properties": { + "name": "London" + } + }, + { + "geometry": { + "type": "Point", + "coordinates": [ + 4.350585937499999, + 51.26878915771344 + ] + }, + "type": "Feature", + "properties": { + "noname": "this feature is missing a name", + "name": null + } + }, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 2.4005126953125, + 48.81228985866255 + ], + [ + 2.78228759765625, + 48.89903236496008 + ], + [ + 2.845458984375, + 48.89903236496008 + ], + [ + 2.86468505859375, + 48.96218736991556 + ], + [ + 2.9278564453125, + 48.93693495409401 + ], + [ + 2.93060302734375, + 48.99283383694349 + ], + [ + 3.04046630859375, + 49.01085236926211 + ], + [ + 3.0157470703125, + 48.96038404976431 + ], + [ + 3.12286376953125, + 48.94415123418794 + ], + [ + 3.1805419921874996, + 48.99824008113872 + ], + [ + 3.2684326171875, + 48.95497369808868 + ], + [ + 3.53759765625, + 49.0900564769189 + ], + [ + 3.57330322265625, + 49.057670047140604 + ], + [ + 3.72161865234375, + 49.095452162534826 + ], + [ + 3.9578247070312496, + 49.06486885623368 + ] + ] + }, + "type": "Feature", + "properties": { + "name": "2011" + } + }, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 7.327880859374999, + 50.52041218671901 + ], + [ + 6.064453125, + 49.6462914122132 + ], + [ + 7.503662109375, + 49.54659778073743 + ], + [ + 6.8115234375, + 49.167338606291075 + ], + [ + 9.635009765625, + 48.99463598353408 + ], + [ + 10.557861328125, + 49.937079756975294 + ], + [ + 8.4814453125, + 49.688954878870305 + ], + [ + 9.173583984375, + 51.04830113331224 + ], + [ + 7.327880859374999, + 50.52041218671901 + ] + ] + ] + }, + "type": "Feature", + "properties": { + "name": "test polygon 2" + } + } + ] +} \ No newline at end of file diff --git a/umap/tests/fixtures/test_upload_non_linear_ring.json b/umap/tests/fixtures/test_upload_non_linear_ring.json new file mode 100644 index 00000000..db22bb0b --- /dev/null +++ b/umap/tests/fixtures/test_upload_non_linear_ring.json @@ -0,0 +1,51 @@ +{ + "crs": null, + "type": "FeatureCollection", + "features": [ + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 7.327880859374999, + 50.52041218671901 + ], + [ + 6.064453125, + 49.6462914122132 + ], + [ + 7.503662109375, + 49.54659778073743 + ], + [ + 6.8115234375, + 49.167338606291075 + ], + [ + 9.635009765625, + 48.99463598353408 + ], + [ + 10.557861328125, + 49.937079756975294 + ], + [ + 8.4814453125, + 49.688954878870305 + ], + [ + 9.173583984375, + 51.04830113331224 + ] + ] + ] + }, + "type": "Feature", + "properties": { + "name": "non linear ring" + } + } + ] +} \ No newline at end of file diff --git a/umap/tests/test_datalayer.py b/umap/tests/test_datalayer.py new file mode 100644 index 00000000..65f8e2f7 --- /dev/null +++ b/umap/tests/test_datalayer.py @@ -0,0 +1,81 @@ +import os + +import pytest +from django.core.files.base import ContentFile + +from .base import DataLayerFactory, MapFactory + +pytestmark = pytest.mark.django_db + + +def test_datalayers_should_be_ordered_by_rank(map, datalayer): + datalayer.rank = 5 + datalayer.save() + c4 = DataLayerFactory(map=map, rank=4) + c1 = DataLayerFactory(map=map, rank=1) + c3 = DataLayerFactory(map=map, rank=3) + c2 = DataLayerFactory(map=map, rank=2) + assert list(map.datalayer_set.all()) == [c1, c2, c3, c4, datalayer] + + +def test_upload_to(map, datalayer): + map.pk = 302 + datalayer.pk = 17 + assert datalayer.upload_to().startswith('datalayer/2/0/302/17_') + + +def test_save_should_use_pk_as_name(map, datalayer): + assert "/{}_".format(datalayer.pk) in datalayer.geojson.name + + +def test_same_geojson_file_name_will_be_suffixed(map, datalayer): + before = datalayer.geojson.name + datalayer.geojson.save(before, ContentFile("{}")) + assert datalayer.geojson.name != before + assert "/{}_".format(datalayer.pk) in datalayer.geojson.name + + +def test_clone_should_return_new_instance(map, datalayer): + clone = datalayer.clone() + assert datalayer.pk != clone.pk + assert datalayer.name == clone.name + assert datalayer.map == clone.map + + +def test_clone_should_update_map_if_passed(datalayer, user, licence): + map = MapFactory(owner=user, licence=licence) + clone = datalayer.clone(map_inst=map) + assert datalayer.pk != clone.pk + assert datalayer.name == clone.name + assert datalayer.map != clone.map + assert map == clone.map + + +def test_clone_should_clone_geojson_too(datalayer): + clone = datalayer.clone() + assert datalayer.pk != clone.pk + assert clone.geojson is not None + assert clone.geojson.path != datalayer.geojson.path + + +def test_should_remove_old_versions_on_save(datalayer, map, settings): + settings.LEAFLET_STORAGE_KEEP_VERSIONS = 3 + root = datalayer.storage_root() + before = len(datalayer.geojson.storage.listdir(root)[1]) + newer = '%s/%s_1440924889.geojson' % (root, datalayer.pk) + medium = '%s/%s_1440923687.geojson' % (root, datalayer.pk) + older = '%s/%s_1440918637.geojson' % (root, datalayer.pk) + for path in [medium, newer, older]: + datalayer.geojson.storage.save(path, ContentFile("{}")) + datalayer.geojson.storage.save(path + '.gz', ContentFile("{}")) + assert len(datalayer.geojson.storage.listdir(root)[1]) == 6 + before + datalayer.save() + files = datalayer.geojson.storage.listdir(root)[1] + assert len(files) == 5 + assert os.path.basename(newer) in files + assert os.path.basename(newer + '.gz') in files + assert os.path.basename(medium) in files + assert os.path.basename(medium + '.gz') in files + assert os.path.basename(datalayer.geojson.path) in files + assert os.path.basename(older) not in files + assert os.path.basename(older + '.gz') not in files diff --git a/umap/tests/test_datalayer_views.py b/umap/tests/test_datalayer_views.py new file mode 100644 index 00000000..b4f90f73 --- /dev/null +++ b/umap/tests/test_datalayer_views.py @@ -0,0 +1,162 @@ +import json + +import pytest +from django.core.files.base import ContentFile +from django.urls import reverse + +from umap.models import DataLayer, Map + +from .base import MapFactory + +pytestmark = pytest.mark.django_db + + +@pytest.fixture +def post_data(): + return { + "name": 'name', + "display_on_load": True, + "rank": 0, + "geojson": '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-3.1640625,53.014783245859235],[-3.1640625,51.86292391360244],[-0.50537109375,51.385495069223204],[1.16455078125,52.38901106223456],[-0.41748046875,53.91728101547621],[-2.109375,53.85252660044951],[-3.1640625,53.014783245859235]]]},"properties":{"_storage_options":{},"name":"Ho god, sounds like a polygouine"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[1.8017578124999998,51.16556659836182],[-0.48339843749999994,49.710272582105695],[-3.1640625,50.0923932109388],[-5.60302734375,51.998410382390325]]},"properties":{"_storage_options":{},"name":"Light line"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[0.63720703125,51.15178610143037]},"properties":{"_storage_options":{},"name":"marker he"}}],"_storage":{"displayOnLoad":true,"name":"new name","id":1668,"remoteData":{},"color":"LightSeaGreen","description":"test"}}' # noqa + } + + +def test_get(client, settings, datalayer): + url = reverse('datalayer_view', args=(datalayer.pk, )) + response = client.get(url) + if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None): + assert response['ETag'] is not None + assert response['Last-Modified'] is not None + assert response['Cache-Control'] is not None + assert 'Content-Encoding' not in response + j = json.loads(response.content.decode()) + assert '_storage' in j + assert 'features' in j + assert j['type'] == 'FeatureCollection' + + +def test_update(client, datalayer, map, post_data): + url = reverse('datalayer_update', args=(map.pk, datalayer.pk)) + client.login(username=map.owner.username, password="123123") + name = 'new name' + rank = 2 + post_data['name'] = name + post_data['rank'] = rank + response = client.post(url, post_data, follow=True) + assert response.status_code == 200 + modified_datalayer = DataLayer.objects.get(pk=datalayer.pk) + assert modified_datalayer.name == name + assert modified_datalayer.rank == rank + # Test response is a json + j = json.loads(response.content.decode()) + assert "id" in j + assert datalayer.pk == j['id'] + + +def test_should_not_be_possible_to_update_with_wrong_map_id_in_url(client, datalayer, map, post_data): # noqa + other_map = MapFactory(owner=map.owner) + url = reverse('datalayer_update', args=(other_map.pk, datalayer.pk)) + client.login(username=map.owner.username, password="123123") + name = 'new name' + post_data['name'] = name + response = client.post(url, post_data, follow=True) + assert response.status_code == 403 + modified_datalayer = DataLayer.objects.get(pk=datalayer.pk) + assert modified_datalayer.name == datalayer.name + + +def test_delete(client, datalayer, map): + url = reverse('datalayer_delete', args=(map.pk, datalayer.pk)) + client.login(username=map.owner.username, password='123123') + response = client.post(url, {}, follow=True) + assert response.status_code == 200 + assert not DataLayer.objects.filter(pk=datalayer.pk).count() + # Check that map has not been impacted + assert Map.objects.filter(pk=map.pk).exists() + # Test response is a json + j = json.loads(response.content.decode()) + assert 'info' in j + + +def test_should_not_be_possible_to_delete_with_wrong_map_id_in_url(client, datalayer, map): # noqa + other_map = MapFactory(owner=map.owner) + url = reverse('datalayer_delete', args=(other_map.pk, datalayer.pk)) + client.login(username=map.owner.username, password='123123') + response = client.post(url, {}, follow=True) + assert response.status_code == 403 + assert DataLayer.objects.filter(pk=datalayer.pk).exists() + + +def test_get_gzipped(client, datalayer, settings): + url = reverse('datalayer_view', args=(datalayer.pk, )) + response = client.get(url, HTTP_ACCEPT_ENCODING='gzip') + if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None): + assert response['ETag'] is not None + assert response['Last-Modified'] is not None + assert response['Cache-Control'] is not None + assert response['Content-Encoding'] == 'gzip' + + +def test_optimistic_concurrency_control_with_good_etag(client, datalayer, map, post_data): # noqa + # Get Etag + url = reverse('datalayer_view', args=(datalayer.pk, )) + response = client.get(url) + etag = response['ETag'] + url = reverse('datalayer_update', + args=(map.pk, datalayer.pk)) + client.login(username=map.owner.username, password="123123") + name = 'new name' + post_data['name'] = 'new name' + response = client.post(url, post_data, follow=True, HTTP_IF_MATCH=etag) + assert response.status_code == 200 + modified_datalayer = DataLayer.objects.get(pk=datalayer.pk) + assert modified_datalayer.name == name + + +def test_optimistic_concurrency_control_with_bad_etag(client, datalayer, map, post_data): # noqa + url = reverse('datalayer_update', args=(map.pk, datalayer.pk)) + client.login(username=map.owner.username, password='123123') + name = 'new name' + post_data['name'] = name + response = client.post(url, post_data, follow=True, HTTP_IF_MATCH='xxx') + assert response.status_code == 412 + modified_datalayer = DataLayer.objects.get(pk=datalayer.pk) + assert modified_datalayer.name != name + + +def test_optimistic_concurrency_control_with_empty_etag(client, datalayer, map, post_data): # noqa + url = reverse('datalayer_update', args=(map.pk, datalayer.pk)) + client.login(username=map.owner.username, password='123123') + name = 'new name' + post_data['name'] = name + response = client.post(url, post_data, follow=True, HTTP_IF_MATCH=None) + assert response.status_code == 200 + modified_datalayer = DataLayer.objects.get(pk=datalayer.pk) + assert modified_datalayer.name == name + + +def test_versions_should_return_versions(client, datalayer, map, settings): + root = datalayer.storage_root() + datalayer.geojson.storage.save( + '%s/%s_1440924889.geojson' % (root, datalayer.pk), + ContentFile("{}")) + datalayer.geojson.storage.save( + '%s/%s_1440923687.geojson' % (root, datalayer.pk), + ContentFile("{}")) + datalayer.geojson.storage.save( + '%s/%s_1440918637.geojson' % (root, datalayer.pk), + ContentFile("{}")) + url = reverse('datalayer_versions', args=(datalayer.pk, )) + versions = json.loads(client.get(url).content.decode()) + assert len(versions['versions']) == 4 + version = {'name': '%s_1440918637.geojson' % datalayer.pk, 'size': 2, + 'at': '1440918637'} + assert version in versions['versions'] + + +def test_version_should_return_one_version_geojson(client, datalayer, map): + root = datalayer.storage_root() + name = '%s_1440924889.geojson' % datalayer.pk + datalayer.geojson.storage.save('%s/%s' % (root, name), ContentFile("{}")) + url = reverse('datalayer_version', args=(datalayer.pk, name)) + assert client.get(url).content.decode() == "{}" diff --git a/umap/tests/test_fields.py b/umap/tests/test_fields.py new file mode 100644 index 00000000..4d744cd3 --- /dev/null +++ b/umap/tests/test_fields.py @@ -0,0 +1,43 @@ +import json + +import pytest + +from umap.models import Map + +pytestmark = pytest.mark.django_db + + +def test_can_use_dict(map): + d = {'locateControl': True} + map.settings = d + map.save() + assert Map.objects.get(pk=map.pk).settings == d + + +def test_can_set_item(map): + d = {'locateControl': True} + map.settings = d + map.save() + map_inst = Map.objects.get(pk=map.pk) + map_inst.settings['color'] = 'DarkGreen' + assert map_inst.settings['locateControl'] is True + + +def test_should_return_a_dict_if_none(map): + map.settings = None + map.save() + assert Map.objects.get(pk=map.pk).settings == {} + + +def test_should_not_double_dumps(map): + map.settings = '{"locate": true}' + map.save() + assert Map.objects.get(pk=map.pk).settings == {'locate': True} + + +def test_value_to_string(map): + d = {'locateControl': True} + map.settings = d + map.save() + field = Map._meta.get_field('settings') + assert json.loads(field.value_to_string(map)) == d diff --git a/umap/tests/test_licence.py b/umap/tests/test_licence.py new file mode 100644 index 00000000..fd5e606b --- /dev/null +++ b/umap/tests/test_licence.py @@ -0,0 +1,12 @@ +import pytest + +from umap.models import DataLayer, Map + +pytestmark = pytest.mark.django_db + + +def test_licence_delete_should_not_remove_linked_maps(map, licence, datalayer): + assert map.licence == licence + licence.delete() + assert Map.objects.filter(pk=map.pk).exists() + assert DataLayer.objects.filter(pk=datalayer.pk).exists() diff --git a/umap/tests/test_map.py b/umap/tests/test_map.py new file mode 100644 index 00000000..c72d3d1f --- /dev/null +++ b/umap/tests/test_map.py @@ -0,0 +1,109 @@ +import pytest +from django.contrib.auth.models import AnonymousUser +from django.urls import reverse + +from umap.models import Map + +from .base import MapFactory + +pytestmark = pytest.mark.django_db + + +def test_anonymous_can_edit_if_status_anonymous(map): + anonymous = AnonymousUser() + map.edit_status = map.ANONYMOUS + map.save() + assert map.can_edit(anonymous) + + +def test_anonymous_cannot_edit_if_not_status_anonymous(map): + anonymous = AnonymousUser() + map.edit_status = map.OWNER + map.save() + assert not map.can_edit(anonymous) + + +def test_non_editors_can_edit_if_status_anonymous(map, user): + assert map.owner != user + map.edit_status = map.ANONYMOUS + map.save() + assert map.can_edit(user) + + +def test_non_editors_cannot_edit_if_not_status_anonymous(map, user): + map.edit_status = map.OWNER + map.save() + assert not map.can_edit(user) + + +def test_editors_cannot_edit_if_status_owner(map, user): + map.edit_status = map.OWNER + map.editors.add(user) + map.save() + assert not map.can_edit(user) + + +def test_editors_can_edit_if_status_editors(map, user): + map.edit_status = map.EDITORS + map.editors.add(user) + map.save() + assert map.can_edit(user) + + +def test_logged_in_user_should_be_allowed_for_anonymous_map_with_anonymous_edit_status(map, user, rf): # noqa + map.owner = None + map.edit_status = map.ANONYMOUS + map.save() + url = reverse('map_update', kwargs={'map_id': map.pk}) + request = rf.get(url) + request.user = user + assert map.can_edit(user, request) + + +def test_clone_should_return_new_instance(map, user): + clone = map.clone() + assert map.pk != clone.pk + assert u"Clone of " + map.name == clone.name + assert map.settings == clone.settings + assert map.center == clone.center + assert map.zoom == clone.zoom + assert map.licence == clone.licence + assert map.tilelayer == clone.tilelayer + + +def test_clone_should_keep_editors(map, user): + map.editors.add(user) + clone = map.clone() + assert map.pk != clone.pk + assert user in map.editors.all() + assert user in clone.editors.all() + + +def test_clone_should_update_owner_if_passed(map, user): + clone = map.clone(owner=user) + assert map.pk != clone.pk + assert map.owner != clone.owner + assert user == clone.owner + + +def test_clone_should_clone_datalayers_and_features_too(map, user, datalayer): + clone = map.clone() + assert map.pk != clone.pk + assert map.datalayer_set.count() == 1 + assert clone.datalayer_set.count() == 1 + other = clone.datalayer_set.all()[0] + assert datalayer in map.datalayer_set.all() + assert other.pk != datalayer.pk + assert other.name == datalayer.name + assert other.geojson is not None + assert other.geojson.path != datalayer.geojson.path + + +def test_publicmanager_should_get_only_public_maps(map, user, licence): + map.share_status = map.PUBLIC + open_map = MapFactory(owner=user, licence=licence, share_status=Map.OPEN) + private_map = MapFactory(owner=user, licence=licence, + share_status=Map.PRIVATE) + assert map in Map.public.all() + assert open_map not in Map.public.all() + assert private_map not in Map.public.all() diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py new file mode 100644 index 00000000..37241776 --- /dev/null +++ b/umap/tests/test_map_views.py @@ -0,0 +1,449 @@ +import json + +import pytest +from django.contrib.auth import get_user_model +from django.urls import reverse + +from umap.models import DataLayer, Map + +from .base import login_required + +pytestmark = pytest.mark.django_db +User = get_user_model() + + +@pytest.fixture +def post_data(): + return { + 'name': 'name', + 'center': '{"type":"Point","coordinates":[13.447265624999998,48.94415123418794]}', # noqa + 'settings': '{"type":"Feature","geometry":{"type":"Point","coordinates":[5.0592041015625,52.05924589011585]},"properties":{"tilelayer":{"maxZoom":20,"url_template":"http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png","minZoom":0,"attribution":"HOT and friends"},"licence":"","description":"","name":"test enrhûmé","tilelayersControl":true,"displayDataBrowserOnLoad":false,"displayPopupFooter":true,"displayCaptionOnLoad":false,"miniMap":true,"moreControl":true,"scaleControl":true,"zoomControl":true,"datalayersControl":true,"zoom":8}}' # noqa + } + + +def test_create(client, user, post_data): + url = reverse('map_create') + # POST only mendatory fields + name = 'test-map-with-new-name' + post_data['name'] = name + client.login(username=user.username, password="123123") + response = client.post(url, post_data) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + created_map = Map.objects.latest('pk') + assert j['id'] == created_map.pk + assert created_map.name == name + + +def test_map_create_permissions(client, settings): + settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = False + url = reverse('map_create') + # POST anonymous + response = client.post(url, {}) + assert login_required(response) + + +def test_map_update_access(client, map, user): + url = reverse('map_update', kwargs={'map_id': map.pk}) + # GET anonymous + response = client.get(url) + assert login_required(response) + # POST anonymous + response = client.post(url, {}) + assert login_required(response) + # GET with wrong permissions + client.login(username=user.username, password="123123") + response = client.get(url) + assert response.status_code == 403 + # POST with wrong permissions + client.login(username=user.username, password="123123") + response = client.post(url, {}) + assert response.status_code == 403 + + +def test_map_update_permissions_access(client, map, user): + url = reverse('map_update_permissions', kwargs={'map_id': map.pk}) + # GET anonymous + response = client.get(url) + assert login_required(response) + # POST anonymous + response = client.post(url, {}) + assert login_required(response) + # GET with wrong permissions + client.login(username=user.username, password="123123") + response = client.get(url) + assert response.status_code == 403 + # POST with wrong permissions + client.login(username=user.username, password="123123") + response = client.post(url, {}) + assert response.status_code == 403 + + +def test_update(client, map, post_data): + url = reverse('map_update', kwargs={'map_id': map.pk}) + # POST only mendatory fields + name = 'new map name' + post_data['name'] = name + client.login(username=map.owner.username, password="123123") + response = client.post(url, post_data) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + assert 'html' not in j + updated_map = Map.objects.get(pk=map.pk) + assert j['id'] == updated_map.pk + assert updated_map.name == name + + +def test_delete(client, map, datalayer): + url = reverse('map_delete', args=(map.pk, )) + client.login(username=map.owner.username, password="123123") + response = client.post(url, {}, follow=True) + assert response.status_code == 200 + assert not Map.objects.filter(pk=map.pk).exists() + assert not DataLayer.objects.filter(pk=datalayer.pk).exists() + # Check that user has not been impacted + assert User.objects.filter(pk=map.owner.pk).exists() + # Test response is a json + j = json.loads(response.content.decode()) + assert 'redirect' in j + + +def test_wrong_slug_should_redirect_to_canonical(client, map): + url = reverse('map', kwargs={'pk': map.pk, 'slug': 'wrong-slug'}) + canonical = reverse('map', kwargs={'pk': map.pk, + 'slug': map.slug}) + response = client.get(url) + assert response.status_code == 301 + assert response['Location'] == canonical + + +def test_wrong_slug_should_redirect_with_query_string(client, map): + url = reverse('map', kwargs={'pk': map.pk, 'slug': 'wrong-slug'}) + url = "{}?allowEdit=0".format(url) + canonical = reverse('map', kwargs={'pk': map.pk, + 'slug': map.slug}) + canonical = "{}?allowEdit=0".format(canonical) + response = client.get(url) + assert response.status_code == 301 + assert response['Location'] == canonical + + +def test_should_not_consider_the_query_string_for_canonical_check(client, map): + url = reverse('map', kwargs={'pk': map.pk, 'slug': map.slug}) + url = "{}?allowEdit=0".format(url) + response = client.get(url) + assert response.status_code == 200 + + +def test_short_url_should_redirect_to_canonical(client, map): + url = reverse('map_short_url', kwargs={'pk': map.pk}) + canonical = reverse('map', kwargs={'pk': map.pk, + 'slug': map.slug}) + response = client.get(url) + assert response.status_code == 301 + assert response['Location'] == canonical + + +def test_old_url_should_redirect_to_canonical(client, map): + url = reverse( + 'map_old_url', + kwargs={'username': map.owner.username, 'slug': map.slug} + ) + canonical = reverse('map', kwargs={'pk': map.pk, + 'slug': map.slug}) + response = client.get(url) + assert response.status_code == 301 + assert response['Location'] == canonical + + +def test_clone_map_should_create_a_new_instance(client, map): + assert Map.objects.count() == 1 + url = reverse('map_clone', kwargs={'map_id': map.pk}) + client.login(username=map.owner.username, password="123123") + response = client.post(url) + assert response.status_code == 200 + assert Map.objects.count() == 2 + clone = Map.objects.latest('pk') + assert clone.pk != map.pk + assert clone.name == u"Clone of " + map.name + + +def test_user_not_allowed_should_not_clone_map(client, map, user, settings): + settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = False + assert Map.objects.count() == 1 + url = reverse('map_clone', kwargs={'map_id': map.pk}) + map.edit_status = map.OWNER + map.save() + response = client.post(url) + assert login_required(response) + client.login(username=user.username, password="123123") + response = client.post(url) + assert response.status_code == 403 + map.edit_status = map.ANONYMOUS + map.save() + client.logout() + response = client.post(url) + assert response.status_code == 403 + assert Map.objects.count() == 1 + + +def test_clone_should_set_cloner_as_owner(client, map, user): + url = reverse('map_clone', kwargs={'map_id': map.pk}) + map.edit_status = map.EDITORS + map.editors.add(user) + map.save() + client.login(username=user.username, password="123123") + response = client.post(url) + assert response.status_code == 200 + assert Map.objects.count() == 2 + clone = Map.objects.latest('pk') + assert clone.pk != map.pk + assert clone.name == u"Clone of " + map.name + assert clone.owner == user + + +def test_map_creation_should_allow_unicode_names(client, map, post_data): + url = reverse('map_create') + # POST only mendatory fields + name = u'Академический' + post_data['name'] = name + client.login(username=map.owner.username, password="123123") + response = client.post(url, post_data) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + created_map = Map.objects.latest('pk') + assert j['id'] == created_map.pk + assert created_map.name == name + # Lower case of the russian original name + # self.assertEqual(created_map.slug, u"академический") + # for now we fallback to "map", see unicode_name branch + assert created_map.slug == 'map' + + +def test_anonymous_can_access_map_with_share_status_public(client, map): + url = reverse('map', args=(map.slug, map.pk)) + map.share_status = map.PUBLIC + map.save() + response = client.get(url) + assert response.status_code == 200 + + +def test_anonymous_can_access_map_with_share_status_open(client, map): + url = reverse('map', args=(map.slug, map.pk)) + map.share_status = map.OPEN + map.save() + response = client.get(url) + assert response.status_code == 200 + + +def test_anonymous_cannot_access_map_with_share_status_private(client, map): + url = reverse('map', args=(map.slug, map.pk)) + map.share_status = map.PRIVATE + map.save() + response = client.get(url) + assert response.status_code == 403 + + +def test_owner_can_access_map_with_share_status_private(client, map): + url = reverse('map', args=(map.slug, map.pk)) + map.share_status = map.PRIVATE + map.save() + client.login(username=map.owner.username, password="123123") + response = client.get(url) + assert response.status_code == 200 + + +def test_editors_can_access_map_with_share_status_private(client, map, user): + url = reverse('map', args=(map.slug, map.pk)) + map.share_status = map.PRIVATE + map.editors.add(user) + map.save() + client.login(username=user.username, password="123123") + response = client.get(url) + assert response.status_code == 200 + + +def test_non_editor_cannot_access_map_if_share_status_private(client, map, user): # noqa + url = reverse('map', args=(map.slug, map.pk)) + map.share_status = map.PRIVATE + map.save() + client.login(username=user.username, password="123123") + response = client.get(url) + assert response.status_code == 403 + + +def test_map_geojson_view(client, map): + url = reverse('map_geojson', args=(map.pk, )) + response = client.get(url) + j = json.loads(response.content.decode()) + assert 'type' in j + + +def test_only_owner_can_delete(client, map, user): + map.editors.add(user) + url = reverse('map_delete', kwargs={'map_id': map.pk}) + client.login(username=user.username, password="123123") + response = client.post(url, {}, follow=True) + assert response.status_code == 403 + + +def test_map_editors_do_not_see_owner_change_input(client, map, user): + map.editors.add(user) + map.edit_status = map.EDITORS + map.save() + url = reverse('map_update_permissions', kwargs={'map_id': map.pk}) + client.login(username=user.username, password="123123") + response = client.get(url) + assert 'id_owner' not in response + + +def test_logged_in_user_can_edit_map_editable_by_anonymous(client, map, user): + map.owner = None + map.edit_status = map.ANONYMOUS + map.save() + client.login(username=user.username, password="123123") + url = reverse('map_update', kwargs={'map_id': map.pk}) + new_name = 'this is my new name' + data = { + 'center': '{"type":"Point","coordinates":[13.447265624999998,48.94415123418794]}', # noqa + 'name': new_name + } + response = client.post(url, data) + assert response.status_code == 200 + assert Map.objects.get(pk=map.pk).name == new_name + + +@pytest.mark.usefixtures('allow_anonymous') +def test_anonymous_create(cookieclient, post_data): + url = reverse('map_create') + # POST only mendatory fields + name = 'test-map-with-new-name' + post_data['name'] = name + response = cookieclient.post(url, post_data) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + created_map = Map.objects.latest('pk') + assert j['id'] == created_map.pk + assert created_map.name == name + key, value = created_map.signed_cookie_elements + assert key in cookieclient.cookies + + +@pytest.mark.usefixtures('allow_anonymous') +def test_anonymous_update_without_cookie_fails(client, anonymap, post_data): # noqa + url = reverse('map_update', kwargs={'map_id': anonymap.pk}) + response = client.post(url, post_data) + assert response.status_code == 403 + + +@pytest.mark.usefixtures('allow_anonymous') +def test_anonymous_update_with_cookie_should_work(cookieclient, anonymap, post_data): # noqa + url = reverse('map_update', kwargs={'map_id': anonymap.pk}) + # POST only mendatory fields + name = 'new map name' + post_data['name'] = name + response = cookieclient.post(url, post_data) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + updated_map = Map.objects.get(pk=anonymap.pk) + assert j['id'] == updated_map.pk + + +@pytest.mark.usefixtures('allow_anonymous') +def test_anonymous_delete(cookieclient, anonymap): + url = reverse('map_delete', args=(anonymap.pk, )) + response = cookieclient.post(url, {}, follow=True) + assert response.status_code == 200 + assert not Map.objects.filter(pk=anonymap.pk).count() + # Test response is a json + j = json.loads(response.content.decode()) + assert 'redirect' in j + + +@pytest.mark.usefixtures('allow_anonymous') +def test_no_cookie_cant_delete(client, anonymap): + url = reverse('map_delete', args=(anonymap.pk, )) + response = client.post(url, {}, follow=True) + assert response.status_code == 403 + + +@pytest.mark.usefixtures('allow_anonymous') +def test_anonymous_edit_url(cookieclient, anonymap): + url = anonymap.get_anonymous_edit_url() + canonical = reverse('map', kwargs={'pk': anonymap.pk, + 'slug': anonymap.slug}) + response = cookieclient.get(url) + assert response.status_code == 302 + assert response['Location'] == canonical + key, value = anonymap.signed_cookie_elements + assert key in cookieclient.cookies + + +@pytest.mark.usefixtures('allow_anonymous') +def test_bad_anonymous_edit_url_should_return_403(cookieclient, anonymap): + url = anonymap.get_anonymous_edit_url() + url = reverse( + 'map_anonymous_edit_url', + kwargs={'signature': "%s:badsignature" % anonymap.pk} + ) + response = cookieclient.get(url) + assert response.status_code == 403 + + +@pytest.mark.usefixtures('allow_anonymous') +def test_authenticated_user_with_cookie_is_attached_as_owner(cookieclient, anonymap, post_data, user): # noqa + url = reverse('map_update', kwargs={'map_id': anonymap.pk}) + cookieclient.login(username=user.username, password="123123") + assert anonymap.owner is None + # POST only mendatory filds + name = 'new map name for authenticat_anonymoused user' + post_data['name'] = name + response = cookieclient.post(url, post_data) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + updated_map = Map.objects.get(pk=anonymap.pk) + assert j['id'] == updated_map.pk + assert updated_map.owner.pk, user.pk + + +@pytest.mark.usefixtures('allow_anonymous') +def test_clone_anonymous_map_should_not_be_possible_if_user_is_not_allowed(client, anonymap, user): # noqa + assert Map.objects.count() == 1 + url = reverse('map_clone', kwargs={'map_id': anonymap.pk}) + anonymap.edit_status = anonymap.OWNER + anonymap.save() + response = client.post(url) + assert response.status_code == 403 + client.login(username=user.username, password="123123") + response = client.post(url) + assert response.status_code == 403 + assert Map.objects.count() == 1 + + +@pytest.mark.usefixtures('allow_anonymous') +def test_clone_map_should_be_possible_if_edit_status_is_anonymous(client, anonymap): # noqa + assert Map.objects.count() == 1 + url = reverse('map_clone', kwargs={'map_id': anonymap.pk}) + anonymap.edit_status = anonymap.ANONYMOUS + anonymap.save() + response = client.post(url) + assert response.status_code == 200 + assert Map.objects.count() == 2 + clone = Map.objects.latest('pk') + assert clone.pk != anonymap.pk + assert clone.name == 'Clone of ' + anonymap.name + assert clone.owner is None + + +@pytest.mark.usefixtures('allow_anonymous') +def test_anyone_can_access_anonymous_map(cookieclient, anonymap): + url = reverse('map', args=(anonymap.slug, anonymap.pk)) + anonymap.share_status = anonymap.PUBLIC + response = cookieclient.get(url) + assert response.status_code == 200 + anonymap.share_status = anonymap.OPEN + response = cookieclient.get(url) + assert response.status_code == 200 + anonymap.share_status = anonymap.PRIVATE + response = cookieclient.get(url) + assert response.status_code == 200 diff --git a/umap/tests/test_tilelayer.py b/umap/tests/test_tilelayer.py new file mode 100644 index 00000000..11e81709 --- /dev/null +++ b/umap/tests/test_tilelayer.py @@ -0,0 +1,21 @@ +import pytest + +from .base import TileLayerFactory + +pytestmark = pytest.mark.django_db + + +def test_tilelayer_json(): + tilelayer = TileLayerFactory(attribution='Attribution', maxZoom=19, + minZoom=0, name='Name', rank=1, tms=True, + url_template='http://{s}.x.fr/{z}/{x}/{y}') + assert tilelayer.json == { + 'attribution': 'Attribution', + 'id': tilelayer.id, + 'maxZoom': 19, + 'minZoom': 0, + 'name': 'Name', + 'rank': 1, + 'tms': True, + 'url_template': 'http://{s}.x.fr/{z}/{x}/{y}' + } From 1ef5e13f4828ea1107e9ce3e92cd562e63e85c4f Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 12:01:53 +0200 Subject: [PATCH 007/239] Remove duplicate short_url declarations --- umap/settings/base.py | 1 - umap/urls.py | 5 ++--- umap/views.py | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/umap/settings/base.py b/umap/settings/base.py index e6490bc5..62529b83 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -164,7 +164,6 @@ UMAP_DEMO_SITE = False UMAP_EXCLUDE_DEFAULT_MAPS = False UMAP_MAPS_PER_PAGE = 5 UMAP_MAPS_PER_PAGE_OWNER = 10 -MAP_SHORT_URL_NAME = "umap_short_url" UMAP_USE_UNACCENT = False UMAP_FEEDBACK_LINK = "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help" # noqa USER_MAPS_URL = 'user_maps' diff --git a/umap/urls.py b/umap/urls.py index 5b735b87..03526259 100644 --- a/umap/urls.py +++ b/umap/urls.py @@ -21,7 +21,8 @@ admin.autodiscover() urlpatterns = [ url(r'^admin/', admin.site.urls), url('', include('social_django.urls', namespace='social')), - url(r'^m/(?P\d+)/$', views.MapShortUrl.as_view(), name='umap_short_url'), + url(r'^m/(?P\d+)/$', views.MapShortUrl.as_view(), + name='map_short_url'), url(r'^ajax-proxy/$', cache_page(180)(views.ajax_proxy), name='ajax-proxy'), url(r'^change-password/', auth_views.password_change, @@ -43,8 +44,6 @@ i18n_urls = [ views.MapOldUrl.as_view(), name='map_old_url'), url(r'^map/anonymous-edit/(?P.+)$', views.MapAnonymousEditUrl.as_view(), name='map_anonymous_edit_url'), - url(r'^m/(?P\d+)/$', views.MapShortUrl.as_view(), - name='map_short_url'), url(r'^pictogram/json/$', views.PictogramJSONList.as_view(), name='pictogram_list_json'), ] diff --git a/umap/views.py b/umap/views.py index bac84e58..e1d26a7f 100644 --- a/umap/views.py +++ b/umap/views.py @@ -439,9 +439,7 @@ class MapView(MapDetailMixin, DetailView): def get_short_url(self): shortUrl = None if hasattr(settings, 'SHORT_SITE_URL'): - short_url_name = getattr(settings, 'MAP_SHORT_URL_NAME', - 'map_short_url') - short_path = reverse_lazy(short_url_name, + short_path = reverse_lazy('map_short_url', kwargs={'pk': self.object.pk}) shortUrl = "%s%s" % (settings.SHORT_SITE_URL, short_path) return shortUrl From 4e5d9a6319986d13d776d203a1a787c230a71aae Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 12:05:04 +0200 Subject: [PATCH 008/239] Add missing factory_boy dev dependency --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index 59dc14cc..95b24a2e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ +factory-boy==2.11.1 pytest==3.0.7 pytest-django==3.1.2 mkdocs==0.16.3 From 8fd541955e493ce57fc13f8dc8e5864715c02763 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 16:28:56 +0200 Subject: [PATCH 009/239] Disable compressor during unittests for now --- pytest.ini | 2 +- umap/tests/settings.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index b9589e63..733af6f1 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ [pytest] -DJANGO_SETTINGS_MODULE=umap.settings +DJANGO_SETTINGS_MODULE=umap.tests.settings diff --git a/umap/tests/settings.py b/umap/tests/settings.py index a018ce88..38fb0d6f 100644 --- a/umap/tests/settings.py +++ b/umap/tests/settings.py @@ -1,3 +1,4 @@ from umap.settings.base import * # pylint: disable=W0614,W0401 SECRET_KEY = 'justfortests' +COMPRESS_ENABLED = False From e0169d569ebdd29cb957d8b590d9a7bafa6eaa5f Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 16:33:46 +0200 Subject: [PATCH 010/239] Remove python2.7 from Travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ed33d532..29a5f023 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ sudo: false language: python python: -- "2.7" - "3.4" - "3.5" - "3.6" From 62a825e6edae36a433a7764f95f57c636314d571 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 19 May 2018 17:16:34 +0200 Subject: [PATCH 011/239] Replace LEAFLET_STORAGE_XXX settings by UMAP_XXXX We keep a retrocompatibility for now. --- umap/decorators.py | 2 +- umap/models.py | 6 +++--- umap/settings/__init__.py | 6 +++++- umap/settings/base.py | 6 +++--- umap/settings/local.py.sample | 4 ++-- umap/tests/conftest.py | 2 +- umap/tests/test_datalayer.py | 2 +- umap/tests/test_datalayer_views.py | 4 ++-- umap/tests/test_map_views.py | 4 ++-- umap/views.py | 10 +++++----- 10 files changed, 25 insertions(+), 21 deletions(-) diff --git a/umap/decorators.py b/umap/decorators.py index a6f27134..971a9257 100644 --- a/umap/decorators.py +++ b/umap/decorators.py @@ -17,7 +17,7 @@ LOGIN_URL = (reverse_lazy(LOGIN_URL) if not LOGIN_URL.startswith("/") def login_required_if_not_anonymous_allowed(view_func): @wraps(view_func) def wrapper(request, *args, **kwargs): - if (not getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False) + if (not getattr(settings, "UMAP_ALLOW_ANONYMOUS", False) and not request.user.is_authenticated): return simple_json_response(login_required=str(LOGIN_URL)) return view_func(request, *args, **kwargs) diff --git a/umap/models.py b/umap/models.py index b2909820..66caa7e3 100644 --- a/umap/models.py +++ b/umap/models.py @@ -38,7 +38,7 @@ def get_default_licence(): """ return Licence.objects.get_or_create( # can't use ugettext_lazy for database storage, see #13965 - name=getattr(settings, "LEAFLET_STORAGE_DEFAULT_LICENCE_NAME", + name=getattr(settings, "UMAP_DEFAULT_LICENCE_NAME", 'No licence set') )[0] @@ -171,7 +171,7 @@ class Map(NamedModel): """ can = False if request and not self.owner: - if (getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False) + if (getattr(settings, "UMAP_ALLOW_ANONYMOUS", False) and self.is_anonymous_owner(request)): can = True if user and user.is_authenticated: @@ -346,7 +346,7 @@ class DataLayer(NamedModel): def purge_old_versions(self): root = self.storage_root() - names = self.get_versions()[settings.LEAFLET_STORAGE_KEEP_VERSIONS:] + names = self.get_versions()[settings.UMAP_KEEP_VERSIONS:] for name in names: for ext in ['', '.gz']: path = os.path.join(root, name + ext) diff --git a/umap/settings/__init__.py b/umap/settings/__init__.py index 000bffd2..6a0d6ee8 100644 --- a/umap/settings/__init__.py +++ b/umap/settings/__init__.py @@ -35,4 +35,8 @@ else: print('Loaded local config from', path) for key in dir(d): if key.isupper(): - globals()[key] = getattr(d, key) + if key.startswith('LEAFLET_STORAGE'): + # Retrocompat pre 1.0, remove me in 1.1. + globals()['UMAP' + key[15:]] = getattr(d, key) + else: + globals()[key] = getattr(d, key) diff --git a/umap/settings/base.py b/umap/settings/base.py index 62529b83..4a175c2a 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -152,12 +152,12 @@ AUTHENTICATION_BACKENDS += ( # ============================================================================= # Miscellaneous project settings # ============================================================================= -LEAFLET_STORAGE_ALLOW_ANONYMOUS = False -LEAFLET_STORAGE_EXTRA_URLS = { +UMAP_ALLOW_ANONYMOUS = False +UMAP_EXTRA_URLS = { 'routing': 'http://www.openstreetmap.org/directions?engine=osrm_car&route={lat},{lng}&locale={locale}#map={zoom}/{lat}/{lng}', # noqa 'ajax_proxy': '/ajax-proxy/?url={url}' } -LEAFLET_STORAGE_KEEP_VERSIONS = 10 +UMAP_KEEP_VERSIONS = 10 SITE_URL = "http://umap.org" SITE_NAME = 'uMap' UMAP_DEMO_SITE = False diff --git a/umap/settings/local.py.sample b/umap/settings/local.py.sample index 3af92754..6404bf80 100644 --- a/umap/settings/local.py.sample +++ b/umap/settings/local.py.sample @@ -69,7 +69,7 @@ SOCIAL_AUTH_BACKEND_ERROR_URL = "/" UMAP_DEMO_SITE = True # Whether to allow non authenticated people to create maps. -LEAFLET_STORAGE_ALLOW_ANONYMOUS = True +UMAP_ALLOW_ANONYMOUS = True # This setting will exclude empty maps (in fact, it will exclude all maps where # the default center has not been updated) @@ -110,4 +110,4 @@ LEAFLET_LATITUDE = 51 LEAFLET_ZOOM = 6 # Number of old version to keep per datalayer. -LEAFLET_STORAGE_KEEP_VERSIONS = 10 +UMAP_KEEP_VERSIONS = 10 diff --git a/umap/tests/conftest.py b/umap/tests/conftest.py index 441513f7..1ac6664f 100644 --- a/umap/tests/conftest.py +++ b/umap/tests/conftest.py @@ -51,7 +51,7 @@ def cookieclient(client, anonymap): @pytest.fixture def allow_anonymous(settings): - settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = True + settings.UMAP_ALLOW_ANONYMOUS = True @pytest.fixture diff --git a/umap/tests/test_datalayer.py b/umap/tests/test_datalayer.py index 65f8e2f7..e1566e0f 100644 --- a/umap/tests/test_datalayer.py +++ b/umap/tests/test_datalayer.py @@ -59,7 +59,7 @@ def test_clone_should_clone_geojson_too(datalayer): def test_should_remove_old_versions_on_save(datalayer, map, settings): - settings.LEAFLET_STORAGE_KEEP_VERSIONS = 3 + settings.UMAP_KEEP_VERSIONS = 3 root = datalayer.storage_root() before = len(datalayer.geojson.storage.listdir(root)[1]) newer = '%s/%s_1440924889.geojson' % (root, datalayer.pk) diff --git a/umap/tests/test_datalayer_views.py b/umap/tests/test_datalayer_views.py index b4f90f73..3727bc80 100644 --- a/umap/tests/test_datalayer_views.py +++ b/umap/tests/test_datalayer_views.py @@ -24,7 +24,7 @@ def post_data(): def test_get(client, settings, datalayer): url = reverse('datalayer_view', args=(datalayer.pk, )) response = client.get(url) - if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None): + if getattr(settings, 'UMAP_XSENDFILE_HEADER', None): assert response['ETag'] is not None assert response['Last-Modified'] is not None assert response['Cache-Control'] is not None @@ -90,7 +90,7 @@ def test_should_not_be_possible_to_delete_with_wrong_map_id_in_url(client, datal def test_get_gzipped(client, datalayer, settings): url = reverse('datalayer_view', args=(datalayer.pk, )) response = client.get(url, HTTP_ACCEPT_ENCODING='gzip') - if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None): + if getattr(settings, 'UMAP_XSENDFILE_HEADER', None): assert response['ETag'] is not None assert response['Last-Modified'] is not None assert response['Cache-Control'] is not None diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py index 37241776..d602e975 100644 --- a/umap/tests/test_map_views.py +++ b/umap/tests/test_map_views.py @@ -36,7 +36,7 @@ def test_create(client, user, post_data): def test_map_create_permissions(client, settings): - settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = False + settings.UMAP_ALLOW_ANONYMOUS = False url = reverse('map_create') # POST anonymous response = client.post(url, {}) @@ -169,7 +169,7 @@ def test_clone_map_should_create_a_new_instance(client, map): def test_user_not_allowed_should_not_clone_map(client, map, user, settings): - settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = False + settings.UMAP_ALLOW_ANONYMOUS = False assert Map.objects.count() == 1 url = reverse('map_clone', kwargs={'map_id': map.pk}) map.edit_status = map.OWNER diff --git a/umap/views.py b/umap/views.py index e1d26a7f..3b43b57a 100644 --- a/umap/views.py +++ b/umap/views.py @@ -304,7 +304,7 @@ def _urls_for_js(urls=None): urls = [url.name for url in urlpatterns + i18n_urls if getattr(url, 'name', None)] urls = dict(zip(urls, [get_uri_template(url) for url in urls])) - urls.update(getattr(settings, 'LEAFLET_STORAGE_EXTRA_URLS', {})) + urls.update(getattr(settings, 'UMAP_EXTRA_URLS', {})) return urls @@ -569,7 +569,7 @@ class MapDelete(DeleteView): class MapClone(View): def post(self, *args, **kwargs): - if not getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False) \ + if not getattr(settings, "UMAP_ALLOW_ANONYMOUS", False) \ and not self.request.user.is_authenticated: return HttpResponseForbidden('Forbidden') owner = self.request.user if self.request.user.is_authenticated else None @@ -674,7 +674,7 @@ class GZipMixin(object): path = self._path() statobj = os.stat(path) ae = self.request.META.get('HTTP_ACCEPT_ENCODING', '') - if re_accepts_gzip.search(ae) and getattr(settings, 'LEAFLET_STORAGE_GZIP', True): + if re_accepts_gzip.search(ae) and getattr(settings, 'UMAP_GZIP', True): gzip_path = "{path}{ext}".format(path=path, ext=self.EXT) up_to_date = True if not os.path.exists(gzip_path): @@ -701,10 +701,10 @@ class DataLayerView(GZipMixin, BaseDetailView): response = None path = self.path() - if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None): + if getattr(settings, 'UMAP_XSENDFILE_HEADER', None): response = HttpResponse() path = path.replace(settings.MEDIA_ROOT, '/internal') - response[settings.LEAFLET_STORAGE_XSENDFILE_HEADER] = path + response[settings.UMAP_XSENDFILE_HEADER] = path else: # TODO IMS statobj = os.stat(path) From 19d2b39423c3b1e81df02728e4526e0b19e189c2 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Sat, 2 Jun 2018 12:21:40 +0200 Subject: [PATCH 012/239] Leaflet.Storage is now integrated inside this repository --- .gitignore | 2 + MANIFEST.in | 1 + Makefile | 26 + package-lock.json | 2465 +++++++++++++++++ package.json | 63 + umap/static/umap/default.css | 569 ++++ umap/static/umap/img/16-white.png | Bin 0 -> 13739 bytes umap/static/umap/img/16-white.svg | 718 +++++ umap/static/umap/img/16.png | Bin 0 -> 11308 bytes umap/static/umap/img/16.svg | 681 +++++ umap/static/umap/img/24-white.png | Bin 0 -> 19034 bytes umap/static/umap/img/24-white.svg | 463 ++++ umap/static/umap/img/24.png | Bin 0 -> 14755 bytes umap/static/umap/img/24.svg | 461 +++ umap/static/umap/img/edit-16.png | Bin 0 -> 430 bytes umap/static/umap/img/icon-bg.png | Bin 0 -> 190 bytes umap/static/umap/img/marker.png | Bin 0 -> 375 bytes umap/static/umap/img/search.gif | Bin 0 -> 1472 bytes .../{autocomplete.js => umap.autocomplete.js} | 0 umap/static/umap/js/umap.controls.js | 1131 ++++++++ umap/static/umap/js/umap.core.js | 521 ++++ umap/static/umap/js/umap.features.js | 1024 +++++++ umap/static/umap/js/umap.forms.js | 666 +++++ umap/static/umap/js/umap.icon.js | 177 ++ umap/static/umap/js/umap.js | 1654 +++++++++++ umap/static/umap/js/umap.layer.js | 1045 +++++++ umap/static/umap/js/umap.popup.js | 218 ++ umap/static/umap/js/umap.slideshow.js | 164 ++ umap/static/umap/js/umap.tableeditor.js | 99 + umap/static/umap/js/umap.ui.js | 176 ++ umap/static/umap/js/umap.xhr.js | 294 ++ umap/static/umap/locale/am_ET.json | 350 +++ umap/static/umap/locale/ar.json | 350 +++ umap/static/umap/locale/ast.json | 350 +++ umap/static/umap/locale/bg.json | 350 +++ umap/static/umap/locale/ca.json | 350 +++ umap/static/umap/locale/cs_CZ.json | 350 +++ umap/static/umap/locale/da.json | 350 +++ umap/static/umap/locale/de.json | 350 +++ umap/static/umap/locale/en.json | 350 +++ umap/static/umap/locale/en_US.json | 350 +++ umap/static/umap/locale/es.json | 350 +++ umap/static/umap/locale/fi.json | 350 +++ umap/static/umap/locale/fr.json | 350 +++ umap/static/umap/locale/gl.json | 350 +++ umap/static/umap/locale/hr.json | 350 +++ umap/static/umap/locale/hu.json | 350 +++ umap/static/umap/locale/id.json | 350 +++ umap/static/umap/locale/it.json | 350 +++ umap/static/umap/locale/ja.json | 350 +++ umap/static/umap/locale/lt.json | 350 +++ umap/static/umap/locale/nl.json | 350 +++ umap/static/umap/locale/pl.json | 350 +++ umap/static/umap/locale/pl_PL.json | 350 +++ umap/static/umap/locale/pt.json | 350 +++ umap/static/umap/locale/pt_BR.json | 350 +++ umap/static/umap/locale/pt_PT.json | 350 +++ umap/static/umap/locale/ru.json | 350 +++ umap/static/umap/locale/si_LK.json | 350 +++ umap/static/umap/locale/sk_SK.json | 350 +++ umap/static/umap/locale/th_TH.json | 350 +++ umap/static/umap/locale/tr.json | 350 +++ umap/static/umap/locale/uk_UA.json | 350 +++ umap/static/umap/locale/vi.json | 350 +++ umap/static/umap/locale/vi_VN.json | 350 +++ umap/static/umap/locale/zh.json | 350 +++ umap/static/umap/locale/zh_CN.json | 350 +++ umap/static/umap/locale/zh_TW.Big5.json | 350 +++ umap/static/umap/locale/zh_TW.json | 350 +++ umap/static/umap/storage.css | 1450 ++++++++++ umap/static/umap/test/.eslintrc | 22 + umap/static/umap/test/Controls.js | 50 + umap/static/umap/test/DataLayer.js | 337 +++ umap/static/umap/test/Feature.js | 236 ++ umap/static/umap/test/Map.js | 302 ++ umap/static/umap/test/Polygon.js | 288 ++ umap/static/umap/test/Polyline.js | 326 +++ umap/static/umap/test/TableEditor.js | 94 + umap/static/umap/test/Util.js | 202 ++ umap/static/umap/test/_pre.js | 301 ++ umap/static/umap/test/index.html | 109 + umap/templates/base.html | 5 +- umap/templates/umap/css.html | 20 +- umap/templates/umap/js.html | 71 +- 84 files changed, 29682 insertions(+), 49 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 umap/static/umap/default.css create mode 100644 umap/static/umap/img/16-white.png create mode 100644 umap/static/umap/img/16-white.svg create mode 100644 umap/static/umap/img/16.png create mode 100644 umap/static/umap/img/16.svg create mode 100644 umap/static/umap/img/24-white.png create mode 100644 umap/static/umap/img/24-white.svg create mode 100644 umap/static/umap/img/24.png create mode 100644 umap/static/umap/img/24.svg create mode 100644 umap/static/umap/img/edit-16.png create mode 100644 umap/static/umap/img/icon-bg.png create mode 100644 umap/static/umap/img/marker.png create mode 100644 umap/static/umap/img/search.gif rename umap/static/umap/js/{autocomplete.js => umap.autocomplete.js} (100%) create mode 100644 umap/static/umap/js/umap.controls.js create mode 100644 umap/static/umap/js/umap.core.js create mode 100644 umap/static/umap/js/umap.features.js create mode 100644 umap/static/umap/js/umap.forms.js create mode 100644 umap/static/umap/js/umap.icon.js create mode 100644 umap/static/umap/js/umap.js create mode 100644 umap/static/umap/js/umap.layer.js create mode 100644 umap/static/umap/js/umap.popup.js create mode 100644 umap/static/umap/js/umap.slideshow.js create mode 100644 umap/static/umap/js/umap.tableeditor.js create mode 100644 umap/static/umap/js/umap.ui.js create mode 100644 umap/static/umap/js/umap.xhr.js create mode 100644 umap/static/umap/locale/am_ET.json create mode 100644 umap/static/umap/locale/ar.json create mode 100644 umap/static/umap/locale/ast.json create mode 100644 umap/static/umap/locale/bg.json create mode 100644 umap/static/umap/locale/ca.json create mode 100644 umap/static/umap/locale/cs_CZ.json create mode 100644 umap/static/umap/locale/da.json create mode 100644 umap/static/umap/locale/de.json create mode 100644 umap/static/umap/locale/en.json create mode 100644 umap/static/umap/locale/en_US.json create mode 100644 umap/static/umap/locale/es.json create mode 100644 umap/static/umap/locale/fi.json create mode 100644 umap/static/umap/locale/fr.json create mode 100644 umap/static/umap/locale/gl.json create mode 100644 umap/static/umap/locale/hr.json create mode 100644 umap/static/umap/locale/hu.json create mode 100644 umap/static/umap/locale/id.json create mode 100644 umap/static/umap/locale/it.json create mode 100644 umap/static/umap/locale/ja.json create mode 100644 umap/static/umap/locale/lt.json create mode 100644 umap/static/umap/locale/nl.json create mode 100644 umap/static/umap/locale/pl.json create mode 100644 umap/static/umap/locale/pl_PL.json create mode 100644 umap/static/umap/locale/pt.json create mode 100644 umap/static/umap/locale/pt_BR.json create mode 100644 umap/static/umap/locale/pt_PT.json create mode 100644 umap/static/umap/locale/ru.json create mode 100644 umap/static/umap/locale/si_LK.json create mode 100644 umap/static/umap/locale/sk_SK.json create mode 100644 umap/static/umap/locale/th_TH.json create mode 100644 umap/static/umap/locale/tr.json create mode 100644 umap/static/umap/locale/uk_UA.json create mode 100644 umap/static/umap/locale/vi.json create mode 100644 umap/static/umap/locale/vi_VN.json create mode 100644 umap/static/umap/locale/zh.json create mode 100644 umap/static/umap/locale/zh_CN.json create mode 100644 umap/static/umap/locale/zh_TW.Big5.json create mode 100644 umap/static/umap/locale/zh_TW.json create mode 100644 umap/static/umap/storage.css create mode 100644 umap/static/umap/test/.eslintrc create mode 100644 umap/static/umap/test/Controls.js create mode 100644 umap/static/umap/test/DataLayer.js create mode 100644 umap/static/umap/test/Feature.js create mode 100644 umap/static/umap/test/Map.js create mode 100644 umap/static/umap/test/Polygon.js create mode 100644 umap/static/umap/test/Polyline.js create mode 100644 umap/static/umap/test/TableEditor.js create mode 100644 umap/static/umap/test/Util.js create mode 100644 umap/static/umap/test/_pre.js create mode 100644 umap/static/umap/test/index.html diff --git a/.gitignore b/.gitignore index a9a3b7a9..abc0e16e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ docs/_build umap/remote_static .idea tmp/* +node_modules/* +umap/static/umap/vendors ### Python ### # Byte-compiled / optimized / DLL files diff --git a/MANIFEST.in b/MANIFEST.in index f9efab73..ea58a895 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,3 +3,4 @@ include requirements.txt recursive-include umap/static * recursive-include umap/templates * recursive-include umap/locale * +recursive-include ui * diff --git a/Makefile b/Makefile index c02b8c8e..6933eee9 100644 --- a/Makefile +++ b/Makefile @@ -6,3 +6,29 @@ compilemessages: django-admin.py compilemessages makemessages: django-admin.py makemessages -a +ui: + mkdir -p umap/static/umap/vendors/leaflet/ && cp -r node_modules/leaflet/dist/** umap/static/umap/vendors/leaflet/ + mkdir -p umap/static/umap/vendors/editable/ && cp -r node_modules/leaflet-editable/src/*.js umap/static/umap/vendors/editable/ + mkdir -p umap/static/umap/vendors/editable/ && cp -r node_modules/leaflet.path.drag/src/*.js umap/static/umap/vendors/editable/ + mkdir -p umap/static/umap/vendors/hash/ && cp -r node_modules/leaflet-hash/*.js umap/static/umap/vendors/hash/ + mkdir -p umap/static/umap/vendors/i18n/ && cp -r node_modules/leaflet-i18n/*.js umap/static/umap/vendors/i18n/ + mkdir -p umap/static/umap/vendors/editinosm/ && cp -r node_modules/leaflet-editinosm/Leaflet.EditInOSM.* umap/static/umap/vendors/editinosm/ + mkdir -p umap/static/umap/vendors/minimap/ && cp -r node_modules/leaflet-minimap/src/** umap/static/umap/vendors/minimap/ + mkdir -p umap/static/umap/vendors/loading/ && cp -r node_modules/leaflet-loading/src/** umap/static/umap/vendors/loading/ + mkdir -p umap/static/umap/vendors/markercluster/ && cp -r node_modules/leaflet.markercluster/dist/** umap/static/umap/vendors/markercluster/ + mkdir -p umap/static/umap/vendors/contextmenu/ && cp -r node_modules/leaflet-contextmenu/dist/** umap/static/umap/vendors/contextmenu/ + mkdir -p umap/static/umap/vendors/heat/ && cp -r node_modules/leaflet.heat/dist/** umap/static/umap/vendors/heat/ + mkdir -p umap/static/umap/vendors/fullscreen/ && cp -r node_modules/leaflet-fullscreen/dist/** umap/static/umap/vendors/fullscreen/ + mkdir -p umap/static/umap/vendors/toolbar/ && cp -r node_modules/leaflet-toolbar/dist/** umap/static/umap/vendors/toolbar/ + mkdir -p umap/static/umap/vendors/formbuilder/ && cp -r node_modules/leaflet-formbuilder/*.js umap/static/umap/vendors/formbuilder/ + mkdir -p umap/static/umap/vendors/measurable/ && cp -r node_modules/leaflet-measurable/Leaflet.Measurable.* umap/static/umap/vendors/measurable/ + mkdir -p umap/static/umap/vendors/photon/ && cp -r node_modules/leaflet.photon/*.js umap/static/umap/vendors/photon/ + mkdir -p umap/static/umap/vendors/csv2geojson/ && cp -r node_modules/csv2geojson/*.js umap/static/umap/vendors/csv2geojson/ + mkdir -p umap/static/umap/vendors/togeojson/ && cp -r node_modules/togeojson/*.js umap/static/umap/vendors/togeojson/ + mkdir -p umap/static/umap/vendors/osmtogeojson/ && cp -r node_modules/osmtogeojson/osmtogeojson.js umap/static/umap/vendors/osmtogeojson/ + mkdir -p umap/static/umap/vendors/georsstogeojson/ && cp -r node_modules/georsstogeojson/GeoRSSToGeoJSON.js umap/static/umap/vendors/georsstogeojson/ + mkdir -p umap/static/umap/vendors/togpx/ && cp -r node_modules/togpx/togpx.js umap/static/umap/vendors/togpx/ + mkdir -p umap/static/umap/vendors/tokml && cp -r node_modules/tokml/tokml.js umap/static/umap/vendors/tokml + + +.PHONY: ui diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..ff0961c3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2465 @@ +{ + "name": "leaflet-storage", + "version": "0.8.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/geojson": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", + "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==", + "optional": true + }, + "JSONStream": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.0.tgz", + "integrity": "sha1-78Ri1aW8lOwAf0siVxrNf28q4BM=", + "requires": { + "jsonparse": "0.0.5", + "through": "2.2.7" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "adm-zip": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.2.1.tgz", + "integrity": "sha1-6AHO3rW9mk6Y1pnFwPQjnicx3L8=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "requires": { + "underscore": "1.7.0", + "underscore.string": "2.4.0" + }, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true, + "optional": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz", + "integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=", + "dev": true, + "requires": { + "readable-stream": "2.0.6" + } + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "requires": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-equal": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", + "integrity": "sha1-7Lt5D1aNQAmKYkK1SAXHWAXrk48=" + }, + "bunker": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", + "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", + "requires": { + "burrito": "0.2.12" + } + }, + "burrito": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", + "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", + "requires": { + "traverse": "0.5.2", + "uglify-js": "1.1.1" + }, + "dependencies": { + "traverse": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", + "integrity": "sha1-4gPFjV9/DjfbbnTArLkpuwm2HYU=" + }, + "uglify-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", + "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=" + } + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "dev": true, + "requires": { + "ini": "1.3.5", + "proto-list": "1.2.4" + }, + "dependencies": { + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "optional": true, + "requires": { + "boom": "0.4.2" + } + }, + "csv2geojson": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/csv2geojson/-/csv2geojson-5.0.2.tgz", + "integrity": "sha1-q9ZJ8uxXaJIZrU8Z0zO+dUVrb1k=", + "requires": { + "concat-stream": "1.5.2", + "d3-dsv": "1.0.1", + "optimist": "0.6.1", + "sexagesimal": "0.5.0" + }, + "dependencies": { + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + } + } + } + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "dev": true, + "optional": true + }, + "d3-dsv": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.1.tgz", + "integrity": "sha1-1JU0fATLHg0mVXu9xHdcTRGiReo=", + "requires": { + "rw": "1.3.3" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true, + "optional": true + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "difflet": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", + "integrity": "sha1-qyOzH1ZJtvqo49KsvTNEZzZcpvo=", + "requires": { + "charm": "0.1.2", + "deep-is": "0.1.3", + "traverse": "0.6.6" + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + }, + "domhandler": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.2.1.tgz", + "integrity": "sha1-Wd+dzSJ+gIs2Wuc+H2aErD2Ub8I=", + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.3.0.tgz", + "integrity": "sha1-mtTVm1r2ymhMYv5tdo7xcOcN8ZI=", + "requires": { + "domelementtype": "1.3.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extract-zip": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.5.0.tgz", + "integrity": "sha1-ksz22B73Cp+kwXRxFMzvbYaIpsQ=", + "dev": true, + "requires": { + "concat-stream": "1.5.0", + "debug": "0.7.4", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz", + "integrity": "sha1-U/fUPFHF5D+ByP3QMyHGMb5o1hE=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + } + }, + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "requires": { + "glob": "3.2.11", + "lodash": "2.4.2" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + } + } + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "dev": true, + "optional": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true, + "optional": true + } + } + }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "1.1.2" + } + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.2.8" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "geojson-area": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/geojson-area/-/geojson-area-0.1.0.tgz", + "integrity": "sha1-1I2AcILPrfSnjfE0m+UPOL8YlK4=", + "requires": { + "wgs84": "0.0.0" + } + }, + "geojson-numeric": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/geojson-numeric/-/geojson-numeric-0.2.0.tgz", + "integrity": "sha1-q5quLqlyekg3B5rP8qqDyHLXLUo=", + "requires": { + "concat-stream": "1.0.1", + "optimist": "0.3.7" + }, + "dependencies": { + "concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "requires": { + "bops": "0.0.6" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "0.0.3" + } + } + } + }, + "geojson-rewind": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/geojson-rewind/-/geojson-rewind-0.2.0.tgz", + "integrity": "sha1-6lWOnkT/A7hlXQoIt1B43DOhXnk=", + "requires": { + "concat-stream": "1.2.1", + "geojson-area": "0.1.0", + "minimist": "0.0.5" + }, + "dependencies": { + "concat-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.2.1.tgz", + "integrity": "sha1-81EAtsRjeL+6i2uA+fDQzN8T3GA=", + "requires": { + "bops": "0.0.6" + } + }, + "minimist": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", + "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=" + } + } + }, + "georsstogeojson": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/georsstogeojson/-/georsstogeojson-0.1.0.tgz", + "integrity": "sha1-9duAeheaK0Z3sJpWsgqdHCT7FlM=", + "requires": { + "xmldom": "0.1.27" + } + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "grunt": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "requires": { + "async": "0.1.22", + "coffee-script": "1.3.3", + "colors": "0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.1.3", + "getobject": "0.1.0", + "glob": "3.1.21", + "grunt-legacy-log": "0.1.3", + "grunt-legacy-util": "0.2.0", + "hooker": "0.2.3", + "iconv-lite": "0.2.11", + "js-yaml": "2.0.5", + "lodash": "0.9.2", + "minimatch": "0.2.14", + "nopt": "1.0.10", + "rimraf": "2.2.8", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + } + } + }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "0.3.0", + "grunt-known-options": "1.1.0", + "nopt": "3.0.6", + "resolve": "1.1.7" + }, + "dependencies": { + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + } + } + }, + "grunt-contrib-concat": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-0.5.1.tgz", + "integrity": "sha1-lTxu/f39LBB6uchQd/LUsk0xzUk=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "source-map": "0.3.0" + } + }, + "grunt-contrib-copy": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-0.5.0.tgz", + "integrity": "sha1-QQB1rEWlhWuhkbHMclclRQ1KAhU=", + "dev": true + }, + "grunt-known-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=", + "dev": true + }, + "grunt-legacy-log": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "requires": { + "colors": "0.6.2", + "grunt-legacy-log-utils": "0.1.1", + "hooker": "0.2.3", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "requires": { + "colors": "0.6.2", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "requires": { + "async": "0.1.22", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "0.9.2", + "underscore.string": "2.2.1", + "which": "1.0.9" + } + }, + "happen": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/happen/-/happen-0.1.3.tgz", + "integrity": "sha1-NXrHYPq4dFueVracudOvLACfFTk=", + "dev": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.15.1", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "integrity": "sha1-uQuxaYByhUEdp//LjdJZhQLTtS0=", + "dev": true, + "optional": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "htmlparser2": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.5.1.tgz", + "integrity": "sha1-b0L3ZX3RnBP31l3pEYQXOUoL5tA=", + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.2.1", + "domutils": "1.3.0", + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "ieee754": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz", + "integrity": "sha1-ToCMLOFExsF4iRjgNNZ5e8bPYoE=", + "dev": true + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "requires": { + "argparse": "0.1.16", + "esprima": "1.0.4" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "jxon": { + "version": "2.0.0-beta.5", + "resolved": "https://registry.npmjs.org/jxon/-/jxon-2.0.0-beta.5.tgz", + "integrity": "sha1-O2qUEE+YAe5oL9BWZF/1Rz2bND4=", + "requires": { + "xmldom": "0.1.27" + } + }, + "kew": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.1.7.tgz", + "integrity": "sha1-CjKoF/8amzsSuMm6z0vE1nmvjnI=", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "leaflet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.3.1.tgz", + "integrity": "sha512-adQOIzh+bfdridLM1xIgJ9VnJbAUY3wqs/ueF+ITla+PLQ1z47USdBKUf+iD9FuUA8RtlT6j6hZBfZoA6mW+XQ==" + }, + "leaflet-contextmenu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/leaflet-contextmenu/-/leaflet-contextmenu-1.4.0.tgz", + "integrity": "sha1-4r2kga8QJggOq6oymX5TH9RPYFw=" + }, + "leaflet-editable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/leaflet-editable/-/leaflet-editable-1.1.0.tgz", + "integrity": "sha1-93dZekCoGic/KHtIn9D+XM1gyNA=" + }, + "leaflet-editinosm": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/leaflet-editinosm/-/leaflet-editinosm-0.2.3.tgz", + "integrity": "sha1-8HFmTEpSe3b3uPm87HRLJIiVwHE=" + }, + "leaflet-formbuilder": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/leaflet-formbuilder/-/leaflet-formbuilder-0.2.3.tgz", + "integrity": "sha1-7ucYzcyMOzABk+U7qASFLAv0l9k=" + }, + "leaflet-fullscreen": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/leaflet-fullscreen/-/leaflet-fullscreen-1.0.2.tgz", + "integrity": "sha1-CcYcS6xF9jsu4Sav2H5c2XZQ/Bs=" + }, + "leaflet-hash": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/leaflet-hash/-/leaflet-hash-0.2.1.tgz", + "integrity": "sha1-w2xxg0fFJDAztXy0uuomEZ2CxwE=" + }, + "leaflet-i18n": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/leaflet-i18n/-/leaflet-i18n-0.3.1.tgz", + "integrity": "sha1-QE513GcE9KI5nRzQXw3R3ReDALU=" + }, + "leaflet-loading": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/leaflet-loading/-/leaflet-loading-0.1.24.tgz", + "integrity": "sha1-6v38GIcY6xPTz3uSJsTAaxbpKRk=" + }, + "leaflet-measurable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/leaflet-measurable/-/leaflet-measurable-0.0.5.tgz", + "integrity": "sha1-A6dXfcxqVYWEo1lldjX47WnnJX8=" + }, + "leaflet-minimap": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/leaflet-minimap/-/leaflet-minimap-3.6.1.tgz", + "integrity": "sha1-KkP/Oz2UekWgrPS978llBbZzpsY=" + }, + "leaflet-toolbar": { + "version": "github:umap-project/Leaflet.toolbar#a730bbe3baf402cdf8337e3271081bfa4ff1a75b" + }, + "leaflet.heat": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/leaflet.heat/-/leaflet.heat-0.2.0.tgz", + "integrity": "sha1-EJ2M9Ybwre5B8Fr/Ax4np3/swik=" + }, + "leaflet.markercluster": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.3.0.tgz", + "integrity": "sha512-bHBaI8kTaLrZxI/ZP7pnNaS8WCKKz98BU1//B5OH9b/kTk6IriduvDtMFGlGBYYr/ymuXCB9lO7HsGBr5dSw5w==" + }, + "leaflet.path.drag": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/leaflet.path.drag/-/leaflet.path.drag-0.0.6.tgz", + "integrity": "sha1-bZw68LnXsDJUSuFr/eaI8BYFFKA=" + }, + "leaflet.photon": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/leaflet.photon/-/leaflet.photon-0.7.3.tgz", + "integrity": "sha1-0U170y6tfkAqF/O+1HKoDxym+UY=" + }, + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mocha": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + } + } + }, + "mocha-phantomjs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha-phantomjs/-/mocha-phantomjs-4.1.0.tgz", + "integrity": "sha1-x14WYS4aavCtjSgeOi/vSdVeUFs=", + "dev": true, + "requires": { + "commander": "2.15.1", + "mocha-phantomjs-core": "1.3.1", + "phantomjs": "1.9.7-15" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "phantomjs": { + "version": "1.9.7-15", + "resolved": "https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.7-15.tgz", + "integrity": "sha1-Czp85jBIaoO+kf9Ogy7uIOlxEVs=", + "dev": true, + "requires": { + "adm-zip": "0.2.1", + "kew": "0.1.7", + "mkdirp": "0.3.5", + "ncp": "0.4.2", + "npmconf": "0.0.24", + "progress": "1.1.8", + "request": "2.36.0", + "request-progress": "0.3.1", + "rimraf": "2.2.8", + "which": "1.0.9" + } + } + } + }, + "mocha-phantomjs-core": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mocha-phantomjs-core/-/mocha-phantomjs-core-1.3.1.tgz", + "integrity": "sha1-WGU4yNcfqN6QxBpGrMBIHB+4Phg=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true + }, + "nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc=", + "requires": { + "abbrev": "1.1.1" + } + }, + "npmconf": { + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/npmconf/-/npmconf-0.0.24.tgz", + "integrity": "sha1-t4h1sIjMw8Cvo+zrPOMkSxtSOQw=", + "dev": true, + "requires": { + "config-chain": "1.1.11", + "inherits": "1.0.2", + "ini": "1.1.0", + "mkdirp": "0.3.5", + "nopt": "2.2.1", + "once": "1.1.1", + "osenv": "0.0.3", + "semver": "1.1.4" + }, + "dependencies": { + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "once": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz", + "integrity": "sha1-nbV0kzzLCMOnYU0VQDLAnqbzOec=", + "dev": true + } + } + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.4.0.tgz", + "integrity": "sha1-y47Dfy/jqphky2eidSUOfhliCiU=", + "dev": true, + "requires": { + "wordwrap": "0.0.3" + } + }, + "osenv": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz", + "integrity": "sha1-zWrY3bKQkVrZ4idlV2Al1BHynLY=", + "dev": true + }, + "osm-polygon-features": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/osm-polygon-features/-/osm-polygon-features-0.9.2.tgz", + "integrity": "sha1-IK5BEwxIbkmjsqPCtYoUGcSYZ3g=" + }, + "osmtogeojson": { + "version": "3.0.0-beta.3", + "resolved": "https://registry.npmjs.org/osmtogeojson/-/osmtogeojson-3.0.0-beta.3.tgz", + "integrity": "sha512-8abt3HLjlMzR1QwlnqnJTRPo7P+lOTf3VMIp1lmGvKno4Il+6LLFuWwohyDs8tPZjaUGuCjK0YjRkapsBMjH1Q==", + "requires": { + "@types/geojson": "1.0.6", + "JSONStream": "0.8.0", + "concat-stream": "1.0.1", + "geojson-numeric": "0.2.0", + "geojson-rewind": "0.2.0", + "htmlparser2": "3.5.1", + "optimist": "0.3.7", + "osm-polygon-features": "0.9.2", + "tiny-osmpbf": "0.1.0", + "xmldom": "0.1.27" + }, + "dependencies": { + "concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "requires": { + "bops": "0.0.6" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "0.0.3" + } + } + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pbf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.1.0.tgz", + "integrity": "sha512-/hYJmIsTmh7fMkHAWWXJ5b8IKLWdjdlAFb3IHkRBn1XUhIYBChVGfVwmHEAV3UfXTxsP/AKfYTXTS/dCPxJd5w==", + "requires": { + "ieee754": "1.1.11", + "resolve-protobuf-schema": "2.0.0" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "phantomjs": { + "version": "1.9.20", + "resolved": "https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.20.tgz", + "integrity": "sha1-RCSsog4U0lXAsIia9va4lz2hDg0=", + "dev": true, + "requires": { + "extract-zip": "1.5.0", + "fs-extra": "0.26.7", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.67.0", + "request-progress": "2.0.1", + "which": "1.2.14" + }, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz", + "integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=", + "dev": true, + "requires": { + "async": "2.6.1", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "qs": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.1.tgz", + "integrity": "sha1-gB/uAw4LlFDWOFrcSKTMVbRK7fw=", + "dev": true + }, + "request": { + "version": "2.67.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.67.0.tgz", + "integrity": "sha1-ivdHgOK/EeoK6aqWXBHxGv0nJ0I=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "bl": "1.0.3", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "1.0.1", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "5.2.1", + "stringstream": "0.0.6", + "tough-cookie": "2.2.2", + "tunnel-agent": "0.4.3" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "tough-cookie": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz", + "integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc=", + "dev": true + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "protocol-buffers-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-2.2.0.tgz", + "integrity": "sha1-0pxs1z+2VZePtpiWkRgNuEQRn2E=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.36.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.36.0.tgz", + "integrity": "sha1-KMbAQmLHuf/dIbklU3RRfubZQ/U=", + "dev": true, + "requires": { + "aws-sign2": "0.5.0", + "forever-agent": "0.5.2", + "form-data": "0.1.4", + "hawk": "1.0.0", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime": "1.2.11", + "node-uuid": "1.4.8", + "oauth-sign": "0.3.0", + "qs": "0.6.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3" + } + }, + "request-progress": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.1.tgz", + "integrity": "sha1-ByHBBdipasayzossia4tXs/Pazo=", + "dev": true, + "requires": { + "throttleit": "0.0.2" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-protobuf-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.0.0.tgz", + "integrity": "sha1-5nsGKmfwLRG9aIbnDv2niEB+D7Q=", + "requires": { + "protocol-buffers-schema": "2.2.0" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "runforcover": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", + "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", + "requires": { + "bunker": "0.1.2" + } + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" + }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "dev": true + }, + "semver": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-1.1.4.tgz", + "integrity": "sha1-LlpOcrqwNHLMl/cnU7RQiRLvVUA=", + "dev": true + }, + "sexagesimal": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/sexagesimal/-/sexagesimal-0.5.0.tgz", + "integrity": "sha1-nYFb0r3dY0tiW6aFG/j+dKWtPvM=" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": "0.10.3" + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "optional": true, + "requires": { + "hoek": "0.9.1" + } + }, + "source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "strxml": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/strxml/-/strxml-0.0.0.tgz", + "integrity": "sha1-j/UxTIyHTbBVBnN2GoHk0/JEFFw=", + "requires": { + "tap": "0.4.13" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "tap": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", + "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", + "requires": { + "buffer-equal": "0.0.2", + "deep-equal": "0.0.0", + "difflet": "0.2.6", + "glob": "3.2.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "nopt": "2.2.1", + "runforcover": "0.0.2", + "slide": "1.1.6", + "yamlish": "0.0.7" + } + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, + "through": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/through/-/through-2.2.7.tgz", + "integrity": "sha1-bo4hIAGR1OtqmfbwEN9Gqhxusr0=" + }, + "tiny-inflate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", + "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" + }, + "tiny-osmpbf": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tiny-osmpbf/-/tiny-osmpbf-0.1.0.tgz", + "integrity": "sha1-ColXFxE+vmquNjxL5e76js2vuSc=", + "requires": { + "pbf": "3.1.0", + "tiny-inflate": "1.0.2" + } + }, + "to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", + "dev": true + }, + "to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=" + }, + "togeojson": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/togeojson/-/togeojson-0.16.0.tgz", + "integrity": "sha1-q1cp5PjJkg5tpfCP2CSQodFqym0=", + "requires": { + "concat-stream": "1.5.2", + "minimist": "1.2.0", + "xmldom": "0.1.27" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "togpx": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/togpx/-/togpx-0.5.4.tgz", + "integrity": "sha1-sz27BUHfBL1rpPULhtqVNCS7d3M=", + "requires": { + "concat-stream": "1.0.1", + "jxon": "2.0.0-beta.5", + "optimist": "0.3.7", + "xmldom": "0.1.27" + }, + "dependencies": { + "concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "requires": { + "bops": "0.0.6" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "0.0.3" + } + } + } + }, + "tokml": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/tokml/-/tokml-0.4.0.tgz", + "integrity": "sha1-fAMhtCRmPKMYegpBny37z5DaNyo=", + "requires": { + "minimist": "0.1.0", + "rw": "0.0.4", + "strxml": "0.0.0" + }, + "dependencies": { + "minimist": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" + }, + "rw": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/rw/-/rw-0.0.4.tgz", + "integrity": "sha1-3iex7VuRdXcuqiKnlmJRC9BZjEw=" + } + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "dev": true, + "requires": { + "optimist": "0.3.7", + "source-map": "0.1.43" + }, + "dependencies": { + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "0.0.3" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "wgs84": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", + "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yamlish": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", + "integrity": "sha1-tK+aHcxjYYhzw9bkUewyE8OaV/s=" + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..1f242064 --- /dev/null +++ b/package.json @@ -0,0 +1,63 @@ +{ + "name": "leaflet-storage", + "version": "0.8.2", + "description": "Manage map and features with Leaflet and expose them for backend storage through an API.", + "directories": { + "test": "test" + }, + "devDependencies": { + "chai": "^3.3.0", + "grunt": "^0.4.4", + "grunt-cli": "^1.2.0", + "grunt-contrib-concat": "^0.5.1", + "grunt-contrib-copy": "^0.5.0", + "happen": "~0.1.3", + "mocha": "^2.3.3", + "mocha-phantomjs": "^4.0.1", + "optimist": "~0.4.0", + "phantomjs": "^1.9.18", + "sinon": "^1.10.3", + "uglify-js": "~2.2.3" + }, + "scripts": { + "test": "firefox test/index.html", + "build": "grunt" + }, + "repository": { + "type": "git", + "url": "git://github.com/umap-project/Leaflet.Storage.git" + }, + "keywords": [ + "leaflet" + ], + "author": "Yohan Boniface", + "license": "WTFPL", + "bugs": { + "url": "https://github.com/umap-project/Leaflet.Storage/issues" + }, + "homepage": "http://wiki.openstreetmap.org/wiki/UMap", + "dependencies": { + "csv2geojson": "5.0.2", + "georsstogeojson": "^0.1.0", + "leaflet": "1.3.1", + "leaflet-contextmenu": "^1.4.0", + "leaflet-editable": "^1.1.0", + "leaflet-editinosm": "0.2.3", + "leaflet-formbuilder": "0.2.3", + "leaflet-fullscreen": "1.0.2", + "leaflet-hash": "0.2.1", + "leaflet-i18n": "0.3.1", + "leaflet-loading": "0.1.24", + "leaflet-measurable": "0.0.5", + "leaflet-minimap": "^3.6.1", + "leaflet-toolbar": "umap-project/Leaflet.toolbar", + "leaflet.heat": "0.2.0", + "leaflet.markercluster": "^1.3.0", + "leaflet.path.drag": "0.0.6", + "leaflet.photon": "0.7.3", + "osmtogeojson": "^3.0.0-beta.3", + "togeojson": "0.16.0", + "togpx": "^0.5.4", + "tokml": "0.4.0" + } +} diff --git a/umap/static/umap/default.css b/umap/static/umap/default.css new file mode 100644 index 00000000..f798045a --- /dev/null +++ b/umap/static/umap/default.css @@ -0,0 +1,569 @@ +div, ul, li, a, section, nav, +h1, h2, h3, h4, h5, h6, label, +hr, input, textarea { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin: 0; +} + +/* *********** */ +/* forms */ +/* *********** */ +input[type="text"], input[type="password"], input[type="date"], +input[type="datetime"], input[type="email"], input[type="number"], +input[type="search"], input[type="tel"], input[type="time"], +input[type="url"], textarea { + 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; + font-size: 14px; + height: 32px; + margin: 0 0 14px; + padding: 7px; + width: 100%; +} +input[type="range"] { + margin-top: 10px; + margin-bottom: 5px; + width: 100%; +} +input[type="checkbox"] { + margin: 0 5px; + vertical-align: middle; +} +textarea { + height: inherit; + padding: 7px; +} +select { + width: 100%; + height: 28px; + line-height: 28px; + color: #efefef; + border: 1px solid #222; + background-color: #393F3F; + margin-top: 5px; +} +select[multiple="multiple"] { + height: auto; +} +.button, input[type="submit"] { + display: block; + margin-bottom: 14px; + text-align: center; + border-radius: 2px; + font-weight: normal; + cursor: pointer; + padding: 7px; + width: 100%; + min-height: 32px; + line-height: 32px; + border: none; + text-decoration: none; +} +.dark .button { + background-color: #2a2e30; + color: #eeeeec; + border: 1px solid #1b1f20; +} +.dark .button:hover, .dark input[type="submit"]:hover { + background-color: #2e3436; +} +.help-text, .helptext { + display: block; + padding: 7px 7px; + margin-bottom: 14px; + background: #393F3F; + color: #ddd; + font-size: 10px; + border-radius: 0 2px; +} +input + .help-text { + margin-top: -14px; +} +.formbox { + min-height: 36px; + line-height: 28px; + margin-bottom: 14px; +} +.formbox.with-switch { + padding-top: 2px; +} +.formbox select { + width: calc(100% - 14px); +} +label { + display: block; + font-size: 12px; + line-height: 21px; + width: 100%; +} +input[type="checkbox"] + label { + display: inline; + padding: 0 14px; +} +select + .error, +input + .error { + display: block; + padding: 7px 7px; + margin-top: -14px; + margin-bottom: 14px; + background: #ddd; + color: #fff; + background-color: #cc0000; + font-size: 11px; + border-radius: 0 2px; +} +input[type="file"] + .error { + margin-top: 0; +} +.fieldset { + border: 1px solid #222; + margin-bottom: 5px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.fieldset .fields { + visibility: hidden; + opacity: 0; + transition: visibility 0s, opacity 0.5s linear; + height: 0; + overflow: hidden; +} +.fieldset.toggle.on .fields { + visibility: visible; + opacity: 1; + height: initial; + padding: 10px; +} +.fieldset.toggle .legend { + text-align: center; + display: block; + cursor: pointer; + background-color: #232729; + height: 30px; + line-height: 30px; + color: #fff; + margin: 0; + font-family: fira_sanslight; + font-size: 1.2em; + padding: 0 5px; +} +/* Switch */ +input.switch:empty { + display: none; +} +input.switch:empty ~ label { + white-space: nowrap; + position: relative; + float: left; + line-height: 2em; + height: 2em; + 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; +} +input.switch:empty ~ label:before, +input.switch:empty ~ label:after { + position: absolute; + display: block; + top: 0; + bottom: 0; + left: 0; + content: ' '; + width: 6em; + -webkit-transition: all 100ms ease-in; + transition: all 100ms ease-in; + color: #c9c9c7; + font-weight: bold; + background-color: #ededed; +} +.dark input.switch:empty ~ label:before, +.dark input.switch:empty ~ label:after { + background-color: #272c2e; +} +input.switch:empty ~ label:after { + width: 3em; + margin-left: 0.1em; + background-color: #ededed; + content: "OFF"; + text-indent: 3.5em; + border: 1px solid #374E75; + font-weight: bold; +} +.dark input.switch:empty ~ label:after { + 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: #215d9c; + content: "ON"; + text-indent: 0.7em; + text-align: left; + font-weight: bold; +} +input.switch:checked ~ label:after { + margin-left: 3em; +} +.button-bar { + margin-top: 5px; +} +.storage-multiplechoice input[type='radio'] { + display: none; +} +.storage-multiplechoice label { + border: 1px solid #374E75; + cursor: pointer; + background-color: #c9c9c7; + height: 30px; + line-height: 30px; + text-align: center; + width: calc(100% / 3); + display: inline-block; +} +.storage-multiplechoice.by4 label { + width: calc(100% / 4); +} +.dark .storage-multiplechoice label { + border: 1px solid black; + background-color: #2c3233; +} +.storage-multiplechoice input[type='radio']:checked + label { + background-color: #215d9c; + box-shadow: inset 0 0 6px 0px #2c3233; + color: #ededed; +} +.inheritable .header, +.inheritable { + clear: both; + overflow: hidden; +} +.inheritable .header { + margin-bottom: 5px; +} +.inheritable .header label { + padding-top: 6px; +} +.inheritable + .inheritable { + border-top: 1px solid #222; + padding-top: 5px; + margin-top: 5px; +} +.inheritable .define, +.inheritable .undefine { + float: right; + width: initial; + min-height: 18px; + line-height: 18px; + margin-bottom: 0; +} +.inheritable .quick-actions { + float: right; +} +.inheritable .quick-actions .formbox { + margin-bottom: 0; +} +.inheritable .quick-actions input { + width: 100px; + margin-right: 5px; +} +.inheritable .define, +.inheritable.undefined .undefine, +.inheritable.undefined .show-on-defined { + display: none; +} +.inheritable.undefined .define { + display: block; +} +i.info { + background-repeat: no-repeat; + background-image: url("../../src/img/16.png"); + background-position: -170px -50px; + display: inline-block; + margin-left: 5px; + vertical-align: middle; + width: 16px; + height: 18px; +} +.dark i.info { + background-image: url("../../src/img/16-white.png"); +} +.with-transition { + /*transition: top .7s, right .7s, left .7s, width .7s, visibility .7s;*/ + transition: all .7s; +} + + + +/* *********** */ +/* Panel */ +/* *********** */ +.leaflet-ui-container { + overflow-x: hidden; +} +#storage-ui-container { + width: 400px; + position: fixed; + top: 0; + bottom: 0; + right: -400px; + padding: 0 20px 40px 20px; + border-left: 1px solid #ddd; + overflow-x: auto; + z-index: 1010; + background-color: #fff; + opacity: 0.98; + cursor: initial; +} +#storage-ui-container.dark { + border-left: 1px solid #222; + background-color: #323737; + color: #efefef; +} +#storage-ui-container.fullwidth { + width: 100%; + z-index: 10000; + padding-left: 0; + padding-right: 0; + transition: all .7s; +} +.storage-edit-enabled #storage-ui-container { + top: 46px; +} +.storage-caption-bar-enabled #storage-ui-container { + bottom: 46px; +} +.storage-ui #storage-ui-container { + right: 0; +} +.leaflet-top, +.leaflet-right { + transition: all .7s; +} +.storage-ui .leaflet-right { + right: 400px; +} +#storage-ui-container, +#storage-alert-container, +#storage-tooltip-container { + -moz-box-sizing:border-box; + -webkit-box-sizing:border-box; + box-sizing: border-box; +} +#storage-ui-container .storage-popup-content img { + /* See https://github.com/Leaflet/Leaflet/commit/61d746818b99d362108545c151a27f09d60960ee#commitcomment-6061847 */ + max-width: 99% !important; +} +#storage-ui-container .storage-popup-content { + max-height: inherit; +} +#storage-ui-container .body { + clear: both; + height: calc(100% - 46px); /* Minus size of toolbox */ +} +#storage-ui-container .toolbox { + padding: 5px 0; + overflow: hidden; +} +#storage-ui-container .toolbox li { + color: #2e3436; + line-height: 32px; + cursor: pointer; + float: right; + display: inline; + padding: 0 7px; + border: 1px solid #b6b6b3; + border-radius: 2px; +} +#storage-ui-container.dark .toolbox li { + color: #d3dfeb; + border: 1px solid #202425; +} +#storage-ui-container .toolbox li:hover { + color: #2e3436; + background-color: #d4d4d2; +} +#storage-ui-container.dark .toolbox li:hover { + color: #eeeeec; + background-color: #353c3e; +} +#storage-ui-container .toolbox li + li { + margin-right: 5px; + margin-left: 5px; +} +.dark input, .dark textarea { + background-color: #232729; + border-color: #1b1f20; + /*box-shadow: inset 0 0 0 1px #215d9c;*/ + color: #efefef; +} + +/* *********** */ +/* Alerts */ +/* *********** */ +#storage-alert-container { + min-height: 46px; + line-height: 46px; + padding-left: 10px; + width: calc(100% - 500px); + position: absolute; + top: -46px; + left: 250px; /* Keep save/cancel button accessible. */ + right: 250px; + box-shadow: 0 1px 7px #999999; + visibility: hidden; + background: none repeat scroll 0 0 rgba(20, 22, 23, 0.8); + font-weight: bold; + color: #fff; + font-size: 0.8em; + z-index: 1002; + border-radius: 2px; +} +#storage-alert-container.error { + background-color: #c60f13; +} +.storage-alert #storage-alert-container { + visibility: visible; + top: 23px; +} +.storage-alert .storage-action { + margin-left: 10px; + background-color: #fff; + color: #999; + padding: 5px; + border-radius: 4px; +} +.storage-alert .storage-action:hover { + color: #000; +} +.storage-alert .error .storage-action { + background-color: #666; + color: #eee; +} +.storage-alert .error .storage-action:hover { + color: #fff; +} + +/* *********** */ +/* Tooltip */ +/* *********** */ +#storage-tooltip-container { + line-height: 20px; + padding: 5px 10px; + width: auto; + position: absolute; + box-shadow: 0 1px 7px #999999; + display: none; + background-color: rgba(40, 40, 40, 0.8); + color: #eeeeec; + font-size: 0.8em; + border-radius: 2px; + z-index: 1004; + font-weight: normal; + max-width: 300px; +} +.storage-tooltip #storage-tooltip-container { + display: block; +} +#storage-tooltip-container.tooltip-top:after { + top: 100%; + left: calc(50% - 11px); + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border-top-color: rgba(30, 30, 30, 0.8); + border-width: 11px; + margin-left: calc(-50% + 21px); +} +#storage-tooltip-container.tooltip.tooltip-left:after { + left: 100%; + top: 50%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border-color: rgba(136, 183, 213, 0); + border-left-color: #333; + border-width: 11px; + margin-top: -10px; +} + + + +/* *********** */ +/* Close link */ +/* *********** */ +.storage-close-icon { + background-repeat: no-repeat; + background-image: url("../../src/img/16.png"); + background-position: -52px -9px; + display: inline; + padding: 0 10px; + vertical-align: middle; +} +.dark .storage-close-icon { + background-image: url("../../src/img/16-white.png"); +} +.dark .storage-close-link { + border: 1px solid #202425; + color: #eeeeec; + padding: 0 7px; + line-height: 32px; + background-color: #323737; +} +.dark .storage-close-link:hover { + background-color: #2e3436; +} +.storage-alert .storage-close-link { + color: #fff; + float: right; + padding-right: 10px; +} +.storage-alert .storage-close-icon { + background-position: -128px -90px; +} + + +/* *********** */ +/* Mobile */ +/* *********** */ +@media all and (orientation:portrait) { + .storage-ui #storage-ui-container { + height: 50%; + max-height: 400px; + width: 100%; + top: inherit!important; + bottom: 0; + right: 0; + left: 0; + } + .storage-ui .leaflet-right { + right: 0; + } + #storage-alert-container { + width: 100%; + left: 0; + right: 0; + } +} diff --git a/umap/static/umap/img/16-white.png b/umap/static/umap/img/16-white.png new file mode 100644 index 0000000000000000000000000000000000000000..afdd15aa753a95e23018be49630f6bcb1fd5cd90 GIT binary patch literal 13739 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 + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/umap/static/umap/img/16.png b/umap/static/umap/img/16.png new file mode 100644 index 0000000000000000000000000000000000000000..5aa09823629fdea4a36f619f72f7de3f14e8160f GIT binary patch literal 11308 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 + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/umap/static/umap/img/24-white.png b/umap/static/umap/img/24-white.png new file mode 100644 index 0000000000000000000000000000000000000000..f5bf14e20eb0f01875606255e7f30520befbbca4 GIT binary patch literal 19034 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 literal 0 HcmV?d00001 diff --git a/umap/static/umap/img/24-white.svg b/umap/static/umap/img/24-white.svg new file mode 100644 index 00000000..96865a43 --- /dev/null +++ b/umap/static/umap/img/24-white.svg @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/umap/static/umap/img/24.png b/umap/static/umap/img/24.png new file mode 100644 index 0000000000000000000000000000000000000000..bfac46bef523ceec9ba104e1e8e99fcc11784a33 GIT binary patch literal 14755 zcmb7rc{Eh<-~SzZ_Mwp7M3O!GE=|^up^%*nLS!e)lrSnpL&jPdO7=Col7vB0)+{AM z)-s{7J|EBTpWh$f=bY!c=S+_29(U$*-=FvUwcW(4W(F*byo?Y8u^1U5QQ+r?;}-)R z_%|{8$N~JI3Dh&PVgN@Z!%Zys{e-`vZ6G+m>i7kVa<|G4@dvD)Ejsl#Do1U~w@O2`KHX|7*Dp6{yHS7LnuRFEE__4tM{XFh-1lqg zHMcLB4-|W4TF6n+F+`u5w{g>Pw!-QgV~@C3i92DKaME2Jq0X-VaJbPtXK929X46_( zTdRb8E;34F)BdN+(kS2ds|x8q>Dd!uc~@mu+Y-tzmqh1Jy-ipt8#Z*-OzVtM)a zyowHT@4uZpfefNo)|PC<7l&{9Po89;IV;YQD8y-@g%Nqfph)OBr>>=eL5~6y zCLH{8T3+wPRm$$xid`IgYuCR1d-v|$BWRyP*M-YA&)PV* z*8lrEkHB)1pFR$(sz<+B5tAwS4HmlCgoWDnc4v~w1NIHE4jfA7G^@sE5yCfR-Xs|+ z|8p1#Vq~ZyZ7Inhs>;+G(9oEfuV2%780|j4Sc$;m zHy}CX0be@*+Sv^qjoI?!#d)k>$VTl6bt3=L6TTQD)VVrCylNs(%xN#~bwkEbE8b9) z^_I8y-aFsD($}vS*@xYr{n&G)N&x`@1CjoUYmWSdFJ8DjcDH59q^xUgkI%1nKjNNc znX_38q3Zlz?4_NN(hSob+qwj^e@|?Aesm&U5Hg1k)5g2Brpew#-8ocNf(D@~b1qv) z;Q~&UuCOys%DUwDo(OG`;E_pKlI9KG?MU(owh#U@4Q&-)xHoi4G9yNspOtaZ8UIo z$`pGY_L$n;f9re-lg}|M2sOkXeBe{U6!0`q>+}*$5|xH{^Yr93rod$#o2>*O;9SIq7hfX(m=3fo?t zs7*&PeQFG3hdZ!2JKbDDHIaDCxJAB7ppu&0z*V*4UG_he@9y5mZ@7|jTDApN4cpb)^(4@Dj9}-MWO*fj{IU)98+tX=86Lnfh%BE_LB9-H|F*!MTdTniO z=&yB^WG(8&)tBFD%4q*JTZ&Td;}eS5WFM$12GgCNl11#cPc`74JsT1&FoBhYRFBs~ zB+9{|?d?-MjB&>Jrj80L{>~}0>8R@3ij|fYcS}(F@J?KG+PBo@lSW)pHosfhU6nEG z(VOU1W!6dgh$M;6sblh&!3L6L6`pEdUte#WZXgsD6%h&wsNCJ%N9_HdfNP}Va97G- zz6^^YX3BqmJ6W<4kz276SU9|NW@(RQstA|moJBH=?ug-6a2l}=Cq`D{Hh((Hh1q~@ z?~H!(#89+!uSu)2uy9`V@327MPky5P(^rQV)jk*oGD72lLt3-?M}CijTGL9rrd*+C zxQvW;dkYJ=tfXYNIz(^Oz}|B0`t@i>N5?}B__QGskM`QVY}~}DV370chi^)$&+qom@Ycib8JUDDU!M8Hx z;~Jq~UVk||r9YmPem`FAmQU-ihM_{Y zM}Q@uXZxUx*flFwB<^1URWjCWj{HK>r<`7{FboVAQJB4EX{k_NT#Rle*Y`>t_aFIi zbBV8)kR7z2?q&}x%}^o~gnM{inWernX%Y=V-?T5OtNYvA*Vk9=){{If-F-1l+R%x$ zCh-!u)v|~JJ{V4p{MGJu(}LMkadSso6za3OA^8I9OrocK^9nI%;C!f*$0OzPyAE0X zwb&(hs8SR(&X%IHRZ=T2zU&br71|GT?6kDB4kn+~y7|zVrIKU8B5nTQVO`|n=9Vol zE90+U$gndrT@)4*6B~iq)6SLF)YRmDR(roRTv%e3rTD7k`SUqbbUR~gj>Q+nwOL4e zO_oJLNR*J15n*bqCfF%|`r!uM?`7vz>MEZnls&ib;)+1C7<-QmOYz;js2deHb-DbN zlM`2MZ2swK=5760scC3vNFlrQ6d65bJ^VXj&gMZPL-tlzulnn|yDyYGMN=03=H=xT z!g5&W(l$3YE&KZWkLGULF*`FsuOY?c(+Z?@i$Z+?&{3eruqvuf0_WK)|3;jBvUOq( z7ooE-T{#}jH0)>J-%`-;2Nf&N6v&T=`_vFO%y4V~26vd6o{qZ5H?M>qTzsVDHlbF} zGwk`7dud8So8JGozXmO&dH8R>AA9a~LN39TNlcefwdAj#5FQed%A&@-?&=$_uE z;+0b8&V`-%D)J$TuQ3$tW+Nk`UOq_X?HD~S*1c-w%8}WiW7FGraZJ|KJgchb1**d| zwRJ2D$^`+Qs(}F>k_BP`@H)4`r0%n$av4h9NDN%`S~>eW~u5*QV6O~8LGYO5N$0% zNO`bs=@;angTd$bJ-H&rky!2P>)TXu_vic8a5A{k!{mDh#rX_(Nx#-@q?G*@`qD2h zUNqmHvWDIeT3h#JL4g}|&BST&Zm-{4Nn9dvnrq5WKOVrOqS|Sl4Y(iHxK`VQH%rXi zLpeA^DZq1opza894u9F+-mbhLM(mRZXo?NHB;e!Y!UZ2Tot~a1Cy+HS#TZJMICs3- z%XSVMQ5OeCm-a{5r>aq6)wXy7lRo$ za1pPHG?Z}a8Z&=R2x#=m>fkwlH|?8$7fW}cev&%8v#HANVLf!X^iBKp_UPXs$i6LP zZBk=UlT6&AG)Q!-X>;k(#IZY_`%Wlca*3H2DA@19^ZrxDQ?TV*$7&CVvQSX9g7^BQw z=zh-ESj?1(iuoebFn4psMyc1NIC*i%DYcc0nNA2%&}Er+Fr_%a;xF2CJN;eO9L&-}^OJU;AcH>2ju?9y)b;3NQTnM`&92xTAu~HxhrW*b< z=yFd9EZ7KzmOmX$Y{WosA^;?Ai4jh<*6jJc^lW!`*8ztr>C}F9sDqAHEMWYWNW3}s~ULPci=lL%L6(;;&4g=o!eNFwSsDtaq5*JL#g)b_m z&S(wd4=+8<$5Yk}MO|4-OeYWoDGTE$HeI+v%;(9;<%ffbuOAxY{d0b7K#{0E>gkMa z-d~0i=5Ycr0qCl&ZFp>UL@;$6Hbk^w9v`la5#kuGfb{F!3?+78{xA%$2-2c&D@Kl7 z&M9uz8YmYt)!KVHLGOiYQJtZLS+#%2gHSYa+!@*HM#sWPIX86zWCant- zT2DY*0S`r|*i*ePb}4iJ`18-b*efsLqCRyfA7awhIQ$e`0Orh>KeW?~`}_n&cj?7d znYZ+t#&SIST0SQht_-cu5ciQ_r%qzm@E@mSHQoDg#!#p^{(}1j1r=AzlB>v|`z|~? zi?0t;KjI`T2jO~;voE+CpTeAm+Eu{G^_C@O2XkwUvxCMl>Owx?9y5kmy+4OZ!Bb|y zn6LybDH0kq6y@MPrbLB}Q@2}oW}UF;=u zI-u(UJ2PDg$FMz=(6#>V+pnFysnK$~#(eey8L?kai@idA_Ok-a=T4eV0~PQOfDyl2 zyd|NV%&0E`iJn9D!QT=l^41bm?06VW3V8O;VTjg*PsjMU$Cal@c#7PHR`V-aHTzVs<~;Tyy?m3 z?<;VIpi%odQDGMj&&`za6=u&=v^jMqe<)NEbA|0d6_Q5vRq#JVn~qf6x^-*U`FX>Z zohn(k_@aT4#D+8J2hk{jmGDIw`Bxs^#x@rPh4Tr?lNXWMt>!zhPk0$$Ii4IE;d=LE zYb&dpkNxu=N+$m|0TjZN)6qcOo>>h}mX;&Aw{f%C@$vD#QvJJ$1pZ-o0cJ=&%|{knARstGxJ!1wf-~u?SJ;NPG{gYH?#T z&)1I1R`MQ=br|aB+v_R)&C6{%2A5zE|o6Pb~T){lRW-Xc38-XWB6^g z&8jdW;;KZjFnr)9x~ry)8Y13A$70bWqaR_r&FpmWd^}VmwPJ?2^%#k`bUUTk zYX|o6n!-=z@medj)U7$Yv8^t=TJE);B#4RYX33a<-SRI0DQ8>DxHo35n1UGxmYghH}4b&f~y*tm`_~3e3|=$YqbNu zsUiQSETD^BUEhBn?HVcId>ZDN9LB`u$ft~7#mYT4Ge(YGAj`V+SG)hXwb(?&m$jh2 z`-iommaVJYLlScRRlki)PYZ|^FhPIw3LODSKqBsRG6X#Ix!$(tI!-9SQ_$%4;5Vlt zSh{Rjg|nsQkIY0l8d>V{$^;7A+oL5-M{dZ!PsrXaeEnL|h37-M_h=bj_`x{6F15l2 zi*uS+)?#CQeNtWdG`0GCCozFO_HD~_gScIgLnU?9r8{^2D0R7CIv?F}r0$cWXv751 zRnI(%xy}|2c6Sa*vm5(1)oL*N$$@h!Y6fA!TEfkt0}EELCX za7+=uSG`dA?*FEwqGFv!1j+rm%DFth^HDdN1Sh(q-<;6>+W9C-vR2%T|lM9VwHYOL2!J$ zi_|mJ46Ad@_}$*?>MOcVUAE**NkSye!Rx1_*z&}eRGkAv`)=YThnVaC4h|o=RgX)d z^VaPjat;px9f2+?vviiLEA^fhEnnz`+y0E5f={xG!w;R4{wa47V*&&>Q5~}#Ula#Y zb^{op-+Kr0h+PSIT;kG2#4d$BiwS-BN$#2Fwr)gCCM(?n=iG zmo>zUjg4)T;BL8-$n8nu8+0b1jU9ro+x6n$>uc*!wfO>gB5tz;s_-DGBzht+i&sW8 zUEZuMgG!5ePwc@LQPnd8;$%=^;ycN|}r(x|RFtNIL3OeQ^su5xmJ?B%g7b#(M&d?n}$ z&sa;Ox3;$KN)mvu)P`?j?(9MS<;BEY2t0*xaHdcBhrv#Q?YqvH(Dgd7T)Ys-Z6eaV zNse^79;BVbrLm?~3j&TFraG;r5qU%VaH6@wS|O0{+nvXiSWg4-9}bQTbg_F>Z)BKq z$sTd+9!e@IY<9%5BFj#AmIvv>cYjv#TYYO#bcWmLf*!UoD?2-oaSJD3VFff3#!fZl zUrCYoHi*7!VqO9YjTgv41gr4m@LDl_q!|M`g#kh9oBTFdQo zsi3px2#7%@b?*!6@toiH&vePm<}~LTsea3oO%su> z8Y7BBSR|qx=#%bQB)fQ*I?(+`I1}H8KqS~XXOa$UePB`GL(xlX{3~OXel%CpQAd%B zfvRG*RGrt5ieGEWe6dR&{y|pGN31&lTbDTzCmt+G(R`ZcIq8OW0$Q;$RaeI<>zoTZ z89t1HOt4F0=tFyn`Wp;@DxKoiJIQIGrtpk9^F2`^lVX)W)Tp)j(v^>yZYTH#l^ofq zR}R@+@l1jcgqXaCpNBF|a&tE(bbY@KmC(k%jbR`5B}Q5TQjzvz>H5~3y=5!Ucuw8>4>u7L$%#MuQq9fj3x5ve$%bm_9g-?Llm-hxAgl! z|Mv8_59hHu814a?7-U(pTPQBL!7*A8(VdhH(_F>A&;fvvwo`$~5BvR`lWn^MipJtP z;!x-7H5+|exwd^Kl8j28pakC%0S}>uqD_!V$eYN*VZeDkAk5QkG(>CsYUNwQYn2Jr z%V{q>)grZLU7)mE^<`d@af4g=uJcE$PaT2e?*HN4PO-hZ`c#C1y1u4hhd}2e@Hv?v z`r-&b<)!9mUJM%ygS~P8?ei7m3eXK)#-|By-$CoA^xl*jyja;yf%X|XxsgHDfota= zws)-C-?BGgHa1R99YWA?C!Bk%mNvF|QN}D)bawD9aj!ViUM=Qu|CCon$C&wHsHOJ$ zr%#{c&SppK1wX!et|&btqas&3YWE^2m-}8>oL~=fDJd&I{24Vq&$7I-SWr-4cV*;c zu@@Lj1#jN`E5hwnu&4B_;85If3k-hap0rMe@9PHE21^HX zpQW9hMl#;--hqk@_1qFbVJG(@+fO9V81U<+qLwSb_2as}eWMmbP5{_ksCCa`}glp<0`D5k;BAr*{yoHAS0LYlymRjD@DRT6n2wwWOce9pKA`S(8vY_uh)Ne2 zHdMMXlOt@<8+J(1G@Ee_f78)J>!Z>)|A(R!o+q3Zk_wVOk%{yf(stVq*$a#$(zDhh zB^Cyef32a{ITIrz)xTu0WgZ3{@Z^igUq4D87LA6L3Kx+v1v^_O3lfn(4m2}Q5Uj3G z8=z;Nm`QZ^w(7mn@FEpkir$%0WA6HAWlRZ$=u7Npu1VB;XZ=jWy9-^eMlJhIjAl3f z>V5G5s~s5BKHHo5#*e3SHXX&1Rh-^@Gs{7ad;tZS0I>irz8o*(3=O?!yo#1D38Wp5PmuK?VRYdK4d`F-6uf{9GMZi z(sXbNgj3bwmJ2)q$pymTr!>Zx(ox;Lje**C{x*xP#`GCLA=bugG7mDBrAE^=oC={b zGs+FRxoeO~L`1~Qc_1df@|tw0+9On)(7Ql>gjD3zWxGahgushPzkK&mtlcF7+~(C|t=%~)dSA`6)kTQl%Z^i@cS zU>%>~y|2cvz7kvYN9qDZkZKAkv~sEVQ0m`Pz}XXUsWj~JZHZ&2Q^>!BGyw9(qp8Ws z_B50r^_)E9PKjFDh*6V6dYieP9mD0Vg>1cKVbiH%5>!L#GDwxN?bwb9Z`i!m8-MDFx-ee_4TdF z!4JJ2u*W-;$PQ{~L@_&Yi2;)Qd^0=+i#{H0P?=N5VE|;uKCIC7BCdyMO{F?S;pGbV z?2=Q5X=-B1PN20F#;(|^(ZNqGH*4R+*4*GXx>Q}U!ihswY)@NyA_}_kPu=6Of`IZ= zJSt)k8NA=7ediVsSi~TJKezV|rl5ZkaEC!+5>zz1F)QE1WIML?6nuQ>4*D=@D#Sgu z*z4E;t{*Ywee%4OkA2w7@CflMWd#V*D@~*6zSheS`cP`@o#j7Tg(HNMgCwGqQ_mjg z(&~_oNI_dBW$)wQpSxI32?g2vZ4%`f*kY=sfRPVCw&Mm8xlgC+r(es4E%Ga;Gb@yg= zgP28-Cv~+`!YYV4q8?x;LJ&tH4c7CNf;j!GWTK}QJRNpUydVJLyc-d*A6`{x4pw;W zt+W4$V*`;6p8J8w7xc<<>^gSoH2QF$v5l~l1RP_(gWatu&Q#X9YOj%EhtK2VFG)l^ znbUN{kxCAakJ09t?$j3OQXF^&iwu2E%O-E)TzTp5`s*Z^+*tssZ;wlx&j7$93mbPD z+Y(Z<8{DD03fl{{VV$EDc_9B8xoE&Rcx5^jfSryPV3;Wygz%M@m**Qv@Ih7vh}3(` zUsQf4sghYBR39(I-L=la@^j}QOb)UK4!$!Nql(7yr*X(1vYr|{0F$vJzU%uD41?SB z=&dhRl#*w5d%t{t@tw*C`81l?w?@c1didHP(Gpf9^E>_R`a55nIX99uOsZOHWdVo) z>n;l4{%17*pZ>=!@NGSr2P|S*v6qG@N1_d|G9Cd2*Hd0YuLsbW-`}O-DOjd1GBHf^ z&6>QwiDmoko<2S&dq;w@H7eBNIotLdA!plB z<*qIEQNV3p;?(&tG*y=?r-axoY)0x<;`P$&WsA-89p$3;|DA#MGx4vhEqKIwBM{3p zzsH{etLoE_?nmST9T|fC(u0YZ(V8-ku?mO12rvo}>Znx~^e*@y4V(oD=>RMQt`=UF3Dk|BR~AJe*`m-8Ix=wz&* zk}271+yhU3IHG62M#J^7Xr?(HYo@|HpBFjxHG6q^`BIMDk&eHN7}UzNSEl0J&l@8& z7#@k(<;Da~PEBP`H*}|Zs46XdW?UpwkN=%eeTp~W9PX`3fmGzlIs$tQ^q-*TrU ze(@SQOvr%*#(nqx3?*uYpP5^XBZ{)b1k<(?ae9-$Rj)W(aPw0gh)&Q!smE>#YD6&d z_gg#9EH0YgeB;euA%9=s0#Jb9@VvCnsVmWT3Kx-tO?D=IQMLB|I0|V}chYL-S9aHw z&F6e7hJH5>Ew%sxK&10OrQpPqh^z?i{}4n&bq}!^r^(kj3XM{S0SQDh*r5aLp7gU* zcae%ya*sntzU}dWbS&y6Yi;1gbRf- zr&czziThRTKk|)V=^-XrI#Z$ZmYnkBKfrl#{K;MV>J^1)^&H6pp&mRNwbQ0y8Pj@9 z?QhgA(IA@Pn0)-k#_Fmjoy-9XA206*n~W_n)D0W7b{tmb{&c`aiQpIP1*!O>p+)k+ zw8h7@>4u=ZZL!*+_R?s*M7{-y{yjzNtv5{_!QJm zC09~dc*ghrW>!{Kc_sw~O>qp*0|~ehngj2&!Rp>d|FQoxJbZ^>*I*>E_%_<*aiGjJ zn?~9}3anKRxq?@dfVKG{QdOrG$!)PoZ0M5>g}aF_FG^f9Meb!6H}Tnjpg1+EZ4+Em zrQO<2ZZn0mDs-42W9a=&5UKxShZcePD-HpWNg2Bm>@M&{?IfdDR`Ec>{7GVKRY{45 z!HA+?$h#|N>Fp);lX$n9TzLF4i^I#<3+R#^dEvQd37X1N>a}kZcbZ`cbrB$dXRZ5! z?xsGX2srJRm(fP_gG@kN*9j^jN6*3m5G^D=vz z(rEVlaRcI(Bfo$uFw++fro&fedWZ@*)R@N3vayK?Cv+c5u9flzX&JHTj*iFJ=yybG z^}ZU*m6esyUoCy#z^+&z?pyl=J(Pvz7$Zj@qW@39v^HFVqA6dA*W_Tbr6%K)1T=^7 zS?-^dcdZ_`hxSy3@*AWiGbdGm6%dWcN;MP>39RFWpn-t_CYPOqr(+dQQOyXsn2#a} zk@VSz1wiB7SF>#QRE*%luvCX7p8FZE73F`*C;T3thPwLXuJPX=k7RE@N;+ySa^OR{ ztAoR(pVvFXeW7UU6Zf&t;Jm^yV}?w5cU?Ln89$XdA&Ow>1UKLWG)46f=%#xB!P64= z?-hI15^#-xj?6Q6h2>xmUwiRV|6^0w_!XaI1PV}Md|YXnuIiarmI`0|pHieQc z8RHBE^5f#-;%i7Nm>spY(e+gE+JIwXCQl9@>`@}_j|7odff{z4k9xBcJfi3%T%f-= z&qdtt_gNl5Y6>2~mDhx3b4|59LJ-$NmiL+~T1tKC#~sc<>X_Ri?>F|0Re)mtFo;b9 z?u!^%Df&fsRfvIxu3W(8>Qy;v-4|pFXgmSSdP*;cc@DAoV%J!r-sOHAJ_Q6Eu9aj5 zaAKaqzQIBA3x~?$gvZc+?pI`spGQTv4=4^C70p-~AMok2fiw^8pRj!{i3KNML7mT} z=tBAGI~iz8+v~~jN8POVwRY*@(}Iae?cTFa=a21TXSTkJ$ey2BIs(YL-mVw82&Ji3 zv*-0+hANEQ2%jKKW>eD+k<&ReAAIi=pr87^TR-1jWwGLB0XBidtzGfFFjrcL69U%v z#eU!puwDtI(3VKjqm!v$iWXeCw=^RwE$xoTI{V-sLxXUN_X;vWFv3#|vzC@Gkwhxs zl-j6-p5wCS$P__p{|BhjX^YzP@zMeZy2`=m1sC@qjShJQMf1U?fijdM@TnHm@r4mR1d&Y45TcuH88Tt-R%RCcsGbZlXO zkdLq7ue}T8U{s%Zl=iG&je}MQ)!Lv~!CKmIE56Crm{R4HHRf)qubvrhd#egf_`(Kj z9ScoPVjoU^mD;UjYNvcvW4GEbjeOt$VY^*bRC(_T7yO+4tAqTz0_If)t}N=13_^)& z7fYu-zaK7@SwymJ|8osR7|W6OATF3qC(%8t*ny^{|4X9j!abNX-rZJ(L4+BheoZ16 zjuF2b8ccUdmETdCu+O%7hZWkddGX@=HmH9#)ChdI9rz8-9kVeq3PRL-ac;1%K3k`7 z?J0F2Rmi)2zyS#JdTb#U>Z~avKoz|;d3=yhe|8`J2F&?t&0FGrK&hJ?+1zEwb_YZ) z(^K$lCQWtk7mfKXjE`ki9M>z_K%-2Y+b|-x~-CycP z%BK$N@%maJQXrd-VpA`l2EwlbrZ#a&jbMeruHPFe4|!uaQa6o5SyPP*=>mK5fX>^F zm&8kdrqA?)kZzHWBjV0iHYel0OGT{+qqj)=?}YI zS6t{XnoYC6;po)izn1OO#M!wxZdH7XWmTdPHuCxNrZ&7SBjA_6!~*dO1;nwU&MM#T zg)j!G32_E!M_MSuT}*5;qW?uANWVDMY_#ufpVHd*29U7YY$A4)`_5TOZK~gw(ArP& zcIl{VgUH^ukhU9X1NxLnQLpJX*zq8-V^%UL86a-e0j6RofB8f2#H9y7LK)jF3!3}O zy3!#ApVmWGN)SN8<4@ICe~2?_FOI$ZIK3eMX(01JT^~5JM8$zS5J{{OKI~ZRwLbps z+c%H=S{2}a0=ba}Y80#V%4%rw%KDYD9w-*vU;u^Lk8K6T8bbgw-$a`YxY=d|$1;T! zote;@;)TF&@q*F@C;@0QIkFmnRwmw{>D8$LzM1B?axwJa;iE^hXp$WyTJq-Ue3>M6 z35AI03!l?=vpe#OfsRBAIGu;kw)s)p_|qvpv-DN6nEuWBvp2IymQYQW1r>y74wl<; zZ%O{6w+Vu%BGj)w+IHUZ*N&d~@0ecV%2?|;*0nwAf!a}`~IxVP`%2@*)T>y%@ zzPOk)0Z_qZFhy8?G2SEz9+8;yMMic&oX=-LZtO;Q5n4M)b;Jw0d=hnHC zeYR1-e|~f)xXk0GoW47b#igSX+(v9UVRLdG=0iFU*iG;hZAjtsDQNDz#6nZlH$FM! z7n<=KOZRl2p9|NTXq5#i%p{N@h)P`29Di5=8|Mw!gE4?WteL4a2n6@BEiM#zW!bg( z4$=H(U41sYK#Y`M?Qpus{sV>9&d2L;>uFv>s&Ee1RuR%cE+CTd7vI(&K*Hi9kc~ZL9`H+VIRwG{`9Iy-)Pj$4*g74Ne+|$TuB5$m6g^cH z04*m(9HFbG$Teasy}~ThTt&L1HM*@$gZth0s%~P*_Op1bBS^pX-6}8837Fsr5X1cZ zUN{fLx+Jq52I#7jla3^BQnbbO>)W?V0}Uk_X+N=gG@ix0&d$oR&xhUe^0M{f(Z^t; znOp9ru`=ntM%@Y#^0E(Q6?xwT=_0v@^0e+6JN?R}c(+*KDdj(hj#1c6(xaS}it#s* zlua#I*-g?}M03$j6e2>O!R4*C>}C{{&tY-0a|pX+)?c$t|C>g^iEd7J+zq!#Uy93O z0r>m`BBCl~>JHS?Qmv%p-2$!mTpB?@3 z<#8G+j}>TOIzbP;$a@FRSVotkox$!}BJfD#!8lHOJ>@ve0#?R*%Ifpk`x;{qi zT#ES_DcCi^rX$2>zH$$H*iAeE^*ZFo(8~#QF5$`sz#RE#Z)UNO4WjXaN%|VlYC35< zuGp)&#`d_Foj?FHbUa&5=WKycV`F29fF?)@v_Vi>kFCc*R(%Tl4~ucWrMxl4HQmO+ zSYY+dKF6sS?gS%lxsev2CywF* zNkqZS0ozADJfBXqgX9fh3TM%SXyuY@tW2J=@8rOlKhIkOZAv(|@4KCMg2so-19?G8 z#clr2zgg%DbhT<{)qZMt_z$}IZ!LOYG7dXlNgY8>tJ{dKo#yJ}e~NuiiUxsh)Fnk)%Ctr_UPSR{h5oGPk~deP(X73*Wur&$Ws# zbw}1ExbWmRU)z2@7`f8io>1HU-FZCfljw?zx1Y{3nX;Y_ti7@A{l}u8>-e1*L|AX% zzC9Q*qsey+GmgD<4R5O6K-!IW(YlsHksC=#3SleGLf!|t**!OMXT$FpYeB!|;12Z8 zk(z=rGPw`eL=yOGE+bMizmIENlh`r_!iD$k$qXhCe~Dw?QC3kY(OSH4_1okB-c_T2 zH=3HP(dP{BB>N_MW&j5B^L0fmtGXxZ;>EWUgFK$EwbKr`JKczpz8)SW-hS___m zLswwGJvwHO$loJ64R~*>f5@xavFHZu&%x;J-+@GsL6IkF%0Ihya8VDCIZKf7%R}Ab zfEYxyfgW=JYI97UX80O-;^S9y@JewV2qVu_{P_OAIR3DRub4hS_36B24P}6A!2KGg zXuezeE}!$4FR_YS9iGdkF-gg9{1(t}zZntcbNyx%iLdHX0}w3Zqn5sP&GVVaIJ{b@ zDqPy?O!ob&4%dR_{3i6D42r*X{w*i2XPDNJS&TQ~v0zJKxjF5s>TP(t zFVkG*Nzzv_jFBgo8j60lbNG6y2=@$z1-j^EIiA)mY%!Ba^vbrabBZ5*6YKNFLI0SO zn8HlTOHak!(-<@a6L~L^;huCyuW#|`d`{JQ9q9K9)G|zB;RgE95+oF;ld;7K2KoWK zk!Nb%icqjQB$NmQ(m3E|nJ?N{n}Hyehsb+bCDWE041bvVYm${s1MiBww?!%{fCdV3 zb_T{x=A_S>?Q1{3q^E%xz@E!c9F0OK+(HDiW;$|(FHv@O3CP3v6x!cR5P&g*KYsk6 z2f(@4_!W!1EBL!bO-+=h?^VNYKj%WM&kLMDT!>@$QwTIC{iM9btF`cUDgiH=UXnlp zMtMK%J$6Y(1o;fL%t83_JpG}ja?Iv3&vESO;N}As%*3#u(^4HGv~pvL zrj2#tn#z_nw?T?k){Rt_L)DoJ5Ml}QHD*ibsL{byKKCFXhWEKW0%+HzE>KEodYDDN7gH5_QdX+MhLIMU``1(5D45W!rG^q=e{=8#lNV0v+#**=1~DQMZ!aZN)E;l>kY) z_NTY&40nK+{AV>f>Nnxw>7tHb%ge@p(^IjmG;(HRTh^IP!q#VMUzC@xF^y+&K~*-! zwryd5emK1wX8rs7W1Rg5o;HE`7-UduElV4yt1s<~~x!2yKlIgQM*TOMei9?OR%BVgScuhLua}dBtQXroh2L{1aXWQ!o z!m9&`KzW{KcJ=|Dq0h_ZzyHurzRoEMro@aNqjI09#e8@22hfEZsmHYjr16DG)WtyT zIw4{vTEJI?n@=cpOc}^8;|FAey9l@8GSV26542zfJY`Ay_K?w6*pNzc@=O#|ak^Ap zOF5?I&f^0die7>M?8T{#rp3I2Jg-l|ZCTigb@ARe;PC^Y1vF_6Bs!nL#tp`{mS2>O zxskh-ShS%hsM}0-_Y^G~7b1YmA5gn~1vt@EZ&bJ*tzAf~`=F(Nwn7^7tJ#sRQx{zV ztvWMa0xFC-EUf0`%a?avu56F*`*$BlnB&0Cg)}_y?ivycd#FAUhe$B-J7B+Knk#m= zT6TVqKY#@ja%3z^_seySaqpOe&J$QU^=P1d5UmvQAbv+A3sQaooe_c`jLJQp+8tW> zV6>0mNW>tPASUS5GImR}>e`>* f|KIVCL_SK=i7X_^uC;;(Dj}oGX2=RX=llN!HYHPP literal 0 HcmV?d00001 diff --git a/umap/static/umap/img/24.svg b/umap/static/umap/img/24.svg new file mode 100644 index 00000000..083830c9 --- /dev/null +++ b/umap/static/umap/img/24.svg @@ -0,0 +1,461 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/umap/static/umap/img/edit-16.png b/umap/static/umap/img/edit-16.png new file mode 100644 index 0000000000000000000000000000000000000000..bfe389cbf921136dbc8e77e4b69339a86424036d GIT binary patch literal 430 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2=n zD-dSmmtT}V`<;yx0|TSBr;B5V zMeo$hd;ORk1rB`t&o?bAePwTF=fWidTTPqVZtqq9C^~`tgW;QgYaxg1#bQ&AopQVH zkUMi@z=_Hl*~vMZcHg|8QfAgYbK^M<#W&BcACh{wcm3*D-W(6BHicU?ey{U);R!I# z_Mc>79Np>6u{_PJ;M`q{=f752vADRbl2$F0zhSc3Z2zW(tMoi4^)D4YQdqNS6?202 z_P@L#mrZKhRc$*Ky{O>(S9H!)T|(^3f$DhnwgY91@g=+Ow*R>~lS?d7FjMTK4{M=} z{K{9cjPgSvtjj} zKfW&K!XIWfg{>~-n8WzpA!PMczDX*Tajg&6vrqL(O}CK?uikqvTXIT&P<>+LABND< Wb(eoME35~GErX}4pUXO@geCx)Sg;2G literal 0 HcmV?d00001 diff --git a/umap/static/umap/img/icon-bg.png b/umap/static/umap/img/icon-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..1f7144b370666e386d7f98458d0c0742f217c768 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCyDx`7I;J! zGca%qgD@k*tT_@uLG}_)Usv|Kj1pYBvMo#wg+L+664!_l=ltB<)VvY~=c3falGGH1 z^30M91$R&1fbd2>aiAhKPZ!4!iOb18-rm2@H?Z~e_Fin2m?6=@!n|Sv>+Hkl=h<4T b*fKM$XkmTuxN>z9PzQsjtDnm{r-UW|;H@<6 literal 0 HcmV?d00001 diff --git a/umap/static/umap/img/marker.png b/umap/static/umap/img/marker.png new file mode 100644 index 0000000000000000000000000000000000000000..3119b80698167f0e2bd7e329dcd73dddf0d5f08b GIT binary patch literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=f!eQwFr$;k>RU;@a7Xh1&)vK31nTYVP`N+*{fmW0{0VFum=qeCpLi9iy*!&b=}NZJPGi~X z8<$yTN61y)SlYCsX4$0Or)oaRto*?wp*72(C4ZIU;)RcsC+^YrvSz5!a#U|{>~{&- zRDC#ai^ikRx*Btmj1A0A%j&XS2zsj!R{2_R<;&8q2bP7cv=)h+Ah{&LPU3~sr2jLs z_?(0;DcyZz@4@L9^?ZrQw=7qwYj1e2TY8@D&Gww*Rkhu{sydqMAM@p3pA6Q#k+1~@ O0fVQjpUXO@geCxxBa<=! literal 0 HcmV?d00001 diff --git a/umap/static/umap/img/search.gif b/umap/static/umap/img/search.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2bf64c0ada8ef2ce5c1e5c25b5bd20d1ba4f2e2 GIT binary patch literal 1472 zcmZ?wbhEHblwy!#XkcUjg8%>jEB@#9a}5c0b_{Se(lcNN2`l~+bS_FwEJ;mKD9FSz{sEj(g!kufyue2f92`7TuK!_w>&Q1wJi7-GeKlh_tP26t&(_W zA9$;s{jTb9rrdS*TeGG_EPBY6V)Lu&Xp*`{jZtOL`AyDiv$n@LGh#E>9b_)!y+zDh z>^j#h`|+kfvP)uOa%d6nu2nq0cX8L8`f7TcGj@5!I^!8hX1>pp-}p>8#j~RFw`1#` z%%WE-o!W0`m;DSC19}A0%@DKy&uTI83NhZXyzEqC*A0iIM<*oI~;jV`^io6pa8z_~pd%FB33)|x3FD9q^I?WBvp1#{v1gqI@Aa`?ISX4RXRLJJN zyY2^QCYp3f7wfI$G}Zn#VWaiptyPVI%i8` z_3DE*=lQ(u8rt0{vYPQUH?MP@!kH7FSEZSsV_Gl2>SK~!;>L29B}Fz;pWJR{GM!rq zG!=V#Ko}auDRrY}{koDx?LCnReW|Bfa}OCUus;3d`>o~gu9VFGotd{IR?s6xHPfv* z|3uU)pQ%@#cAaJ8!sb#)#^7JR&7FBiCoGul~v0oTF&!5v35pm^yWF% z73-q^2$?AMTiA$H?@rc~WM-SKyL@BS!MbUS+_7d1S8xb$KC0g67k)6ea`T!>FLkGs z%7(C&^MbkK3?J#0?y3{o{(52m%bP9Ai(Z<$h)q4NFnOA_-NIwHh0>lRx*CX_3&fhf zz$UZZe^eRZ#g%io>hinLgipOH>3%CZw|}KTutl z@*u1xLvzLAIa_XVZ92!hg13lcM$5v)zFX;e?Yp-qSshn-UAj8&UdQT&DY{s W@-$Ah!$0#<=A;Xt^sC3kU=08>NK0b? literal 0 HcmV?d00001 diff --git a/umap/static/umap/js/autocomplete.js b/umap/static/umap/js/umap.autocomplete.js similarity index 100% rename from umap/static/umap/js/autocomplete.js rename to umap/static/umap/js/umap.autocomplete.js diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js new file mode 100644 index 00000000..0f6aad8b --- /dev/null +++ b/umap/static/umap/js/umap.controls.js @@ -0,0 +1,1131 @@ +L.Storage.BaseAction = L.ToolbarAction.extend({ + + initialize: function (map) { + this.map = map; + this.options.toolbarIcon = { + className: this.options.className, + tooltip: this.options.tooltip + }; + L.ToolbarAction.prototype.initialize.call(this); + if (this.options.helpMenu && !this.map.helpMenuActions[this.options.className]) this.map.helpMenuActions[this.options.className] = this; + } + +}); + +L.Storage.ImportAction = L.Storage.BaseAction.extend({ + + options: { + helpMenu: true, + className: 'upload-data dark', + tooltip: L._('Import data') + ' (Ctrl+I)' + }, + + addHooks: function () { + this.map.importPanel(); + } + +}); + +L.Storage.EditPropertiesAction = L.Storage.BaseAction.extend({ + + options: { + helpMenu: true, + className: 'update-map-settings dark', + tooltip: L._('Edit map settings') + }, + + addHooks: function () { + this.map.edit(); + } + +}); + +L.Storage.ChangeTileLayerAction = L.Storage.BaseAction.extend({ + + options: { + helpMenu: true, + className: 'dark update-map-tilelayers', + tooltip: L._('Change tilelayers') + }, + + addHooks: function () { + this.map.updateTileLayers(); + } + +}); + +L.Storage.ManageDatalayersAction = L.Storage.BaseAction.extend({ + + options: { + className: 'dark manage-datalayers', + tooltip: L._('Manage layers') + }, + + addHooks: function () { + this.map.manageDatalayers(); + } + +}); + +L.Storage.UpdateExtentAction = L.Storage.BaseAction.extend({ + + options: { + className: 'update-map-extent dark', + tooltip: L._('Save this center and zoom') + }, + + addHooks: function () { + this.map.updateExtent(); + } + +}); + +L.Storage.UpdatePermsAction = L.Storage.BaseAction.extend({ + + options: { + className: 'update-map-permissions dark', + tooltip: L._('Update permissions and editors') + }, + + addHooks: function () { + this.map.updatePermissions(); + } + +}); + +L.Storage.DrawMarkerAction = L.Storage.BaseAction.extend({ + + options: { + helpMenu: true, + className: 'storage-draw-marker dark', + tooltip: L._('Draw a marker') + }, + + addHooks: function () { + this.map.startMarker(); + } + +}); + +L.Storage.DrawPolylineAction = L.Storage.BaseAction.extend({ + + options: { + helpMenu: true, + className: 'storage-draw-polyline dark', + tooltip: L._('Draw a polyline') + }, + + addHooks: function () { + this.map.startPolyline(); + } + +}); + +L.Storage.DrawPolygonAction = L.Storage.BaseAction.extend({ + + options: { + helpMenu: true, + className: 'storage-draw-polygon dark', + tooltip: L._('Draw a polygon') + }, + + addHooks: function () { + this.map.startPolygon(); + } + +}); + +L.Storage.AddPolylineShapeAction = L.Storage.BaseAction.extend({ + + options: { + className: 'storage-draw-polyline-multi dark', + tooltip: L._('Add a line to the current multi') + }, + + addHooks: function () { + this.map.editedFeature.editor.newShape(); + } + +}); + +L.Storage.AddPolygonShapeAction = L.S.AddPolylineShapeAction.extend({ + + options: { + className: 'storage-draw-polygon-multi dark', + tooltip: L._('Add a polygon to the current multi') + } + +}); + +L.Storage.BaseFeatureAction = L.ToolbarAction.extend({ + + initialize: function (map, feature, latlng) { + this.map = map; + this.feature = feature; + this.latlng = latlng; + L.ToolbarAction.prototype.initialize.call(this); + this.postInit(); + }, + + postInit: function () {}, + + hideToolbar: function () { + this.map.removeLayer(this.toolbar); + }, + + addHooks: function () { + this.onClick({latlng: this.latlng}); + this.hideToolbar(); + } + +}); + +L.Storage.CreateHoleAction = L.S.BaseFeatureAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-new-hole', + tooltip: L._('Start a hole here') + } + }, + + onClick: function (e) { + this.feature.startHole(e); + } + +}); + +L.Storage.ToggleEditAction = L.S.BaseFeatureAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-toggle-edit', + tooltip: L._('Toggle edit mode (shift-click)') + } + }, + + onClick: function (e) { + if (this.feature._toggleEditing) this.feature._toggleEditing(e); // Path + else this.feature.edit(e); // Marker + } + +}); + +L.Storage.DeleteFeatureAction = L.S.BaseFeatureAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-delete-all', + tooltip: L._('Delete this feature') + } + }, + + postInit: function () { + if (!this.feature.isMulti()) this.options.toolbarIcon.className = 'storage-delete-one-of-one'; + }, + + onClick: function (e) { + this.feature.confirmDelete(e); + } + +}); + +L.Storage.DeleteShapeAction = L.S.BaseFeatureAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-delete-one-of-multi', + tooltip: L._('Delete this shape') + } + }, + + onClick: function (e) { + this.feature.enableEdit().deleteShapeAt(e.latlng); + } + +}); + +L.Storage.ExtractShapeFromMultiAction = L.S.BaseFeatureAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-extract-shape-from-multi', + tooltip: L._('Extract shape to separate feature') + } + }, + + onClick: function (e) { + this.feature.isolateShape(e.latlng); + } + +}); + +L.Storage.BaseVertexAction = L.S.BaseFeatureAction.extend({ + + initialize: function (map, feature, latlng, vertex) { + this.vertex = vertex; + L.S.BaseFeatureAction.prototype.initialize.call(this, map, feature, latlng); + } + +}); + +L.Storage.DeleteVertexAction = L.S.BaseVertexAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-delete-vertex', + tooltip: L._('Delete this vertex (Alt-click)') + } + }, + + onClick: function () { + this.vertex.delete(); + } + +}); + +L.Storage.SplitLineAction = L.S.BaseVertexAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-split-line', + tooltip: L._('Split line') + } + }, + + onClick: function () { + this.vertex.split(); + } + +}); + +L.Storage.ContinueLineAction = L.S.BaseVertexAction.extend({ + + options: { + toolbarIcon: { + className: 'storage-continue-line', + tooltip: L._('Continue line') + } + }, + + onClick: function () { + this.vertex.continue(); + } + +}); + +// Leaflet.Toolbar doesn't allow twice same toolbar class… +L.Storage.SettingsToolbar = L.Toolbar.Control.extend({}); +L.Storage.DrawToolbar = L.Toolbar.Control.extend({ + + initialize: function (options) { + L.Toolbar.Control.prototype.initialize.call(this, options); + this.map = this.options.map; + this.map.on('seteditedfeature', this.redraw, this); + }, + + appendToContainer: function (container) { + this.options.actions = []; + if (this.map.options.enableMarkerDraw) { + this.options.actions.push(L.S.DrawMarkerAction); + } + if (this.map.options.enablePolylineDraw) { + this.options.actions.push(L.S.DrawPolylineAction); + if (this.map.editedFeature && this.map.editedFeature instanceof L.S.Polyline) { + this.options.actions.push(L.S.AddPolylineShapeAction); + } + } + if (this.map.options.enablePolygonDraw) { + this.options.actions.push(L.S.DrawPolygonAction); + if (this.map.editedFeature && this.map.editedFeature instanceof L.S.Polygon) { + this.options.actions.push(L.S.AddPolygonShapeAction); + } + } + L.Toolbar.Control.prototype.appendToContainer.call(this, container); + }, + + redraw: function () { + var container = this._control.getContainer(); + container.innerHTML = ''; + this.appendToContainer(container); + } + +}); + + +L.Storage.EditControl = L.Control.extend({ + + options: { + position: 'topright' + }, + + onAdd: function (map) { + var container = L.DomUtil.create('div', 'leaflet-control-edit-enable storage-control'), + edit = L.DomUtil.create('a', '', container); + edit.href = '#'; + edit.title = L._('Enable editing') + ' (Ctrl-E)'; + + L.DomEvent + .addListener(edit, 'click', L.DomEvent.stop) + .addListener(edit, 'click', map.enableEdit, map); + return container; + } + +}); + +/* Share control */ +L.Control.Embed = L.Control.extend({ + + options: { + position: 'topleft' + }, + + onAdd: function (map) { + var container = L.DomUtil.create('div', 'leaflet-control-embed storage-control'); + + var link = L.DomUtil.create('a', '', container); + link.href = '#'; + link.title = L._('Embed and share this map'); + + L.DomEvent + .on(link, 'click', L.DomEvent.stop) + .on(link, 'click', map.renderShareBox, map) + .on(link, 'dblclick', L.DomEvent.stopPropagation); + + return container; + } +}); + +L.Storage.MoreControls = L.Control.extend({ + + options: { + position: 'topleft' + }, + + onAdd: function () { + var container = L.DomUtil.create('div', ''), + more = L.DomUtil.create('a', 'storage-control-more storage-control-text', container), + less = L.DomUtil.create('a', 'storage-control-less storage-control-text', container); + more.href = '#'; + more.title = L._('More controls'); + + L.DomEvent + .on(more, 'click', L.DomEvent.stop) + .on(more, 'click', this.toggle, this); + + less.href = '#'; + less.title = L._('Hide controls'); + + L.DomEvent + .on(less, 'click', L.DomEvent.stop) + .on(less, 'click', this.toggle, this); + + return container; + }, + + toggle: function () { + var pos = this.getPosition(), + corner = this._map._controlCorners[pos], + className = 'storage-more-controls'; + if (L.DomUtil.hasClass(corner, className)) L.DomUtil.removeClass(corner, className); + else L.DomUtil.addClass(corner, className); + } + +}); + + +L.Storage.DataLayersControl = L.Control.extend({ + + options: { + position: 'topleft' + }, + + labels: { + zoomToLayer: L._('Zoom to layer extent'), + toggleLayer: L._('Show/hide layer'), + editLayer: L._('Edit') + }, + + initialize: function (map, options) { + this.map = map; + L.Control.prototype.initialize.call(this, options); + }, + + _initLayout: function (map) { + var container = this._container = L.DomUtil.create('div', 'leaflet-control-browse storage-control'), + actions = L.DomUtil.create('div', 'storage-browse-actions', container); + this._datalayers_container = L.DomUtil.create('ul', 'storage-browse-datalayers', actions); + + var link = L.DomUtil.create('a', 'storage-browse-link', actions); + link.href = '#'; + link.title = link.innerHTML = L._('Browse data'); + + var toggle = L.DomUtil.create('a', 'storage-browse-toggle', container); + toggle.href = '#'; + + L.DomEvent + .on(toggle, 'click', L.DomEvent.stop); + + L.DomEvent + .on(link, 'click', L.DomEvent.stop) + .on(link, 'click', map.openBrowser, map); + + map.whenReady(function () { + this.update(); + }, this); + + if (!L.Browser.touch) { + L.DomEvent.disableClickPropagation(container); + L.DomEvent.on(container, 'mousewheel', L.DomEvent.stopPropagation); + L.DomEvent.on(container, 'MozMousePixelScroll', L.DomEvent.stopPropagation); + L.DomEvent.on(container, { + mouseenter: this.expand, + mouseleave: this.collapse + }, this); + } else { + L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); + L.DomEvent.on(toggle, 'click', L.DomEvent.stop) + .on(toggle, 'click', this.expand, this); + map.on('click', this.collapse, this); + } + + return container; + }, + + onAdd: function (map) { + if (!this._container) this._initLayout(map); + if (map.options.datalayersControl === 'expanded') this.expand(); + return this._container; + }, + + onRemove: function (map) { + this.collapse(); + }, + + update: function () { + if (this._datalayers_container && this._map) { + this._datalayers_container.innerHTML = ''; + this._map.eachDataLayerReverse(function (datalayer) { + this.addDataLayer(this._datalayers_container, datalayer); + }, this) + } + }, + + expand: function () { + L.DomUtil.addClass(this._container, 'expanded'); + }, + + collapse: function () { + if (this._map.options.datalayersControl === 'expanded') return; + L.DomUtil.removeClass(this._container, 'expanded'); + }, + + addDataLayer: function (container, datalayer, draggable) { + var datalayerLi = L.DomUtil.create('li', '', container); + if (draggable) L.DomUtil.element('i', {className: 'drag-handle', title: L._('Drag to reorder')}, datalayerLi); + datalayer.renderToolbox(datalayerLi); + var title = L.DomUtil.add('span', 'layer-title', datalayerLi, datalayer.options.name); + + datalayerLi.id = 'browse_data_toggle_' + L.stamp(datalayer); + L.DomUtil.classIf(datalayerLi, 'off', !datalayer.isVisible()); + + title.innerHTML = datalayer.options.name; + }, + + newDataLayer: function () { + var datalayer = this.map.createDataLayer({}); + datalayer.edit(); + }, + + openPanel: function () { + if (!this.map.editEnabled) return; + var container = L.DomUtil.create('ul', 'storage-browse-datalayers'); + this.map.eachDataLayerReverse(function (datalayer) { + this.addDataLayer(container, datalayer, true); + }, this); + var orderable = new L.S.Orderable(container); + orderable.on('drop', function (e) { + var layer = this.map.datalayers[e.src.dataset.id], + other = this.map.datalayers[e.dst.dataset.id], + minIndex = Math.min(e.initialIndex, e.finalIndex); + if (e.finalIndex === 0) layer.bringToTop(); + else if (e.finalIndex > e.initialIndex) layer.insertBefore(other); + else layer.insertAfter(other); + this.map.eachDataLayerReverse(function (datalayer) { + if (datalayer.getRank() >= minIndex) datalayer.isDirty = true; + }); + this.map.indexDatalayers(); + }, this); + + var bar = L.DomUtil.create('div', 'button-bar', container), + add = L.DomUtil.create('a', 'show-on-edit block add-datalayer button', bar); + add.href = '#'; + add.innerHTML = add.title = L._('Add a layer'); + + L.DomEvent + .on(add, 'click', L.DomEvent.stop) + .on(add, 'click', this.newDataLayer, this); + + this.map.ui.openPanel({data: {html: container}, className: 'dark'}); + } + +}); + +L.Storage.DataLayer.include({ + + renderToolbox: function (container) { + var toggle = L.DomUtil.create('i', 'layer-toggle', container), + zoomTo = L.DomUtil.create('i', 'layer-zoom_to', container), + edit = L.DomUtil.create('i', 'layer-edit show-on-edit', container), + table = L.DomUtil.create('i', 'layer-table-edit show-on-edit', container), + remove = L.DomUtil.create('i', 'layer-delete show-on-edit', container); + zoomTo.title = L._('Zoom to layer extent'); + toggle.title = L._('Show/hide layer'); + edit.title = L._('Edit'); + table.title = L._('Edit properties in a table'); + remove.title = L._('Delete layer'); + L.DomEvent.on(toggle, 'click', this.toggle, this); + L.DomEvent.on(zoomTo, 'click', this.zoomTo, this); + L.DomEvent.on(edit, 'click', this.edit, this); + L.DomEvent.on(table, 'click', this.tableEdit, this); + L.DomEvent.on(remove, 'click', function () { + if (!this.isVisible()) return; + if (!confirm(L._('Are you sure you want to delete this layer?'))) return; + this._delete(); + this.map.ui.closePanel(); + }, this); + L.DomUtil.addClass(container, this.getHidableClass()); + L.DomUtil.classIf(container, 'off', !this.isVisible()); + container.dataset.id = L.stamp(this); + }, + + getHidableElements: function () { + return document.querySelectorAll('.' + this.getHidableClass()); + }, + + getHidableClass: function () { + return 'show_with_datalayer_' + L.stamp(this); + }, + + propagateRemote: function () { + var els = this.getHidableElements(); + for (var i = 0; i < els.length; i++) { + L.DomUtil.classIf(els[i], 'remotelayer', this.isRemoteLayer()); + } + }, + + propagateHide: function () { + var els = this.getHidableElements(); + for (var i = 0; i < els.length; i++) { + L.DomUtil.addClass(els[i], 'off'); + } + }, + + propagateShow: function () { + this.onceLoaded(function () { + var els = this.getHidableElements(); + for (var i = 0; i < els.length; i++) { + L.DomUtil.removeClass(els[i], 'off'); + } + }, this); + } + +}); + +L.Storage.DataLayer.addInitHook(function () { + this.on('hide', this.propagateHide); + this.on('show', this.propagateShow); + this.propagateShow(); +}); + + +L.Storage.Map.include({ + + _openBrowser: function () { + var browserContainer = L.DomUtil.create('div', 'storage-browse-data'), + title = L.DomUtil.add('h3', 'storage-browse-title', browserContainer, this.options.name), + filter = L.DomUtil.create('input', '', browserContainer), + filterValue = '', + featuresContainer = L.DomUtil.create('div', 'storage-browse-features', browserContainer), + filterKeys = (this.options.filterKey || this.options.sortKey || 'name').split(','); + filter.type = 'text'; + filter.placeholder = L._('Filter…'); + + var addFeature = function (feature) { + var feature_li = L.DomUtil.create('li', feature.getClassName() + ' feature'), + zoom_to = L.DomUtil.create('i', 'feature-zoom_to', feature_li), + edit = L.DomUtil.create('i', 'show-on-edit feature-edit', feature_li), + color = L.DomUtil.create('i', 'feature-color', feature_li), + title = L.DomUtil.create('span', 'feature-title', feature_li), + symbol = feature._getIconUrl ? L.S.Icon.prototype.formatUrl(feature._getIconUrl(), feature): null; + zoom_to.title = L._('Bring feature to center'); + edit.title = L._('Edit this feature'); + title.innerHTML = feature.getDisplayName() || '—'; + color.style.backgroundColor = feature.getOption('color'); + if (symbol) { + color.style.backgroundImage = 'url(' + symbol + ')'; + } + L.DomEvent.on(zoom_to, 'click', function (e) { + e.callback = this.view; + this.bringToCenter(e); + }, feature); + L.DomEvent.on(title, 'click', function (e) { + e.callback = this.view + this.bringToCenter(e); + }, feature); + L.DomEvent.on(edit, 'click', function () { + this.edit(); + }, feature); + return feature_li; + }; + + var append = function (datalayer) { + var container = L.DomUtil.create('div', datalayer.getHidableClass(), featuresContainer), + headline = L.DomUtil.create('h5', '', container); + container.id = 'browse_data_datalayer_' + datalayer.storage_id; + datalayer.renderToolbox(headline); + L.DomUtil.add('span', '', headline, datalayer.options.name); + var ul = L.DomUtil.create('ul', '', container); + L.DomUtil.classIf(container, 'off', !datalayer.isVisible()); + + var build = function () { + ul.innerHTML = ''; + datalayer.eachFeature(function (feature) { + if (filterValue && !feature.matchFilter(filterValue, filterKeys)) return; + ul.appendChild(addFeature(feature)); + }); + }; + build(); + datalayer.on('datachanged', build); + datalayer.map.ui.once('panel:closed', function () { + datalayer.off('datachanged', build); + }); + datalayer.map.ui.once('panel:ready', function () { + datalayer.map.ui.once('panel:ready', function () { + datalayer.off('datachanged', build); + }); + }); + }; + + var appendAll = function () { + featuresContainer.innerHTML = ''; + filterValue = filter.value; + this.eachBrowsableDataLayer(function (datalayer) { + append(datalayer); + }); + }; + L.bind(appendAll, this)(); + L.DomEvent.on(filter, 'input', appendAll, this); + var link = L.DomUtil.create('li', ''); + L.DomUtil.create('i', 'storage-icon-16 storage-caption', link); + var label = L.DomUtil.create('span', '', link); + label.innerHTML = label.title = L._('About'); + L.DomEvent.on(link, 'click', this.displayCaption, this); + this.ui.openPanel({data: {html: browserContainer}, actions: [link]}); + } + +}); + + + +L.Storage.TileLayerControl = L.Control.extend({ + options: { + position: 'topleft' + }, + + onAdd: function () { + var container = L.DomUtil.create('div', 'leaflet-control-tilelayers storage-control'); + + var link = L.DomUtil.create('a', '', container); + link.href = '#'; + link.title = L._('Change map background'); + + L.DomEvent + .on(link, 'click', L.DomEvent.stop) + .on(link, 'click', this.openSwitcher, this) + .on(link, 'dblclick', L.DomEvent.stopPropagation); + + return container; + }, + + openSwitcher: function (options) { + this._tilelayers_container = L.DomUtil.create('ul', 'storage-tilelayer-switcher-container'); + this.buildList(options); + }, + + buildList: function (options) { + this._map.eachTileLayer(function (tilelayer) { + this.addTileLayerElement(tilelayer, options); + }, this); + this._map.ui.openPanel({data: {html: this._tilelayers_container}, className: options.className}); + }, + + addTileLayerElement: function (tilelayer, options) { + var selectedClass = this._map.hasLayer(tilelayer) ? 'selected' : '', + el = L.DomUtil.create('li', selectedClass, this._tilelayers_container), + img = L.DomUtil.create('img', '', el), + name = L.DomUtil.create('div', '', el); + img.src = L.Util.template(tilelayer.options.url_template, this._map.demoTileInfos); + name.innerHTML = tilelayer.options.name; + L.DomEvent.on(el, 'click', function () { + this._map.selectTileLayer(tilelayer); + this._map.ui.closePanel(); + if (options && options.callback) options.callback(tilelayer); + }, this); + } + + +}); + +L.S.AttributionControl = L.Control.Attribution.extend({ + + options: { + prefix: '' + }, + + _update: function () { + L.Control.Attribution.prototype._update.call(this); + if (this._map.options.shortCredit) { + L.DomUtil.add('span', '', this._container, ' — ' + L.Util.toHTML(this._map.options.shortCredit)); + } + var link = L.DomUtil.add('a', '', this._container, ' — ' + L._('About')); + L.DomEvent + .on(link, 'click', L.DomEvent.stop) + .on(link, 'click', this._map.displayCaption, this._map) + .on(link, 'dblclick', L.DomEvent.stop); + if (window.top === window.self) { + // We are not in iframe mode + var home = L.DomUtil.add('a', '', this._container, ' — ' + L._('Home')); + home.href = '/'; + } + } + +}); + + +L.Storage.LocateControl = L.Control.extend({ + + options: { + position: 'topleft' + }, + + onAdd: function (map) { + var container = L.DomUtil.create('div', 'leaflet-control-locate storage-control'), + link = L.DomUtil.create('a', '', container); + link.href = '#'; + link.title = L._('Center map on your location'); + var fn = function () { + map.locate({ + setView: true, + enableHighAccuracy: true + }); + }; + + L.DomEvent + .on(link, 'click', L.DomEvent.stop) + .on(link, 'click', fn, map) + .on(link, 'dblclick', L.DomEvent.stopPropagation); + + return container; + } +}); + + +L.Storage.Search = L.PhotonSearch.extend({ + + onBlur: function (e) { + // Overrided because we don't want to hide the results on blur. + this.fire('blur'); + }, + + formatResult: function (feature, el) { + var self = this; + var tools = L.DomUtil.create('span', 'search-result-tools', el), + zoom = L.DomUtil.create('i', 'feature-zoom_to', tools), + edit = L.DomUtil.create('i', 'feature-edit show-on-edit', tools); + zoom.title = L._('Zoom to this place'); + edit.title = L._('Save this location as new feature'); + // We need to use "mousedown" because Leaflet.Photon listen to mousedown + // on el. + L.DomEvent.on(zoom, 'mousedown', function (e) { + L.DomEvent.stop(e); + self.zoomToFeature(feature); + }); + L.DomEvent.on(edit, 'mousedown', function (e) { + L.DomEvent.stop(e); + var datalayer = self.map.defaultDataLayer(); + var layer = datalayer.geojsonToFeatures(feature); + layer.isDirty = true; + layer.edit(); + }); + this._formatResult(feature, el); + }, + + zoomToFeature: function (feature) { + var zoom = Math.max(this.map.getZoom(), 16); // Never unzoom. + this.map.setView([feature.geometry.coordinates[1], feature.geometry.coordinates[0]], zoom); + }, + + onSelected: function (feature) { + this.zoomToFeature(feature); + this.map.ui.closePanel(); + } + +}); + +L.Storage.SearchControl = L.Control.extend({ + + options: { + position: 'topleft', + }, + + onAdd: function (map) { + var container = L.DomUtil.create('div', 'leaflet-control-search storage-control'), + self = this; + + L.DomEvent.disableClickPropagation(container); + var link = L.DomUtil.create('a', '', container); + link.href = '#'; + L.DomEvent.on(link, 'click', function (e) { + L.DomEvent.stop(e); + self.openPanel(map); + }); + return container; + }, + + openPanel: function (map) { + var options = { + limit: 10, + noResultLabel: L._('No results'), + } + if (map.options.photonUrl) options.url = map.options.photonUrl; + var container = L.DomUtil.create('div', ''); + + var title = L.DomUtil.create('h3', '', container); + title.textContent = L._('Search location'); + var input = L.DomUtil.create('input', 'photon-input', container); + var resultsContainer = L.DomUtil.create('div', 'photon-autocomplete', container); + this.search = new L.S.Search(map, input, options); + var id = Math.random(); + this.search.on('ajax:send', function () { + map.fire('dataloading', {id: id}); + }); + this.search.on('ajax:return', function () { + map.fire('dataload', {id: id}); + }); + this.search.resultsContainer = resultsContainer; + map.ui.once('panel:ready', function () { + input.focus(); + }); + map.ui.openPanel({data: {html: container}}); + } + +}); + + +L.Control.MiniMap.include({ + + initialize: function (layer, options) { + L.Util.setOptions(this, options); + this._layer = this._cloneLayer(layer); + }, + + onMainMapBaseLayerChange: function (e) { + var layer = this._cloneLayer(e.layer); + if (this._miniMap.hasLayer(this._layer)) { + this._miniMap.removeLayer(this._layer); + } + this._layer = layer; + this._miniMap.addLayer(this._layer); + }, + + _cloneLayer: function (layer) { + return new L.TileLayer(layer._url, L.Util.extend({}, layer.options)); + } + +}); + + +L.Control.Loading.include({ + + onAdd: function (map) { + this._container = L.DomUtil.create('div', 'storage-loader', map._controlContainer); + map.on('baselayerchange', this._layerAdd, this); + this._addMapListeners(map); + this._map = map; + }, + + _showIndicator: function () { + L.DomUtil.addClass(this._map._container, 'storage-loading'); + }, + + _hideIndicator: function() { + L.DomUtil.removeClass(this._map._container, 'storage-loading'); + } + +}); + + +/* +* Make it dynamic +*/ +L.S.ContextMenu = L.Map.ContextMenu.extend({ + + _createItems: function (e) { + this._map.setContextMenuItems(e); + L.Map.ContextMenu.prototype._createItems.call(this); + }, + + _showAtPoint: function (pt, e) { + this._items = []; + this._container.innerHTML = ''; + this._createItems(e); + L.Map.ContextMenu.prototype._showAtPoint.call(this, pt, e); + } + +}); + +L.S.IframeExporter = L.Class.extend({ + includes: [L.Mixin.Events], + + options: { + includeFullScreenLink: true, + currentView: false, + keepCurrentDatalayers: false + }, + + queryString: { + scaleControl: false, + miniMap: false, + scrollWheelZoom: false, + zoomControl: true, + allowEdit: false, + moreControl: true, + searchControl: null, + tilelayersControl: null, + embedControl: null, + datalayersControl: true, + onLoadPanel: 'none', + captionBar: false + }, + + dimensions: { + width: '100%', + height: '300px' + }, + + initialize: function (map) { + this.map = map; + this.baseUrl = window.location.protocol + '//' + window.location.host + window.location.pathname; + // Use map default, not generic default + this.queryString.onLoadPanel = this.map.options.onLoadPanel; + }, + + getMap: function () { + return this.map; + }, + + build: function () { + var datalayers = []; + if (this.options.keepCurrentDatalayers) { + this.map.eachDataLayer(function (datalayer) { + if (datalayer.isVisible() && datalayer.storage_id) { + datalayers.push(datalayer.storage_id); + } + }); + this.queryString.datalayers = datalayers.join(','); + } else { + delete this.queryString.datalayers; + } + var currentView = this.options.currentView ? window.location.hash : '', + iframeUrl = this.baseUrl + '?' + this.map.xhr.buildQueryString(this.queryString) + currentView, + code = ''; + if (this.options.includeFullScreenLink) { + code += '

' + L._('See full screen') + '

'; + } + return code; + } + +}); + +L.S.Editable = L.Editable.extend({ + + initialize: function (map, options) { + L.Editable.prototype.initialize.call(this, map, options); + this.on('editable:drawing:start editable:drawing:click', this.drawingTooltip); + this.on('editable:drawing:end', this.closeTooltip); + // Layer for items added by users + this.on('editable:drawing:cancel', function (e) { + if (e.layer._latlngs && e.layer._latlngs.length < e.layer.editor.MIN_VERTEX) e.layer.del(); + if (e.layer instanceof L.S.Marker) e.layer.del(); + }); + this.on('editable:drawing:commit', function (e) { + e.layer.isDirty = true; + if (this.map.editedFeature !== e.layer) e.layer.edit(e); + }); + this.on('editable:editing', function (e) { + var layer = e.layer; + layer.isDirty = true; + if (layer._tooltip && layer.isTooltipOpen()) { + layer._tooltip.setLatLng(layer.getCenter()); + layer._tooltip.update(); + } + }); + this.on('editable:vertex:ctrlclick', function (e) { + var index = e.vertex.getIndex(); + if (index === 0 || index === e.vertex.getLastIndex() && e.vertex.continue) e.vertex.continue(); + }); + this.on('editable:vertex:altclick', function (e) { + if (e.vertex.editor.vertexCanBeDeleted(e.vertex)) e.vertex.delete(); + }); + this.on('editable:vertex:rawclick', this.onVertexRawClick); + }, + + createPolyline: function (latlngs) { + return new L.Storage.Polyline(this.map, latlngs); + }, + + createPolygon: function (latlngs) { + var polygon = new L.Storage.Polygon(this.map, latlngs); + return polygon; + }, + + createMarker: function (latlng) { + return new L.Storage.Marker(this.map, latlng); + }, + + connectCreatedToMap: function (layer) { + // Overrided from Leaflet.Editable + var datalayer = this.map.defaultDataLayer(); + datalayer.addLayer(layer); + layer.isDirty = true; + return layer; + }, + + drawingTooltip: function (e) { + var content; + if (e.layer instanceof L.Marker) content = L._('Click to add a marker'); + else if (e.layer instanceof L.Polyline) { + if (!e.layer.editor._drawnLatLngs.length) { + if (e.layer instanceof L.Polygon) content = L._('Click to start drawing a polygon'); + else if (e.layer instanceof L.Polyline) content = L._('Click to start drawing a line'); + } else if (e.layer.editor._drawnLatLngs.length < e.layer.editor.MIN_VERTEX) { + content = L._('Click to continue drawing'); + } else { + content = L._('Click last point to finish shape'); + } + } + if (content) this.map.ui.tooltip({content: content}); + }, + + closeTooltip: function () { + this.map.ui.closeTooltip(); + }, + + onVertexRawClick: function (e) { + e.layer.onVertexRawClick(e); + L.DomEvent.stop(e); + e.cancel(); + } + +}); diff --git a/umap/static/umap/js/umap.core.js b/umap/static/umap/js/umap.core.js new file mode 100644 index 00000000..3dd091c5 --- /dev/null +++ b/umap/static/umap/js/umap.core.js @@ -0,0 +1,521 @@ +/* Poor man pub/sub handler, enough for now */ + +L.StorageSingleton = L.Evented.extend({}); +L.Storage = new L.StorageSingleton(); +L.S = L.Storage; +L.Storage.Map = L.Map.extend({}); + +/* +* Utils +*/ +L.Util.queryString = function (name, fallback) { + var decode = function (s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }; + var qs = window.location.search.slice(1).split('&'), qa = {}; + for (var i in qs) { + var key = qs[i].split('='); + if (!key) continue; + qa[decode(key[0])] = key[1] ? decode(key[1]) : 1; + } + return qa[name] || fallback; +}; + +L.Util.booleanFromQueryString = function (name) { + var value = L.Util.queryString(name); + return value === '1' || value === 'true'; +}; + +L.Util.setFromQueryString = function (options, name) { + var value = L.Util.queryString(name); + if (typeof value !== 'undefined') options[name] = value; +}; + +L.Util.setBooleanFromQueryString = function (options, name) { + var value = L.Util.queryString(name); + if (typeof value !== 'undefined') options[name] = value == '1' || value == 'true'; +}; +L.Util.setNullableBooleanFromQueryString = function (options, name) { + var value = L.Util.queryString(name); + if (typeof value !== 'undefined') { + if (value === 'null') value = null; + else if (value === '0' || value === 'false') value = false; + else value = true; + options[name] = value; + } +}; +L.Util.escapeHTML = function (s) { + s = s? s.toString() : ''; + return s.replace(/$1'); + r = r.replace(/^## (.*)/gm, '

$1

'); + r = r.replace(/^# (.*)/gm, '

$1

'); + r = r.replace(/^---/gm, '
'); + + // bold, italics + r = r.replace(/\*\*(.*?)\*\*/g, '$1'); + r = r.replace(/\*(.*?)\*/g, '$1'); + + // unordered lists + r = r.replace(/^\*\* (.*)/gm, '
    • $1
'); + r = r.replace(/^\* (.*)/gm, '
  • $1
'); + for (ii = 0; ii < 3; ii++) r = r.replace(new RegExp('' + newline + '