Add counters to cards

This commit is contained in:
2025-04-30 22:50:43 +02:00
parent ece8d1ad94
commit 2e06e94fde
7 changed files with 71 additions and 14 deletions

View File

@@ -39,8 +39,10 @@
</tbody> </tbody>
</table> </table>
<div class="d-grid gap-2 mb-1 d-md-block"> <div class="d-grid gap-2 mb-1 d-md-block">
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="company" search=d.item.slug %}">Show all rolling stock</a> {% with items=d.item.num_items %}
<a class="btn btn-sm btn-outline-primary{% if items == 0 %} disabled{% endif %}" href="{% url 'filtered' _filter="company" search=d.item.slug %}">Show {{ items }} item{{ items | pluralize}}</a>
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_company_change' d.item.pk %}">Edit</a>{% endif %} {% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_company_change' d.item.pk %}">Edit</a>{% endif %}
{% endwith %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -30,8 +30,10 @@
</tbody> </tbody>
</table> </table>
<div class="d-grid gap-2 mb-1 d-md-block"> <div class="d-grid gap-2 mb-1 d-md-block">
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="manufacturer" search=d.item.slug %}">Show all rolling stock</a> {% with items=d.item.num_items %}
<a class="btn btn-sm btn-outline-primary{% if items == 0 %} disabled{% endif %}" href="{% url 'filtered' _filter="manufacturer" search=d.item.slug %}">Show {{ items }} item{{ items | pluralize}}</a>
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_manufacturer_change' d.item.pk %}">Edit</a>{% endif %} {% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_manufacturer_change' d.item.pk %}">Edit</a>{% endif %}
{% endwith %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -20,8 +20,10 @@
</tbody> </tbody>
</table> </table>
<div class="d-grid gap-2 mb-1 d-md-block"> <div class="d-grid gap-2 mb-1 d-md-block">
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="type" search=d.item.slug %}">Show all rolling stock</a> {% with items=d.item.num_items %}
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.item.pk %}">Edit</a>{% endif %} <a class="btn btn-sm btn-outline-primary{% if items == 0 %} disabled{% endif %}" href="{% url 'filtered' _filter="type" search=d.item.slug %}">Show {{ items }} item{{ items | pluralize}}</a>
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_rollingstocktype_change' d.item.pk %}">Edit</a>{% endif %}
{% endwith %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -28,8 +28,10 @@
</tbody> </tbody>
</table> </table>
<div class="d-grid gap-2 mb-1 d-md-block"> <div class="d-grid gap-2 mb-1 d-md-block">
<a class="btn btn-sm btn-outline-primary{% if d.item.num_items == 0 %} disabled{% endif %}" href="{% url 'filtered' _filter="scale" search=d.item.slug %}">Show all rolling stock</a> {% with items=d.item.num_items %}
<a class="btn btn-sm btn-outline-primary{% if items == 0 %} disabled{% endif %}" href="{% url 'filtered' _filter="scale" search=d.item.slug %}">Show {{ items }} item{{ items | pluralize}}</a>
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.item.pk %}">Edit</a>{% endif %} {% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.item.pk %}">Edit</a>{% endif %}
{% endwith %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -109,7 +109,11 @@
{% endif %} {% endif %}
<tr> <tr>
<th scope="row">Length</th> <th scope="row">Length</th>
<td>{{ consist.length }} | {% for t in consist.get_type_count %}{{ t.count }}x {{ t.type }} {{t.category }}{% if not forloop.last %} + {% endif %}{% endfor %}</td> <td>{{ consist.length }}</td>
</tr>
<tr>
<th scope="row">Composition</th>
<td>{% for t in consist.get_type_count %}{{ t.count }}x {{ t.type }} {{t.category }}{% if not forloop.last %} &raquo; {% endif %}{% endfor %}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -7,7 +7,7 @@ from urllib.parse import unquote
from django.views import View from django.views import View
from django.http import Http404, HttpResponseBadRequest from django.http import Http404, HttpResponseBadRequest
from django.db.utils import OperationalError, ProgrammingError from django.db.utils import OperationalError, ProgrammingError
from django.db.models import Q, Count from django.db.models import F, Q, Count
from django.shortcuts import render, get_object_or_404, get_list_or_404 from django.shortcuts import render, get_object_or_404, get_list_or_404
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator from django.core.paginator import Paginator
@@ -490,7 +490,11 @@ class Manufacturers(GetData):
item_type = "manufacturer" item_type = "manufacturer"
def get_data(self, request): def get_data(self, request):
return Manufacturer.objects.filter(self.filter) return Manufacturer.objects.filter(
self.filter
).annotate(
num_items=Count("rollingstock") + Count("rollingclass"),
).order_by("name")
# overload get method to filter by category # overload get method to filter by category
def get(self, request, category, page=1): def get(self, request, category, page=1):
@@ -506,18 +510,50 @@ class Companies(GetData):
item_type = "company" item_type = "company"
def get_data(self, request): def get_data(self, request):
return Company.objects.all() return Company.objects.annotate(
num_rollingstock=(
Count(
"rollingclass__rolling_class",
filter=Q(
rollingclass__rolling_class__in=(
RollingStock.objects.get_published(request.user)
)
),
distinct=True
)
)
).annotate(
num_consists=(
Count(
"consist",
filter=Q(
consist__in=(
Consist.objects.get_published(request.user)
),
),
distinct=True
)
)
).annotate(
num_items=F("num_rollingstock") + F("num_consists")
).order_by("name")
class Scales(GetData): class Scales(GetData):
title = "Scales" title = "Scales"
item_type = "scale" item_type = "scale"
queryset = Scale.objects.all()
def get_data(self, request): def get_data(self, request):
return Scale.objects.annotate( return Scale.objects.annotate(
num_items=Count("rollingstock") num_items=Count(
) # .filter(num_items__gt=0) to filter data with no items "rollingstock",
filter=Q(
rollingstock__in=RollingStock.objects.get_published(
request.user
)
),
),
).order_by("-ratio_int", "-tracks", "scale")
class Types(GetData): class Types(GetData):
@@ -525,7 +561,16 @@ class Types(GetData):
item_type = "rolling_stock_type" item_type = "rolling_stock_type"
def get_data(self, request): def get_data(self, request):
return RollingStockType.objects.all() return RollingStockType.objects.annotate(
num_items=Count(
"rollingclass__rolling_class",
filter=Q(
rollingclass__rolling_class__in=(
RollingStock.objects.get_published(request.user)
)
),
)
).order_by("order")
class Books(GetData): class Books(GetData):

View File

@@ -1,4 +1,4 @@
from ram.utils import git_suffix from ram.utils import git_suffix
__version__ = "0.17.5" __version__ = "0.17.6"
__version__ += git_suffix(__file__) __version__ += git_suffix(__file__)