Skip to content

Commit 20bf7da

Browse files
n11ikNik Sauer
and
Nik Sauer
authored
added workshop log to device detail (#238)
Co-authored-by: Nik Sauer <[email protected]>
1 parent a1131cf commit 20bf7da

File tree

4 files changed

+92
-45
lines changed

4 files changed

+92
-45
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Generated by Django 5.2 on 2025-04-30 09:32
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('api', '0012_alter_airqualityrecord_workshop'),
11+
('devices', '0020_device_created_at'),
12+
]
13+
14+
operations = [
15+
migrations.AlterField(
16+
model_name='airqualityrecord',
17+
name='device',
18+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='air_quality_records', to='devices.device'),
19+
),
20+
]

app/api/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class AirQualityRecord(models.Model):
3131
iaq_acc = models.SmallIntegerField(null=True, blank=True)
3232
iaq_static = models.FloatField(null=True, blank=True)
3333
pressure = models.FloatField(null=True, blank=True)
34-
device = models.ForeignKey(Device, on_delete=models.CASCADE, null=True)
34+
device = models.ForeignKey(Device, on_delete=models.CASCADE, null=True, related_name='air_quality_records')
3535
workshop = models.ForeignKey(Workshop, on_delete=models.CASCADE, null=True, blank=True, related_name='air_quality_records')
3636
participant = models.ForeignKey(Participant, on_delete=models.CASCADE, null=True, blank=True)
3737
lat = models.FloatField(null=True, blank=True)

app/devices/views.py

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -67,51 +67,68 @@ def get_context_data(self, **kwargs):
6767
round(status.battery_voltage, 2)
6868
for status in device_status_qs
6969
if status.battery_soc is not None and status.battery_voltage is not None
70-
]
71-
72-
# query changes
73-
organization_changes = device.history.filter(changes__icontains = '"current_organization"').all().order_by('-timestamp')
74-
room_changes = device.history.filter(changes__icontains = '"current_room"').all().order_by('-timestamp')
75-
user_changes = device.history.filter(changes__icontains = '"current_user"').all().order_by('-timestamp')
76-
77-
organization_change_log = []
78-
room_change_log = []
79-
user_change_log = []
80-
81-
# prepare changes
82-
for h in organization_changes:
83-
prev = h.changes['current_organization'][0]
84-
next = h.changes['current_organization'][1]
85-
organization_change_log.append({
86-
'timestamp': h.timestamp,
87-
'prev': None if prev == 'None' else Organization.objects.filter(id=prev).first(),
88-
'next': None if next == 'None' else Organization.objects.filter(id=next).first(),
89-
})
90-
for h in room_changes:
91-
prev = h.changes['current_room'][0]
92-
next = h.changes['current_room'][1]
93-
room_change_log.append({
94-
'timestamp': h.timestamp,
95-
'prev': None if prev == 'None' else Room.objects.filter(id=prev).first(),
96-
'next': None if next == 'None' else Room.objects.filter(id=next).first(),
97-
})
98-
for h in user_changes:
99-
prev = h.changes['current_user'][0]
100-
next = h.changes['current_user'][1]
101-
user_change_log.append({
102-
'timestamp': h.timestamp,
103-
'prev': None if prev == 'None' else CustomUser.objects.filter(id=prev).first(),
104-
'next': None if next == 'None' else CustomUser.objects.filter(id=next).first(),
105-
})
106-
107-
context['organization_change_log'] = organization_change_log
108-
context['room_change_log'] = room_change_log
109-
context['user_change_log'] = user_change_log
110-
70+
]
11171
# Serialize data to JSON format
11272
context['battery_times'] = json.dumps(battery_times, cls=DjangoJSONEncoder)
11373
context['battery_charges'] = json.dumps(battery_charges, cls=DjangoJSONEncoder)
11474
context['battery_voltages'] = json.dumps(battery_voltages, cls=DjangoJSONEncoder)
75+
76+
# query changes
77+
organization_changes = device.history.filter(changes__icontains = '"current_organization"').all().order_by('-timestamp')
78+
room_changes = device.history.filter(changes__icontains = '"current_room"').all().order_by('-timestamp')
79+
user_changes = device.history.filter(changes__icontains = '"current_user"').all().order_by('-timestamp')
80+
81+
organization_change_log = []
82+
room_change_log = []
83+
user_change_log = []
84+
workshop_change_log = []
85+
86+
# prepare changes
87+
for h in organization_changes:
88+
prev = h.changes['current_organization'][0]
89+
next = h.changes['current_organization'][1]
90+
organization_change_log.append({
91+
'timestamp': h.timestamp,
92+
'prev': None if prev == 'None' else Organization.objects.filter(id=prev).first(),
93+
'next': None if next == 'None' else Organization.objects.filter(id=next).first(),
94+
})
95+
for h in room_changes:
96+
prev = h.changes['current_room'][0]
97+
next = h.changes['current_room'][1]
98+
room_change_log.append({
99+
'timestamp': h.timestamp,
100+
'prev': None if prev == 'None' else Room.objects.filter(id=prev).first(),
101+
'next': None if next == 'None' else Room.objects.filter(id=next).first(),
102+
})
103+
for h in user_changes:
104+
prev = h.changes['current_user'][0]
105+
next = h.changes['current_user'][1]
106+
user_change_log.append({
107+
'timestamp': h.timestamp,
108+
'prev': None if prev == 'None' else CustomUser.objects.filter(id=prev).first(),
109+
'next': None if next == 'None' else CustomUser.objects.filter(id=next).first(),
110+
})
111+
112+
# time, workshop
113+
workshop_changes = []
114+
for record in reversed(sorted((record.time, record.workshop.name) for record in device.air_quality_records.all())):
115+
if not workshop_changes or workshop_changes[-1][1] != record[1]:
116+
workshop_changes.append(record)
117+
118+
for i in range(0, len(workshop_changes)):
119+
workshop_change_log.append({
120+
'timestamp': workshop_changes[i][0],
121+
'prev': None if i == len(workshop_changes) - 1 else workshop_changes[i + 1][1],
122+
'next': workshop_changes[i][1]
123+
})
124+
125+
current_workshop = workshop_change_log[0]['next'] if workshop_change_log else None
126+
127+
context['organization_change_log'] = organization_change_log
128+
context['room_change_log'] = room_change_log
129+
context['user_change_log'] = user_change_log
130+
context['workshop_change_log'] = workshop_change_log
131+
context['current_workshop'] = current_workshop
115132

116133
# Fetch all DeviceLogs entries related to this Device, ordered by timestamp descendingly
117134
device_logs_qs = DeviceLogs.objects.filter(device=device).order_by('-timestamp')
@@ -180,7 +197,7 @@ class DeviceEditView(UpdateView):
180197
model = Device
181198
form_class = DeviceForm
182199
template_name = 'devices/form.html'
183-
success_url = reverse_lazy('device-list') # URL to redirect to after a successful update
200+
success_url = reverse_lazy('devices-list') # URL to redirect to after a successful update
184201

185202
def get_queryset(self):
186203
"""
@@ -221,7 +238,7 @@ def get_queryset(self):
221238
class DeviceDeleteView(LoginRequiredMixin, DeleteView):
222239
model = Device
223240
template_name = 'devices/confirm_delete.html' # Confirmation page template
224-
success_url = reverse_lazy('device-list') # Redirect here after deletion
241+
success_url = reverse_lazy('devices-list') # Redirect here after deletion
225242

226243
def get_object(self, queryset = None):
227244
device = super().get_object(queryset)

app/templates/devices/detail.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,17 @@ <h2>{% trans "Device:" %} {{ device.device_name }}</h2>
106106
{% endfor %}
107107
</ul>
108108
</li>
109-
109+
<li class="list-group-item">
110+
<strong>{% trans "Workshop" %}:</strong> {{ current_workshop|default:_("N/A") }}
111+
<!-- change log -->
112+
<ul class="list-group">
113+
{% for entry in workshop_change_log %}
114+
<li class="list-group-item">{{ entry.timestamp|naturaltime }}, {% trans "Workshop changed from" %} {{ entry.prev }} {% trans "to" %} {{ entry.next }}</li>
115+
{% empty %}
116+
<li class="list-group-item">{% trans "No logs available." %}</li>
117+
{% endfor %}
118+
</ul>
119+
</li>
110120
</ul>
111121

112122
<!-- Notes Section -->

0 commit comments

Comments
 (0)