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)