Scope device uniqueness per parent, null type/location for sub-components, hide sub-components from list, flat battery summary for parent devices

This commit is contained in:
2026-06-09 19:26:31 -05:00
parent 2a54cd8297
commit 23eeeafff7
7 changed files with 340 additions and 42 deletions
+2
View File
@@ -56,6 +56,7 @@
</div>
</div><!-- #battery-fields -->
{% if not prefill_parent %}
<div class="form-group">
<label>Type</label>
{% set _preset_types = ['Remote Control','Game Controller','Flashlight','Lock','Sensor','Toy','Clock','Smoke Detector'] %}
@@ -94,6 +95,7 @@
placeholder="e.g. Living Room, Bedroom"
style="display:none;margin-top:0.4rem;">
</div>
{% endif %}
<div class="form-group">
<label for="notes">Notes</label>
+37 -14
View File
@@ -63,6 +63,20 @@
<td style="border:none;">{{ device.location }}</td>
</tr>
{% endif %}
{% if device.is_subcomponent() and device.parent %}
{% if device.parent.device_type %}
<tr>
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Type</td>
<td style="border:none;">{{ device.parent.device_type }} <span class="text-muted" style="font-size:0.85em;">(inherited)</span></td>
</tr>
{% endif %}
{% if device.parent.location %}
<tr>
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Location</td>
<td style="border:none;">{{ device.parent.location }} <span class="text-muted" style="font-size:0.85em;">(inherited)</span></td>
</tr>
{% endif %}
{% endif %}
{% if device.notes %}
<tr>
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Notes</td>
@@ -116,24 +130,30 @@
{% endif %}
{% if device.has_children() %}
<div class="card">
<h2>Batteries in Sub-components</h2>
{% for child in device.children %}
{% set child_installed = child.batteries | selectattr('status', 'eq', 'installed') | list %}
<h3 style="margin:0.75rem 0 0.4rem;font-size:1rem;">
<a href="{{ url_for('device_detail', device_id=child.id) }}">{{ child.name }}</a>
<small class="text-muted" style="font-weight:normal;">&nbsp;{{ child_installed|length }}/{{ child.battery_slots }}</small>
</h3>
{% if child_installed %}
<div class="card" id="installed">
<h2>Installed Batteries</h2>
{% if flat_installed %}
<div class="table-wrap">
<table class="responsive-table">
<thead><tr><th>Label</th><th>Brand</th>{% if ha_enabled %}<th>Bat %</th>{% endif %}<th>Last Charged</th></tr></thead>
<thead><tr>
<th>Component</th><th>Label</th><th>Brand</th>
{% if ha_enabled %}<th>Bat %</th>{% endif %}
<th>Last Charged</th>
</tr></thead>
<tbody>
{% for b in child_installed %}
{% for b, comp_name, comp_id in flat_installed %}
<tr>
<td data-label="Component"><a href="{{ url_for('device_detail', device_id=comp_id) }}">{{ comp_name }}</a></td>
<td data-label="Label"><a href="{{ url_for('battery_detail', battery_id=b.id) }}">{{ b.label }}</a></td>
<td data-label="Brand">{{ b.brand }}</td>
{% if ha_enabled %}<td data-label="Bat %">{% if b.battery_percentage is not none %}{{ b.battery_percentage }}%{% else %}—{% endif %}</td>{% endif %}
{% if ha_enabled %}
<td data-label="Bat %">
{% if b.battery_percentage is not none %}
{% if b.battery_percentage < 20 %}<span class="badge badge-warning">⚠ {{ b.battery_percentage }}%</span>
{% else %}{{ b.battery_percentage }}%{% endif %}
{% else %}—{% endif %}
</td>
{% endif %}
<td data-label="Last Charged" class="text-muted">{{ b.charge_logs[-1].charged_date if b.charge_logs else '—' }}</td>
</tr>
{% endfor %}
@@ -141,9 +161,8 @@
</table>
</div>
{% else %}
<p class="text-muted" style="margin:0 0 0.5rem;">No batteries installed.</p>
<p class="text-muted">No batteries installed across sub-components.</p>
{% endif %}
{% endfor %}
</div>
{% endif %}
@@ -407,6 +426,7 @@ function addInstallRow() {
<input type="number" id="edit-slots" name="battery_slots" value="{{ device.battery_slots }}" min="1" required>
</div>
{% endif %}
{% if not device.is_subcomponent() %}
<div class="form-group">
<label>Type</label>
{% set _preset_types = ['Remote Control','Game Controller','Flashlight','Lock','Sensor','Toy','Clock','Smoke Detector'] %}
@@ -427,6 +447,7 @@ function addInstallRow() {
placeholder="Enter device type"
style="display:{% if device.device_type and device.device_type not in _preset_types %}''{% else %}none{% endif %};margin-top:0.4rem;">
</div>
{% endif %}
{% if not device.has_children() %}
<div class="form-group">
<label>Battery Size</label>
@@ -452,6 +473,7 @@ function addInstallRow() {
style="display:{% if device.battery_size and device.battery_size not in _preset_sizes %}''{% else %}none{% endif %};margin-top:0.4rem;">
</div>
{% endif %}
{% if not device.is_subcomponent() %}
<div class="form-group">
<label>Location</label>
<select id="edit-location-select" onchange="editLocationSelectChanged(this)">
@@ -469,6 +491,7 @@ function addInstallRow() {
placeholder="e.g. Living Room, Bedroom"
style="display:{% if device.location and device.location not in device_locations|default([]) %}''{% else %}none{% endif %};margin-top:0.4rem;">
</div>
{% endif %}
<div class="form-group">
<label for="edit-notes">Notes</label>
+8 -9
View File
@@ -57,9 +57,10 @@
</thead>
<tbody>
{% for d in devices %}
{% set installed = d.installed_count() %}
{% if installed == 0 %}{% set fill_state = 'empty' %}
{% elif installed >= d.battery_slots %}{% set fill_state = 'full' %}
{% set installed = d.effective_installed_count() %}
{% set total_slots = d.effective_slots() %}
{% if installed == 0 or total_slots == 0 %}{% set fill_state = 'empty' %}
{% elif installed >= total_slots %}{% set fill_state = 'full' %}
{% else %}{% set fill_state = 'partial' %}{% endif %}
<tr data-type="{{ d.device_type or '' }}"
data-battery-size="{{ d.battery_size or '' }}"
@@ -68,19 +69,17 @@
data-name="{{ d.name|lower }}">
<td data-label="Device">
<a href="{{ url_for('device_detail', device_id=d.id) }}"><strong>{{ d.name }}</strong></a>
{% if d.parent %}
<br><small class="text-muted"><a href="{{ url_for('device_detail', device_id=d.parent.id) }}">{{ d.parent.name }}</a></small>
{% elif d.has_children() %}
{% if d.has_children() %}
<br><small class="text-muted">{{ d.children|length }} sub-component{{ 's' if d.children|length != 1 }}</small>
{% endif %}
</td>
<td data-label="Type">{{ d.device_type or '—' }}</td>
<td data-label="Size">{{ d.battery_size or '—' }}</td>
<td data-label="Location">{{ d.location or '—' }}</td>
<td data-label="Slots">{{ d.battery_slots }}</td>
<td data-label="Slots">{{ total_slots }}</td>
<td data-label="Installed">
{{ installed }} / {{ d.battery_slots }}
{% if installed >= d.battery_slots %}
{{ installed }} / {{ total_slots }}
{% if total_slots > 0 and installed >= total_slots %}
<span class="badge badge-retired">Full</span>
{% endif %}
</td>