From e729dbf3ca79ade20a82679e8bf0565ce524fd77 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:26:28 +0100 Subject: [PATCH 1/5] Add social account login capability (#994) (#995) * Add settings and urls * Login template * Update requirements.txt * Add setting fo socialaccount * Add pre_social_login signal receiver * Fix connect user socialaccount * Update base settings * Update settings * Management fo role and backend of user logged by socialaccount * Update requirements.txt * Typo * Add ACCOUNT_EMAIL_VERIFICATION = 'none' * Change login backend order --------- Co-authored-by: wlorenzetti (cherry picked from commit d62c1419dfd6656e16b11d5648815bc49eeb06e5) Co-authored-by: Walter Lorenzetti --- g3w-admin/base/settings/base.py | 40 +++++++---- .../base/settings/local_settings_example.py | 4 ++ g3w-admin/base/urls.py | 3 + g3w-admin/templates/login.html | 72 ++++++++++--------- g3w-admin/usersmanage/receivers.py | 2 + .../socialaccount/provider_list.html | 22 ++++++ g3w-admin/usersmanage/vendors/__init__.py | 0 .../usersmanage/vendors/allauth/__init__.py | 0 .../usersmanage/vendors/allauth/adapter.py | 58 +++++++++++++++ requirements.txt | 6 +- 10 files changed, 159 insertions(+), 48 deletions(-) create mode 100644 g3w-admin/usersmanage/templates/socialaccount/provider_list.html create mode 100644 g3w-admin/usersmanage/vendors/__init__.py create mode 100644 g3w-admin/usersmanage/vendors/allauth/__init__.py create mode 100644 g3w-admin/usersmanage/vendors/allauth/adapter.py diff --git a/g3w-admin/base/settings/base.py b/g3w-admin/base/settings/base.py index 9b42c437e..fcf39d36d 100644 --- a/g3w-admin/base/settings/base.py +++ b/g3w-admin/base/settings/base.py @@ -48,7 +48,7 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.gis', - #'django.contrib.sites', + 'django.contrib.sites', ] THIRD_PARTY_APPS = [ @@ -75,7 +75,13 @@ 'about', 'django_bleach', 'django_registration', - 'captcha' + 'captcha', + "allauth", + "allauth.account", + "allauth.socialaccount", + "allauth.socialaccount.providers.microsoft", + "allauth.socialaccount.providers.google", + "allauth.usersessions" ] G3WADMIN_APPS = [ @@ -104,6 +110,10 @@ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', 'qdjango.process_events_middleware.process_events_middleware', + + # Allauth middleware + 'allauth.account.middleware.AccountMiddleware', + 'allauth.usersessions.middleware.UserSessionsMiddleware' ] @@ -127,10 +137,6 @@ 'loaders': [ 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader' - #('django.template.loaders.cached.Loader', [ - # 'django.template.loaders.filesystem.Loader', - # 'django.template.loaders.app_directories.Loader' - #]), ], }, }, @@ -142,7 +148,6 @@ ATOMIC_REQUESTS = True # Password validation -# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -162,6 +167,7 @@ AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', 'guardian.backends.ObjectPermissionBackend', + 'allauth.account.auth_backends.AuthenticationBackend' ) GUARDIAN_RAISE_403 = True @@ -241,8 +247,6 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.9/howto/static-files/ - STATIC_URL = '/static/' SITE_TITLE = 'g3w-admin' @@ -252,7 +256,7 @@ QDJANGO_PRJ_CACHE = True QDJANGO_PRJ_CACHE_KEY = 'qdjango_prj_' -# data for proxy server +# Data for proxy server PROXY_SERVER = False # LOGGING_CONFIG = None @@ -303,7 +307,6 @@ SITE_ID = 1 - INTERNAL_IPS = [ '127.0.0.1', ] @@ -344,7 +347,6 @@ # QPLOTLY DEFAULT SETTINGS # ------------------------ - LOAD_QPLOTLY_FROM_PROJECT = False # VENDOR KEYS SETTINGS @@ -387,4 +389,16 @@ # Settings for ReCaptcha v2. Default checkbox RECAPTCHA_VERSION2_TYPE = 'checkbox' # or 'invisible' -SILENCED_SYSTEM_CHECKS = ['captcha.recaptcha_test_key_error'] \ No newline at end of file +SILENCED_SYSTEM_CHECKS = ['captcha.recaptcha_test_key_error'] + +# SOCIAL ACCOUNT LOGIN SETTINGS +# ----------------------------- +SOCIALACCOUNT_LOGIN_ON_GET = True +SOCIALACCOUNT_ADAPTER = 'usersmanage.vendors.allauth.adapter.G3WSocialAccountAdapter' + +# Activate/deactivate user login session tracking +USERSESSIONS_TRACK_ACTIVITY = False + +SOCIALACCOUNT_ONLY = True +SOCIALACCOUNT_USER_ROLE = 'Viewer Level 1' +ACCOUNT_EMAIL_VERIFICATION = 'none' \ No newline at end of file diff --git a/g3w-admin/base/settings/local_settings_example.py b/g3w-admin/base/settings/local_settings_example.py index c4589d510..4b124f9b3 100644 --- a/g3w-admin/base/settings/local_settings_example.py +++ b/g3w-admin/base/settings/local_settings_example.py @@ -163,3 +163,7 @@ 'worker_type': 'process', }, } + +# For social login +# Activate/deactivate user login session tracking +USERSESSIONS_TRACK_ACTIVITY = False \ No newline at end of file diff --git a/g3w-admin/base/urls.py b/g3w-admin/base/urls.py index 4bea8cf2c..541c84fba 100644 --- a/g3w-admin/base/urls.py +++ b/g3w-admin/base/urls.py @@ -168,8 +168,11 @@ ), name="django_registration_disallowed", ), + path('allauthg/', include('allauth.urls')), ] + + ############################################################# # PASSWORD RESET (user password reset by email) # USERNAME RECOVERY (username recovery by email) diff --git a/g3w-admin/templates/login.html b/g3w-admin/templates/login.html index f66ccc7de..78c0fc87f 100644 --- a/g3w-admin/templates/login.html +++ b/g3w-admin/templates/login.html @@ -1,4 +1,5 @@ {% extends "base_login.html" %} +{% load socialaccount %} {% load static %} {% load i18n %} @@ -22,42 +23,47 @@

{% trans 'LOGIN ERROR' %}!

{% trans 'Username and/or password uncorrect' %} {% endif %} -
- {% csrf_token %} -
- - -
-
- - -
-
{{ form.captcha }}
-
-
- -
-
- {% if SETTINGS.RESET_USER_PASSWORD %} -
-
- {% trans 'Forgot your password?' %} + + {% csrf_token %} +
+ +
-
-
- - {% endif %} - {% if SETTINGS.REGISTRATION_OPEN %} -
-
- {% trans 'Sign up' %} +
{{ form.captcha }}
+
+
+ +
-
- {% endif %} - + +
+ {% include "socialaccount/provider_list.html" with process="login" %} +
+ + {% if SETTINGS.RESET_USER_PASSWORD %} + + + {% endif %} + {% if SETTINGS.REGISTRATION_OPEN %} + + {% endif %} +
{% include 'include/login_page_version.html' %}
diff --git a/g3w-admin/usersmanage/receivers.py b/g3w-admin/usersmanage/receivers.py index a07ffc399..b528716c3 100644 --- a/g3w-admin/usersmanage/receivers.py +++ b/g3w-admin/usersmanage/receivers.py @@ -104,3 +104,5 @@ def send_email_to_user(sender, **kwargs): ) user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL, fail_silently=True) + + diff --git a/g3w-admin/usersmanage/templates/socialaccount/provider_list.html b/g3w-admin/usersmanage/templates/socialaccount/provider_list.html new file mode 100644 index 000000000..b3b60307a --- /dev/null +++ b/g3w-admin/usersmanage/templates/socialaccount/provider_list.html @@ -0,0 +1,22 @@ +{% load allauth socialaccount %} +{% load i18n %} +{% get_providers as socialaccount_providers %} +{% if socialaccount_providers %} +
+

- {% trans 'OR' %} -

+
+ {% for provider in socialaccount_providers %} + {% if provider.id == "openid" %} + {% for brand in provider.get_brands %} + {% provider_login_url provider openid=brand.openid_url process=process as href %} + {% element provider name=brand.name provider_id=provider.id href=href %} + {% endelement %} + {% endfor %} + {% endif %} + {% provider_login_url provider process=process scope=scope auth_params=auth_params as href %} + + {% endfor %} +
+{% endif %} diff --git a/g3w-admin/usersmanage/vendors/__init__.py b/g3w-admin/usersmanage/vendors/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/g3w-admin/usersmanage/vendors/allauth/__init__.py b/g3w-admin/usersmanage/vendors/allauth/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/g3w-admin/usersmanage/vendors/allauth/adapter.py b/g3w-admin/usersmanage/vendors/allauth/adapter.py new file mode 100644 index 000000000..343d169e6 --- /dev/null +++ b/g3w-admin/usersmanage/vendors/allauth/adapter.py @@ -0,0 +1,58 @@ +# coding=utf-8 +"""" +.. note:: This program is free software; you can redistribute it and/or modify + it under the terms of the Mozilla Public License 2.0. + +""" + +__author__ = 'lorenzetti@gis3w.it' +__date__ = '2024-12-17' +__copyright__ = 'Copyright 2015 - 2024, Gis3w' +__license__ = 'MPL 2.0' + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from allauth.socialaccount.adapter import DefaultSocialAccountAdapter +from allauth.account.models import EmailAddress +from usersmanage.models import User, Group as AuthGroup, Userbackend, USER_BACKEND_DEFAULT +from usersmanage.configs import G3W_EDITOR1, G3W_EDITOR2, G3W_VIEWER1 + +class G3WSocialAccountAdapter(DefaultSocialAccountAdapter): + + def _set_user_role_backend(self, user): + """ + Set the role and the backend for the user login by social + """ + + # Role to se from settings + role = settings.SOCIALACCOUNT_USER_ROLE \ + if settings.SOCIALACCOUNT_USER_ROLE in (G3W_EDITOR1, G3W_EDITOR2, G3W_VIEWER1) else G3W_VIEWER1 + + AuthGroup.objects.get(name=role).user_set.add(user) + + # Backend + if not hasattr(user, 'userbackend'): + Userbackend(user=user, backend=USER_BACKEND_DEFAULT).save() + + def pre_social_login(self, request, sociallogin): + + # Social account already exists, so this is just a login + if sociallogin.is_existing: + return + + # some social logins don't have an email address + if not sociallogin.email_addresses: + return + try: + existing_user = User.objects.get(email=sociallogin.email_addresses[0].email) + self._set_user_role_backend(existing_user) + except ObjectDoesNotExist: + return + + # if it does, connect this new social login to the existing user + sociallogin.connect(request, existing_user) + + def save_user(self, request, sociallogin, form=None): + user = super(G3WSocialAccountAdapter, self).save_user(request, sociallogin, form=form) + self._set_user_role_backend(user) + return user \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2ab928343..66015f121 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ django-ordered-model==3.3.0 django-ajax-selects==2.2.0 django-modeltranslation==0.17.5 django-filter -django-bleach +django-bleach==3.0.1 pathlib2 lxml psycopg2-binary @@ -30,7 +30,7 @@ django-import-export==3.2.0 coverage urllib3 python-magic -celery==4.4.7 +celery #==5.0.2 deprecation huey==2.4.3 redis==4.5.4 @@ -40,3 +40,5 @@ django-recaptcha==3.0.0 pydantic==2.6.3 weasyprint==63.0 distro==1.7.0 +django-allauth[socialaccount]==0.63.6 + From da83083a8d5dde40f608c16e8d6197ffe69c91b0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:03:24 +0100 Subject: [PATCH 2/5] Fix PyQt object translate (#997) (#998) Co-authored-by: wlorenzetti (cherry picked from commit a03b7c0ec725440289d6b5c3d7ce1540d01625cc) Co-authored-by: Walter Lorenzetti --- g3w-admin/qplotly/utils/qplotly_factory.py | 28 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/g3w-admin/qplotly/utils/qplotly_factory.py b/g3w-admin/qplotly/utils/qplotly_factory.py index 6ba862235..971433ecf 100644 --- a/g3w-admin/qplotly/utils/qplotly_factory.py +++ b/g3w-admin/qplotly/utils/qplotly_factory.py @@ -44,6 +44,12 @@ GeoConstraintsFilter, ) +from qgis.PyQt.QtCore import ( + QDate, + QDateTime, + QTime +) + class QplotlyFactoring(PlotFactory): @@ -92,6 +98,22 @@ def build_layout(self): self.layout = self._build_layout() + def _pyqt2py(self, value): + """ + Check if the value is a PyQT object and translate it in native python object + """ + + tp = type(value) + if tp in (QDate, QDateTime, QTime): + if tp == QDate: + value = value.toPyDate() + if tp == QDateTime: + value = value.toPyDateTime() + if tp == QTime: + value = value.toPyTime() + + return value + def fetch_values_from_layer(self): """ (Re)fetches plot values from the source layer. @@ -238,7 +260,7 @@ def add_source_field_or_expression(field_or_expression): if x == NULL or x is None: continue elif self.settings.properties['x_name']: - x = f[self.settings.properties['x_name']] + x = self._pyqt2py(f[self.settings.properties['x_name']]) if x == NULL or x is None: continue @@ -248,7 +270,7 @@ def add_source_field_or_expression(field_or_expression): if y == NULL or y is None: continue elif self.settings.properties['y_name']: - y = f[self.settings.properties['y_name']] + y = self._pyqt2py(f[self.settings.properties['y_name']]) if y == NULL or y is None: continue @@ -258,7 +280,7 @@ def add_source_field_or_expression(field_or_expression): if z == NULL or z is None: continue elif self.settings.properties['z_name']: - z = f[self.settings.properties['z_name']] + z = self._pyqt2py(f[self.settings.properties['z_name']]) if z == NULL or z is None: continue From d7c4904e37bea416d7b0c4e76e6cf86d6ac4d627 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 08:56:23 +0100 Subject: [PATCH 3/5] Add management for setting SOCIALACCOUNT_USER_GROUP (#1001) (#1002) Co-authored-by: wlorenzetti (cherry picked from commit a38eabd16f56091cf8835804325219bcc0b94d7f) Co-authored-by: Walter Lorenzetti --- .../usersmanage/vendors/allauth/adapter.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/g3w-admin/usersmanage/vendors/allauth/adapter.py b/g3w-admin/usersmanage/vendors/allauth/adapter.py index 343d169e6..241159225 100644 --- a/g3w-admin/usersmanage/vendors/allauth/adapter.py +++ b/g3w-admin/usersmanage/vendors/allauth/adapter.py @@ -17,11 +17,16 @@ from usersmanage.models import User, Group as AuthGroup, Userbackend, USER_BACKEND_DEFAULT from usersmanage.configs import G3W_EDITOR1, G3W_EDITOR2, G3W_VIEWER1 +import logging + +logging = logging.getLogger('g3wadmin.debug') + class G3WSocialAccountAdapter(DefaultSocialAccountAdapter): def _set_user_role_backend(self, user): """ Set the role and the backend for the user login by social + Set up alse the group of user if the settings is set """ # Role to se from settings @@ -34,6 +39,22 @@ def _set_user_role_backend(self, user): if not hasattr(user, 'userbackend'): Userbackend(user=user, backend=USER_BACKEND_DEFAULT).save() + # Add User group if is set + if hasattr(settings, 'SOCIALACCOUNT_USER_GROUP'): + try: + ugroup = AuthGroup.objects.get(name=settings.SOCIALACCOUNT_USER_GROUP) + + # Test user role group compatibility + if role in (G3W_VIEWER1, ) and ugroup.grouprole.role != 'viewer': + raise Exception(f"User role {G3W_VIEWER1} not compatible with user group {ugroup}") + + # Assign user to group + ugroup.user_set.add(user) + except Exception as e: + logging.error("[SOCIAL AUTH] Error setting user group: {}".format(e)) + + + def pre_social_login(self, request, sociallogin): # Social account already exists, so this is just a login From 5c0de56b21699ff575f229accd49f317fb056be9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:51:01 +0100 Subject: [PATCH 4/5] Fix media update (#1000) (#1003) * Fix media update * Try to restore the correct media path --------- Co-authored-by: wlorenzetti (cherry picked from commit 4af4f36a970a504fbe68b8af3dbc12e4b0775f5e) Co-authored-by: Walter Lorenzetti --- g3w-admin/core/utils/vector.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/g3w-admin/core/utils/vector.py b/g3w-admin/core/utils/vector.py index 2d6a02318..44cc340b6 100644 --- a/g3w-admin/core/utils/vector.py +++ b/g3w-admin/core/utils/vector.py @@ -89,6 +89,15 @@ def get_domain(self): else: return '{}://{}'.format(schema, self.request.get_host()) + def _new_path(self, file_name): + """ Build new path to save media file """ + + return reverse('user-media', kwargs={ + 'project_type': self.type, + 'layer_id': self.layer.pk, + 'file_name': file_name + }) + def new_value(self, change=False): """ Build and save media value from client """ @@ -162,11 +171,17 @@ def new_value(self, change=False): # build new value self.feature_properties[field] = '{}{}'.format(self.get_domain(), - reverse('user-media', kwargs={ - 'project_type': self.type, - 'layer_id': self.layer.pk, - 'file_name': file_name - })) + self._new_path(file_name)) + else: + if is_media_view: + + value = current_field_value + # Try to fix old record saved with temp_uploads path + if os.path.exists(path_file_to_save): + value = self._new_path(file_name) + + # Restore to current_feature value + self.feature_properties[field] = value if delete_old: to_delete = '{}/{}'.format(path_to_save, current_file_name) From cc5154f3fa95c4822b55607c3a25d609afd8cab6 Mon Sep 17 00:00:00 2001 From: Francesco Boccacci Date: Mon, 23 Dec 2024 15:30:05 +0100 Subject: [PATCH 5/5] :arrow_up: Client v3.10.7 (#993) * :arrow_up: Client https://github.com/g3w-suite/g3w-client/pull/695 * :arrow_up: Client https://github.com/g3w-suite/g3w-client/pull/695/commits/e8d2b911bdf66c7c666df8a74c4f0cb024480d1f * :arrow_up: Client https://github.com/g3w-suite/g3w-client/releases/tag/v3.10.7 --------- Co-authored-by: Walter Lorenzetti --- README.md | 2 +- g3w-admin/client/static/client/js/app.min.js | 2 +- g3w-admin/client/static/client/js/app.min.js.map | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 943184fbe..9ff930042 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Software releases follow theese main branches as described in the compatibility | Branch | Python | Django | QGIS | [client] | First release | Status | |------------|----------------|----------------|---------------|--------------|---------------|----------------| | [dev] | 3.10 | 3.2 | 3.34 | dev | Unreleased | ⚠️️ Unstable | -| [v.3.8.x] | 3.10 | 3.2 | 3.34 | 3.10.6 | Dec 2024 | 🪲️ Bug fixing | +| [v.3.8.x] | 3.10 | 3.2 | 3.34 | 3.10.7 | Dec 2024 | 🪲️ Bug fixing | | [v.3.7.x] | 3.10 | 3.2 | 3.34 | 3.9.6 | Dec 2023 | 🪲️ Bug fixing | | [v.3.6.x] | 3.10 | 3.2 | 3.28 | 3.8.15 | May 2023 | 🚨 End of Life | | [v.3.5.x] | 3.10 | 2.2 | 3.22 | 3.7 | Nov 2022 | 🚨 End of Life | diff --git a/g3w-admin/client/static/client/js/app.min.js b/g3w-admin/client/static/client/js/app.min.js index 2a824caae..9759fc535 100644 --- a/g3w-admin/client/static/client/js/app.min.js +++ b/g3w-admin/client/static/client/js/app.min.js @@ -1,2 +1,2 @@ -!function r(i,a,o){function s(t,e){if(!a[t]){if(!i[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}n=a[t]={exports:{}},i[t][0].call(n.exports,function(e){return s(i[t][1][e]||e)},n,n.exports,r,i,a,o)}return a[t].exports}for(var l="function"==typeof require&&require,e=0;e=",lte:"<=",NOT:"!=",eq:"=",gt:">",lt:"<",IN:"IN",LIKE:"LIKE",ILIKE:"ILIKE",AND:"AND",OR:"OR"}),r=n.FILTER_EXPRESSION_OPERATORS=r({lte:"<=",ltgt:"!=",ilike:"ILIKE",like:"LIKE"},o),s=n.GEOMETRY_FIELDS=["geometryProperty","boundedBy","geom","the_geom","geometry","bbox","GEOMETRY","geoemtria","geometria"],l=n.GEOMETRY_TYPES={POINT:"Point",POINTZ:"PointZ",POINTM:"PointM",POINTZM:"PointZM",POINT25D:"Point25D",MULTIPOINT:"MultiPoint",MULTIPOINTZ:"MultiPointZ",MULTIPOINTM:"MutliPointM",MULTIPOINTZM:"MultiPointZM",MULTIPOINT25D:"MultiPoint25D",LINESTRING:"LineString",LINESTRINGZ:"LineStringZ",LINESTRINGM:"LineStringM",LINESTRINGZM:"LineStringZM",LINESTRING25D:"LineString25D",LINE:"Line",LINEZ:"LineZ",LINEM:"LineM",LINEZM:"LineZM",LINE25D:"Line25D",MULTILINESTRING:"MultiLineString",MULTILINESTRINGZ:"MultiLineStringZ",MULTILINESTRINGM:"MultiLineStringM",MULTILINESTRINGZM:"MultiLineStringZM",MULTILINESTRING25D:"MultiLineString25D",MULTILINE:"MultiLine",MULTILINEZ:"MultiLineZ",MULTILINEM:"MultiLineM",MULTILINEZM:"MultiLineZM",MULTILINE25D:"MultiLine25D",POLYGON:"Polygon",POLYGONZ:"PolygonZ",POLYGONM:"PolygonM",POLYGONZM:"PolygonZM",POLYGON25D:"Polygon25D",MULTIPOLYGON:"MultiPolygon",MULTIPOLYGONZ:"MultiPolygonZ",MULTIPOLYGONM:"MultiPolygonM",MULTIPOLYGONZM:"MultiPolygonZM",MULTIPOLYGON25D:"MultiPolygon25D",GEOMETRYCOLLECTION:"GeometryCollection",GEOMETRYCOLLECTIONZ:"GeometryCollectionZ",GEOMETRYCOLLECTIONM:"GeometryCollectionM",GEOMETRYCOLLECTIONZM:"GeometryCollectionZM",GEOMETRYCOLLECTION25D:"GeometryCollection25D"},u=(n.LIST_OF_RELATIONS_TITLE="info.list_of_relations",n.LIST_OF_RELATIONS_ID="__G3W_LIST_OF_RELATIONS_ID__",n.LOCALSTORAGE_EXTERNALWMS_ITEM="externalwms",n.MAP_SETTINGS={ZOOM:{maxScale:1e3},ANIMATION:{duration:2e3},LAYER_POSITIONS:{default:"top",getPositions:function(){return["top","bottom"]}}}),c=n.PRINT_FORMATS=[{value:"png",label:"PNG"},{value:"jpg",label:"JPG"},{value:"svg",label:"SVG"},{value:"pdf",label:"PDF"},{value:"geopdf",label:"GEOPDF"}],d=n.PRINT_RESOLUTIONS=[150,300],p=n.PRINT_SCALES=[{value:100,label:"1:100"},{value:200,label:"1:200"},{value:500,label:"1:500"},{value:1e3,label:"1:1.000"},{value:2e3,label:"1:2.000"},{value:2500,label:"1:2.500"},{value:5e3,label:"1:5.000"},{value:1e4,label:"1:10.000"},{value:2e4,label:"1:20.000"},{value:25e3,label:"1:25.000"},{value:5e4,label:"1:50.000"},{value:1e5,label:"1:100.000"},{value:25e4,label:"1:250.000"},{value:5e5,label:"1:500.000"},{value:1e6,label:"1:1.000.000"},{value:25e5,label:"1:2.500.000"},{value:5e6,label:"1:5.000.000"},{value:1e7,label:"1:10.000.000"},{value:2e7,label:"1:20.000.000"},{value:5e7,label:"1:50.000.000"},{value:1e8,label:"1:100.000.000"},{value:25e7,label:"1:250.000.000"},{value:5e8,label:"1:500.000.000"}],f=n.QUERY_POINT_TOLERANCE={unit:"pixel",value:10},h=(n.SEARCH_ALLVALUE="__G3W_ALL__",n.SEARCH_RETURN_TYPES=["data","search"]),g=(n.TIMEOUT=6e4,n.TOC_LAYERS_INIT_STATUS="not_collapsed",n.TOC_THEMES_INIT_STATUS="collapsed",n.VIEWPORT={resize:{map:{min:200},content:{min:200}}}),m=n.ZINDEXES={usermessage:{tool:2}},v=n.API_BASE_URLS={ABOUT:{macrogroups:"/about/api/macrogroup/",nomacrogoups:"/about/api/group/nomacrogroup/",projects:"/about/api/group/__G3W_GROUP_ID__/projects/",group:"/about/api/group/"},CRS:"/crs/"},y=n.FONT_AWESOME_ICONS={"change-map":"fas fa-map-signs",map:"far fa-map",file:"fas fa-file-code",marker:"fas fa-map-marker-alt",relation:"fas fa-sitemap",tools:"fas fa-cogs",tool:"fas fa-cog",search:"fas fa-search",print:"fas fa-print",info:"fas fa-info-circle","info-circle":"fas fa-info-circle",globe:"fas fa-globe",mail:"fas fa-envelope",mobile:"fas fa-mobile",fax:"fas fa-fax",user:"fas fa-user",bars:"fas fa-bars",uncheck:"far fa-square",check:"far fa-check-square",checkmark:"fa fa-check",filluncheck:"fas fa-square",table:"fas fa-table",trash:"fas fa-trash","trash-o":"far fa-trash-alt",pencil:"fas fa-pencil-alt","ellips-h":"fas fa-ellipsis-h","ellips-v":"fas fa-ellipsis-v","arrow-up":"fas fa-chevron-up","arrow-down":"fas fa-chevron-down","arrow-left":"fas fa-chevron-left","arrow-right":"fas fa-chevron-right","resize-h":"fas fa-arrows-alt-h","resize-v":"fas fa-arrows-alt-v","resize-default":"fas fa-compress","caret-up":"fas fa-caret-up","caret-down":"fas fa-caret-down","caret-left":"fas fa-caret-left","caret-right":"fas fa-caret-right","empty-circle":"far fa-circle","cloud-upload":"fas fa-cloud-upload-alt",spinner:"fas fa-spinner",minus:"fas fa-minus","minus-square":"far fa-minus-square",plus:"fas fa-plus","plus-circle":"fas fa-plus-circle","plus-square":"far fa-plus-square",grid:"fas fa-th",home:"fas fa-home",folder:"fas fa-folder","sign-out":"fas fa-sign-out-alt",close:"fas fa-times",time:"far fa-clock",calendar:"fas fa-calendar-alt",list:"fas fa-list-alt",link:"fas fa-link",unlink:"fas fa-unlink",eye:"far fa-eye","eye-close":"far fa-eye-slash",save:"far fa-save",pdf:"fas fa-file-pdf",image:"far fa-image",video:"far fa-file-video",unknow:"far fa-question-circle",zip:"far fa-file-archive",text:"far fa-file-alt",excel:"far fa-file-excel",xls:"far fa-file-excel",gpx:"fas fa-location-arrow",gpkg:"fas fa-box-open",shapefile:"fas fa-file-archive",csv:"fas fa-file-csv",geotiff:"fas fa-th",ppt:"far fa-file-powerpoint",circle:"fas fa-circle",calculator:"fas fa-calculator",picture:"far fa-image",keyboard:"far fa-keyboard","file-download":"fas fa-file-download",copy:"far fa-copy",draw:"fas fa-draw-polygon",chart:"fas fa-chart-bar","chart-line":"fas fa-chart-line","chart-area":"fas fa-chart-area","chart-pie":"fas fa-chart-pie",run:"fas fa-play",warning:"fas fa-exclamation-circle",alert:"fas fa-exclamation-triangle",crosshairs:"fas fa-crosshairs",success:"far fa-check-circle",back:"fas fa-chevron-circle-left","file-upload":"fas fa-file-upload",wifi:"fas fa-wifi",mouse:"fas fa-mouse","copy-paste":"far fa-copy","vector-square":"fas fa-vector-square",download:"fas fa-download",credits:"fas fa-euro-sign",filter:"fas fa-filter",plugin:"fas fa-plug",invert:"fas fa-exchange-alt",clear:"fas fa-broom",palette:"fas fa-palette",layers:"fas fa-layer-group","sign-in":"fas fa-sign-in-alt",language:"fas fa-language",target:"fas fa-bullseye",pin:"fas fa-map-pin",square:"far fa-square",move:"fas fa-arrows-alt",moon:"fas fa-moon",sun:"fas fa-sun",refresh:"fas fa-sync-alt",pause:"fas fa-pause","step-backward":"fas fa-step-backward","fast-backward":"fas fa-fast-backward","step-forward":"fas fa-step-forward","fast-forward":"fas fa-fast-forward",crop:"fas fa-crop-alt",exit:"fas fa-door-open",slider:"fas fa-sliders-h",bookmark:"fas fa-bookmark",reply:"fas fa-reply",share:"fas fa-share","share-alt":"fa fa-share-alt","external-link":"fa fa-external-link-alt"},_=n.LOCAL_ITEM_IDS={MESSAGES:{id:"MESSAGES",value:{}},SPATIALBOOKMARKS:{id:"SPATIALBOOKMARKS",value:{}}},b=(n.LOGO_GIS3W="images/logo_gis3w_156_85.png",n.SPATIAL_METHODS=["intersects","within"]),w=(n.DOTS_PER_INCH=96,n.INCHES_PER_UNIT={m:39.37,degrees:4374754});n.default={APP_VERSION:e,API_BASE_URLS:v,DEFAULT_EDITING_CAPABILITIES:i,DOTS_PER_INCH:96,DOWNLOAD_FORMATS:a,FILTER_OPERATORS:o,FILTER_EXPRESSION_OPERATORS:r,FONT_AWESOME_ICONS:y,G3W_FID:"g3w_fid",GEOMETRY_FIELDS:s,GEOMETRY_TYPES:l,INCHES_PER_UNIT:w,LIST_OF_RELATIONS_TITLE:"info.list_of_relations",LIST_OF_RELATIONS_ID:"__G3W_LIST_OF_RELATIONS_ID__",LOCAL_ITEM_IDS:_,LOCALSTORAGE_EXTERNALWMS_ITEM:"externalwms",LOGO_GIS3W:"images/logo_gis3w_156_85.png",MAP_SETTINGS:u,PRINT_FORMATS:c,PRINT_RESOLUTIONS:d,PRINT_SCALES:p,QUERY_POINT_TOLERANCE:f,SEARCH_ALLVALUE:"__G3W_ALL__",SEARCH_RETURN_TYPES:h,SPATIAL_METHODS:b,TIMEOUT:6e4,TOC_LAYERS_INIT_STATUS:"not_collapsed",TOC_THEMES_INIT_STATUS:"collapsed",VIEWPORT:g,ZINDEXES:m}},{"../version":454}],6:[function(e,t,n){function r(){this._error=(0"+t+"
"):$(t):t,$(this._parent).append(n),o.push({content:n,options:e}),a.resolve()):t.mount&&"function"==typeof t.mount?(-1!==(r=o.findIndex(function(e){return e.content.getId&&e.content.getId()===t.getId()}))&&o[r].content.unmount().then(function(){return o.splice(r,1)}),t.mount(this._parent,e.append||!1).then(function(){$(i._parent).localize(),o.push({content:t,options:e}),a.resolve(t)})):(this._parent.appendChild(t),o.push({content:t,options:e}),a.resolve()),a.promise()}},{key:"_unmount",value:function(e){var t=$.Deferred();return e instanceof o.default||e instanceof a.default?e.unmount().then(function(){return t.resolve()}):($(this._parent).empty(),t.resolve()),t.promise()}},{key:"forEach",value:function(t){this.state.contentsdata.forEach(function(e){return t(e.content)})}},{key:"getLength",value:function(){return this.state.contentsdata.length}},{key:"getComponentById",value:function(t){return(this.getContentData().find(function(e){return e.content.id==t})||{}).content}}]),n}(e.default)},{"core/g3w-component":8,"core/g3w-panel":10,"core/g3wobject":11}],8:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var i=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e)){var n=t,r=[],i=!0,t=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(i=(o=s.next()).done)&&(r.push(o.value),!n||r.length!==n);i=!0);}catch(e){t=!0,a=e}finally{try{!i&&s.return&&s.return()}finally{if(t)throw a}}return r}throw new TypeError("Invalid attempt to destructure non-iterable instance")},r=function(e,t,n){return t&&a(e.prototype,t),n&&a(e,n),e};function a(e,t){for(var n=0;n=this.state.maxscale&&e<=this.state.minscale)},e.getStyles=function(){return(this.config.source.external?this.config.source:this.config).styles},e.getStyle=function(){return this.config.source.external?this.config.source.styles:this.config.styles?this.config.styles.find(function(e){return e.current}).name:""},e.getOpacity=function(){return this.state.opacity},e.setCurrentStyle=function(t){var n=!1;return this.config.styles.forEach(function(e){e.name===t&&(n=!e.current),e.current=e.name===t}),n},e.getCurrentStyle=function(){return this.config.styles.find(function(e){return e.current})},e.setDisabled=function(e){if(this.state.scalebasedvisibility){for(var e=(0,o.getScaleFromResolution)(e,1=this.state.maxscale&&e<=this.state.minscale),this.state.disabled=0===this.state.minscale?!(e>=this.state.maxscale):this.state.disabled,!0),n=this.state.parentGroup;n;)t=t&&n.checked,n=n.parentGroup;t&&this.setVisible(!this.state.disabled),this.isFilterable()&&this.setTocHighlightable(!this.state.disabled)}else this.state.disabled=!1},e.getMultiLayerId=function(){return this.config.multilayerid},e.getGeometryType=function(){return this.config.geometrytype},e.getOwsMethod=function(){return this.config.ows_method},e.setProjection=function(){this.config.projection=l.get(0t&&(e=$(this).position().left,n>$(this).outerWidth()&&(t+=n-$(this).outerWidth()),$(this).css("left",t+"px"),t=e,n=$(this).outerWidth())}),$(this.element).hide()},e.setEnable=function(e){$(this.element).find("button").first().toggleClass("g3w-ol-disabled",!e),!e&&this._interaction&&this._interaction.setActive(!1),this._enabled=e},e.getEnable=function(){return this._enabled},e.setVisible=function(){var e=!(0\n \n ',watch:{method:function(e){return t.setSpatialMethod(e)}},created:function(){o.default.setCloseUserMessageBeforeSetContent(!1)},beforeDestroy:function(){o.default.setCloseUserMessageBeforeSetContent(!0)}};break;case"custom":this.toggledTool=r}"hover"===e&&this._createToolOnHoverButton()},e._createToolOnHoverButton=function(){var t=this;this._onhover&&(this._toolButton=$(''),$(this.element).prepend(this._toolButton),this._toolButton.on("click",function(e){e.stopPropagation(),t.showToggledTool(!0)}),$(this.element).hover(function(){return t._toggled&&t._toolButton.show()}),$(this.element).mouseleave(function(){return t._toolButton.hide()}))},e.showToggledTool=function(){!(0