New AppConfig settings APPLICATION_NAME and EXTRA_HEAD_HTML

This commit is contained in:
Martin Mahner 2019-12-05 11:36:24 +01:00
parent 6592815288
commit 34b970cf5d
15 changed files with 79 additions and 14 deletions

View file

@ -8,6 +8,11 @@ Changelog
- Django 3.0 support and tests. - Django 3.0 support and tests.
- Python 3.8 support and tests. - Python 3.8 support and tests.
- Testsuite now uses pytest. - Testsuite now uses pytest.
- New AppConfig setting "APPLICATION_NAME" that can be used to replace the term
"dpaste" throughout the UI.
- New AppConfig setting "EXTRA_HEAD_HTML" that can be used to add custom HTML
to each template, specifically used for custom CSS styles, to easily override
the stock UI of dpaste.
3.3.1 (2019-08-04): 3.3.1 (2019-08-04):
------------------- -------------------

View file

@ -7,8 +7,10 @@ name = "pypi"
dpaste = {editable = true,extras = ["dev"],path = "."} dpaste = {editable = true,extras = ["dev"],path = "."}
[scripts] [scripts]
runserver = "sh -c \"./manage.py migrate && ./manage.py runserver 0:8000\""
test = "pytest dpaste" test = "pytest dpaste"
cleanup = "sh -c \"isort -rc dpaste && black --skip-string-normalization --line-length=80 --exclude='/(migrations)/' dpaste\"" cleanup = "sh -c \"isort -rc dpaste && black --skip-string-normalization --line-length=80 --exclude='/(migrations)/' dpaste\""
docs = "sphinx-build docs docs/_build/html"
[pipenv] [pipenv]
allow_prereleases = true allow_prereleases = true

13
Pipfile.lock generated
View file

@ -292,10 +292,10 @@
}, },
"jsx-lexer": { "jsx-lexer": {
"hashes": [ "hashes": [
"sha256:80a107c08e5eb18188fc43b222859702bc83d5ed534bf63e1df6f2f77cc66e19", "sha256:1cb35102b78525aa3f587dc327f3208c0e1c76d5cdea64d4f9c3ced05d10c017",
"sha256:b1245cc02870376822fe8cc8e910810337ab6211425cf0089de504bf9da2afc6" "sha256:b879c7fafe974440a1dd9f9544dfb8629fa22078ada7f769c8fbb06149eac5d1"
], ],
"version": "==0.0.7" "version": "==0.0.8"
}, },
"livereload": { "livereload": {
"hashes": [ "hashes": [
@ -459,6 +459,13 @@
], ],
"version": "==2.8.1" "version": "==2.8.1"
}, },
"pytest-django": {
"hashes": [
"sha256:17592f06d51c2ef4b7a0fb24aa32c8b6998506a03c8439606cb96db160106659",
"sha256:ef3d15b35ed7e46293475e6f282e71a53bcd8c6f87bdc5d5e7ad0f4d49352127"
],
"version": "==3.7.0"
},
"pytz": { "pytz": {
"hashes": [ "hashes": [
"sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",

View file

@ -7,7 +7,7 @@ header {
align-items: center; align-items: center;
color: $headerTextColor; color: $headerTextColor;
background: linear-gradient(to right, $headerBgColor1, $headerBgColor2); background-color: $headerBgColor;
// Subheadline e.g. Reply Bar // Subheadline e.g. Reply Bar
&.sub { &.sub {

View file

@ -13,8 +13,7 @@ $borderColor: #EDEDED; // Used for separators, select borders, etc.
// Header // Header
$headerTextColor: white; // Header text color $headerTextColor: white; // Header text color
$headerBgColor1: #4A90E2; // Header gradient background left $headerBgColor: #4A90E2; // Header background
$headerBgColor2: #72B4E4; // Header gradient background right
$btnBgColor: #4A90E2; // Buttons (Header, Meta) $btnBgColor: #4A90E2; // Buttons (Header, Meta)
$btnBorderColor: #33639C; $btnBorderColor: #33639C;

View file

@ -1,4 +1,5 @@
from django.apps import AppConfig, apps from django.apps import AppConfig, apps
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -6,6 +7,25 @@ class dpasteAppConfig(AppConfig):
name = 'dpaste' name = 'dpaste'
verbose_name = 'dpaste' verbose_name = 'dpaste'
# The application title used throughout the user interface.
APPLICATION_NAME = 'dpaste'
# This content is loaded in the <head> section of each template.
# You can use it to add any HTML tags, specifically custom CSS styles.
# This may can give you an easier way to adjust the UI to your needs
# than having to add a template folder, plus custom template, plus
# css static file etc.
#
# Example:
#
# EXTRA_HEAD_HTML = """
# <style type="text/css">
# header{ background-color: red; }
# .btn { background-color: blue; border: 3px solid yellow; }
# </style>
# """
EXTRA_HEAD_HTML = ''
# Integer. Length of the random slug for each new snippet. In the rare # Integer. Length of the random slug for each new snippet. In the rare
# case an existing slug is generated again, the length will increase by # case an existing slug is generated again, the length will increase by
# one more character. # one more character.
@ -599,3 +619,14 @@ class dpasteAppConfig(AppConfig):
if site: if site:
return 'https://{0}'.format(site.domain) return 'https://{0}'.format(site.domain)
return 'https://dpaste.de' return 'https://dpaste.de'
@property
def extra_template_context(self):
"""
Returns a dictionary with context variables which are passed to
all Template Views.
"""
return {
'dpaste_application_name': self.APPLICATION_NAME,
'dpaste_extra_head_html': mark_safe(self.EXTRA_HEAD_HTML),
}

View file

@ -2,6 +2,7 @@
Settings for the test suite Settings for the test suite
""" """
import django import django
from .base import * from .base import *
SECRET_KEY = 'test-key' SECRET_KEY = 'test-key'

View file

@ -2,14 +2,16 @@
{% load i18n %} {% load i18n %}
{% block title %}{% trans "About" %}{% endblock %} {% block title %}{% blocktrans with name=dpaste_application_name %}About {{ name }}{% endblocktrans %}{% endblock %}
{% block body_type %}text-page{%endblock %} {% block body_type %}text-page{%endblock %}
{% block page %} {% block page %}
<article> <article>
<h2 class="first-item">{% trans "About dpaste" %}</h2> <h2 class="first-item">
{% blocktrans with name=dpaste_application_name %}About {{ name }}{% endblocktrans %}
</h2>
<p> <p>
This site is powered by dpaste, an <strong>open source</strong> This site is powered by dpaste, an <strong>open source</strong>

View file

@ -8,11 +8,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
{% block meta %}<meta name="robots" content="noindex, nofollow"/>{% endblock %} {% block meta %}<meta name="robots" content="noindex, nofollow"/>{% endblock %}
<style type="text/css">{% staticinline "dpaste.css" %}</style> <style type="text/css">{% staticinline "dpaste.css" %}</style>
{{ dpaste_extra_head_html }}
</head> </head>
<body {% block body_type %}{%endblock %}> <body {% block body_type %}{%endblock %}>
<header> <header>
<h1>{% block headline %}<a class="home" href="{% url "snippet_new" %}">dpaste</a>{% endblock %}</h1> <h1>{% block headline %}<a class="home" href="{% url "snippet_new" %}">{{ dpaste_application_name }}</a>{% endblock %}</h1>
<nav> <nav>
<a class="nav-link" href="{% url "dpaste_about" %}">{% trans "About" %}</a> <a class="nav-link" href="{% url "dpaste_about" %}">{% trans "About" %}</a>
<a class="nav-link" href="{% url "snippet_history" %}">{% trans "History" %}</a> <a class="nav-link" href="{% url "snippet_history" %}">{% trans "History" %}</a>

View file

@ -2,7 +2,7 @@
{% load i18n %} {% load i18n %}
{% block title %}dpaste/{{ snippet.secret_id }} ({{ snippet.lexer_name }}){% endblock %} {% block title %}{{ dpaste_application_name }}/{{ snippet.secret_id }} ({{ snippet.lexer_name }}){% endblock %}
{% block body_type %}{%endblock %} {% block body_type %}{%endblock %}

View file

@ -5,7 +5,7 @@
{% block nav_new %}{% endblock %} {% block nav_new %}{% endblock %}
{% block meta %}{% endblock %} {% block meta %}{% endblock %}
{% block title %}{% trans "dpaste" %}{% endblock %} {% block title %}{{ dpaste_application_name }}{% endblock %}
{% block body_type %}text-page{%endblock %} {% block body_type %}text-page{%endblock %}

View file

@ -307,7 +307,7 @@ class SnippetTestCase(TestCase):
self.assertEqual(Snippet.objects.count(), 1) self.assertEqual(Snippet.objects.count(), 1)
def test_delete_management_snippet_that_never_expires_will_not_get_deleted( def test_delete_management_snippet_that_never_expires_will_not_get_deleted(
self self,
): ):
""" """
Snippets without an expiration date wont get deleted automatically. Snippets without an expiration date wont get deleted automatically.

View file

@ -1,4 +1,4 @@
from django.conf.urls import url, include from django.conf.urls import include, url
urlpatterns = [ urlpatterns = [
url(r'^', include('dpaste.urls.dpaste_api')), url(r'^', include('dpaste.urls.dpaste_api')),

View file

@ -1,3 +1,4 @@
from django.apps import apps
from django.conf import settings from django.conf import settings
from django.conf.urls import url from django.conf.urls import url
from django.views.generic import TemplateView from django.views.generic import TemplateView
@ -5,12 +6,16 @@ from django.views.generic import TemplateView
from .. import views from .. import views
L = getattr(settings, 'DPASTE_SLUG_LENGTH', 4) L = getattr(settings, 'DPASTE_SLUG_LENGTH', 4)
config = apps.get_app_config('dpaste')
urlpatterns = [ urlpatterns = [
url(r'^$', views.SnippetView.as_view(), name='snippet_new'), url(r'^$', views.SnippetView.as_view(), name='snippet_new'),
url( url(
r'^about/$', r'^about/$',
TemplateView.as_view(template_name='dpaste/about.html'), TemplateView.as_view(
template_name='dpaste/about.html',
extra_context=config.extra_template_context,
),
name='dpaste_about', name='dpaste_about',
), ),
url(r'^history/$', views.SnippetHistory.as_view(), name='snippet_history'), url(r'^history/$', views.SnippetHistory.as_view(), name='snippet_history'),

View file

@ -51,6 +51,11 @@ class SnippetView(FormView):
snippet = form.save() snippet = form.save()
return HttpResponseRedirect(snippet.get_absolute_url()) return HttpResponseRedirect(snippet.get_absolute_url())
def get_context_data(self, **kwargs):
ctx = super(SnippetView, self).get_context_data(**kwargs)
ctx.update(config.extra_template_context)
return ctx
class SnippetDetailView(SnippetView, DetailView): class SnippetDetailView(SnippetView, DetailView):
""" """
@ -144,6 +149,7 @@ class SnippetDetailView(SnippetView, DetailView):
'raw_mode': config.RAW_MODE_ENABLED, 'raw_mode': config.RAW_MODE_ENABLED,
} }
) )
ctx.update(config.extra_template_context)
return ctx return ctx
@ -175,6 +181,11 @@ class SnippetRawView(SnippetDetailView):
context, **response_kwargs context, **response_kwargs
) )
def get_context_data(self, **kwargs):
ctx = super(SnippetView, self).get_context_data(**kwargs)
ctx.update(config.extra_template_context)
return ctx
class SnippetHistory(TemplateView): class SnippetHistory(TemplateView):
""" """
@ -202,6 +213,7 @@ class SnippetHistory(TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super(SnippetHistory, self).get_context_data(**kwargs) ctx = super(SnippetHistory, self).get_context_data(**kwargs)
ctx.update({'snippet_list': self.get_user_snippets()}) ctx.update({'snippet_list': self.get_user_snippets()})
ctx.update(config.extra_template_context)
return ctx return ctx