Skip to content

Commit

Permalink
♻️ Refactor HD Views using MapEntityMixin
Browse files Browse the repository at this point in the history
  • Loading branch information
Chatewgne committed Dec 20, 2022
1 parent 2efcb97 commit e9e84c5
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 135 deletions.
12 changes: 11 additions & 1 deletion geotrek/common/filters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from django.utils.translation import gettext_lazy as _
from django_filters import ModelMultipleChoiceFilter, RangeFilter
from mapentity.filters import MapEntityFilterSet

from geotrek.common.models import HDViewPoint

from django_filters import RangeFilter, ModelMultipleChoiceFilter
from .fields import OneLineRangeField


Expand All @@ -27,3 +30,10 @@ def get_queryset(self, request=None):
if self.queryset is not None:
return self.queryset
return self.model.objects.all()


class HDViewPointFilterSet(MapEntityFilterSet):

class Meta(MapEntityFilterSet.Meta):
model = HDViewPoint
fields = ['title']
4 changes: 2 additions & 2 deletions geotrek/common/migrations/0029_hdviewpoint.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Generated by Django 3.2.16 on 2022-12-19 10:04
# Generated by Django 3.2.16 on 2022-12-20 16:02

from django.conf import settings
import django.contrib.gis.db.models.fields
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
import uuid


Expand Down
84 changes: 5 additions & 79 deletions geotrek/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from colorfield.fields import ColorField
from django.conf import settings
from django.contrib import auth
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.gis.db import models as gis_models
Expand All @@ -13,14 +12,17 @@
from django.urls import reverse
from django.utils.http import urlencode
from django.utils.translation import gettext_lazy as _
from mapentity.models import MapEntityMixin
from paperclip.models import Attachment as BaseAttachment
from paperclip.models import FileType as BaseFileType
from paperclip.models import License as BaseLicense
from PIL import Image

from geotrek.authent.models import StructureOrNoneRelated

from .managers import AccessibilityAttachmentManager
from .mixins.models import OptionalPictogramMixin, PictogramMixin, TimeStampedModelMixin
from .mixins.models import (OptionalPictogramMixin, PictogramMixin,
TimeStampedModelMixin)


def attachment_accessibility_upload(instance, filename):
Expand Down Expand Up @@ -272,7 +274,7 @@ class Meta:
abstract = True


class HDViewPoint(TimeStampedModelMixin):
class HDViewPoint(TimeStampedModelMixin, MapEntityMixin):
picture = models.FileField(verbose_name=_("Picture"), upload_to="hdviewpoints/")
geom = gis_models.PointField(verbose_name=_("Location"),
srid=settings.SRID)
Expand Down Expand Up @@ -305,28 +307,10 @@ class Meta:
def __str__(self):
return self.title

@property
def structure(self):
return self.content_object.structure

def same_structure(self, user):
""" Returns True if the user is in the same structure or has
bypass_structure permission, False otherwise. """
return (user.profile.structure == self.structure
or user.is_superuser
or user.has_perm('authent.can_bypass_structure'))

@property
def full_url(self):
return reverse('common:hdviewpoint_detail', kwargs={'pk': self.pk})

def get_absolute_url(self):
return self.full_url

@classmethod
def get_add_url(cls):
return reverse('common:hdviewpoint_add')

@classmethod
def get_list_url(cls):
return reverse('admin:common_hdviewpoint_changelist')
Expand All @@ -339,67 +323,9 @@ def get_generic_picture_tile_url(self):
url = self.get_picture_tile_url(0, 0, 0).replace("/0/0/0.png", "/{z}/{x}/{y}.png")
return url

def get_layer_detail_url(self):
return reverse("{app_name}:{model_name}-drf-detail".format(app_name=self._meta.app_label.lower(),
model_name=self._meta.model_name.lower()),
kwargs={"format": "geojson", "pk": self.pk})

def get_detail_url(self):
return reverse('common:hdviewpoint_detail', args=[self.pk])

@property
def thumbnail_url(self):
return reverse('common:hdviewpoint-thumbnail', kwargs={'pk': self.pk, 'fmt': 'png'})

def get_update_url(self):
return reverse('common:hdviewpoint_change', args=[self.pk])

def get_annotate_url(self):
return reverse('common:hdviewpoint_annotate', args=[self.pk])

def get_delete_url(self):
return reverse('common:hdviewpoint_delete', args=[self.pk])

@classmethod
def get_permission_codename(cls, entity_kind):
operations = {
'update': 'change',
'update_geom': 'change_geom',
'detail': 'read',
'layer': 'read',
'list': 'read',
'-drf-list': 'read',
'markup': 'read',
}
perm = operations.get(entity_kind, entity_kind)
opts = cls._meta
appname = opts.app_label.lower()
return '%s.%s' % (appname, auth.get_permission_codename(perm, opts))

@classmethod
def get_content_type_id(cls):
return ContentType.objects.get_for_model(cls).pk

def get_geom(self):
return self.geom

def get_map_image_extent(self, srid=settings.API_SRID):
obj = self.geom
obj.transform(srid)
return obj.extent

@classmethod
def get_create_label(cls):
return _("Add a new HD view")

@property
def icon_small(self):
return 'images/hdviewpoint-16.png'

@property
def icon_big(self):
return 'images/hdviewpoint-96.png'

@property
def modelname(self):
return self._meta.model_name
28 changes: 24 additions & 4 deletions geotrek/common/serializers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from django.conf import settings
from django.urls import reverse
from django.db import models as django_db_models
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.translation import get_language
from mapentity.serializers import MapentityGeojsonModelSerializer
from rest_framework import serializers as rest_serializers
from rest_framework_gis.fields import GeometryField
from rest_framework_gis.fields import (GeometryField,
GeometrySerializerMethodField)
from rest_framework_gis.serializers import GeoFeatureModelSerializer

from .models import HDViewPoint, Theme, RecordSource, TargetPortal, FileType, Attachment, Label
from .models import (Attachment, FileType, HDViewPoint, Label, RecordSource,
TargetPortal, Theme)


class TranslatedModelSerializer(rest_serializers.ModelSerializer):
Expand Down Expand Up @@ -94,14 +97,31 @@ class Meta:
fields = ('id', 'pictogram', 'name', 'advice', 'filter_rando')


class HDViewPointAPISerializer(TranslatedModelSerializer):
class HDViewPointSerializer(TranslatedModelSerializer):
class Meta:
model = HDViewPoint
fields = (
'id', 'uuid', 'author', 'title', 'legend', 'license'
)


class HDViewPointGeoJSONSerializer(MapentityGeojsonModelSerializer):
api_geom = GeometrySerializerMethodField()

def get_api_geom(self, obj):
return obj.geom.transform(4326, clone=True)

class Meta(MapentityGeojsonModelSerializer.Meta):
model = HDViewPoint
fields = ('id', 'title')


class HDViewPointAPISerializer(HDViewPointSerializer):
class Meta(HDViewPointSerializer.Meta):
id_field = 'id'
fields = HDViewPointSerializer.Meta.fields


class HDViewPointAPIGeoJSONSerializer(GeoFeatureModelSerializer, HDViewPointAPISerializer):
# Annotated geom field with API_SRID
api_geom = GeometryField(read_only=True, precision=7)
Expand Down
5 changes: 0 additions & 5 deletions geotrek/common/static/common/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,6 @@ fieldset {
visibility: visible;
opacity: 1;
}
li.history.hdviewpoint > a,
li.history.hdviewpoint button:first-child {
background: url(/static/images/hdviewpoint-16.png) no-repeat;
background-position: left center;
}
.form-actions {
z-index: 1000;
}
11 changes: 0 additions & 11 deletions geotrek/common/templates/common/hdviewpoint_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,6 @@
{% block head %}
{% block title %}{{ object }} | {{ block.super }}{% endblock title %}
{{ block.super }}
<style>
.list-panel.{{ object.modelname }},
.form-panel.{{ object.modelname }},
.details-panel.{{ object.modelname }} {
background-image: url({% static object.icon_big %});
background-position: left top -3%;
}
.nav-item.{{ object.modelname }} .btn-list {
background-image: url({% static object.icon_big %});
}
</style>
{% endblock head %}
{% block mainpanel %}
<div class="details-panel detail col-12 col-lg-7 {{ object.modelname }}">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ <h3 id="with-tooltip" >{% trans "HD Views" %}
</a>
{% if perms.common.change_hdviewpoint %}
&nbsp;
<a href="{% url 'common:hdviewpoint_change' viewpoint.pk %}" class="update-action">
<a href="{% url 'common:hdviewpoint_update' viewpoint.pk %}" class="update-action">
{% trans "Update" %}
</a>
{% endif %}
Expand Down
11 changes: 4 additions & 7 deletions geotrek/common/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class HDViewPointTestCase(TestCase):
def setUpTestData(cls):
structure = StructureFactory(name="MyStructure")
cls.trek = TrekFactory(structure=structure)
cls.vp = HDViewPointFactory(content_object=cls.trek)
cls.vp = HDViewPointFactory(content_object=cls.trek, title='Panorama')
cls.user = UserFactory()
UserProfileFactory(structure=structure, user=cls.user)

Expand All @@ -74,9 +74,6 @@ def test_tiles_url(self):
self.vp.get_generic_picture_tile_url(), f"/api/hdviewpoint/drf/hdviewpoints/{self.vp.pk}/tiles/{{z}}/{{x}}/{{y}}.png?source=vips"
)

def test_icons(self):
self.assertIn('hdviewpoint-16.png', self.vp.icon_small)
self.assertIn('hdviewpoint-96.png', self.vp.icon_big)

def test_same_structure(self):
self.assertTrue(self.vp.same_structure(self.user))
def test_properties(self):
self.assertEqual(str(self.vp), 'Panorama')
self.assertIn('admin/', self.vp.get_list_url())
4 changes: 2 additions & 2 deletions geotrek/common/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,8 @@ def setUpTestData(cls):
cls.license = LicenseFactory()
# Create user with proper permissions
cls.user_perm = UserFactory.create()
read_perm = Permission.objects.get(codename="read_hdviewpoint")
add_perm = Permission.objects.get(codename="add_hdviewpoint")
read_perm = Permission.objects.get(codename="read_hdviewpoint")
update_perm = Permission.objects.get(codename="change_hdviewpoint")
delete_perm = Permission.objects.get(codename="delete_hdviewpoint")
cls.user_perm.user_permissions.add(add_perm, read_perm, update_perm, delete_perm)
Expand Down Expand Up @@ -470,7 +470,7 @@ def test_crud_view(self):
'geom': "SRID=2154;POINT(0 0)"
}
response = self.client.post(vp.get_update_url(), data)
self.assertRedirects(response, f"/hdviewpoint/{vp.pk}", status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
self.assertRedirects(response, f"/hdviewpoint/{vp.pk}/", status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
vp = HDViewPoint.objects.first()
self.assertEqual(vp.legend, "Something else")
self.assertEqual(vp.license, None)
Expand Down
17 changes: 5 additions & 12 deletions geotrek/common/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.urls import path, converters, register_converter
from mapentity.registry import MapEntityOptions
from geotrek.common.models import HDViewPoint
from mapentity.registry import MapEntityOptions, registry
from rest_framework.routers import DefaultRouter

from .views import (HDViewPointAPIViewSet, HDViewPointAnnotate, HDViewPointCreate, HDViewPointDetail, HDViewPointUpdate, HDViewPointDelete,
TiledHDViewPointViewSet, JSSettings, DocumentPublic, DocumentBookletPublic, import_view,
import_update_json, ThemeViewSet, MarkupPublic, sync_view, sync_update_json, SyncRandoRedirect,
from .views import (HDViewPointAnnotate, TiledHDViewPointViewSet, JSSettings, DocumentPublic, DocumentBookletPublic,
import_view, import_update_json, ThemeViewSet, MarkupPublic, sync_view, sync_update_json, SyncRandoRedirect,
CheckExtentsView)


Expand All @@ -15,8 +15,6 @@ class LangConverter(converters.StringConverter):
register_converter(LangConverter, 'lang')

app_name = 'common'


urlpatterns = [
path('api/settings.json', JSSettings.as_view(), name='settings_json'),
path('tools/extents/', CheckExtentsView.as_view(), name='check_extents'),
Expand All @@ -26,17 +24,12 @@ class LangConverter(converters.StringConverter):
path('commands/syncview', sync_view, name='sync_randos_view'),
path('commands/statesync/', sync_update_json, name='sync_randos_state'),
path('api/<lang:lang>/themes.json', ThemeViewSet.as_view({'get': 'list'}), name="themes_json"),
path('hdviewpoint/add', HDViewPointCreate.as_view(), name="hdviewpoint_add"),
path('hdviewpoint/<int:pk>', HDViewPointDetail.as_view(), name="hdviewpoint_detail"),
path('hdviewpoint/edit/<int:pk>', HDViewPointUpdate.as_view(), name="hdviewpoint_change"),
path('hdviewpoint/delete/<int:pk>', HDViewPointDelete.as_view(), name="hdviewpoint_delete"),
path('hdviewpoint/annotate/<int:pk>', HDViewPointAnnotate.as_view(), name="hdviewpoint_annotate"),
]

rest_router = DefaultRouter(trailing_slash=False)
rest_router.register(r'api/hdviewpoint/drf/hdviewpoints',
HDViewPointAPIViewSet, basename="hdviewpoint-drf")
rest_router.register(r'api/hdviewpoint/drf/hdviewpoints', TiledHDViewPointViewSet)
urlpatterns += registry.register(HDViewPoint, menu=False)
urlpatterns += rest_router.urls


Expand Down
Loading

0 comments on commit e9e84c5

Please sign in to comment.