From 75e723b627c83c55906f773ad0c0fbde0ebda2aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?=
 <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de>
Date: Wed, 4 Jan 2023 21:03:14 +0100
Subject: [PATCH] Introduce static file compression

Add compressor and sass compiler dependencies
Introduce corresponding settings
Use compressor in templates
Move only partially used dependencies to higher level for better re-usability
Add custom tags to create css and js for fontawesome separately
This implements the first part of #162
---
 .../templates/AKDashboard/dashboard.html      |  8 ------
 .../AKDashboard/dashboard_event.html          |  8 ------
 AKModel/templates/AKModel/user.html           |  8 ------
 AKModel/templatetags/tags_AKModel.py          | 19 ++++++++++++++
 AKPlan/templates/AKPlan/plan_wall.html        | 18 ++++++++-----
 AKPlanning/settings.py                        | 24 ++++++++++++++++++
 .../AKSubmission/submission_overview.html     |  5 ----
 .../templates/AKSubmission/submit_new.html    |  3 ---
 requirements.txt                              |  2 ++
 templates/base.html                           | 25 ++++++++++++++-----
 10 files changed, 76 insertions(+), 44 deletions(-)

diff --git a/AKDashboard/templates/AKDashboard/dashboard.html b/AKDashboard/templates/AKDashboard/dashboard.html
index 7086854e..48925af3 100644
--- a/AKDashboard/templates/AKDashboard/dashboard.html
+++ b/AKDashboard/templates/AKDashboard/dashboard.html
@@ -4,14 +4,6 @@
 {% load i18n %}
 {% load static %}
 
-{% block imports %}
-
-    {{ block.super }}
-
-    <link rel="stylesheet" href="{% static 'AKDashboard/style.css' %}">
-
-{% endblock %}
-
 {% block breadcrumbs %}
     <li class="breadcrumb-item">AKPlanning</li>
 {% endblock %}
diff --git a/AKDashboard/templates/AKDashboard/dashboard_event.html b/AKDashboard/templates/AKDashboard/dashboard_event.html
index 4a4726a9..626ca4b0 100644
--- a/AKDashboard/templates/AKDashboard/dashboard_event.html
+++ b/AKDashboard/templates/AKDashboard/dashboard_event.html
@@ -6,14 +6,6 @@
 {% load tags_AKModel %}
 {% load tz %}
 
-{% block imports %}
-
-    {{ block.super }}
-
-    <link rel="stylesheet" href="{% static 'AKDashboard/style.css' %}">
-
-{% endblock %}
-
 {% block breadcrumbs %}
     <li class="breadcrumb-item"><a href="{% url 'dashboard:dashboard' %}">AKPlanning</a></li>
     <li class="breadcrumb-item active">{{ event }}</li>
diff --git a/AKModel/templates/AKModel/user.html b/AKModel/templates/AKModel/user.html
index 47ccc35a..b18b0cb9 100644
--- a/AKModel/templates/AKModel/user.html
+++ b/AKModel/templates/AKModel/user.html
@@ -6,14 +6,6 @@
 
 {% load tags_AKModel %}
 
-{% block imports %}
-
-    {{ block.super }}
-
-    <link rel="stylesheet" href="{% static 'AKDashboard/style.css' %}">
-
-{% endblock %}
-
 {% block breadcrumbs %}
     <li class="breadcrumb-item">
         {% if 'AKDashboard'|check_app_installed %}
diff --git a/AKModel/templatetags/tags_AKModel.py b/AKModel/templatetags/tags_AKModel.py
index 3bec0320..06560dc7 100644
--- a/AKModel/templatetags/tags_AKModel.py
+++ b/AKModel/templatetags/tags_AKModel.py
@@ -1,6 +1,9 @@
 from django import template
 from django.apps import apps
 from django.conf import settings
+from django.utils.html import format_html, mark_safe, conditional_escape
+from django.templatetags.static import static
+from fontawesome_6.app_settings import get_css
 
 register = template.Library()
 
@@ -39,3 +42,19 @@ def wiki_owners_export(owners, event):
         return str(owner)
 
     return ", ".join(to_link(owner) for owner in owners.all())
+
+
+css = get_css()
+
+
+@register.simple_tag
+def fontawesome_6_css():
+    return mark_safe(conditional_escape('\n').join(format_html(
+            '<link href="{}" rel="stylesheet" media="all">', stylesheet) for stylesheet in css))
+
+
+@register.simple_tag
+def fontawesome_6_js():
+    return mark_safe(format_html(
+        '<script type="text/javascript" src="{}"></script>', static('fontawesome_6/js/django-fontawesome.js')
+    ))
\ No newline at end of file
diff --git a/AKPlan/templates/AKPlan/plan_wall.html b/AKPlan/templates/AKPlan/plan_wall.html
index 717c7ffd..0e20819d 100644
--- a/AKPlan/templates/AKPlan/plan_wall.html
+++ b/AKPlan/templates/AKPlan/plan_wall.html
@@ -1,3 +1,4 @@
+{% load compress %}
 {% load static %}
 {% load i18n %}
 {% load django_bootstrap5 %}
@@ -14,12 +15,17 @@
     <title>{% block title %}AK Planning{% endblock %}</title>
 
     {# Load Bootstrap CSS and JavaScript as well as font awesome #}
-    {% bootstrap_css %}
-    {% bootstrap_javascript %}
-    <script src="{% static 'common/vendor/jquery/jquery-3.6.3.min.js' %}"></script>
-    {% fontawesome_6_static %}
-
-    <link rel="stylesheet" href="{% static 'common/css/custom.css' %}">
+    {% compress css %}
+        {% bootstrap_css %}
+        {% fontawesome_6_css %}
+        <link rel="stylesheet" href="{% static 'common/css/custom.css' %}">
+    {% endcompress %}
+
+    {% compress js %}
+        {% bootstrap_javascript %}
+        <script src="{% static 'common/vendor/jquery/jquery-3.6.3.min.js' %}"></script>
+        {% fontawesome_6_js %}
+    {% endcompress %}
 
     {% include "AKModel/load_fullcalendar.html" %}
 
diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py
index 5c416d92..1c306397 100644
--- a/AKPlanning/settings.py
+++ b/AKPlanning/settings.py
@@ -54,9 +54,11 @@ INSTALLED_APPS = [
     'registration',
     'bootstrap_datepicker_plus',
     'django_tex',
+    'compressor',
 ]
 
 MIDDLEWARE = [
+    'django.middleware.gzip.GZipMiddleware',
     'debug_toolbar.middleware.DebugToolbarMiddleware',
     'django.middleware.security.SecurityMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
@@ -162,6 +164,12 @@ STATICFILES_DIRS = (
     'static_common',
 )
 
+STATICFILES_FINDERS = (
+    'django.contrib.staticfiles.finders.FileSystemFinder',
+    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+    'compressor.finders.CompressorFinder',
+)
+
 # Settings for Bootstrap
 BOOTSTRAP5 = {
     # Use custom CSS
@@ -177,6 +185,22 @@ BOOTSTRAP5 = {
 FONTAWESOME_6_CSS_URL = STATIC_URL + "fontawesomefree/css/all.min.css"
 FONTAWESOME_6_PREFIX = "fa"
 
+# Compressor and minifier config
+COMPRESS_ENABLED = True
+COMPRESS_CSS_HASHING_METHOD = 'content'
+COMPRESS_PRECOMPILERS = (
+    ('text/x-scss', 'django_libsass.SassCompiler'),
+)
+COMPRESS_FILTERS = {
+    'css': [
+        'compressor.filters.css_default.CssAbsoluteFilter',
+        'compressor.filters.cssmin.rCSSMinFilter',
+    ],
+    'js': [
+        'compressor.filters.jsmin.JSMinFilter',
+    ]
+}
+
 # Treat wishes as seperate category in submission views?
 WISHES_AS_CATEGORY = True
 
diff --git a/AKSubmission/templates/AKSubmission/submission_overview.html b/AKSubmission/templates/AKSubmission/submission_overview.html
index 43a59ed1..41518c81 100644
--- a/AKSubmission/templates/AKSubmission/submission_overview.html
+++ b/AKSubmission/templates/AKSubmission/submission_overview.html
@@ -29,11 +29,6 @@
     </style>
 
     {% include "AKSubmission/ak_interest_script.html" %}
-
-    {% if event.active %}
-        <link href="{% static 'common/vendor/select2/select2.min.css' %}" rel="stylesheet" />
-        <script src="{% static 'common/vendor/select2/select2.min.js' %}"></script>
-    {% endif %}
 {% endblock %}
 
 {% block breadcrumbs %}
diff --git a/AKSubmission/templates/AKSubmission/submit_new.html b/AKSubmission/templates/AKSubmission/submit_new.html
index 1b0d94b2..b2c3a2ca 100644
--- a/AKSubmission/templates/AKSubmission/submit_new.html
+++ b/AKSubmission/templates/AKSubmission/submit_new.html
@@ -9,9 +9,6 @@
 {% block title %}{% trans "AKs" %}: {{ event.name }} - {% trans "New AK" %}{% endblock %}
 
 {% block imports %}
-    <link rel="stylesheet" href="{% static 'common/vendor/chosen-js/chosen.css' %}">
-    <link rel="stylesheet" href="{% static 'common/css/bootstrap-chosen.css' %}">
-
     {% include "AKModel/load_fullcalendar_availabilities.html" %}
 
     <script>
diff --git a/requirements.txt b/requirements.txt
index edd6ea90..43194a7d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,5 +11,7 @@ django-debug-toolbar==3.8.1
 django-bootstrap-datepicker-plus==5.0.2
 django-tex==1.1.10
 django-csp==3.7
+django-compressor==4.1
+django-libsass==0.9
 mysqlclient==2.1.1  # for production deployment
 tzdata==2022.7
diff --git a/templates/base.html b/templates/base.html
index 34ebb647..38e00fe5 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,3 +1,4 @@
+{% load compress %}
 {% load static %}
 {% load i18n %}
 {% load django_bootstrap5 %}
@@ -13,12 +14,24 @@
     <title>{% block title %}AK Planning{% endblock %}</title>
 
     <!-- Load bootstrap, jquery and fontawesome-->
-    {% bootstrap_css %}
-    {% bootstrap_javascript %}
-    <script src="{% static 'common/vendor/jquery/jquery-3.6.3.min.js' %}"></script>
-    {% fontawesome_6_static %}
-
-    <link rel="stylesheet" href="{% static 'common/css/custom.css' %}">
+    {% compress css %}
+        {% bootstrap_css %}
+        <link rel="stylesheet" href="{% static 'common/vendor/chosen-js/chosen.css' %}">
+        <link rel="stylesheet" href="{% static 'common/css/bootstrap-chosen.css' %}">
+        {% if 'AKDashboard'|check_app_installed %}
+            <link rel="stylesheet" href="{% static 'AKDashboard/style.css' %}">
+        {% endif %}
+        <link href="{% static 'common/vendor/select2/select2.min.css' %}" rel="stylesheet" />
+        {% fontawesome_6_css %}
+        <link rel="stylesheet" href="{% static 'common/css/custom.css' %}">
+    {% endcompress %}
+
+    {% compress js %}
+        {% bootstrap_javascript %}
+        <script src="{% static 'common/vendor/jquery/jquery-3.6.3.min.js' %}"></script>
+        <script src="{% static 'common/vendor/select2/select2.min.js' %}"></script>
+        {% fontawesome_6_js %}
+    {% endcompress %}
 
     <script type='text/javascript'>
         var changed_form = false;
-- 
GitLab