[rentals] Simplify locker index view/template rendering

Also create locker info instances when a new locker unit is created
This commit is contained in:
Adam Goldsmith 2022-02-16 22:44:54 -05:00
parent 937646798a
commit ff723e019d
4 changed files with 39 additions and 53 deletions

View File

@ -29,10 +29,11 @@ server = [
[tool.black] [tool.black]
[tool.djlint] [tool.djlint]
profile="django"
extension = ".dj.html" extension = ".dj.html"
indent = 2 indent = 2
blank_line_after_tag = "load,extends" blank_line_after_tag = "load,extends"
ignore = "T003,H017,H030,H031" ignore = "T003,H017,H021,H030,H031"
[[tool.pdm.source]] [[tool.pdm.source]]
url = "https://pypi.org/simple" url = "https://pypi.org/simple"

View File

@ -1,5 +1,5 @@
from django.core import validators from django.core import validators
from django.db import models from django.db import models, transaction
from membershipworks.models import Member from membershipworks.models import Member
@ -29,6 +29,17 @@ class LockerUnit(models.Model):
rows = models.PositiveIntegerField(default=5) rows = models.PositiveIntegerField(default=5)
columns = models.PositiveIntegerField(default=2) columns = models.PositiveIntegerField(default=2)
def save(self, *args, **kwargs):
if self._state.adding:
# Create LockerInfo for each locker
with transaction.atomic():
super().save(self, *args, **kwargs)
for column in range(self.columns):
for row in range(self.rows):
self.lockers.create(column=column + 1, row=row + 1)
else:
super().save(self, *args, **kwargs)
class Meta: class Meta:
# TODO: add constraint to check for letter overlaps # TODO: add constraint to check for letter overlaps
constraints = [ constraints = [
@ -47,20 +58,6 @@ class LockerUnit(models.Model):
def number_for_locker(self, column: int, row: int) -> int: def number_for_locker(self, column: int, row: int) -> int:
return row + self.first_number + (self.columns - column - 1) * self.rows return row + self.first_number + (self.columns - column - 1) * self.rows
def iter_doors(self):
for row in range(self.rows):
for column in range(self.columns):
# TODO: filter could be optimized
(locker, _) = self.lockers.get_or_create(
locker_unit=self, row=row, column=column
)
yield (
self.letter_for_column(column),
self.number_for_locker(column, row),
locker,
)
# TODO: add check constraint to ensure that column and number are within locker_unit bounds # TODO: add check constraint to ensure that column and number are within locker_unit bounds
class LockerInfo(models.Model): class LockerInfo(models.Model):
@ -92,11 +89,17 @@ class LockerInfo(models.Model):
) )
] ]
@property
def letter(self) -> str:
return self.locker_unit.letter_for_column(self.column)
@property
def number(self) -> int:
return self.locker_unit.number_for_locker(self.column, self.row)
@property @property
def address(self) -> str: def address(self) -> str:
letter = self.locker_unit.letter_for_column(self.column) return f"{self.letter}{self.number}"
number = self.locker_unit.number_for_locker(self.column, self.row)
return f"{letter}{number}"
def __str__(self): def __str__(self):
return f"{self.locker_unit}-{self.address} [{self.renter}]" return f"{self.locker_unit}-{self.address} [{self.renter}]"

View File

@ -25,22 +25,6 @@
gap: 0.5rem; gap: 0.5rem;
} }
.locker[data-columns="2"] {
grid-template-columns: repeat(2, min-content);
}
.locker[data-columns="4"] {
grid-template-columns: repeat(4, min-content);
}
.locker[data-columns="6"] {
grid-template-columns: repeat(6, min-content);
}
.locker[data-columns="8"] {
grid-template-columns: repeat(8, min-content);
}
.locker[data-columns="10"] {
grid-template-columns: repeat(10, min-content);
}
.locker .door { .locker .door {
background-color: hsl(24, 100%, 25%); background-color: hsl(24, 100%, 25%);
border: 0.2rem solid black; border: 0.2rem solid black;
@ -63,21 +47,22 @@
<div>{{ bank.location }}</div> <div>{{ bank.location }}</div>
<div class="lockers"> <div class="lockers">
{% for unit, lockers in units.items %} {% for unit, lockers in units.items %}
<div class="locker" data-columns="{{ unit.columns }}"> <div class="locker"
{% for row, column, locker, form in lockers %} style="grid-template-columns: repeat({{ unit.columns }}, min-content);">
<div class="dropdown"> {% for locker_form in lockers %}
<div class="dropdown"
style="grid-row-start: {{ locker_form.instance.row|add:"1" }}; grid-column-start: {{ locker_form.instance.column|add:"
1>
<span class="door {{ perms.rentals.view_lockerinfo|yesno:"btn dropdown-toggle," }}" <span class="door {{ perms.rentals.view_lockerinfo|yesno:"btn dropdown-toggle," }}"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
aria-haspopup="true" aria-haspopup="true"
aria-expanded="false" aria-expanded="false"
data-rented="{{ locker.renter|yesno:"true,false" }}" data-rented="{{ locker_form.instance.renter|yesno:"true,false" }}">
data-row="{{ row }}" <h3 class="locker-address">{{ locker_form.instance.address }}</h3>
data-column="{{ column }}">
<h3 class="locker-name">{{ bank.initial }}{{ row }}{{ column }}</h3>
<div class="locker-status"> <div class="locker-status">
{% if locker.renter is not None %} {% if locker_form.instance.renter is not None %}
{% if perms.rentals.view_lockerinfo %} {% if perms.rentals.view_lockerinfo %}
{{ locker.renter }} {{ locker_form.instance.renter }}
{% else %} {% else %}
Occupied Occupied
{% endif %} {% endif %}
@ -88,19 +73,19 @@
</span> </span>
{% if perms.rentals.view_lockerinfo %} {% if perms.rentals.view_lockerinfo %}
<div class="dropdown-menu"> <div class="dropdown-menu">
<div class="dropdown-header">{{ locker }}</div> <div class="dropdown-header">{{ locker_form.instance }}</div>
<form class="p-2" <form class="p-2"
action="{% url 'rentals:locker' locker.id %}" action="{% url 'rentals:locker' locker_form.instance.id %}"
method="post"> method="post">
{% csrf_token %} {% csrf_token %}
<fieldset {{ perms.rentals.change_lockerinfo|yesno:",disabled" }}> <fieldset {{ perms.rentals.change_lockerinfo|yesno:",disabled" }}>
{% for field in form.visible_fields %} {% for field in locker_form.visible_fields %}
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ field }} {{ field }}
{{ field.label_tag }} {{ field.label_tag }}
{{ field.errors }} {{ field.errors }}
{% if field.help_text %} {% if field.help_text %}
<p class="form-text"> <p class="form-text text-nowrap">
{{ field.help_text|safe }} {{ field.help_text|safe }}
</p> </p>
{% endif %} {% endif %}
@ -108,7 +93,7 @@
{% endfor %} {% endfor %}
</fieldset> </fieldset>
{% if perms.rentals.change_lockerinfo %} {% if perms.rentals.change_lockerinfo %}
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %} {% for hidden in locker_form.hidden_fields %}{{ hidden }}{% endfor %}
<input class="btn btn-primary" type="submit" value="Submit"> <input class="btn btn-primary" type="submit" value="Submit">
{% endif %} {% endif %}
</form> </form>

View File

@ -11,10 +11,7 @@ from .forms import LockerInfoForm
def lockerIndex(request): def lockerIndex(request):
locker_banks = { locker_banks = {
bank: { bank: {
unit: [ unit: [LockerInfoForm(instance=locker) for locker in unit.lockers.all()]
(col, num, locker, LockerInfoForm(instance=locker))
for col, num, locker in unit.iter_doors()
]
for unit in bank.units.all() for unit in bank.units.all()
} }
for bank in LockerBank.objects.all() for bank in LockerBank.objects.all()