BS5 Theme

This commit is contained in:
Aaron Kable
2023-10-07 08:20:22 +00:00
committed by Ariel Rin
parent 567d97f38a
commit 2e78aa5f26
161 changed files with 3198 additions and 1655 deletions

View File

View File

@@ -0,0 +1,9 @@
from django.apps import AppConfig
class ThemeConfig(AppConfig):
name = "allianceauth.theme"
label = "theme"
def ready(self):
pass

View File

View File

@@ -0,0 +1,11 @@
from django.apps import AppConfig
class BootstrapThemeConfig(AppConfig):
name = "allianceauth.theme.bootstrap"
label = "bootstrap"
version = "5.3.0"
verbose_name = f"Bootstrap v{version}"
def ready(self):
pass

View File

@@ -0,0 +1,33 @@
from allianceauth import hooks
from allianceauth.theme.hooks import ThemeHook
class BootstrapThemeHook(ThemeHook):
"""
Bootstrap in all its glory!
https://getbootstrap.com/
"""
def __init__(self):
ThemeHook.__init__(
self,
"Bootstrap",
"Powerful, extensible, and feature-packed frontend toolkit.",
css=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css",
"integrity": "sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg=="
}],
js=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js",
"integrity": "sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ=="
}, {
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js",
"integrity": "sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w=="
}],
header_padding="3.5em"
)
@hooks.register('theme_hook')
def register_darkly_hook():
return BootstrapThemeHook()

View File

@@ -0,0 +1,11 @@
from django.apps import AppConfig
class BootstrapDarkThemeConfig(AppConfig):
name = "allianceauth.theme.bootstrap_dark"
label = "bootstrap_dark"
version = "5.3.0"
verbose_name = f"Bootstrap Dark v{version}"
def ready(self):
pass

View File

@@ -0,0 +1,34 @@
from allianceauth import hooks
from allianceauth.theme.hooks import ThemeHook
class BootstrapDarkThemeHook(ThemeHook):
"""
Bootstrap in all its glory!
https://getbootstrap.com/
"""
def __init__(self):
ThemeHook.__init__(
self,
"Bootstrap Dark",
"Powerful, extensible, and feature-packed frontend toolkit.",
css=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css",
"integrity": "sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg=="
}],
js=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js",
"integrity": "sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ=="
}, {
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js",
"integrity": "sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w=="
}],
html_tags="data-bs-theme=dark",
header_padding="3.5em"
)
@hooks.register('theme_hook')
def register_bootstrap_dark_hook():
return BootstrapDarkThemeHook()

View File

View File

@@ -0,0 +1,11 @@
from django.apps import AppConfig
class DarklyThemeConfig(AppConfig):
name = "allianceauth.theme.darkly"
label = "darkly"
version = "5.3.0"
verbose_name = f"Bootswatch Darkly v{version}"
def ready(self):
pass

View File

@@ -0,0 +1,33 @@
from allianceauth import hooks
from allianceauth.theme.hooks import ThemeHook
class DarklyThemeHook(ThemeHook):
"""
The default auth theme
https://bootswatch.com/darkly/
"""
def __init__(self):
ThemeHook.__init__(
self,
"Darkly",
"Flatly in night mode!",
css=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.0/darkly/bootstrap.min.css",
"integrity": "sha512-3xynESL0QF3ERUl9se1VJk043nWT+UzWJveifBw7kLtC226vyGINZFtmyK015F83KBSNW+67alYSY2cCj1LHOQ=="
}],
js=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js",
"integrity": "sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ=="
}, {
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js",
"integrity": "sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w=="
}],
header_padding="4.5em"
)
@hooks.register('theme_hook')
def register_darkly_hook():
return DarklyThemeHook()

View File

View File

@@ -0,0 +1,11 @@
from django.apps import AppConfig
class FlatlyThemeConfig(AppConfig):
name = "allianceauth.theme.flatly"
label = "flatly"
version = "5.3.0"
verbose_name = f"Bootswatch Flatly v{version}"
def ready(self):
pass

View File

@@ -0,0 +1,33 @@
from allianceauth import hooks
from allianceauth.theme.hooks import ThemeHook
class FlatlyThemeHook(ThemeHook):
"""
auth light theme
https://bootswatch.com/flatly/
"""
def __init__(self):
ThemeHook.__init__(
self,
"Flatly",
"Flat and modern!",
css=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.0/flatly/bootstrap.min.css",
"integrity": "sha512-N/JRw8RFoUkWgQIpunoKtmZShzrHbs724xV4DMh+LSNjebmrgNy2dzAIUhoOqSazEZ/bLlulWy2muCxletfrsA=="
}],
js=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js",
"integrity": "sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ=="
}, {
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js",
"integrity": "sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w=="
}],
header_padding="4.5em"
)
@hooks.register('theme_hook')
def register_flatly_hook():
return FlatlyThemeHook()

View File

@@ -0,0 +1,47 @@
from typing import List, Optional
class ThemeHook:
"""
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
these can be local or CDN delivered
"""
def __init__(self,
name: str,
description: str,
css: List[dict],
js: List[dict],
css_template: Optional[str] = None,
js_template: Optional[str] = None,
html_tags: Optional[str] = "",
header_padding: Optional[str] = "4em"):
"""
:param name: Theme python name
:type name: str
:param description: Theme verbose name
:type description: str
:param css: CSS paths to load
:type css: List[dict]
:param js: JS paths to load
:type js: List[dict]
:param css_template: _description_, defaults to None
:type css_template: Optional[str], optional
:param js_template: _description_, defaults to None
:type js_template: Optional[str], optional
"""
self.name = name
self.description = description
# Direct from CDN
self.css = css
self.js = js
# Load a django template with static file definitions
self.css_template = css_template
self.js_template = js_template
self.html_tags = html_tags
self.header_padding = header_padding
def get_name(self):
return f"{self.__class__.__module__}.{self.__class__.__name__}"

View File

View File

@@ -0,0 +1,11 @@
from django.apps import AppConfig
class MateriaThemeConfig(AppConfig):
name = "allianceauth.theme.materia"
label = "materia"
version = "5.3.0"
verbose_name = f"Bootswatch Materia v{version}"
def ready(self):
pass

View File

@@ -0,0 +1,33 @@
from allianceauth import hooks
from allianceauth.theme.hooks import ThemeHook
class MateriaThemeHook(ThemeHook):
"""
Materia theme
https://bootswatch.com/materia/
"""
def __init__(self):
ThemeHook.__init__(
self,
"Materia",
"Material is the metaphor",
css=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.0/materia/bootstrap.min.css",
"integrity": "sha512-FukZyva60KXjmN0uleimuMCoAUwuRha1fSCdzWtxZ29YBIev3gGBU0FpTIEfmGZ9YSrmgW4Pv5geC/q11RuATg=="
}],
js=[{
"url": "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js",
"integrity": "sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ=="
}, {
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js",
"integrity": "sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w=="
}],
header_padding="5.25em"
)
@hooks.register('theme_hook')
def register_materia_hook():
return MateriaThemeHook()

View File

View File

@@ -0,0 +1,10 @@
{% load static %}
<!-- allianceauth.theme.{{ theme.name }} CSS -->
{% if theme.css_template %}
{% include theme.css_template %}
{% else %}
{% for x in theme.css %}
<link rel="stylesheet" href="{{ x.url }}" integrity="{{ x.integrity }}" crossorigin="anonymous" referrerpolicy="no-referrer"/>
{% endfor %}
{% endif %}
<!-- allianceauth.theme.{{ theme.name }} CSS Ends -->

View File

@@ -0,0 +1,10 @@
{% load static %}
<!-- allianceauth.theme.{{ theme.name }} JS -->
{% if theme.js_template %}
{% include theme.css_template %}
{% else %}
{% for x in theme.js %}
<script src="{{ x.url }}" integrity="{{ x.integrity }}" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
{% endfor %}
{% endif %}
<!-- allianceauth.theme.{{ theme.name }} JS Ends-->

View File

@@ -0,0 +1,9 @@
<form action="{% url 'theme' %}?next={{ next|urlencode }}" method="post">
{% csrf_token %}
<select name="theme" value="theme" class="form-select" aria-label="" onchange="this.form.submit()">
<option selected>Select Theme</option>
{% for theme in themes %}
<option value="{{ theme.get_name }}">{{ theme.name }}</option>
{% endfor %}
</select>
</form>

View File

@@ -0,0 +1,73 @@
from django import template
from django.conf import settings
from allianceauth.hooks import get_hooks
register = template.Library()
def hook_to_name(th):
return f"{th.__class__.__module__}.{th.__class__.__name__}"
def get_theme_from_hooks(theme, hooks):
for h in hooks:
_h = h()
_hn = hook_to_name(_h)
if _hn == theme:
return _h
def get_theme(request):
theme = settings.DEFAULT_THEME
hooks = get_hooks('theme_hook')
if request.user:
theme = request.user.profile.theme or theme
theme_hook = get_theme_from_hooks(theme, hooks)
if not theme_hook:
theme_hook = get_theme_from_hooks(settings.DEFAULT_THEME, hooks)
return theme_hook
def get_theme_context(request):
return {
'theme': get_theme(request)
}
@register.inclusion_tag('theme/theme_imports_css.html', takes_context=True)
def theme_css(context):
request = context['request']
return get_theme_context(request)
@register.simple_tag(takes_context=True)
def theme_html_tags(context):
request = context['request']
theme = get_theme(request)
return getattr(theme, "html_tags", "")
@register.simple_tag(takes_context=True)
def header_padding_size(context):
request = context['request']
theme = get_theme(request)
return getattr(theme, "header_padding")
@register.inclusion_tag('theme/theme_imports_js.html', takes_context=True)
def theme_js(context):
request = context['request']
return get_theme_context(request)
@register.inclusion_tag('theme/theme_select.html', takes_context=True)
def theme_select(context):
request = context['request']
return {
'next': request.path,
'themes': get_hooks('theme_hook')
}