feat: add footer, header and improve layout
This commit is contained in:
parent
72bf6bffb8
commit
6fd74833a3
17 changed files with 305 additions and 30 deletions
0
base/__init__.py
Normal file
0
base/__init__.py
Normal file
3
base/admin.py
Normal file
3
base/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
base/apps.py
Normal file
6
base/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class BaseConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'base'
|
26
base/migrations/0001_initial.py
Normal file
26
base/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Generated by Django 5.0.2 on 2024-02-29 20:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='NavigationSettings',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('linkedin_url', models.URLField(blank=True, verbose_name='LinkedIn URL')),
|
||||||
|
('github_url', models.URLField(blank=True, verbose_name='GitHub URL')),
|
||||||
|
('mastodon_url', models.URLField(blank=True, verbose_name='Mastodon URL')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
42
base/migrations/0002_footertext.py
Normal file
42
base/migrations/0002_footertext.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Generated by Django 5.0.2 on 2024-02-29 21:00
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('base', '0001_initial'),
|
||||||
|
('wagtailcore', '0091_remove_revision_submitted_for_moderation'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='FooterText',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('translation_key', models.UUIDField(default=uuid.uuid4, editable=False)),
|
||||||
|
('live', models.BooleanField(default=True, editable=False, verbose_name='live')),
|
||||||
|
('has_unpublished_changes', models.BooleanField(default=False, editable=False, verbose_name='has unpublished changes')),
|
||||||
|
('first_published_at', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='first published at')),
|
||||||
|
('last_published_at', models.DateTimeField(editable=False, null=True, verbose_name='last published at')),
|
||||||
|
('go_live_at', models.DateTimeField(blank=True, null=True, verbose_name='go live date/time')),
|
||||||
|
('expire_at', models.DateTimeField(blank=True, null=True, verbose_name='expiry date/time')),
|
||||||
|
('expired', models.BooleanField(default=False, editable=False, verbose_name='expired')),
|
||||||
|
('body', wagtail.fields.RichTextField()),
|
||||||
|
('latest_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='latest revision')),
|
||||||
|
('live_revision', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.revision', verbose_name='live revision')),
|
||||||
|
('locale', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtailcore.locale')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name_plural': 'Footer Text',
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('translation_key', 'locale')},
|
||||||
|
},
|
||||||
|
bases=(wagtail.models.PreviewableMixin, models.Model),
|
||||||
|
),
|
||||||
|
]
|
0
base/migrations/__init__.py
Normal file
0
base/migrations/__init__.py
Normal file
65
base/models.py
Normal file
65
base/models.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
from django.db import models
|
||||||
|
from modelcluster.models import ClusterableModel
|
||||||
|
from wagtail.admin.panels import (
|
||||||
|
FieldPanel,
|
||||||
|
MultiFieldPanel,
|
||||||
|
PublishingPanel
|
||||||
|
)
|
||||||
|
from wagtail.fields import RichTextField
|
||||||
|
from wagtail.models import (
|
||||||
|
DraftStateMixin,
|
||||||
|
PreviewableMixin,
|
||||||
|
RevisionMixin,
|
||||||
|
TranslatableMixin,
|
||||||
|
)
|
||||||
|
from wagtail.snippets.models import register_snippet
|
||||||
|
|
||||||
|
from wagtail.contrib.settings.models import (
|
||||||
|
BaseGenericSetting,
|
||||||
|
register_setting,
|
||||||
|
)
|
||||||
|
|
||||||
|
@register_setting
|
||||||
|
class NavigationSettings(BaseGenericSetting):
|
||||||
|
linkedin_url = models.URLField(verbose_name="LinkedIn URL", blank=True)
|
||||||
|
github_url = models.URLField(verbose_name="GitHub URL", blank=True)
|
||||||
|
mastodon_url = models.URLField(verbose_name="Mastodon URL", blank=True)
|
||||||
|
|
||||||
|
panels = [
|
||||||
|
MultiFieldPanel(
|
||||||
|
[
|
||||||
|
FieldPanel("linkedin_url"),
|
||||||
|
FieldPanel("github_url"),
|
||||||
|
FieldPanel("mastodon_url"),
|
||||||
|
],
|
||||||
|
"Social settings",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
@register_snippet
|
||||||
|
class FooterText(
|
||||||
|
DraftStateMixin,
|
||||||
|
RevisionMixin,
|
||||||
|
PreviewableMixin,
|
||||||
|
TranslatableMixin,
|
||||||
|
models.Model,
|
||||||
|
):
|
||||||
|
|
||||||
|
body = RichTextField()
|
||||||
|
|
||||||
|
panels = [
|
||||||
|
FieldPanel("body"),
|
||||||
|
PublishingPanel(),
|
||||||
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Footer text"
|
||||||
|
|
||||||
|
def get_preview_template(self, request, mode_name):
|
||||||
|
return "base.html"
|
||||||
|
|
||||||
|
def get_preview_context(self, request, mode_name):
|
||||||
|
return {"footer_text": self.body}
|
||||||
|
|
||||||
|
class Meta(TranslatableMixin.Meta):
|
||||||
|
verbose_name_plural = "Footer Text"
|
5
base/templates/base/includes/footer_text.html
Normal file
5
base/templates/base/includes/footer_text.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% load wagtailcore_tags %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{ footer_text|richtext }}
|
||||||
|
</div>
|
0
base/templatetags/__init__.py
Normal file
0
base/templatetags/__init__.py
Normal file
23
base/templatetags/navigation_tags.py
Normal file
23
base/templatetags/navigation_tags.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from django import template
|
||||||
|
from wagtail.models import Site
|
||||||
|
from base.models import FooterText
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.inclusion_tag("base/includes/footer_text.html", takes_context=True)
|
||||||
|
def get_footer_text(context):
|
||||||
|
footer_text = context.get("footer_text", "")
|
||||||
|
|
||||||
|
if not footer_text:
|
||||||
|
instance = FooterText.objects.filter(live=True).first()
|
||||||
|
footer_text = instance.body if instance else ""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"footer_text": footer_text,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=True)
|
||||||
|
def get_site_root(context):
|
||||||
|
return Site.find_for_request(context["request"]).root_page
|
3
base/tests.py
Normal file
3
base/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
base/views.py
Normal file
3
base/views.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
|
@ -24,9 +24,11 @@ BASE_DIR = os.path.dirname(PROJECT_DIR)
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
"base",
|
||||||
"blog",
|
"blog",
|
||||||
"home",
|
"home",
|
||||||
"search",
|
"search",
|
||||||
|
"wagtail.contrib.settings",
|
||||||
"wagtail.contrib.forms",
|
"wagtail.contrib.forms",
|
||||||
"wagtail.contrib.redirects",
|
"wagtail.contrib.redirects",
|
||||||
"wagtail.embeds",
|
"wagtail.embeds",
|
||||||
|
@ -74,6 +76,7 @@ TEMPLATES = [
|
||||||
"django.template.context_processors.request",
|
"django.template.context_processors.request",
|
||||||
"django.contrib.auth.context_processors.auth",
|
"django.contrib.auth.context_processors.auth",
|
||||||
"django.contrib.messages.context_processors.messages",
|
"django.contrib.messages.context_processors.messages",
|
||||||
|
"wagtail.contrib.settings.context_processors.settings"
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
*,
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, "Helvetica Neue", Arial, sans-serif, Apple Color Emoji, "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 10px;
|
||||||
|
display: grid;
|
||||||
|
gap: 3vw;
|
||||||
|
grid-template-rows: min-content 1fr min-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
border-top: 2px dotted;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
border-bottom: 2px dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-homepage main {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link {
|
||||||
|
position: absolute;
|
||||||
|
top: -30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus-visible {
|
||||||
|
top: 5px;
|
||||||
|
}
|
|
@ -1,46 +1,57 @@
|
||||||
{% load static wagtailcore_tags wagtailuserbar %}
|
{% load static wagtailcore_tags %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8"/>
|
||||||
<title>
|
<title>
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% if page.seo_title %}{{ page.seo_title }}{% else %}{{ page.title }}{% endif %}
|
{% if page.seo_title %}{{ page.seo_title }}{% else %}{{ page.title }}{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block title_suffix %}
|
{% block title_suffix %}
|
||||||
{% wagtail_site as current_site %}
|
{% wagtail_site as current_site %}
|
||||||
{% if current_site and current_site.site_name %}- {{ current_site.site_name }}{% endif %}
|
{% if current_site and current_site.site_name %}- {{ current_site.site_name }}{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</title>
|
</title>
|
||||||
{% if page.search_description %}
|
{% if page.search_description %}
|
||||||
<meta name="description" content="{{ page.search_description }}" />
|
<meta name="description" content="{{ page.search_description }}"/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
|
||||||
{# Force all links in the live preview panel to be opened in a new tab #}
|
{# Force all links in the live preview panel to be opened in a new tab #}
|
||||||
{% if request.in_preview_panel %}
|
{% if request.in_preview_panel %}
|
||||||
<base target="_blank">
|
<base target="_blank">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Global stylesheets #}
|
<meta name="color-scheme" content="light dark">
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'css/iamkonstantin_web.css' %}">
|
|
||||||
|
|
||||||
{% block extra_css %}
|
<link rel="icon"
|
||||||
|
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🍩</text></svg>"/>
|
||||||
|
|
||||||
|
|
||||||
|
{# Global stylesheets #}
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static 'css/iamkonstantin_web.css' %}">
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
{# Override this in templates to add extra stylesheets #}
|
{# Override this in templates to add extra stylesheets #}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="{% block body_class %}{% endblock %}">
|
<body class="{% block body_class %}{% endblock %}">
|
||||||
{% wagtailuserbar %}
|
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
{% include "includes/header.html" %}
|
||||||
|
|
||||||
{# Global javascript #}
|
<main id="main">
|
||||||
<script type="text/javascript" src="{% static 'js/iamkonstantin_web.js' %}"></script>
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
{% block extra_js %}
|
{% include "includes/footer.html" %}
|
||||||
{# Override this in templates to add extra javascript #}
|
|
||||||
{% endblock %}
|
{# Global javascript #}
|
||||||
</body>
|
<script type="text/javascript" src="{% static 'js/iamkonstantin_web.js' %}"></script>
|
||||||
|
|
||||||
|
{% block extra_js %}
|
||||||
|
{# Override this in templates to add extra javascript #}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
24
iamkonstantin_web/templates/includes/footer.html
Normal file
24
iamkonstantin_web/templates/includes/footer.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{% load navigation_tags %}
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Built with Wagtail</p>
|
||||||
|
|
||||||
|
{% with linkedin_url=settings.base.NavigationSettings.linkedin_url github_url=settings.base.NavigationSettings.github_url mastodon_url=settings.base.NavigationSettings.mastodon_url %}
|
||||||
|
{% if linkedin_url or github_url or mastodon_url %}
|
||||||
|
<p>
|
||||||
|
Follow me on:
|
||||||
|
{% if github_url %}
|
||||||
|
<a href="{{ github_url }}">GitHub</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if linkedin_url %}
|
||||||
|
<a href="{{ linkedin_url }}">Twitter</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if mastodon_url %}
|
||||||
|
<a href="{{ mastodon_url }}">Mastodon</a>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
{% get_footer_text %}
|
||||||
|
</footer>
|
16
iamkonstantin_web/templates/includes/header.html
Normal file
16
iamkonstantin_web/templates/includes/header.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{% load wagtailcore_tags navigation_tags wagtailuserbar %}
|
||||||
|
<header>
|
||||||
|
{# Add this: #}
|
||||||
|
<a href="#main" class="skip-link">Skip to content</a>
|
||||||
|
|
||||||
|
{% get_site_root as site_root %}
|
||||||
|
<nav>
|
||||||
|
<p>
|
||||||
|
<a href="{% pageurl site_root %}">{{ site_root.title }}</a> |
|
||||||
|
{% for menuitem in site_root.get_children.live.in_menu %}
|
||||||
|
<a href="{% pageurl menuitem %}">{{ menuitem.title }}</a>{% if not forloop.last %} | {% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
</nav>
|
||||||
|
{% wagtailuserbar "top-right" %}
|
||||||
|
</header>
|
Loading…
Add table
Add a link
Reference in a new issue