376 lines
14 KiB
Python
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)
|