[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.djlint]
profile="django"
extension = ".dj.html"
indent = 2
blank_line_after_tag = "load,extends"
ignore = "T003,H017,H030,H031"
ignore = "T003,H017,H021,H030,H031"
[[tool.pdm.source]]
url = "https://pypi.org/simple"

View File

@ -1,5 +1,5 @@
from django.core import validators
from django.db import models
from django.db import models, transaction
from membershipworks.models import Member
@ -29,6 +29,17 @@ class LockerUnit(models.Model):
rows = models.PositiveIntegerField(default=5)
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:
# TODO: add constraint to check for letter overlaps
constraints = [
@ -47,20 +58,6 @@ class LockerUnit(models.Model):
def number_for_locker(self, column: int, row: int) -> int:
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
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
def address(self) -> str:
letter = self.locker_unit.letter_for_column(self.column)
number = self.locker_unit.number_for_locker(self.column, self.row)
return f"{letter}{number}"
return f"{self.letter}{self.number}"
def __str__(self):
return f"{self.locker_unit}-{self.address} [{self.renter}]"

View File

@ -25,22 +25,6 @@
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 {
background-color: hsl(24, 100%, 25%);
border: 0.2rem solid black;
@ -63,21 +47,22 @@
<div>{{ bank.location }}</div>
<div class="lockers">
{% for unit, lockers in units.items %}
<div class="locker" data-columns="{{ unit.columns }}">
{% for row, column, locker, form in lockers %}
<div class="dropdown">
<div class="locker"
style="grid-template-columns: repeat({{ unit.columns }}, min-content);">
{% 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," }}"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
data-rented="{{ locker.renter|yesno:"true,false" }}"
data-row="{{ row }}"
data-column="{{ column }}">
<h3 class="locker-name">{{ bank.initial }}{{ row }}{{ column }}</h3>
data-rented="{{ locker_form.instance.renter|yesno:"true,false" }}">
<h3 class="locker-address">{{ locker_form.instance.address }}</h3>
<div class="locker-status">
{% if locker.renter is not None %}
{% if locker_form.instance.renter is not None %}
{% if perms.rentals.view_lockerinfo %}
{{ locker.renter }}
{{ locker_form.instance.renter }}
{% else %}
Occupied
{% endif %}
@ -88,19 +73,19 @@
</span>
{% if perms.rentals.view_lockerinfo %}
<div class="dropdown-menu">
<div class="dropdown-header">{{ locker }}</div>
<div class="dropdown-header">{{ locker_form.instance }}</div>
<form class="p-2"
action="{% url 'rentals:locker' locker.id %}"
action="{% url 'rentals:locker' locker_form.instance.id %}"
method="post">
{% csrf_token %}
<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">
{{ field }}
{{ field.label_tag }}
{{ field.errors }}
{% if field.help_text %}
<p class="form-text">
<p class="form-text text-nowrap">
{{ field.help_text|safe }}
</p>
{% endif %}
@ -108,7 +93,7 @@
{% endfor %}
</fieldset>
{% 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">
{% endif %}
</form>

View File

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