diff --git a/config/mixins.py b/config/mixins.py index ec39e2d..491425b 100644 --- a/config/mixins.py +++ b/config/mixins.py @@ -23,7 +23,9 @@ class HTMXFormComponent(TemplateView): instance = self.get_object() if initial: - return self.form_class(initial=self.get_initial_values(instance), instance=instance) + return self.form_class( + initial=self.get_initial_values(instance), instance=instance + ) return self.form_class(self.request.POST, instance=instance) diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 6c751de..023ba9e 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -34,7 +34,6 @@ server { add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - add_header Accept-Encoding "gzip, compress, br" # gzip gzip on; diff --git a/scripts/build_static.sh b/scripts/build_static.sh index 01415ce..4e7d9eb 100644 --- a/scripts/build_static.sh +++ b/scripts/build_static.sh @@ -10,9 +10,3 @@ nvm install 22 python manage.py tailwind install python manage.py tailwind build python manage.py collectstatic --noinput - -# Clean npm -rm -rf ~/.nvm -rm -rf ~/.npm -rm -rf ~/.bower -rm -rf /code/theme/static_src/node_modules/ diff --git a/scripts/run.sh b/scripts/run.sh index 776e356..d442af7 100644 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -8,7 +8,12 @@ WORKER_NUM_PROCESSES=${WORKER_NUM_PROCESSES:=1} RUN_SERVER=${RUN_SERVER:="FALSE"} RUN_CELERY=${RUN_CELERY:="FALSE"} +export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm + [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion + python manage.py compilemessages +python manage.py build_tailwind_theme if [ $RUN_SERVER = "TRUE" ]; then service nginx start diff --git a/theme/management/__init__.py b/theme/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/theme/management/commands/__init__.py b/theme/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/theme/management/commands/build_tailwind_theme.py b/theme/management/commands/build_tailwind_theme.py new file mode 100644 index 0000000..1ee67e5 --- /dev/null +++ b/theme/management/commands/build_tailwind_theme.py @@ -0,0 +1,30 @@ +import os +from django.conf import settings +from django.core.management.base import BaseCommand +from django.template.loader import render_to_string +from django.core.management import call_command +from web.models import WebSettings + + +class Command(BaseCommand): + """ + Usage: + + python manage.py build_tailwind_theme + """ + + def handle(self, *args, **options): + web_settings = WebSettings.load() + path = os.path.join( + settings.BASE_DIR, "theme", "static_src", "tailwind.config.js" + ) + result = str( + render_to_string( + "theme/tailwind.config.template.js", context=web_settings.theme_colors + ) + ) + with open(path, "w") as f: + f.write(result) + + call_command("tailwind", "build") + call_command("collectstatic", "--no-input") diff --git a/theme/templates/theme/tailwind.config.template.js b/theme/templates/theme/tailwind.config.template.js new file mode 100644 index 0000000..4d83010 --- /dev/null +++ b/theme/templates/theme/tailwind.config.template.js @@ -0,0 +1,90 @@ +/** + * This is a minimal config. + * + * If you need the full config, get it from here: + * https://unpkg.com/browse/tailwindcss@latest/stubs/defaultConfig.stub.js + */ +const colors = require('tailwindcss/colors') + + +module.exports = { + content: [ + /** + * HTML. Paths to Django template files that will contain Tailwind CSS classes. + */ + + /* Templates within theme app (/templates), e.g. base.html. */ + '../templates/**/*.html', + + /* + * Main templates directory of the project (BASE_DIR/templates). + * Adjust the following line to match your project structure. + */ + '../../templates/**/*.html', + + /* + * Templates in other django apps (BASE_DIR//templates). + * Adjust the following line to match your project structure. + */ + '../../**/templates/**/*.html', + + /** + * JS: If you use Tailwind CSS in JavaScript, uncomment the following lines and make sure + * patterns match your project structure. + */ + /* JS 1: Ignore any JavaScript in node_modules folder. */ + // '!../../**/node_modules', + /* JS 2: Process all JavaScript files in the project. */ + // '../../**/*.js', + + /** + * Python: If you use Tailwind CSS classes in Python, uncomment the following line + * and make sure the pattern below matches your project structure. + */ + // '../../**/*.py' + ], + darkMode: 'class', + theme: { + extend: { + colors: { + {% if gray %} + gray: { + {% for k, v in gray.items %} + {{k}}: '{{v}}'{% if not forloop.last %},{% endif %} + {% endfor %} + }, + {% else %} + gray: colors.zinc, + {% endif %} + {% if accent %} + accent: { + {% for k, v in accent.items %} + {{k}}: '{{v}}'{% if not forloop.last %},{% endif %} + {% endfor %} + }, + {% else %} + accent: colors.teal, + {% endif %} + {% if primary %} + primary: { + {% for k, v in primary.items %} + {{k}}: '{{v}}'{% if not forloop.last %},{% endif %} + {% endfor %} + }, + {% else %} + primary: colors.rose, + {% endif %} + } + } + }, + plugins: [ + /** + * '@tailwindcss/forms' is the forms plugin that provides a minimal styling + * for forms. If you don't like it or have own styling for forms, + * comment the line below to disable '@tailwindcss/forms'. + */ + require('@tailwindcss/forms'), + require('@tailwindcss/typography'), + require('@tailwindcss/aspect-ratio'), + ], +} diff --git a/web/apps.py b/web/apps.py index c11daac..e3fe3ab 100644 --- a/web/apps.py +++ b/web/apps.py @@ -4,3 +4,6 @@ from django.apps import AppConfig class WebConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "web" + + def ready(self): + from .signals import rebuild_theme diff --git a/web/migrations/0003_websettings_theme_colors.py b/web/migrations/0003_websettings_theme_colors.py new file mode 100644 index 0000000..8de5b66 --- /dev/null +++ b/web/migrations/0003_websettings_theme_colors.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.4 on 2025-01-21 11:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("web", "0002_remove_websettings_logo_240_websettings_logo_256"), + ] + + operations = [ + migrations.AddField( + model_name="websettings", + name="theme_colors", + field=models.JSONField( + default=dict, verbose_name="colores del tema", blank=True + ), + ), + ] diff --git a/web/models.py b/web/models.py index 738ec24..c6f8463 100644 --- a/web/models.py +++ b/web/models.py @@ -86,6 +86,9 @@ class WebSettings(SingletonModel): logo_128 = models.ImageField( upload_to="assets", blank=True, null=True, verbose_name=_("logo 128x128") ) + theme_colors = models.JSONField( + default=dict, verbose_name=_("colores del tema"), blank=True + ) def get_resized_logo(self, size): width, height = size diff --git a/web/signals.py b/web/signals.py index f01e2dc..1a75ca5 100644 --- a/web/signals.py +++ b/web/signals.py @@ -1,7 +1,9 @@ +from django.db.models.signals import post_save from django.dispatch import receiver - +from django.core.management import call_command from shop.models import Cart, CartItem from shop.signals import clear_cart, send_order_email +from web.models import WebSettings @receiver(clear_cart, dispatch_uid="clear_cart") @@ -13,3 +15,11 @@ def create_payment_from_redsys(sender, **kwargs): @receiver(send_order_email, dispatch_uid="send_order_email") def create_payment_from_redsys(sender, **kwargs): pass + + +@receiver(post_save, sender=WebSettings) +def rebuild_theme(sender, instance: WebSettings, **kwargs): + try: + call_command("build_tailwind_theme") + except Exception: + pass diff --git a/web/urls.py b/web/urls.py index ed70028..be01c13 100644 --- a/web/urls.py +++ b/web/urls.py @@ -11,7 +11,8 @@ from web.views.components import ( list_wishlisted_products, update_customer_address, user_info_component, - wishlist_button, change_password_component, + wishlist_button, + change_password_component, ) from web.views.users import ( login,