Skip to content

Commit

Permalink
Feat: agency logos configurable via Admin (#2514)
Browse files Browse the repository at this point in the history
  • Loading branch information
lalver1 authored Nov 18, 2024
2 parents 11f5380 + 6bea2ea commit f8f6fe5
Show file tree
Hide file tree
Showing 27 changed files with 133 additions and 90 deletions.
2 changes: 1 addition & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ DJANGO_SUPERUSER_EMAIL=benefits-admin@calitp.org
DJANGO_SUPERUSER_PASSWORD=superuser12345!

DJANGO_DB_RESET=true
DJANGO_DB_DIR=.
DJANGO_STORAGE_DIR=.
DJANGO_DB_FILE=django.db
DJANGO_DB_FIXTURES="benefits/core/migrations/local_fixtures.json"

Expand Down
7 changes: 7 additions & 0 deletions appcontainer/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ http {
add_header Cache-Control public;
}

# path for uploaded files
location /media/ {
alias /home/calitp/app/data/uploads/;
expires 1y;
add_header Cache-Control public;
}

location / {
# checks for static file, if not found proxy to app
try_files $uri @proxy_to_app;
Expand Down
12 changes: 11 additions & 1 deletion benefits/core/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def unique_values(original_list):


def _agency_context(agency: models.TransitAgency):
return {
agency_context = {
"eligibility_index_url": agency.eligibility_index_url,
"help_templates": unique_values([f.help_template for f in agency.enrollment_flows.all() if f.help_template]),
"info_url": agency.info_url,
Expand All @@ -25,6 +25,16 @@ def _agency_context(agency: models.TransitAgency):
"slug": agency.slug,
}

if agency.logo_large and agency.logo_small:
agency_context.update(
{
"logo_small_url": agency.logo_small.url,
"logo_large_url": agency.logo_large.url,
}
)

return agency_context


def agency(request):
"""Context processor adds some information about the active agency to the request context."""
Expand Down
36 changes: 36 additions & 0 deletions benefits/core/migrations/0031_transitagency_logo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 5.1.2 on 2024-11-14 18:05

import benefits.core.models
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("core", "0030_enrollmentevent_extra_claims"),
]

operations = [
migrations.AddField(
model_name="transitagency",
name="logo_large",
field=models.ImageField(
blank=True,
default=None,
help_text="The large version of the transit agency's logo.",
null=True,
upload_to=benefits.core.models.agency_logo_large,
),
),
migrations.AddField(
model_name="transitagency",
name="logo_small",
field=models.ImageField(
blank=True,
default=None,
help_text="The small version of the transit agency's logo.",
null=True,
upload_to=benefits.core.models.agency_logo_small,
),
),
]
4 changes: 3 additions & 1 deletion benefits/core/migrations/local_fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@
"transit_processor_client_id": "",
"transit_processor_client_secret_name": "cst-transit-processor-client-secret",
"staff_group": 2,
"customer_service_group": 2
"customer_service_group": 2,
"logo_large": "agencies/cst-lg.png",
"logo_small": "agencies/cst-sm.png"
}
},
{
Expand Down
28 changes: 28 additions & 0 deletions benefits/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from functools import cached_property
import importlib
import logging
import os
import uuid

from django.conf import settings
Expand Down Expand Up @@ -126,6 +127,19 @@ def __str__(self):
return self.name


def _agency_logo(instance, filename, size):
base, ext = os.path.splitext(filename)
return f"agencies/{instance.slug}-{size}" + ext


def agency_logo_small(instance, filename):
return _agency_logo(instance, filename, "sm")


def agency_logo_large(instance, filename):
return _agency_logo(instance, filename, "lg")


class TransitAgency(models.Model):
"""An agency offering transit service."""

Expand Down Expand Up @@ -191,6 +205,20 @@ class TransitAgency(models.Model):
help_text="The group of users who are allowed to do in-person eligibility verification and enrollment.",
related_name="+",
)
logo_large = models.ImageField(
default=None,
null=True,
blank=True,
upload_to=agency_logo_large,
help_text="The large version of the transit agency's logo.",
)
logo_small = models.ImageField(
default=None,
null=True,
blank=True,
upload_to=agency_logo_small,
help_text="The small version of the transit agency's logo.",
)

def __str__(self):
return self.long_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ <h3 id="{{ aria_labelledby_id }}" class="modal-title h1 p-0 mb-4 pb-lg-2s text-c
<a href="{{ agency.eligibility_index_url }}" class="card m-0 d-inline-block">
<div class="card-body d-flex flex-row-reverse flex-lg-column justify-content-center align-items-center">
<img class="sm d-lg-none ms-auto"
src="{% get_static_prefix %}img/agencies/{{ agency.slug }}-sm.svg"
src="{{ agency.logo_small_url }}"
width="52"
height="36"
alt="{% blocktranslate with agency=agency.short_name %}{{ agency }} logo{% endblocktranslate %}">
<img class="lg d-none d-lg-block"
src="{% get_static_prefix %}img/agencies/{{ agency.slug }}-lg.svg"
src="{{ agency.logo_large_url }}"
width="148"
height="72"
alt="{% blocktranslate with agency=agency.short_name %}{{ agency }} logo{% endblocktranslate %}">
Expand Down
15 changes: 12 additions & 3 deletions benefits/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ def RUNTIME_ENVIRONMENT():

WSGI_APPLICATION = "benefits.wsgi.application"

DATABASE_DIR = os.environ.get("DJANGO_DB_DIR", BASE_DIR)
STORAGE_DIR = os.environ.get("DJANGO_STORAGE_DIR", BASE_DIR)
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(DATABASE_DIR, os.environ.get("DJANGO_DB_FILE", "django.db")),
"NAME": os.path.join(STORAGE_DIR, os.environ.get("DJANGO_DB_FILE", "django.db")),
}
}

Expand Down Expand Up @@ -234,14 +234,23 @@ def RUNTIME_ENVIRONMENT():
STATICFILES_DIRS = [os.path.join(BASE_DIR, "benefits", "static")]
# use Manifest Static Files Storage by default
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": os.environ.get(
"DJANGO_STATICFILES_STORAGE", "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
)
}
},
}
STATIC_ROOT = os.path.join(BASE_DIR, "static")

# User-uploaded files

MEDIA_ROOT = os.path.join(STORAGE_DIR, "uploads/")

MEDIA_URL = "/media/"

# Logging configuration
LOG_LEVEL = os.environ.get("DJANGO_LOG_LEVEL", "DEBUG" if DEBUG else "WARNING")
LOGGING = {
Expand Down
3 changes: 0 additions & 3 deletions benefits/static/img/agencies/cst-lg.svg

This file was deleted.

3 changes: 0 additions & 3 deletions benefits/static/img/agencies/cst-sm.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/mst-lg.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/mst-sm.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/nevco-lg.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/nevco-sm.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/sacrt-lg.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/sacrt-sm.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/sbmtd-lg.svg

This file was deleted.

9 changes: 0 additions & 9 deletions benefits/static/img/agencies/sbmtd-sm.svg

This file was deleted.

5 changes: 5 additions & 0 deletions benefits/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.contrib import admin
from django.http import HttpResponse
from django.urls import include, path
from django.conf.urls.static import static

logger = logging.getLogger(__name__)

Expand All @@ -37,6 +38,10 @@ def trigger_error(request):

urlpatterns.append(path("error/", trigger_error))

# serve user-uploaded media files
# https://docs.djangoproject.com/en/5.1/howto/static-files/#serving-files-uploaded-by-a-user-during-development
urlpatterns.extend(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT))

# simple route to read a pre-defined "secret"
# this "secret" does not contain sensitive information
# and is only configured in the dev environment for testing/debugging
Expand Down
2 changes: 1 addition & 1 deletion bin/reset_db.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ DB_RESET="${DJANGO_DB_RESET:-true}"

if [[ $DB_RESET = true ]]; then
# construct the path to the database file from environment or default
DB_DIR="${DJANGO_DB_DIR:-.}"
DB_DIR="${DJANGO_STORAGE_DIR:-.}"
DB_FILE="${DJANGO_DB_FILE:-django.db}"
DB_PATH="${DB_DIR}/${DB_FILE}"

Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ If blank or an invalid key, analytics events aren't captured (though may still b

A list of strings representing the host/domain names that this Django site can serve.

### `DJANGO_DB_DIR`
### `DJANGO_STORAGE_DIR`

!!! warning "Deployment configuration"

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies = [
"requests==2.32.3",
"sentry-sdk==2.18.0",
"six==1.16.0",
"pillow==11.0.0",
"django-multiselectfield==0.1.13",
]

Expand Down
2 changes: 1 addition & 1 deletion terraform/app_service.tf
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ resource "azurerm_linux_web_app" "main" {

# Django settings
"DJANGO_ALLOWED_HOSTS" = "${local.secret_prefix}django-allowed-hosts)",
"DJANGO_DB_DIR" = "${local.secret_prefix}django-db-dir)",
"DJANGO_STORAGE_DIR" = "${local.secret_prefix}django-storage-dir)",
"DJANGO_DEBUG" = local.is_prod ? null : "${local.secret_prefix}django-debug)",
"DJANGO_LOG_LEVEL" = "${local.secret_prefix}django-log-level)",

Expand Down
22 changes: 21 additions & 1 deletion tests/pytest/core/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@

import pytest

from benefits.core.models import SecretNameField, EnrollmentFlow, TransitAgency, EnrollmentEvent, EnrollmentMethods
from benefits.core.models import (
SecretNameField,
EnrollmentFlow,
TransitAgency,
EnrollmentEvent,
EnrollmentMethods,
agency_logo_small,
agency_logo_large,
)
import benefits.secrets


Expand Down Expand Up @@ -413,6 +421,18 @@ def test_TransitAgency_for_user_in_group_not_linked_to_any_agency():
assert TransitAgency.for_user(user) is None


@pytest.mark.django_db
def test_agency_logo_small(model_TransitAgency):

assert agency_logo_small(model_TransitAgency, "local_filename.png") == "agencies/test-sm.png"


@pytest.mark.django_db
def test_agency_logo_large(model_TransitAgency):

assert agency_logo_large(model_TransitAgency, "local_filename.png") == "agencies/test-lg.png"


@pytest.mark.django_db
def test_EnrollmentEvent_create(model_TransitAgency, model_EnrollmentFlow):
ts = timezone.now()
Expand Down
3 changes: 3 additions & 0 deletions uploads/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*
!*/
!agencies/cst-*.png
Binary file added uploads/agencies/cst-lg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added uploads/agencies/cst-sm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f8f6fe5

Please sign in to comment.