Skip to content

Commit

Permalink
Merge pull request #1173 from Metro-Records/hcg/wagtail
Browse files Browse the repository at this point in the history
Install Wagtail and transition About page to CMS
  • Loading branch information
hancush authored Dec 2, 2024
2 parents aa6efe9 + 80a2ba4 commit 0ce6b79
Show file tree
Hide file tree
Showing 39 changed files with 2,024 additions and 384 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,5 @@ jobs:
DATABASE_URL: postgis://postgres:postgres@localhost:5432/lametro
SEARCH_URL: http://localhost:9200
run: |
flake8 .
black --check .
cp .env.local.example .env.local
pytest -sv
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ lametro/secrets.py
.env

.venv
media/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ RUN pip install pip==24.0 && \

COPY . /app

RUN DJANGO_SETTINGS_MODULE=councilmatic.minimal_settings python manage.py collectstatic
RUN DJANGO_SETTINGS_MODULE=councilmatic.minimal_settings python manage.py collectstatic --no-input

ENTRYPOINT ["/app/docker-entrypoint.sh"]
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ Grab the values for the `AWS_ACCESS_KEY_ID` and the `AWS_SECRET_ACCESS_KEY` and

Now you should be able to start uploading some files!

## Review Apps
This repo is set up to deploy review apps on Heroku, and those pull from the staging database to match the experience of deploying as closely as possible! However, note that in order to prevent unapproved model changes from effecting the staging database, migrations are prevented from running on review apps. So those will still have to be reviewed locally.

### Review apps for Wagtail changes

1. Configure the S3 connection, as documented above.
2. Once a release phase successfully completes, provision an Essential 0 database for your review app.
3. Retrieve the URI from the Credentials tab.
4. Run `export HEROKU_DATABASE_URL=<YOUR URI HERE>`.
5. If needed, run `docker compose run --rm -e DATABASE_URL=${HEROKU_DATABASE_URI} scrapers` to populate initial legislative data.
6. Run `docker compose run --rm -e DATABASE_URL=${HEROKU_DATABASE_URI} app python manage.py load_content` to populate initial CMS content from the version controlled fixtures.

## Adding a new board member

Hooray! A new member has been elected or appointed to the Board of Directors.
Expand Down Expand Up @@ -205,9 +217,10 @@ This will start the Locust web server on http://localhost:8089. For more details
see the [Locust documentation](https://docs.locust.io/en/stable/).

## Review Apps

This repo is set up to deploy review apps on Heroku, and those pull from the staging database to match the experience of deploying as closely as possible! However, note that in order to prevent unapproved model changes from effecting the staging database, migrations are prevented from running on review apps. So those will still have to be reviewed locally.

## Updating the documentation
## Updating the Documentation

To make changes to the documentation, [install Quarto](https://quarto.org/docs/get-started/).

Expand Down
5 changes: 5 additions & 0 deletions councilmatic/minimal_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@

import os

SECRET_KEY = "really super secret"

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT = os.path.join(BASE_DIR, "static")
STATIC_URL = "/static/"

INSTALLED_APPS = (
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.staticfiles",
"django.contrib.gis",
"opencivicdata.core",
"opencivicdata.legislative",
"lametro",
"councilmatic_core",
"wagtail",
"debug_toolbar",
"captcha",
)
Expand Down
27 changes: 24 additions & 3 deletions councilmatic/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
REMOTE_ANALYTICS_FOLDER=(str, ""),
GOOGLE_SERVICE_ACCT_API_KEY=(str, ""),
GOOGLE_API_KEY=(str, ""),
WAGTAILADMIN_BASE_URL=(str, "https://boardagendas.metro.net"),
)

# Core Django Settings
Expand Down Expand Up @@ -125,6 +126,20 @@
"template_profiler_panel",
"captcha",
"markdownify.apps.MarkdownifyConfig",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.contrib.typed_table_block",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
"modelcluster",
"taggit",
)

try:
Expand All @@ -142,6 +157,7 @@
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
)

ROOT_URLCONF = "councilmatic.urls"
Expand Down Expand Up @@ -187,6 +203,9 @@
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "static")

MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

# Third Party Keys
RECAPTCHA_PUBLIC_KEY = env("RECAPTCHA_PUBLIC_KEY")
RECAPTCHA_PRIVATE_KEY = env("RECAPTCHA_PRIVATE_KEY")
Expand Down Expand Up @@ -231,10 +250,9 @@
)
from django.core.files.storage import get_storage_class

S3Storage = get_storage_class("storages.backends.s3boto3.S3Boto3Storage")

AWS_QUERYSTRING_AUTH = False
COUNCILMATIC_HEADSHOT_STORAGE_BACKEND = S3Storage()
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
COUNCILMATIC_HEADSHOT_STORAGE_BACKEND = get_storage_class(DEFAULT_FILE_STORAGE)

else:
print("AWS not configured. Defaulting to local storage...")
Expand Down Expand Up @@ -326,3 +344,6 @@ def custom_sampler(ctx):

# Hard time limit on HTTP requests
REQUEST_TIMEOUT = 5

WAGTAIL_SITE_NAME = "boardagendas.metro.net"
WAGTAILADMIN_BASE_URL = env("WAGTAILADMIN_BASE_URL")
12 changes: 9 additions & 3 deletions councilmatic/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from django.conf import settings
from django.conf.urls import include, url
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path
from django.views.static import serve
from django.views.decorators.cache import never_cache

from haystack.query import EmptySearchQuerySet

from wagtail.admin import urls as wagtailadmin_urls
from wagtail import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls

from councilmatic_core.views import (
CouncilmaticSearchForm,
)
Expand All @@ -23,7 +28,6 @@
LAMetroEventDetail,
LABillDetail,
LABoardMembersView,
LAMetroAboutView,
LACommitteeDetailView,
LACommitteesView,
LAPersonDetailView,
Expand Down Expand Up @@ -63,7 +67,6 @@
),
url(r"^archive-search", LAMetroArchiveSearch.as_view(), name="archive-search"),
url(r"^$", never_cache(LAMetroIndexView.as_view()), name="index"),
url(r"^about/$", LAMetroAboutView.as_view(), name="about"),
url(
r"^board-report/(?P<slug>[^/]+)/$",
LABillDetail.as_view(),
Expand Down Expand Up @@ -129,9 +132,12 @@
name="lametro_ses_endpoint",
),
path("smartlogic/", include("smartlogic.urls", namespace="smartlogic")),
path("cms/", include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
path("", include(wagtail_urls)),
url(r"", include("councilmatic_core.urls")),
url(r"^test-logging/$", test_logging, name="test_logging"),
]
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG:
import debug_toolbar
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ services:
DATABASE_URL: 'postgis://postgres:postgres@postgres/lametro'
SHARED_DB: "True"
OCD_DIVISION_CSV: '/app/lametro_divisions.csv'
command: sh -c 'pupa update --rpm=600 lametro people && pupa update --rpm=600 lametro bills window=14 && pupa update --rpm=600 lametro events window=14'
command: sh -c 'pupa update --rpm=600 lametro people && pupa update --rpm=600 lametro bills window=7 && pupa update --rpm=600 lametro events window=7'
volumes:
- ./lametro/secrets.py:/app/lametro/secrets.py
- ./data/lametro_divisions.csv:/app/lametro_divisions.csv
Expand Down
66 changes: 66 additions & 0 deletions lametro/blocks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from wagtail import blocks
from wagtail.images.blocks import ImageChooserBlock
from wagtail.contrib.typed_table_block.blocks import TypedTableBlock


class NavigationBlock(blocks.StaticBlock):
class Meta:
template = "lametro/blocks/navigation.html"
icon = "bars"

def get_context(self, *args, **kwargs):
context = super().get_context(*args, **kwargs)

if parent_context := kwargs.get("parent_context"):
context["navigation_items"] = {
section.value["heading"] or "Unnamed Section": section.value["anchor"]
for section in parent_context["page"].body
if section.value["anchor"]
}

return context


class Breakpoints(blocks.StructBlock):
class Meta:
help_text = "Max number of columns to display on different devices"

sm = blocks.IntegerBlock(default=1, help_text="Mobile phone")
md = blocks.IntegerBlock(default=2, help_text="Tablet")
lg = blocks.IntegerBlock(default=4, help_text="Desktop")


class ResponsiveContent(blocks.StructBlock):
breakpoints = Breakpoints()
content = blocks.StreamBlock(
[
(
"table",
TypedTableBlock(
[
("rich_text", blocks.RichTextBlock()),
]
),
)
]
)


class ContentBlock(blocks.StreamBlock):
text = blocks.RichTextBlock()
image = ImageChooserBlock()
table = TypedTableBlock(
[
("rich_text", blocks.RichTextBlock()),
]
)
navigation = NavigationBlock()
responsive_element = ResponsiveContent()


class ArticleBlock(blocks.StructBlock):
heading = blocks.CharBlock(required=False)
content = ContentBlock()
anchor = blocks.CharBlock(
required=False, help_text="Add anchor to enable direct links to this section"
)
1,385 changes: 1,385 additions & 0 deletions lametro/fixtures/cms_content.json

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 50 additions & 0 deletions lametro/management/commands/dump_content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from pathlib import Path
import subprocess

from django.apps import apps
from django.core.management.base import BaseCommand
from django.core.management import call_command


class Command(BaseCommand):
"""
Dump core Wagtail content and any custom pages and/or Django models
where the include_in_dump attribute is True. Also copy images uploaded
locally to the fixtures directory, so that they can be loaded to default
storage (usually S3) during deployment.
"""

def handle(self, **options):
app_models = apps.get_app_config("lametro").get_models()

excluded_app_models = [
f"lametro.{m.__name__}"
for m in app_models
if not getattr(m, "include_in_dump", False)
]

call_command(
"dumpdata",
natural_foreign=True,
indent=4,
output=Path("lametro/fixtures/cms_content.json"),
exclude=[
"contenttypes",
"auth.permission",
"wagtailcore.groupcollectionpermission",
"wagtailcore.grouppagepermission",
"wagtailsearch.indexentry",
"sessions",
]
+ excluded_app_models,
)

subprocess.run(
[
"cp",
"-R",
"media/.",
"lametro/fixtures/initial_images/",
],
check=True,
)
Loading

0 comments on commit 0ce6b79

Please sign in to comment.