diff --git a/combo_plugin_gnm/__init__.py b/combo_plugin_gnm/__init__.py
index bee5ea9..4524f52 100644
--- a/combo_plugin_gnm/__init__.py
+++ b/combo_plugin_gnm/__init__.py
@@ -27,9 +27,6 @@ class AppConfig(django.apps.AppConfig):
name = __name__
verbose_name = _('GNM Extension')
- def ready(self):
- from . import signals
-
def get_before_urls(self):
from . import urls
return urls.urlpatterns
diff --git a/combo_plugin_gnm/signals.py b/combo_plugin_gnm/signals.py
deleted file mode 100644
index 40e5c02..0000000
--- a/combo_plugin_gnm/signals.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-# combo-plugin-gnm - Combo GNM plugin
-# Copyright (C) 2017-2019 Entr'ouvert
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Affero General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from django.db.models.signals import post_save
-from django.dispatch import receiver
-
-from combo.middleware import get_request
-from combo.profile.models import Profile
-
-@receiver(post_save, sender=Profile)
-def new_profile(sender, instance=None, created=False, **kwargs):
- if not created:
- return
- request = get_request()
- saml_info = request.session.get('mellon_session', {})
- if False:
- # if profile has an address push it to the favourite places datastore
- saml_info['address'][0]
-
- # fill dashboard with suggestions
diff --git a/combo_plugin_gnm/templatetags/gnm.py b/combo_plugin_gnm/templatetags/gnm.py
index 7e363ee..14af88c 100644
--- a/combo_plugin_gnm/templatetags/gnm.py
+++ b/combo_plugin_gnm/templatetags/gnm.py
@@ -24,6 +24,7 @@ import random
import re
from dateutil.parser import parse as dateutil_parse
+from pyproj import Geod
from requests import RequestException
from django import template
@@ -37,7 +38,7 @@ from django.utils.text import slugify
from django.utils.timezone import is_naive, make_aware
from django.utils.safestring import mark_safe
-from combo.apps.dashboard.models import DashboardCell
+from combo.apps.dashboard.models import DashboardCell, Tile
from combo.apps.maps.models import Map, MapLayer
from combo.data.models import Page, CellBase, ConfigJsonCell
from combo.public.views import render_cell
@@ -509,8 +510,29 @@ def as_commune(user_data):
@register.assignment_tag
-def get_suggestions(request, cell, user_data, places_data):
- tile_data = []
+def get_suggestions(request, user_data, places_data):
+ # fill initial dashboard based on this layout:
+ ## au quotidien
+ # mairie tile
+ # closest velov/tcl/swimming pool/etc. tiles
+ ## environnement
+ # air quality
+ # pollen
+
+ if not getattr(request, 'user', None) or not request.user.is_authenticated():
+ # no user
+ return ['no user']
+
+ dashboard = DashboardCell.objects.all().filter(page__snapshot__isnull=True)[0]
+ if Tile.objects.filter(dashboard=dashboard, user=request.user).exists():
+ # dashboard already filled
+ return ['already filled']
+
+ mairie_tile = None
+ service_tiles = []
+ airquality_tile = {'key': 'airquality', 'parameters': settings.COMBO_MAP_DEFAULT_POSITION}
+ pollen_tile = {'key': 'pollen'}
+
addresses = []
city = user_data.get('city') or user_data.get('address_city')
if city:
@@ -528,42 +550,38 @@ def get_suggestions(request, cell, user_data, places_data):
if 'Annexe' in feature['properties']['nom']:
continue
if city_slug in slugify(feature['properties']['nom']):
- tile_data.append({'key': maplayer.slug,
- 'properties': feature['properties']})
+ mairie_tile = {'key': maplayer.slug, 'properties': feature['properties']}
break
- if random.random() < 0.3:
- tile_data.append({'key': 'airquality'})
- if random.random() < 0.1:
- tile_data.append({'key': 'pollen'})
-
- if user_data.get('address_street'):
+ address = None
+ if places_data and places_data.get('data'):
+ place_data = places_data['data'][0]
+ address = u'%(adresse)s, %(ville)s, France' % place_data['content']
+ elif user_data.get('address_street'):
if not user_data.get('address_number'):
user_data['address_number'] = ''
- addresses.append(u'%(address_number)s %(address_street)s, %(address_city)s, France' % user_data)
+ address = u'%(address_number)s %(address_street)s, %(address_city)s, France' % user_data
- if places_data:
- for place_data in places_data.get('data'):
- addresses.append(u'%(adresse)s, %(ville)s, France' % place_data['content'])
-
- coords = []
- nominatim_url = 'https://nominatim.entrouvert.org'
- for address in addresses:
+ coords = None
+ if address:
+ nominatim_url = settings.COMBO_GEOCODING_SERVICE
url = '%s/search?q=%s&accept-language=fr&format=json' % (
nominatim_url, quote(address.encode('utf-8')))
try:
search_result = requests.get(url, timeout=2, without_user=True,
cache_duration=300).json()
except RequestException:
- continue
- if not search_result:
- continue
- coords.append({'lon': search_result[0]['lon'], 'lat': search_result[0]['lat']})
+ pass
+ if search_result:
+ coords = {'lon': search_result[0]['lon'], 'lat': search_result[0]['lat']}
- for coord in coords:
- lat1, lat2 = float(coord['lat']) - 0.008, float(coord['lat']) + 0.008
- lon1, lon2 = float(coord['lon']) - 0.006, float(coord['lon']) + 0.006
- for maplayer in MapLayer.objects.filter(slug__in=('velov', 'piscine', 'tcl')):
+ if coords:
+ airquality_tile = {'key': 'airquality', 'parameters': coords}
+
+ lat1, lat2 = float(coords['lat']) - 0.008, float(coords['lat']) + 0.008
+ lon1, lon2 = float(coords['lon']) - 0.006, float(coords['lon']) + 0.006
+ geod = Geod(ellps='WGS84')
+ for maplayer in MapLayer.objects.filter(slug__in=('velov', 'piscine', 'tcl', 'bibliotheque', 'mdr')):
url = maplayer.geojson_url + '&BBOX=%s,%s,%s,%s' % (lat1, lon1, lat2, lon2)
try:
data_result = requests.get(url, timeout=2, without_user=True,
@@ -574,34 +592,54 @@ def get_suggestions(request, cell, user_data, places_data):
if not features:
continue
for feature in features:
- # thanks to the flat earth society
- feature['distance'] = math.sqrt(
- (float(coord['lon']) - feature['geometry']['coordinates'][0])**2 +
- (float(coord['lat']) - feature['geometry']['coordinates'][1])**2)
+ feature['distance'] = geod.inv(
+ float(coords['lon']),
+ float(coords['lat']),
+ float(feature['geometry']['coordinates'][0]),
+ float(feature['geometry']['coordinates'][1]))[2]
features.sort(key=lambda x: x['distance'])
- # take two closest features
- for feature in features[:2]:
- tile_data.append({'key': maplayer.slug, 'properties': feature['properties']})
+ # take closest feature
+ if features:
+ service_tiles.append({'key': maplayer.slug, 'properties': features[0]['properties']})
- dashboard = DashboardCell.objects.all()[0]
- cells = []
- seen = {}
- for data in tile_data:
- cell = ConfigJsonCell(key=data['key'], order=1,
- page_id=cell.page_id, placeholder='_auto_tile')
- cell_form_keys = [x['varname'] for x in settings.JSON_CELL_TYPES[cell.key].get('form') or {}]
- cell.parameters = {}
- for key in cell_form_keys:
- cell.parameters[key] = data['properties'].get(key)
- cell_uid = repr((data['key'], cell.parameters))
- if cell_uid in seen:
- continue
- seen[cell_uid] = True
+ tiles = []
+ if mairie_tile or service_tiles:
+ tiles.append({'key': 'group-title', 'parameters': {'text': 'Au quotidien'}})
+ if mairie_tile:
+ tiles.append(mairie_tile)
+ if service_tiles:
+ random.shuffle(service_tiles)
+ tiles.extend(service_tiles)
+
+ if airquality_tile or pollen_tile:
+ tiles.append({'key': 'group-title', 'parameters': {'text': 'Environnement'}})
+ if airquality_tile:
+ tiles.append(airquality_tile)
+ if pollen_tile:
+ tiles.append(pollen_tile)
+
+ for i, tile_data in enumerate(tiles):
+ if 'properties' in tile_data:
+ cell_form_keys = [x['varname'] for x in settings.JSON_CELL_TYPES[tile_data['key']].get('form') or {}]
+ tile_data['parameters'] = {}
+ for key in cell_form_keys:
+ tile_data['parameters'][key] = tile_data['properties'].get(key)
+
+ cell = ConfigJsonCell(
+ key=tile_data['key'],
+ parameters=tile_data.get('parameters', {}),
+ order=0,
+ page_id=dashboard.page_id,
+ placeholder='_suggested_tile')
cell.save()
- cells.append(render_cell(request, cell=cell).content)
+ tile = Tile(
+ dashboard=dashboard,
+ cell=cell,
+ user=request.user,
+ order=i+1)
+ tile.save()
- random.shuffle(cells)
- return cells[:5]
+ return tiles
@register.assignment_tag
def get_gnm_portal_url():
diff --git a/debian/50gnm.py b/debian/50gnm.py
index 0738ce2..26aa57a 100644
--- a/debian/50gnm.py
+++ b/debian/50gnm.py
@@ -8,6 +8,7 @@ MELLON_ADD_AUTHNREQUEST_NEXT_URL_EXTENSION = True
COMBO_MAP_TILE_URLTEMPLATE = "https://tiles.entrouvert.org/hdm/{z}/{x}/{y}.png"
COMBO_MAP_ATTRIBUTION = "© OpenStreetMap"
+COMBO_GEOCODING_SERVICE = 'https://nominatim.entrouvert.org'
COMBO_DASHBOARD_ENABLED = True
COMBO_DASHBOARD_NEW_TILE_POSITION = 'first'
@@ -248,6 +249,12 @@ JSON_CELL_TYPES = {
"name": u"Lieux favoris",
"force_async": False,
"cache_duration": 600,
+ "additional-data": [
+ {
+ "key": "userdata",
+ "url": "[idp_url]api/users/[user_nameid]/"
+ }
+ ],
"actions": {
"create": {
"url": "[passerelle_url]jsondatastore/lieux-favoris/data/create?name_id=[user_nameid]"
@@ -314,7 +321,8 @@ JSON_CELL_TYPES = {
"suggestions": {
"name": "Suggestions",
"url": "[idp_url]api/users/[user_nameid]/",
- "loading-message": "Recherche de suggestions…",
+ "force_async": True,
+ "loading-message": "Assemblage en cours, quelques secondes…",
"additional-data": [
{"key": "places",
"url": "[passerelle_url]jsondatastore/lieux-favoris/data/?name_id=[user_nameid]"