-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
44e93cc
commit 18c0cc1
Showing
98 changed files
with
8,233 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Use an official Python runtime based on Debian 10 "buster" as a parent image. | ||
FROM python:3.8.1-slim-buster | ||
|
||
# Add user that will be used in the container. | ||
RUN useradd wagtail | ||
|
||
# Port used by this container to serve HTTP. | ||
EXPOSE 8000 | ||
|
||
# Set environment variables. | ||
# 1. Force Python stdout and stderr streams to be unbuffered. | ||
# 2. Set PORT variable that is used by Gunicorn. This should match "EXPOSE" | ||
# command. | ||
ENV PYTHONUNBUFFERED=1 \ | ||
PORT=8000 | ||
|
||
# Install system packages required by Wagtail and Django. | ||
RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-recommends \ | ||
build-essential \ | ||
libpq-dev \ | ||
libmariadbclient-dev \ | ||
libjpeg62-turbo-dev \ | ||
zlib1g-dev \ | ||
libwebp-dev \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
# Install the application server. | ||
RUN pip install "gunicorn==20.0.4" | ||
|
||
# Install the project requirements. | ||
COPY requirements.txt / | ||
RUN pip install -r /requirements.txt | ||
|
||
# Use /app folder as a directory where the source code is stored. | ||
WORKDIR /app | ||
|
||
# Set this directory to be owned by the "wagtail" user. This Wagtail project | ||
# uses SQLite, the folder needs to be owned by the user that | ||
# will be writing to the database file. | ||
RUN chown wagtail:wagtail /app | ||
|
||
# Copy the source code of the project into the container. | ||
COPY --chown=wagtail:wagtail . . | ||
|
||
# Use user "wagtail" to run the build commands below and the server itself. | ||
USER wagtail | ||
|
||
# Collect static files. | ||
RUN python manage.py collectstatic --noinput --clear | ||
|
||
# Runtime command that executes when "docker run" is called, it does the | ||
# following: | ||
# 1. Migrate the database. | ||
# 2. Start the application server. | ||
# WARNING: | ||
# Migrating database at the same time as starting the server IS NOT THE BEST | ||
# PRACTICE. The database should be migrated manually or using the release | ||
# phase facilities of your hosting platform. This is used only so the | ||
# Wagtail instance can be started with a simple "docker run" command. | ||
CMD set -xe; python manage.py migrate --noinput; gunicorn unblocklife.wsgi:application |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[[source]] | ||
url = "https://pypi.org/simple" | ||
verify_ssl = true | ||
name = "pypi" | ||
|
||
[packages] | ||
django = "*" | ||
tzdata = "*" # Fixes "zoneinfo._common.ZoneInfoNotFoundError" on docker server | ||
wagtail = "*" | ||
whitenoise = "*" | ||
|
||
[dev-packages] | ||
black = "*" | ||
flake8 = "*" | ||
isort = "*" | ||
|
||
[requires] | ||
python_version = "3.10" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.contrib import admin | ||
|
||
# Register your models here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class CoursesConfig(AppConfig): | ||
default_auto_field = 'django.db.models.BigAutoField' | ||
name = 'courses' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
from django.db import models | ||
from wagtail.models import Page | ||
from django.shortcuts import redirect, render | ||
from wagtail.fields import RichTextField | ||
from wagtail.admin.panels import FieldPanel, MultiFieldPanel | ||
from wagtail.search import index | ||
from wagtail.fields import StreamField | ||
from wagtail import blocks | ||
from wagtail.images.blocks import ImageChooserBlock | ||
from modelcluster.contrib.taggit import ClusterTaggableManager | ||
from modelcluster.fields import ParentalKey | ||
from taggit.models import Tag, TaggedItemBase | ||
from home.blocks import BaseStreamBlock, TrainerBlock | ||
from wagtail.contrib.routable_page.models import RoutablePageMixin, route | ||
from wagtail.admin.filters import WagtailFilterSet | ||
|
||
|
||
class CoursesIndexPage(RoutablePageMixin, Page): | ||
max_count=1 | ||
summary = models.CharField(blank=True, max_length=255) | ||
image = models.ForeignKey( | ||
"wagtailimages.Image", | ||
null=True, | ||
blank=True, | ||
on_delete=models.SET_NULL, | ||
related_name="+", | ||
help_text="Landscape mode only; horizontal width between 1000px and 3000px.", | ||
) | ||
|
||
template = "courses/courses_index_page.html" | ||
|
||
content_panels = Page.content_panels + [ | ||
FieldPanel('summary'), | ||
FieldPanel("image") | ||
] | ||
|
||
def get_context(self, request, *args, **kwargs): | ||
context = super().get_context(request, *args, **kwargs) | ||
context['course_entries'] = CoursesPage.objects.child_of(self).live().order_by('-date') | ||
return context | ||
|
||
subpage_types = ["CoursesPage"] | ||
|
||
def children(self): | ||
return self.get_children().specific().live() | ||
|
||
@route(r"^tags/$", name="tag_archive") | ||
@route(r"^tags/([\w-]+)/$", name="tag_archive") | ||
def tag_archive(self, request, tag=None): | ||
try: | ||
tag = Tag.objects.get(slug=tag) | ||
except Tag.DoesNotExist: | ||
if tag: | ||
msg = 'There are no Course Pagess tagged with "{}"'.format(tag) | ||
messages.add_message(request, messages.INFO, msg) | ||
return redirect(self.url) | ||
course_entries = self.get_posts(tag=tag) | ||
context = {"self": self, "tag": tag, "course_entries": course_entries} | ||
return render(request, "courses/courses_index_page.html", context) | ||
|
||
def serve_preview(self, request, mode_name): | ||
return self.serve(request) | ||
|
||
# Returns the child CoursePage objects for this CoursePageIndex. | ||
# If a tag is used then it will filter the posts by tag. | ||
def get_posts(self, tag=None): | ||
posts = CoursesPage.objects.live().descendant_of(self) | ||
if tag: | ||
posts = posts.filter(tags=tag) | ||
return posts | ||
# Returns the list of Tags for all child posts of this CoursePage. | ||
def get_child_tags(self): | ||
tags = [] | ||
for post in self.get_posts(): | ||
# Not tags.append() because we don't want a list of lists | ||
tags += post.get_tags | ||
tags = sorted(set(tags)) | ||
return tags | ||
|
||
|
||
|
||
class CoursesPageTag(TaggedItemBase): | ||
""" | ||
This model allows us to create a many-to-many relationship between | ||
the CoursePage object and tags. There's a longer guide on using it at | ||
https://docs.wagtail.org/en/stable/reference/pages/model_recipes.html#tagging | ||
""" | ||
|
||
content_object = ParentalKey( | ||
"CoursesPage", related_name="tagged_items", on_delete=models.CASCADE | ||
) | ||
|
||
|
||
|
||
|
||
|
||
|
||
class CoursesPage(Page): | ||
author = models.CharField(max_length=255) | ||
date = models.DateField("Post date") | ||
summary = models.CharField(max_length=1000) | ||
start_date = models.DateField(null=True, help_text="Schedule Start Date") | ||
end_date = models.DateField( null=True, help_text="Schedule End Date") | ||
feed_image = models.ForeignKey( | ||
'wagtailimages.Image', | ||
null=True, | ||
blank=True, | ||
on_delete=models.SET_NULL, | ||
related_name='+' | ||
) | ||
body = StreamField( BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True) | ||
trainers = StreamField( TrainerBlock(), verbose_name="Trainers", blank=True, use_json_field=True) | ||
|
||
tags = ClusterTaggableManager(through=CoursesPageTag, blank=True) | ||
|
||
search_fields = Page.search_fields + [ | ||
index.SearchField('summary'), | ||
index.SearchField('author'), | ||
index.SearchField('body'), | ||
index.SearchField('trainers'), | ||
] | ||
|
||
content_panels = Page.content_panels + [ | ||
FieldPanel('trainers'), | ||
FieldPanel('date'), | ||
FieldPanel('summary'), | ||
FieldPanel('start_date'), | ||
FieldPanel('end_date'), | ||
FieldPanel('body'), | ||
FieldPanel('author'), | ||
FieldPanel("tags"), | ||
] | ||
panels = [ | ||
FieldPanel('start_date'), | ||
] | ||
|
||
|
||
promote_panels = [ | ||
MultiFieldPanel(Page.promote_panels, "Common page configuration"), | ||
FieldPanel('feed_image'), | ||
] | ||
|
||
@property | ||
def get_tags(self): | ||
""" | ||
Similar to the authors function above we're returning all the tags that | ||
are related to the course page into a list we can access on the template. | ||
We're additionally adding a URL to access CoursePage objects with that tag | ||
""" | ||
tags = self.tags.all() | ||
base_url = self.get_parent().url | ||
for tag in tags: | ||
tag.url = f"{base_url}tags/{tag.slug}/" | ||
return tags | ||
|
||
# Specifies parent to CoursePage as being CourseIndexPages | ||
parent_page_types = ["CoursesIndexPage"] | ||
|
||
# Specifies what content types can exist as children of CoursePage. | ||
# Empty list means that no child content types are allowed. | ||
subpage_types = [] | ||
|
||
class CoursesPageFillterSet(WagtailFilterSet): | ||
class Meta: | ||
model = CoursesPage | ||
fields = ["start_date"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
{% extends "base.html" %} | ||
|
||
{% load wagtailcore_tags wagtailimages_tags %} | ||
|
||
{% block body_class %}template-blogindexpage{% endblock %} | ||
|
||
{% block content %} | ||
|
||
<div class="h-28"></div> | ||
|
||
<section id="blog" class="text-gray-700 body-font border-t border-gray-200"> | ||
<div class="container px-5 py-24 mx-auto"> | ||
<div class="flex flex-wrap w-full mb-20 flex-col items-center text-center"> | ||
<h1 class="sm:text-3xl text-2xl font-medium title-font mb-2 text-gray-900"> {{ page.title }} </h1> | ||
<p class="lg:w-1/2 w-full leading-relaxed text-base"> {{ page.summary }} </p> | ||
|
||
</div> | ||
<div class="flex flex-wrap -m-4"> | ||
{% for post in course_entries %} | ||
|
||
<div class="xl:w-1/3 md:w-1/2 p-4"> | ||
<div class="border border-gray-300 p-6 rounded-lg"> | ||
|
||
{% image post.feed_image fill-840x240 as img %} | ||
|
||
|
||
<div | ||
class="w-full inline-flex items-center justify-center rounded-full bg-green-100 text-green-500 mb-4"> | ||
<img class="object-cover object-center h-full w-full" src="{{img.url}}"> | ||
</div> | ||
<div> | ||
<h2 class="text-2xl text-gray-900 font-medium title-font mb-2"> {{ post.title }} </h2> | ||
<p></p> | ||
<p class="leading-relaxed text-lg"> {{ post.specific.summary }}</p> | ||
<a href="{% pageurl post %}" class="mt-3 text-green-500 inline-flex items-center text-xl">Read More | ||
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" | ||
stroke-width="2" class="w-4 h-4 ml-2" viewBox="0 0 24 24"> | ||
<path d="M5 12h14M12 5l7 7-7 7"></path> | ||
</svg> | ||
</a> | ||
</div> | ||
</div> | ||
</div> | ||
{% endfor %} | ||
|
||
</div> | ||
|
||
</div> | ||
</section> | ||
|
||
|
||
{% endblock %} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
{% extends "base.html" %} | ||
{% load wagtailcore_tags %} | ||
{% block body_class %}template-blogpage{% endblock %} | ||
|
||
{% block content %} | ||
{% load wagtailcore_tags wagtailimages_tags %} | ||
<div class="h-10"></div> | ||
<div class="flex justify-center items-center"> | ||
{% image page.feed_image fill-840x240 as img %} | ||
<img src='{{ img.url }}' alt='#' class="p-4 rounded rounded-lg" /> | ||
|
||
</div> | ||
|
||
<div class="w-full flex justify-center items-center px-2 sm:px-10 md:px-24"> | ||
<div class="pt-24"> | ||
<h1 class="mb-4 text-2xl md:text-4xl font-extrabold leading-none tracking-tight text-gray-900 md:text-5xl lg:text-6xl px-4 ">{{ page.title }} </h1> | ||
<div class=" grid grid-cols-1 gap-4"> | ||
<p class="text-sm dark:text-gray-600 px-4 mb-4 md:mb-0">by | ||
<a rel="noopener noreferrer" href="#" target="_blank" class="underline dark:text-violet-600"> | ||
<span itemprop="name">{{ page.author }}</span> | ||
</a>on | ||
<time datetime="2021-02-12 15:34:18-0200"> {{ page.date }} </time> | ||
</p> | ||
<div class=" border-2 border-dotted rounded rounded-lg shadow shadow-lg md:mt-0 w-full md:w-3/4"> | ||
<p class="font-bold border-b-2 border-gray-400 text-2xl"> Schedule </p> | ||
<p> Start Date: <time datetime="2021-02-12 15:34:18-0200"> {{ page.start_date }} </time> </p> | ||
<p> End Date: <time datetime="2021-02-12 15:34:18-0200"> {{ page.end_date }} </time> </p> | ||
</div> | ||
</div> | ||
|
||
<div class="pt-4"> | ||
{% for trainer in page.trainers %} | ||
<div class="px-4 md:px-0"> {{ trainer }} </div> | ||
{% endfor %} | ||
|
||
</div> | ||
|
||
<div class="h-32"></div> | ||
|
||
|
||
{% for block in page.body %} | ||
<div class="md:px-0"> {{ block }} </div> | ||
{% endfor %} | ||
|
||
<hr> | ||
|
||
{% if page.get_tags %} | ||
<h3 class="my-4 font-bold">Find more blog posts with similar tags</h3> | ||
<div class=""> | ||
{% for tag in page.get_tags %} | ||
<span class="border-2 rounded rounded-3xl p-4 inline-flex items-baseline"> <svg xmlns="http://www.w3.org/2000/svg" class="pt-2 pr-2" width="24px" height="24px" viewBox="0 0 24 24" fill="currentColor"><path d="M10.9042 2.10025L20.8037 3.51446L22.2179 13.414L13.0255 22.6063C12.635 22.9969 12.0019 22.9969 11.6113 22.6063L1.71184 12.7069C1.32131 12.3163 1.32131 11.6832 1.71184 11.2926L10.9042 2.10025ZM11.6113 4.22157L3.83316 11.9997L12.3184 20.485L20.0966 12.7069L19.036 5.28223L11.6113 4.22157ZM13.7327 10.5855C12.9516 9.80448 12.9516 8.53815 13.7327 7.7571C14.5137 6.97606 15.78 6.97606 16.5611 7.7571C17.3421 8.53815 17.3421 9.80448 16.5611 10.5855C15.78 11.3666 14.5137 11.3666 13.7327 10.5855Z"></path></svg> | ||
<a href="{{ tag.url }}" class="blog-tags__pill">{{ tag }}</a> </span> | ||
{% endfor %} | ||
</div> | ||
{% endif %} | ||
|
||
|
||
|
||
<div class="w-full relative pt-10"> | ||
<div class="absolute right-4 bg-gray-400 hover:bg-gray-800 hover:text-white p-4 rounded rounded-lg"> | ||
<a rel="noopener noreferrer" href="{{ page.get_parent.url }}" class="flex items-center justify-between w-full"> | ||
<span class="text-xs font-bold tracking-wider uppercase">Return to Courses</span> | ||
<svg viewBox="0 0 24 24" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round" class="w-4 stroke-current dark:text-violet-600"> | ||
<line x1="5" y1="12" x2="19" y2="12"></line> | ||
<polyline points="12 5 19 12 12 19"></polyline> | ||
</svg> | ||
</a> | ||
</div> | ||
|
||
|
||
<hr> | ||
<div class="h-10"></div> | ||
|
||
{% endblock content %} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.test import TestCase | ||
|
||
# Create your tests here. |
Oops, something went wrong.