conventionschedule-android/webstorage/webproj/bff/views.py

376 lines
14 KiB
Python

from django.shortcuts import render
# Create your views here.
import json
import datetime
import mimetypes
from pathlib import Path
from django.conf import settings
from django.views import View
from django.urls import reverse
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import resolve_url
from django.shortcuts import get_object_or_404
from django.utils.html import escape
from django.views.generic import TemplateView
from django.utils.decorators import method_decorator
from django.views.decorators.http import last_modified
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from . import models
#
# Trivial views
#
class SoonView(TemplateView):
template_name = "soon.html"
class LegalTosView(TemplateView):
template_name = "legal/tos.html"
class LegalPrivView(TemplateView):
template_name = "legal/privacy.html"
class HelpView(TemplateView):
template_name = "help.html"
#
# ABSTRACT VIEWS
#
class TemplateViewLoggedIn(TemplateView, LoginRequiredMixin):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
class ViewLoggedIn(View, LoginRequiredMixin):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
all_models = [
models.LanguagePhrase,
models.LanguageText,
models.LanguageRichText,
models.LanguageInvariantImage,
models.LanguageImage,
models.Announcement,
models.ActivityCategory,
models.Place,
models.Color,
models.Timezone,
models.RegistrationBenefitDefinition,
models.RegistrationTierDefinition,
models.ConventionRegistrationTier,
models.ConventionActivity,
models.ConventionSeries,
models.SocialMedia,
models.ConventionEdition,
models.BannerChange,
models.MapImage,
models.AdditionalRules,
models.ConventionRegistrationLink,
]
def db_last_modification(request, *args, **kwargs):
times = [model.objects.order_by('-modified')[0].modified for model in all_models if model.objects.exists()]
if len(times) > 0:
return max(times)
else:
return datetime.datetime.now()
class HomeView(TemplateView):
template_name = "index.html"
def get(self, request, *args, **kwargs):
def inner(request, *args, **kwargs):
context = self.get_context_data(**kwargs)
context['conventions_series'] = models.ConventionSeries.objects.order_by('id').all()
return self.render_to_response(context)
# return inner(request, *args, **kwargs)
wrapped = last_modified(db_last_modification)(inner)
return wrapped(request, *args, **kwargs)
class DjangoModelConversorToNativeStructures:
@staticmethod
def language_string(language_string: models.LanguageString) -> dict:
if language_string is None:
return {'uuid': None}
return {
'alias': language_string.reminder_alias,
'uuid': language_string.resource_uuid.hex,
'pt': language_string.pt,
'en': language_string.en,
'es': language_string.es,
}
@staticmethod
def language_image(language_image: models.LanguageImage) -> dict:
if language_image is None:
return {'uuid': None}
return {
'alias': language_image.reminder_alias,
'uuid': language_image.resource_uuid.hex,
'pt': language_image.pt.url,
'en': language_image.en.url,
'es': language_image.es.url,
}
@staticmethod
def social_media(social_media: models.SocialMedia) -> dict:
return {
'alias': social_media.reminder_alias,
'name': DMCTNS.language_string(social_media.name),
'url': DMCTNS.language_string(social_media.url),
'color': DMCTNS.color(social_media.color),
'icon': social_media.icon,
'ordering': social_media.ordering,
}
@staticmethod
def decompose_date(date) -> dict:
return {
'formatted': str(date),
'yr': int(date.strftime('%Y')),
'mo': int(date.strftime('%m')),
'dy': int(date.strftime('%d')),
'mn': int(date.strftime('%M')),
'hr': int(date.strftime('%H')),
'sc': int(date.strftime('%S')),
'wd': int(date.strftime('%w')),
}
@staticmethod
def timezone(tz) -> dict:
return {
'name': tz.reminder_alias,
'hr': tz.hour,
'mn': tz.minute,
}
@staticmethod
def registration_tier(registration_tier: models.ConventionRegistrationTier):
return {
'level': registration_tier.level,
'is_lowest': registration_tier.is_lowest,
'uuid': registration_tier.resource_uuid.hex,
'tier': DMCTNS.language_string(registration_tier.tier.title),
'benefits': [
DMCTNS.language_string(item.description)
for item in registration_tier.benefits.all()
],
}
@staticmethod
def color(color: models.Color) -> dict:
if color is None:
return {'uuid': None}
return {
'alias': color.reminder_alias,
'uuid': color.resource_uuid.hex,
'color': color.color,
'opacity': color.opacity,
}
@staticmethod
def place(place: models.Place) -> dict:
return {
'uuid': place.resource_uuid.hex,
'label': DMCTNS.language_string(place.name),
'color': DMCTNS.color(place.color),
'ordering': place.ordering,
}
@staticmethod
def activity_category(activity_category: models.ActivityCategory) -> dict:
return {
'uuid': activity_category.resource_uuid.hex,
'label': DMCTNS.language_string(activity_category.name),
'color': DMCTNS.color(activity_category.color),
'ordering': activity_category.ordering,
}
@staticmethod
def additional_rule(additional_rule: models.AdditionalRules) -> dict:
return {
'uuid': additional_rule.resource_uuid.hex,
'name': DMCTNS.language_string(additional_rule.name),
'rules': DMCTNS.language_string(additional_rule.rules),
'ordering': additional_rule.ordering,
}
@staticmethod
def banner(banner: models.BannerChange) -> dict:
return {
'uuid': banner.resource_uuid.hex,
'alias': banner.reminder_alias,
'show_up_after': DMCTNS.decompose_date(banner.show_up_after),
'hide_after': DMCTNS.decompose_date(banner.hide_after),
'banner': DMCTNS.language_image(banner.banner),
}
@staticmethod
def event(event: models.ConventionActivity) -> dict:
return {
'uuid': event.resource_uuid.hex,
'conbook_key': event.conbook_key,
'conbook_pages': event.conbook_pages,
'title': DMCTNS.language_string(event.title),
'subtitle': DMCTNS.language_string(event.subtitle),
'description': DMCTNS.language_string(event.description),
'time_start': DMCTNS.decompose_date(event.time_start),
'time_end': DMCTNS.decompose_date(event.time_end),
'places': [
item.resource_uuid.hex
for item in event.places.all()
],
'categories': [
item.resource_uuid.hex
for item in event.categories.all()
],
'attendable_by': [
item.resource_uuid.hex
for item in event.attendable_by.all()
],
'language': event.language,
'hidden_from_time_table': event.hidden_from_time_table,
'picture': DMCTNS.language_image(event.picture),
}
@staticmethod
def registration_link(link: models.ConventionRegistrationLink) -> dict:
return {
'uuid': link.resource_uuid.hex,
'alias': link.reminder_alias,
'ordering': link.ordering,
'name': DMCTNS.language_string(link.name),
'url': DMCTNS.language_string(link.url),
'color': DMCTNS.color(link.color),
'appears': DMCTNS.decompose_date(link.appears),
'vanishes': DMCTNS.decompose_date(link.vanishes),
}
@staticmethod
def map_image(map_image: models.MapImage) -> dict:
return {
'uuid': map_image.resource_uuid.hex,
'alias': map_image.reminder_alias,
'name': DMCTNS.language_string(map_image.name),
'image': DMCTNS.language_image(map_image.image),
}
@staticmethod
def convention_edition(convention_edition: models.ConventionEdition) -> dict:
return {
'uuid': convention_edition.resource_uuid.hex,
'name': DMCTNS.language_string(convention_edition.name),
'places': [
DMCTNS.place(item)
for item in models.Place.objects.filter(on_activities__in=convention_edition.events.all()).distinct()
],
'tags': [
DMCTNS.activity_category(item)
for item in models.ActivityCategory.objects.filter(on_activities__in=convention_edition.events.all()).distinct()
],
'lowest_registration_tier': (
convention_edition.registration_tiers.order_by('level', '-is_lowest').all()[0].resource_uuid.hex
) if convention_edition.registration_tiers.exists() else None,
'registration_tiers': [
DMCTNS.registration_tier(item)
for item in convention_edition.registration_tiers.order_by('level', '-is_lowest').all()
],
'theme': DMCTNS.language_string(convention_edition.theme),
'hashtag_reminder': convention_edition.hashtag_reminder,
'timezone': DMCTNS.timezone(convention_edition.timezone),
'rule_621_checker': convention_edition.rule_621_checker,
'next_edition': DMCTNS.decompose_date(convention_edition.next_edition_date),
'ceremony_opening_time': DMCTNS.decompose_date(convention_edition.ceremony_opening_time),
'ceremony_closing_time': DMCTNS.decompose_date(convention_edition.ceremony_closing_time),
'split_day_into_n_parts': convention_edition.split_day_into_n_parts,
'image_default_event': DMCTNS.language_image(convention_edition.image_default_event),
'image_favorites': DMCTNS.language_image(convention_edition.image_favorites),
'maps': [
DMCTNS.map_image(item)
for item in convention_edition.maps.all()
],
'language': convention_edition.language,
'events': [
DMCTNS.event(item)
for item in convention_edition.events.all()
],
'additional_rules': [
DMCTNS.additional_rule(item)
for item in convention_edition.additional_rules.all()
],
'registration_links': [
DMCTNS.registration_link(item)
for item in convention_edition.registration_links.all()
],
'fire_notifications_n_minutes_before': convention_edition.fire_notifications_n_minutes_before,
'convention_day_start_time': DMCTNS.decompose_date(convention_edition.convention_day_start_time),
'convention_day_end_time': DMCTNS.decompose_date(convention_edition.convention_day_end_time),
}
@staticmethod
def convention_series(convention_series: models.ConventionSeries) -> dict:
return {
'uuid': convention_series.resource_uuid.hex,
'name': DMCTNS.language_string(convention_series.name),
'featured': None if convention_series.featured is None else convention_series.featured.resource_uuid.hex,
'editions': [
DMCTNS.convention_edition(item)
for item in convention_series.editions.all()
],
'timezone': DMCTNS.timezone(convention_series.timezone),
'social_medias': [
DMCTNS.social_media(item)
for item in convention_series.social_medias.all()
],
'default_banner': DMCTNS.language_image(convention_series.default_banner),
'banners': [
DMCTNS.banner(item)
for item in convention_series.banners.all()
],
'language': convention_series.language,
'statute': DMCTNS.language_string(convention_series.statute),
}
DMCTNS = DjangoModelConversorToNativeStructures
class ConventionsJsonView(View):
def get(self, request, *args, **kwargs):
def inner(request, *args, **kwargs):
is_prettified_output = kwargs.get('mode', 'minified') == 'prettified'
root = get_object_or_404(models.ConventionSeries, url=kwargs.get('identifier'))
data = DMCTNS.convention_series(root)
json_pretty_print_settings = dict()
if is_prettified_output:
json_pretty_print_settings['indent'] = 4
return HttpResponse(
json.dumps(
data,
**json_pretty_print_settings
),
content_type='application/json'
)
if settings.DEBUG:
return inner(request, *args, **kwargs)
wrapped = last_modified(db_last_modification)(inner)
return wrapped(request, *args, **kwargs)