diff --git a/cards/templates/cards/list.html b/cards/templates/cards/list.html index 4c7169d..5f88004 100644 --- a/cards/templates/cards/list.html +++ b/cards/templates/cards/list.html @@ -15,6 +15,9 @@
Export table
+
+ Print cards +
{% if card_count is not None %} diff --git a/cards/templates/cards/print.html b/cards/templates/cards/print.html new file mode 100644 index 0000000..82ba0a1 --- /dev/null +++ b/cards/templates/cards/print.html @@ -0,0 +1,55 @@ +{% extends 'cards/base.html' %} + +{% block content %} +
+
+ ← Back to list +

Print cards

+
+

Select which cards to include and choose a design. Click Open printable view to open the print preview in a new tab (you can then print to PDF or to an A4 printer).

+ + +
+{% endblock %} diff --git a/cards/templates/cards/printable.html b/cards/templates/cards/printable.html new file mode 100644 index 0000000..facc379 --- /dev/null +++ b/cards/templates/cards/printable.html @@ -0,0 +1,71 @@ + + + + + + Printable cards + + + +
+
+ ← Back to selection +
+
+ +
+
+ + {% for page_cards in pages %} +
+
+ {% for card in page_cards %} + + {% endfor %} +
+
+ {% endfor %} + + diff --git a/cards/urls.py b/cards/urls.py index 4c20092..2bc73e8 100644 --- a/cards/urls.py +++ b/cards/urls.py @@ -9,6 +9,8 @@ urlpatterns = [ path('/edit/', views.card_edit, name='edit'), path('/delete/', views.card_delete, name='delete'), path('preview//', views.preview_card, name='preview'), + path('print/', views.print_cards, name='print'), + path('print/preview/', views.print_preview, name='print_preview'), path('backgrounds/', views.background_list, name='backgrounds'), path('backgrounds/create/', views.background_create, name='background_create'), path('backgrounds//edit/', views.background_edit, name='background_edit'), diff --git a/cards/views.py b/cards/views.py index 4cc6f00..1876ff8 100644 --- a/cards/views.py +++ b/cards/views.py @@ -412,6 +412,48 @@ def export_table(request): return render(request, 'cards/export_table.html', {'json_text': json_text}) +def print_cards(request): + """Selection UI where the user picks which cards to print and which design.""" + qs = Dinosaur.objects.order_by('name') + background = BackgroundImage.get_active() if BackgroundImage.objects.exists() else None + return render(request, 'cards/print.html', {'cards': qs, 'background': background}) + + +def print_preview(request): + """Render a printable view of selected cards. + + POST params: + - cards: repeated card pks + - design: design number + - scale: optional scale factor + + Returns an HTML A4-friendly document that the browser can print or save as PDF. + """ + # Accept POST or GET for easier testing + data = request.POST if request.method == 'POST' else request.GET + pks = data.getlist('cards') + if not pks: + return HttpResponseBadRequest('No cards selected') + try: + design = int(data.get('design', '1')) + except Exception: + design = 1 + scale = float(data.get('scale', '1')) if data.get('scale') else 1.0 + # Fetch cards preserving the given order + cards = list(Dinosaur.objects.filter(pk__in=pks)) + # Reorder according to provided pks + pk_to_card = {str(c.pk): c for c in cards} + ordered = [pk_to_card[pk] for pk in pks if pk in pk_to_card] + + # Build pages: two cards per A4 page (2-up) + pages = [] + per_page = 2 + for i in range(0, len(ordered), per_page): + pages.append(ordered[i:i+per_page]) + + return render(request, 'cards/printable.html', {'pages': pages, 'design': design, 'scale': scale}) + + def _parse_pasted_input(text): """Try to parse pasted LLM output into a list of suggestion dicts.