diff --git a/Dockerfile b/Dockerfile index f1263ee..6391932 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ ARG NODE_IMG_TAG=20.5.1 FROM node:${NODE_IMG_TAG}-bookworm-slim as frontend-base COPY . ./app WORKDIR /app/frontend +RUN mkdir -p ./node_modules RUN npm install RUN mkdir -p ./dist/css RUN npm run build @@ -81,6 +82,7 @@ ENV PORT=8000 \ REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt \ CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # Install non-dev versions of packages (smaller) +RUN apt-get update && apt-get install -y "curl" RUN set -ex \ && apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install \ @@ -90,6 +92,8 @@ RUN set -ex \ "libjpeg62-turbo" \ "zlib1g" \ "libwebp-dev" \ + "nodejs" \ + "npm" \ && rm -rf /var/lib/apt/lists/* # Copy the entrypoint script into the Docker image COPY --chown=wagtail:wagtail container-entrypoint.sh / @@ -100,6 +104,7 @@ COPY --from=build \ # Copy compiled css from frontend stage # In the final stage of your Dockerfile... COPY --from=frontend-base /app/frontend/dist/css /app/frontend/dist/css +COPY --from=frontend-base /app/frontend/node_modules /app/frontend/node_modules # Use /app folder as a directory where the source code is stored. WORKDIR /app # Copy project diff --git a/README.md b/README.md index 9da7d7c..fc06d06 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,11 @@ This project uses Poetry for dependency management. Poetry is a Python tool that Dependencies are specified in the `pyproject.toml`, and the exact versions of the dependencies are locked in the `poetry.lock`. To install the dependencies, run `poetry install`. To add a new dependency, run `poetry add {dependency}`. +Note that you don't need to run `poetry install`, as Docker handles this when building. + ## Using the Makefile -Ensure you have the superuser credentials you want in your .env.dev file prior to running `make build-dev`. +Ensure you have the superuser credentials you want in your .env.dev file prior to running `make build`. The Makefile provides several commands for building and running the project: - `make build`: Builds and starts the Docker images for the development environment. @@ -43,3 +45,24 @@ The Makefile provides several commands for building and running the project: - `make down-prod`: Stops the Docker containers for the production environment. - `make test`: Runs the tests. - `make refresh-db`: Deletes all Docker volumes (use with caution). + +## Building Tailwind + +When you attempt to use a class that isn't currently used anywhere in the project, the live reload will not rebuild the CSS, and thus, these classes won't work until you rebuild the CSS: + +1. Open Docker Desktop +2. In the Containers tab, click on the `web-1` container (within the `website` container) +3. Move to the `Exec` tab within this container +4. Move into the `frontend` folder with `cd frontend` +5. Run `npm run build` to rebuild the CSS + +You'll need to do this every time you use a currently unused class. + +## Wagtail Migrations + +Wagtail migrations should be handled within the Docker container. The process for doing this is largely the same as building Tailwind: + +1. Open Docker Desktop +2. In the Containers tab, click on the `web-1` container (within the `website` container) +3. Move to the `Exec` tab within this container +4. Run `python manage.py makemigrations` and then `python manage.py migrate` (if successful) diff --git a/app/impact_areas/__init__.py b/app/impact_areas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/impact_areas/admin.py b/app/impact_areas/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/app/impact_areas/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/app/impact_areas/apps.py b/app/impact_areas/apps.py new file mode 100644 index 0000000..5301481 --- /dev/null +++ b/app/impact_areas/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ImpactAreasConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app.impact_areas' diff --git a/app/impact_areas/migrations/0001_initial.py b/app/impact_areas/migrations/0001_initial.py new file mode 100644 index 0000000..fa7bd1a --- /dev/null +++ b/app/impact_areas/migrations/0001_initial.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.7 on 2024-05-02 21:22 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0089_log_entry_data_json_null_to_object'), + ] + + operations = [ + migrations.CreateModel( + name='ImpactAreasPage', + 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')), + ('test', wagtail.fields.RichTextField(blank=True)), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + ] diff --git a/app/impact_areas/migrations/0002_rename_test_impactareaspage_intro.py b/app/impact_areas/migrations/0002_rename_test_impactareaspage_intro.py new file mode 100644 index 0000000..9714fad --- /dev/null +++ b/app/impact_areas/migrations/0002_rename_test_impactareaspage_intro.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2024-05-02 21:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='impactareaspage', + old_name='test', + new_name='intro', + ), + ] diff --git a/app/impact_areas/migrations/0003_impactareaspage_image.py b/app/impact_areas/migrations/0003_impactareaspage_image.py new file mode 100644 index 0000000..59ace8e --- /dev/null +++ b/app/impact_areas/migrations/0003_impactareaspage_image.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.7 on 2024-05-06 20:58 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailimages', '0025_alter_image_file_alter_rendition_file'), + ('impact_areas', '0002_rename_test_impactareaspage_intro'), + ] + + operations = [ + migrations.AddField( + model_name='impactareaspage', + name='image', + field=models.ForeignKey(blank=True, help_text='Header image', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image'), + ), + ] diff --git a/app/impact_areas/migrations/0004_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0004_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..28667f3 --- /dev/null +++ b/app/impact_areas/migrations/0004_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-06 23:47 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0003_impactareaspage_image'), + ] + + operations = [ + migrations.AddField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock(form_classname='title')), ('description', wagtail.blocks.RichTextBlock()), ('link', wagtail.blocks.URLBlock())], blank=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/0005_alter_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0005_alter_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..b975942 --- /dev/null +++ b/app/impact_areas/migrations/0005_alter_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-06 23:48 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0004_impactareaspage_impact_area_blocks'), + ] + + operations = [ + migrations.AlterField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock(form_classname='title')), ('description', wagtail.blocks.RichTextBlock()), ('link', wagtail.blocks.URLBlock())], null=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/0006_alter_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0006_alter_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..acc6292 --- /dev/null +++ b/app/impact_areas/migrations/0006_alter_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-06 23:50 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0005_alter_impactareaspage_impact_area_blocks'), + ] + + operations = [ + migrations.AlterField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock(form_classname='title')), ('description', wagtail.blocks.CharBlock()), ('link', wagtail.blocks.URLBlock())], null=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/0007_alter_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0007_alter_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..960bd8e --- /dev/null +++ b/app/impact_areas/migrations/0007_alter_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-06 23:54 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0006_alter_impactareaspage_impact_area_blocks'), + ] + + operations = [ + migrations.AlterField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock()), ('description', wagtail.blocks.RichTextBlock()), ('link', wagtail.blocks.URLBlock())], null=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/0008_alter_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0008_alter_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..34fe8c5 --- /dev/null +++ b/app/impact_areas/migrations/0008_alter_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-06 23:58 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0007_alter_impactareaspage_impact_area_blocks'), + ] + + operations = [ + migrations.AlterField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('impact_area_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock()), ('description', wagtail.blocks.RichTextBlock()), ('link', wagtail.blocks.URLBlock())]))], null=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/0009_alter_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0009_alter_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..9527fca --- /dev/null +++ b/app/impact_areas/migrations/0009_alter_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-07 16:12 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0008_alter_impactareaspage_impact_area_blocks'), + ] + + operations = [ + migrations.AlterField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('impact_area_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock()), ('description', wagtail.blocks.RichTextBlock()), ('link', wagtail.blocks.URLBlock(null=True))]))], null=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/0010_alter_impactareaspage_impact_area_blocks.py b/app/impact_areas/migrations/0010_alter_impactareaspage_impact_area_blocks.py new file mode 100644 index 0000000..0333000 --- /dev/null +++ b/app/impact_areas/migrations/0010_alter_impactareaspage_impact_area_blocks.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2024-05-07 16:13 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('impact_areas', '0009_alter_impactareaspage_impact_area_blocks'), + ] + + operations = [ + migrations.AlterField( + model_name='impactareaspage', + name='impact_area_blocks', + field=wagtail.fields.StreamField([('impact_area_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock()), ('description', wagtail.blocks.RichTextBlock()), ('link', wagtail.blocks.URLBlock(required=False))]))], null=True, use_json_field=True), + ), + ] diff --git a/app/impact_areas/migrations/__init__.py b/app/impact_areas/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/impact_areas/models.py b/app/impact_areas/models.py new file mode 100644 index 0000000..0aa0a50 --- /dev/null +++ b/app/impact_areas/models.py @@ -0,0 +1,41 @@ +from django.db import models + +from wagtail.models import Page +from wagtail.fields import RichTextField, StreamField +from wagtail.blocks import StreamBlock, CharBlock, URLBlock, RichTextBlock, StructBlock +from wagtail.images.blocks import ImageChooserBlock +from wagtail.admin.panels import FieldPanel, MultiFieldPanel + + +class IndividualBlock(StructBlock): + image = ImageChooserBlock() + title = CharBlock() + description = RichTextBlock() + link = URLBlock(required=False) + + +class ImpactAreaBlock(StreamBlock): + impact_area_block = IndividualBlock() + + +class ImpactAreasPage(Page): + intro = RichTextField(blank=True) + + image = models.ForeignKey( + "wagtailimages.Image", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="+", + help_text="Header image" + ) + + impact_area_blocks = StreamField(ImpactAreaBlock(), use_json_field=True, null=True) + + content_panels = Page.content_panels + [ + MultiFieldPanel([ + FieldPanel('image'), + FieldPanel('intro') + ], heading="Header section"), + FieldPanel('impact_area_blocks') + ] diff --git a/app/impact_areas/templates/impact_areas/impact_areas_page.html b/app/impact_areas/templates/impact_areas/impact_areas_page.html new file mode 100644 index 0000000..c5867f9 --- /dev/null +++ b/app/impact_areas/templates/impact_areas/impact_areas_page.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load static %} +{% load wagtailcore_tags %} +{% load wagtailimages_tags %} +{% load compress %} +{% block body_class %}template-impactareaspage{% endblock %} +{% block extra_css %} + {% compress css %} + {% endcompress css %} +{% endblock extra_css %} + +{% block content %} + {% include "ui/components/BasePageHeader.html" with title=page.title intro=page.intro image=page.image %} + +
+ {% for block in page.impact_area_blocks %} + {% include "ui/components/LearnMoreAboutBlurbWithImage.html" with title=block.value.title description=block.value.description image=block.value.image link=block.value.link %} + {% endfor %} +
+{% endblock %} \ No newline at end of file diff --git a/app/impact_areas/tests.py b/app/impact_areas/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/impact_areas/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/impact_areas/views.py b/app/impact_areas/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/app/impact_areas/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/app/ui/__init__.py b/app/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/ui/admin.py b/app/ui/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/app/ui/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/app/ui/apps.py b/app/ui/apps.py new file mode 100644 index 0000000..84bc3f8 --- /dev/null +++ b/app/ui/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UiConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app.ui' diff --git a/app/ui/migrations/__init__.py b/app/ui/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/ui/models.py b/app/ui/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/app/ui/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/app/ui/templates/ui/components/BasePageHeader.html b/app/ui/templates/ui/components/BasePageHeader.html new file mode 100644 index 0000000..c0172b0 --- /dev/null +++ b/app/ui/templates/ui/components/BasePageHeader.html @@ -0,0 +1,24 @@ +{% comment %} +==> PARAMETERS +- title: A string, the title shown in the header +- intro: An HTML element (regular usage would be a

with some text in it) +- image: A Wagtail image +{% endcomment %} + +{% load wagtailimages_tags %} + +{% image image original as image_p %} +

+
+
+
+

+ {{ title }} +

+
+
+ {{ intro|safe }} +
+
+
+
\ No newline at end of file diff --git a/app/ui/templates/ui/components/LearnMoreAboutBlurbWithImage.html b/app/ui/templates/ui/components/LearnMoreAboutBlurbWithImage.html new file mode 100644 index 0000000..964521d --- /dev/null +++ b/app/ui/templates/ui/components/LearnMoreAboutBlurbWithImage.html @@ -0,0 +1,26 @@ +{% load wagtailimages_tags %} +{% image image original as image_p %} + +
+
+ +
+ +

+ {{ title }} +

+ +
+ {{ description }} +
+ +

+ + Learn More about {{ title }} + + + + + +

+
\ No newline at end of file diff --git a/app/ui/tests.py b/app/ui/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/ui/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/ui/views.py b/app/ui/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/app/ui/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index fa999b3..3d379d9 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -11,6 +11,7 @@ services: volumes: - .:/app # Mount the codebase for development - /app/frontend/dist/css # Mount only the necessary directory for live reload + - /app/frontend/node_modules - /app/*/templates # Mount Django templates directory ports: - 8000:8000 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5e5a8c9..8781ce2 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tailwindcss/forms": "^0.5.7", "autoprefixer": "^10.4.16", - "postcss": "^8.4.33", + "postcss": "^8.4.32", "postcss-cli": "^10.1.0", "postcss-import": "^15.1.0", "prettier-plugin-tailwindcss": "^0.5.9", diff --git a/frontend/package.json b/frontend/package.json index 3613728..f8f27bd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,7 +14,8 @@ }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "npx postcss ../hot_osm/static/css/hot_osm.css --config ./postcss.config.js -o ./dist/css/hot_osm_processed.css && prettier --write ." + "build": "npx postcss ../hot_osm/static/css/hot_osm.css --config ./postcss.config.js -o ./dist/css/hot_osm_processed.css && prettier --write .", + "watch:css": "npx postcss ../hot_osm/static/css/hot_osm.css --config ./postcss.config.js -o ./dist/css/hot_osm_processed.css --watch" }, "repository": { "type": "git", diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index f1c8dac..12a703d 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -2,5 +2,5 @@ module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, - } -} + }, +}; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 1c75384..68af97b 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -2,54 +2,55 @@ module.exports = { future: {}, - content: ["../*/templates/*.{html,js}", "../*/templates/**/*.{html,js}"], + content: [ + "../*/templates/*.{html,js}", + "../*/templates/**/*.{html,js}", + "../app/*/templates/*.{html,js}", + "../app/*/templates/**/*.{html,js}", + ], darkMode: "media", theme: { extend: { - spacing: { - "hot-1": "0.625rem", // 10px - "hot-1.2": "0.75rem", // 12px - "hot-1.5": "0.9375rem", // 15px - "hot-2": "1.25rem", // 20px - "hot-2.6": "1.625rem", // 26px - "hot-3": "1.875rem", // 30px - "hot-3.4": "2.125rem", // 34px - "hot-4": "2.5rem", // 40px - "hot-6": "3.75rem", // 60px - "hot-6.6": "4.125rem", // 66px - "hot-8": "5rem", // 80px - "hot-10": "6.25rem", // 100px - "hot-12": "7.5rem", // 120px - }, - fontFamily: { - barlow: "var(--font-barlow)", - archivo: "var(--font-archivo)", - }, - fontSize: { - h1: "var(--font-size-h1)", // 56pt - h2: "var(--font-size-h2)", // 48pt - h3: "var(--font-size-h3)", // 38pt - h4: "var(--font-size-h4)", // 32pt - h5: "var(--font-size-h5)", // 28pt - intro: "var(--font-size-intro)", // 22pt - "base-20": "var(--font-size-base-20)", // 20pt - "base-18": "var(--font-size-base-18)", // 18pt - "base-16": "var(--font-size-base-16)", // 16pt - }, - colors: { - "hot-red": "var(--hot-red)", - "hot-navy": "var(--hot-navy)", - "hot-dark-grey": "var(--hot-dark-grey)", - "hot-slate-grey": "var(--hot-slate-grey)", - "hot-light-grey": "var(--hot-light-grey)", - "hot-off-white": "var(--hot-off-white)", - "hot-white": "var(--hot-white)", - "hot-black": "var(--hot-black)", - }, + spacing: { + "hot-1": "0.625rem", // 10px + "hot-1.2": "0.75rem", // 12px + "hot-1.5": "0.9375rem", // 15px + "hot-2": "1.25rem", // 20px + "hot-2.6": "1.625rem", // 26px + "hot-3": "1.875rem", // 30px + "hot-3.4": "2.125rem", // 34px + "hot-4": "2.5rem", // 40px + "hot-6": "3.75rem", // 60px + "hot-6.6": "4.125rem", // 66px + "hot-8": "5rem", // 80px + "hot-10": "6.25rem", // 100px + "hot-12": "7.5rem", // 120px + }, + fontFamily: { + barlow: "var(--font-barlow)", + archivo: "var(--font-archivo)", + }, + fontSize: { + h1: "var(--font-size-h1)", // 56pt + h2: "var(--font-size-h2)", // 48pt + h3: "var(--font-size-h3)", // 38pt + h4: "var(--font-size-h4)", // 32pt + h5: "var(--font-size-h5)", // 28pt + intro: "var(--font-size-intro)", // 22pt + base: "var(--font-size-base)", // 20pt + }, + colors: { + "hot-red": "var(--hot-red)", + "hot-navy": "var(--hot-navy)", + "hot-dark-grey": "var(--hot-dark-grey)", + "hot-slate-grey": "var(--hot-slate-grey)", + "hot-light-grey": "var(--hot-light-grey)", + "hot-off-white": "var(--hot-off-white)", + "hot-white": "var(--hot-white)", + "hot-black": "var(--hot-black)", + }, }, }, variants: {}, - plugins: [ - require("@tailwindcss/forms"), - ], + plugins: [require("@tailwindcss/forms")], }; diff --git a/hot_osm/locale/en/LC_MESSAGES/django.po b/hot_osm/locale/en/LC_MESSAGES/django.po index ab7f8f5..e84db45 100644 --- a/hot_osm/locale/en/LC_MESSAGES/django.po +++ b/hot_osm/locale/en/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-14 08:59+0000\n" +"POT-Creation-Date: 2024-05-02 21:38+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/hot_osm/locale/es/LC_MESSAGES/django.po b/hot_osm/locale/es/LC_MESSAGES/django.po index abf1c64..d5aa379 100644 --- a/hot_osm/locale/es/LC_MESSAGES/django.po +++ b/hot_osm/locale/es/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-14 08:59+0000\n" +"POT-Creation-Date: 2024-05-02 21:38+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/hot_osm/locale/fr/LC_MESSAGES/django.po b/hot_osm/locale/fr/LC_MESSAGES/django.po index 8bbb1e9..5eaf4fd 100644 --- a/hot_osm/locale/fr/LC_MESSAGES/django.po +++ b/hot_osm/locale/fr/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-14 08:59+0000\n" +"POT-Creation-Date: 2024-05-02 21:38+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/hot_osm/settings/base.py b/hot_osm/settings/base.py index 9ead378..8bc8c1f 100644 --- a/hot_osm/settings/base.py +++ b/hot_osm/settings/base.py @@ -29,6 +29,8 @@ INSTALLED_APPS = [ "home", + "app.impact_areas", + "app.ui", "search", "users", "utils", diff --git a/hot_osm/static/css/hot_osm.css b/hot_osm/static/css/hot_osm.css index a87df9a..b1337ff 100644 --- a/hot_osm/static/css/hot_osm.css +++ b/hot_osm/static/css/hot_osm.css @@ -13,32 +13,37 @@ --hot-white: #FFFFFF; --hot-black: #000000; - /* Font Family */ + /* Font Family */ --font-barlow: "Barlow Condensed", sans-serif; --font-archivo: "Archivo", sans-serif; + font-family: var(--font-archivo); /* Font Size */ - --font-size-h1: 3.5rem; /* 56pt */ - --font-size-h2: 3rem; /* 48pt */ - --font-size-h3: 2.375rem; /* 38pt */ - --font-size-h4: 2rem; /* 32pt */ - --font-size-h5: 1.75rem; /* 28pt */ - --font-size-intro: 1.375rem; /* 22pt */ - --font-size-base-20: 1.25rem; /* 20pt */ - --font-size-base-18: 1.125rem; /* 18pt */ - --font-size-base-16: 1rem; /* 16pt */ + --font-size-h1: 2.55rem; + --font-size-h2: 2.11rem; + --font-size-h3: 1.77rem; + --font-size-h4: 1.66rem; + --font-size-h5: 1.33rem; + --font-size-intro: 1.11rem; + --font-size-base: 1rem; } /* Custom styling for the language select element */ .language-select { - -moz-appearance: none; /* Removes Firefox's default select styling */ - -webkit-appearance: none; /* Removes Chrome's default select styling */ - appearance: none; /* Removes the default select styling for other browsers */ - /* Custom Globe SVG: */ - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' id='globe'%3E%3Crect width='16' height='16' fill='none'%3E%3C/rect%3E%3Ccircle cx='128' cy='128' r='96' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8'%3E%3C/circle%3E%3Cline x1='37.467' x2='218.532' y1='96' y2='96' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8'%3E%3C/line%3E%3Cline x1='37.471' x2='218.534' y1='160' y2='160' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8'%3E%3C/line%3E%3Cellipse cx='128' cy='128' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8' rx='40' ry='93.423'%3E%3C/ellipse%3E%3C/svg%3E"); - background-repeat: no-repeat; /* Ensures the SVG only appears once */ - background-size: 18px 18px; /* Controls the size of the SVG */ - padding-right: 27.25px; /* Adds space on the right side of the select element to prevent SVG overlap with the text */ + -moz-appearance: none; + /* Removes Firefox's default select styling */ + -webkit-appearance: none; + /* Removes Chrome's default select styling */ + appearance: none; + /* Removes the default select styling for other browsers */ + /* Custom Globe SVG: */ + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' id='globe'%3E%3Crect width='16' height='16' fill='none'%3E%3C/rect%3E%3Ccircle cx='128' cy='128' r='96' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8'%3E%3C/circle%3E%3Cline x1='37.467' x2='218.532' y1='96' y2='96' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8'%3E%3C/line%3E%3Cline x1='37.471' x2='218.534' y1='160' y2='160' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8'%3E%3C/line%3E%3Cellipse cx='128' cy='128' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='8' rx='40' ry='93.423'%3E%3C/ellipse%3E%3C/svg%3E"); + background-repeat: no-repeat; + /* Ensures the SVG only appears once */ + background-size: 18px 18px; + /* Controls the size of the SVG */ + padding-right: 27.25px; + /* Adds space on the right side of the select element to prevent SVG overlap with the text */ } /* Removes IE's default dropdown arrow */ @@ -48,6 +53,6 @@ /* Removes the default focus outline and box-shadow */ .language-select:focus { - outline: none !important; - box-shadow: none !important; -} + outline: none !important; + box-shadow: none !important; +} \ No newline at end of file