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:
@@ -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>
|
||||
|
||||
@@ -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;"> {{ 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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user