From 0c2673832926d89f9649cdcd24fd4c460cdac034 Mon Sep 17 00:00:00 2001
From: "Auguste \"laggron42\" Charpentier" <laggron42@gmail.com>
Date: Tue, 21 Jan 2025 14:11:40 +0100
Subject: [PATCH] display special preview

---
 .../templates/generate_ball_preview.html      |  2 +-
 admin_panel/preview/urls.py                   |  5 +-
 admin_panel/preview/views.py                  | 37 +++++++++-
 .../admin/bd_models/special/change_form.html  | 73 +++++++++++++++++++
 4 files changed, 111 insertions(+), 6 deletions(-)
 create mode 100644 admin_panel/templates/admin/bd_models/special/change_form.html

diff --git a/admin_panel/bd_models/templates/generate_ball_preview.html b/admin_panel/bd_models/templates/generate_ball_preview.html
index b0f8a968..3d219da3 100644
--- a/admin_panel/bd_models/templates/generate_ball_preview.html
+++ b/admin_panel/bd_models/templates/generate_ball_preview.html
@@ -5,7 +5,7 @@
 <nav id="preview-sidebar">
     <h2>Preview</h2>
     <div id="preview-content">
-        <img src="/ball/generate/{{ object_id }}" width="100%"/>
+        <img src="/{% if request.resolver_match.url_name == "bd_models_ball_change" %}ball{% else %}special{% endif %}/generate/{{ object_id }}" width="100%"/>
         <h5>Save to reload the preview</h5>
     </div>
 </nav>
\ No newline at end of file
diff --git a/admin_panel/preview/urls.py b/admin_panel/preview/urls.py
index 1c8a668c..c2ab2f6c 100644
--- a/admin_panel/preview/urls.py
+++ b/admin_panel/preview/urls.py
@@ -1,7 +1,8 @@
 from django.urls import path
 
-from .views import render_image
+from .views import render_ballinstance, render_special
 
 urlpatterns = [
-    path("ball/generate/<int:ball_pk>", render_image),
+    path("ball/generate/<int:ball_pk>", render_ballinstance),
+    path("special/generate/<int:special_pk>", render_special),
 ]
diff --git a/admin_panel/preview/views.py b/admin_panel/preview/views.py
index 748f833d..077d078f 100644
--- a/admin_panel/preview/views.py
+++ b/admin_panel/preview/views.py
@@ -1,9 +1,11 @@
 import os
 
+from django.contrib import messages
 from django.http import HttpRequest, HttpResponse
 from tortoise import Tortoise
 
 from ballsdex.__main__ import init_tortoise
+from ballsdex.core.image_generator.image_gen import draw_card
 from ballsdex.core.models import (
     Ball,
     BallInstance,
@@ -17,9 +19,14 @@
 )
 
 
-async def render_image(request: HttpRequest, ball_pk: int) -> HttpResponse:
-    from ballsdex.core.image_generator.image_gen import draw_card
+async def _refresh_cache():
+    """
+    Similar to the bot's `load_cache` function without the fancy display. Also handles
+    initializing the connection to Tortoise.
 
+    This must be called on every request, since the image generation relies on cache and we
+    do *not* want caching in the admin panel to happen (since we're actively editing stuff).
+    """
     if not Tortoise._inited:
         await init_tortoise(os.environ["BALLSDEXBOT_DB_URL"], skip_migrations=True)
     balls.clear()
@@ -38,8 +45,32 @@ async def render_image(request: HttpRequest, ball_pk: int) -> HttpResponse:
     for special in await Special.all():
         specials[special.pk] = special
 
+
+async def render_ballinstance(request: HttpRequest, ball_pk: int) -> HttpResponse:
+    await _refresh_cache()
+
     ball = await Ball.get(pk=ball_pk)
-    instance = BallInstance(ball=ball, count=1)
+    instance = BallInstance(ball=ball)
+    image = draw_card(instance, media_path="./media/")
+
+    response = HttpResponse(content_type="image/png")
+    image.save(response, "PNG")  # type: ignore
+    return response
+
+
+async def render_special(request: HttpRequest, special_pk: int) -> HttpResponse:
+    await _refresh_cache()
+
+    ball = await Ball.first()
+    if ball is None:
+        messages.warning(
+            request,
+            "You must create a countryball before being able to generate a special's preview.",
+        )
+        return HttpResponse(status_code=422)
+
+    special = await Special.get(pk=special_pk)
+    instance = BallInstance(ball=ball, special=special)
     image = draw_card(instance, media_path="./media/")
 
     response = HttpResponse(content_type="image/png")
diff --git a/admin_panel/templates/admin/bd_models/special/change_form.html b/admin_panel/templates/admin/bd_models/special/change_form.html
new file mode 100644
index 00000000..dfc03162
--- /dev/null
+++ b/admin_panel/templates/admin/bd_models/special/change_form.html
@@ -0,0 +1,73 @@
+<!--
+This file has been copied from
+https://github.com/django/django/blob/8914b571eb5f93722b9741b1da9eb69347271b11/django/contrib/admin/templates/admin/change_form.html
+
+The entire "content" block has to be overwritten to add a sidebar containing the preview generator
+for ball creation/edition form.
+-->
+
+{% extends "admin/change_form.html" %}
+{% load i18n admin_urls static admin_modify %}
+
+{% block content %}
+{% if request.resolver_match.url_name == "bd_models_special_change" %}
+<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}">
+<div id="content-main">
+    {% block object-tools %}
+    {% if change and not is_popup %}
+    <ul class="object-tools">
+        {% block object-tools-items %}
+        {% change_form_object_tools %}
+        {% endblock %}
+    </ul>
+    {% endif %}
+    {% endblock %}
+    <div class="module" id="changelist">
+    <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}" {% endif %}method="post" id="{{ opts.model_name }}_form" novalidate style="flex-basis:66%;min-width:0;">{% csrf_token %}{% block form_top %}{% endblock %}
+        <div>
+            {% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
+            {% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
+            {% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
+            {% if errors %}
+            <p class="errornote">
+                {% blocktranslate count counter=errors|length %}Please correct the error below.{% plural %}Please
+                correct the errors below.{% endblocktranslate %}
+            </p>
+            {{ adminform.form.non_field_errors }}
+            {% endif %}
+
+            {% block field_sets %}
+            {% for fieldset in adminform %}
+            {% include "admin/includes/fieldset.html" with heading_level=2 prefix="fieldset" id_prefix=0 id_suffix=forloop.counter0 %}
+            {% endfor %}
+            {% endblock %}
+
+            {% block after_field_sets %}{% endblock %}
+
+            {% block inline_field_sets %}
+            {% for inline_admin_formset in inline_admin_formsets %}
+            {% include inline_admin_formset.opts.template %}
+            {% endfor %}
+            {% endblock %}
+
+            {% block after_related_objects %}{% endblock %}
+
+            {% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
+
+            {% block admin_change_form_document_ready %}
+            <script id="django-admin-form-add-constants" src="{% static 'admin/js/change_form.js' %}" {% if adminform and add %} data-model-name="{{ opts.model_name }}" {% endif %} async>
+                </script>
+            {% endblock %}
+
+            {# JavaScript for prepopulated fields #}
+            {% prepopulated_fields_js %}
+
+        </div>
+    </form>
+    {% include "generate_ball_preview.html" %}
+</div>
+</div>
+{% else %}
+    {{ block.super }}
+{% endif %}
+{% endblock %}
\ No newline at end of file