rudimentary theme support

This commit is contained in:
Gwendolyn 2024-01-06 13:26:34 +01:00
parent b44197a1c5
commit 9399e5c377
23 changed files with 925 additions and 307 deletions

View file

@ -9,10 +9,10 @@ from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import FieldDoesNotExist
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Q
from django.db.models import Q, Prefetch
from django.forms import (BooleanField, CharField, ChoiceField, DecimalField, Form, JSONField, ModelChoiceField,
ModelForm, MultipleChoiceField, Select, ValidationError)
from django.forms.widgets import HiddenInput
from django.forms.widgets import HiddenInput, TextInput
from django.utils.translation import get_language
from django.utils.translation import gettext_lazy as _
from shapely.geometry.geo import mapping
@ -21,8 +21,10 @@ from pydantic import ValidationError as PydanticValidationError
from c3nav.editor.models import ChangeSet, ChangeSetUpdate
from c3nav.mapdata.fields import GeometryField
from c3nav.mapdata.forms import I18nModelFormMixin
from c3nav.mapdata.models import GraphEdge
from c3nav.mapdata.models import GraphEdge, LocationGroup
from c3nav.mapdata.models.access import AccessPermission
from c3nav.mapdata.models.geometry.space import ObstacleGroup
from c3nav.mapdata.models.theme import ThemeLocationGroupBackgroundColor, ThemeObstacleGroupBackgroundColor
from c3nav.routing.schemas import LocateRequestPeerSchema
@ -32,6 +34,69 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
super().__init__(*args, **kwargs)
creating = not self.instance.pk
if self._meta.model.__name__ == 'Theme':
if creating:
locationgroup_theme_colors = {}
obstaclegroup_theme_colors = {}
else:
locationgroup_theme_colors = {
l.location_group_id: l
for l in self.instance.location_groups.filter(theme_id=self.instance.pk)
}
obstaclegroup_theme_colors = {
o.obstacle_group_id: o
for o in self.instance.obstacle_groups.filter(theme_id=self.instance.pk)
}
# TODO: can we get the model class via relationships?
for locationgroup in LocationGroup.objects.prefetch_related(
Prefetch('theme_colors', ThemeLocationGroupBackgroundColor.objects.only('fill_color'))).all():
related = locationgroup_theme_colors.get(locationgroup.pk, None)
value = related.fill_color if related is not None else None
other_themes_colors = {
l.title: l.fill_color
for l in locationgroup.theme_colors.all()
if related is None or l.pk != related.pk
}
if len(other_themes_colors) > 0:
other_themes_colors = json.dumps(other_themes_colors)
else:
other_themes_colors = False
field = CharField(max_length=32,
label=locationgroup.title,
required=False,
initial=value,
widget=TextInput(attrs={
'data-themed-color': True,
'data-color-base-theme': locationgroup.color if locationgroup.color else False,
'data-colors-other-themes': other_themes_colors,
}))
self.fields[f'locationgroup_{locationgroup.pk}'] = field
for obstaclegroup in ObstacleGroup.objects.prefetch_related(
Prefetch('theme_colors', ThemeObstacleGroupBackgroundColor.objects.only('fill_color'))).all():
related = obstaclegroup_theme_colors.get(obstaclegroup.pk, None)
value = related.fill_color if related is not None else None
other_themes_colors = {
o.title: o.fill_color
for o in obstaclegroup.theme_colors.all()
if related is None or o.pk != related.pk
}
if len(other_themes_colors) > 0:
other_themes_colors = json.dumps(other_themes_colors)
else:
other_themes_colors = False
field = CharField(max_length=32,
label=obstaclegroup.title,
required=False,
initial=value,
widget=TextInput(attrs={
'data-themed-color': True,
'data-color-base-theme': obstaclegroup.color if obstaclegroup.color else False,
'data-colors-other-themes': other_themes_colors,
}))
self.fields[f'obstaclegroup_{obstaclegroup.pk}'] = field
if hasattr(self.instance, 'author_id'):
if self.instance.author_id is None:
self.instance.author = request.user
@ -309,6 +374,35 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
groups = tuple((int(val) if val.isdigit() else val) for val in groups)
self.instance.groups.set(groups)
if self._meta.model.__name__ == 'Theme':
locationgroup_colors = {l.location_group_id: l for l in self.instance.location_groups.all()}
for locationgroup in LocationGroup.objects.all():
value = self.cleaned_data[f'locationgroup_{locationgroup.pk}']
if value:
color = locationgroup_colors.get(locationgroup.pk,
ThemeLocationGroupBackgroundColor(theme=self.instance,
location_group=locationgroup))
color.fill_color = value
color.save()
else:
color = locationgroup_colors.get(locationgroup.pk, None)
if color is not None:
color.delete()
obstaclegroup_colors = {o.obstacle_group_id: o for o in self.instance.obstacle_groups.all()}
for obstaclegroup in ObstacleGroup.objects.all():
value = self.cleaned_data[f'obstaclegroup_{obstaclegroup.pk}']
if value:
color = obstaclegroup_colors.get(obstaclegroup.pk,
ThemeObstacleGroupBackgroundColor(theme=self.instance,
obstacle_group=obstaclegroup))
color.fill_color = value
color.save()
else:
color = obstaclegroup_colors.get(obstaclegroup.pk)
if color is not None:
color.delete()
def create_editor_form(editor_model):
possible_fields = ['slug', 'name', 'title', 'title_plural', 'help_text', 'position_secret',