diff --git a/project/core/settings/base.py b/project/core/settings/base.py index 965e5ab..181d04c 100644 --- a/project/core/settings/base.py +++ b/project/core/settings/base.py @@ -26,6 +26,7 @@ INSTALLED_APPS = [ 'accounts', 'chapters', + 'hangouts', 'home', 'invites', 'search', @@ -43,6 +44,7 @@ 'wagtail.admin', 'wagtail.core', 'wagtail.contrib.modeladmin', + "wagtail.contrib.routable_page", 'modelcluster', 'taggit', diff --git a/project/hangouts/__init__.py b/project/hangouts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/project/hangouts/admin.py b/project/hangouts/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/project/hangouts/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/project/hangouts/apps.py b/project/hangouts/apps.py new file mode 100644 index 0000000..31aa520 --- /dev/null +++ b/project/hangouts/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HangoutsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'hangouts' diff --git a/project/hangouts/migrations/0001_initial.py b/project/hangouts/migrations/0001_initial.py new file mode 100644 index 0000000..aa74f6d --- /dev/null +++ b/project/hangouts/migrations/0001_initial.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.6 on 2021-12-08 05:13 + +from django.db import migrations, models +import django.db.models.deletion +import modelcluster.contrib.taggit +import modelcluster.fields +import wagtail.core.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0062_comment_models_and_pagesubscription'), + ('taggit', '0003_taggeditem_add_unique_index'), + ] + + operations = [ + migrations.CreateModel( + name='Hangout', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('description', wagtail.core.fields.RichTextField()), + ('link', models.URLField(blank=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='HangoutsIndexPage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('introduction', wagtail.core.fields.RichTextField()), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='HangoutTag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content_object', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='hangouts.hangout')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hangouts_hangouttag_items', to='taggit.tag')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='hangout', + name='topics', + field=modelcluster.contrib.taggit.ClusterTaggableManager(blank=True, help_text='A comma-separated list of tags.', through='hangouts.HangoutTag', to='taggit.Tag', verbose_name='Tags'), + ), + ] diff --git a/project/hangouts/migrations/__init__.py b/project/hangouts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/project/hangouts/models.py b/project/hangouts/models.py new file mode 100644 index 0000000..a88f81b --- /dev/null +++ b/project/hangouts/models.py @@ -0,0 +1,102 @@ +from django.db import models +from django.shortcuts import redirect +from modelcluster.contrib.taggit import ClusterTaggableManager +from modelcluster.fields import ParentalKey +from taggit.managers import TaggableManager +from taggit.models import Tag, TaggedItemBase +from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel +from wagtail.contrib.routable_page.models import RoutablePageMixin, route +from wagtail.core.blocks import URLBlock +from wagtail.core.fields import RichTextField, StreamField +from wagtail.core.models import Page + + +def topics_with_url(topics, parent_url): + """ + Adding a URL to access Hangouts objects of the same tag + """ + for topic in topics: + topic.url = "/" + "/".join( + s.strip("/") for s in [parent_url, "topics", topic.slug] + ) + return topics + + +class HangoutTag(TaggedItemBase): + content_object = ParentalKey( + "hangouts.Hangout", related_name="tagged_items", on_delete=models.CASCADE + ) + + +# Create your models here. +class Hangout(Page): + description = RichTextField() + topics = ClusterTaggableManager(through=HangoutTag, blank=True) + link = models.URLField(blank=True) + + content_panels = Page.content_panels + [ + FieldPanel("description", classname="full"), + FieldPanel("topics", classname="full"), + FieldPanel("link", classname="full"), + ] + parent_page_types = [ + "hangouts.HangoutsIndexPage", + ] + subpage_types = [] + + @property + def get_topics(self): + topics = self.topics.all() + + return topics_with_url(topics, self.get_parent().url) + + +class HangoutsIndexPage(RoutablePageMixin, Page): + introduction = RichTextField() + + content_panels = Page.content_panels + [ + FieldPanel("introduction"), + ] + + parent_page_types = [ + "home.HomePage", + ] + + subpage_types = ["hangouts.Hangout"] + + max_count = 1 + + def get_context(self, request, *args, **kwargs): + context = super().get_context(request, *args, **kwargs) + context["hangouts"] = self.get_hangouts() + return context + + @route(r"^topics/$", name="topic_archive") + @route(r"^topics/([\w-]+)/$", name="topic_archive") + def tag_archive(self, request, topic=None): + + try: + topic = Tag.objects.get(slug=topic) + except Tag.DoesNotExist: + if topic: + msg = 'There are no hangouts in the topic "{}"'.format(topic) + messages.add_message(request, messages.INFO, msg) + return redirect(self.url) + + hangouts = self.get_hangouts(topic=topic) + + return self.render( + request, context_overrides={"topic": topic, "hangouts": hangouts} + ) + + def get_hangouts(self, topic=None): + hangouts = ( + Hangout.objects.live().descendant_of(self).order_by("-last_published_at") + ) + if topic: + hangouts = hangouts.filter(topics=topic) + return hangouts + + def get_child_topics(self): + topics = Tag.objects.filter(hangout__in=self.get_hangouts()).distinct() + return topics_with_url(topics, self.url) diff --git a/project/hangouts/templates/hangouts/hangout.html b/project/hangouts/templates/hangouts/hangout.html new file mode 100644 index 0000000..93131ae --- /dev/null +++ b/project/hangouts/templates/hangouts/hangout.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block title %}{{ page.title }}{% endblock title %} + +{% load wagtailcore_tags %} + +{% block content %} +