ui: Allow users to provide a CSS file to customize styling

- Don't include the file if it does not exist to avoid a 404 error every time a
page it loaded.

- Load the file from a know path under the already known custom static path.

Tests:

- When the user.css file is created, it added to the web page. It is prioritized
over the main.css with CSS cascading rules.

- When the user.css file does not exist on the filesystem, it is not added to
the web page.

- When custom static directory (/var/www/plint) does not exist on the
filesystem, a debug log message is printed that this directory is not served.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2024-11-27 10:32:33 -08:00 committed by James Valleroy
parent 37e6e3b9b3
commit 3f20c1668d
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
3 changed files with 27 additions and 3 deletions

View File

@ -8,7 +8,7 @@ import re
from django.utils.translation import gettext as _
from django.utils.translation import gettext_noop
from plinth import cfg
from plinth import cfg, web_server
from plinth.utils import is_user_admin
@ -35,6 +35,7 @@ def common(request):
'active_menu_urls': active_menu_urls,
'box_name': _(cfg.box_name),
'user_is_admin': is_user_admin(request, True),
'user_css': web_server.get_user_css(),
'notifications': notifications_context['notifications'],
'notifications_max_severity': notifications_context['max_severity']
}

View File

@ -50,10 +50,14 @@
<link rel="apple-touch-icon" sizes="72x72" href="{% static 'theme/img/apple-touch-icon-72px-precomposed.png' %}"/>
<link rel="apple-touch-icon" sizes="114x114" href="{% static 'theme/img/apple-touch-icon-114px-precomposed.png' %}"/>
<!-- Bootstrap base CSS -->
<!-- Stylesheets -->
<link rel="stylesheet" href="{% static '/javascript/bootstrap4/css/bootstrap.min.css' %}"/>
<link rel="stylesheet" href="{% static '/javascript/fork-awesome/css/fork-awesome.css' %}"/>
<link rel="stylesheet" href="{% static 'theme/css/main.css' %}"/>
{% if user_css %}
<link rel="stylesheet" href="{% static user_css %}"/>
{% endif %}
<!-- Local link to system jQuery -->
<!-- TODO Deferring jQuery is causing scripts to be loaded before jQuery is available -->
<script type="text/javascript" src="{% static '/javascript/jquery/jquery.min.js' %}"></script>

View File

@ -5,6 +5,7 @@ Setup CherryPy web server.
import logging
import os
import pathlib
import sys
import warnings
from typing import ClassVar
@ -27,6 +28,24 @@ MODULES_EXCLUDED_FROM_AUTORELOAD = [
'psycopg2',
]
_CUSTOM_STATIC_URL = '/custom/static'
_USER_CSS_PATH = 'css/user.css'
def get_custom_static_url():
"""Return the URL path fragment for custom static URL."""
return f'{cfg.server_dir}{_CUSTOM_STATIC_URL}'
def get_user_css():
"""Return the URL path fragement for user CSS if it exists else None."""
user_css_path = pathlib.Path(cfg.custom_static_dir) / _USER_CSS_PATH
if not user_css_path.exists():
return None
return get_custom_static_url() + '/' + _USER_CSS_PATH
def _mount_static_directory(static_dir, static_url):
config = {
@ -64,7 +83,7 @@ def init():
_mount_static_directory(static_dir, web_framework.get_static_url())
custom_static_dir = cfg.custom_static_dir
custom_static_url = '/plinth/custom/static'
custom_static_url = get_custom_static_url()
if os.path.exists(custom_static_dir):
_mount_static_directory(custom_static_dir, custom_static_url)
else: