Files
LEDMatrix/web_interface/templates/v3/partials/durations.html
T
ChuckBuildsandClaude Sonnet 5 3ab6a731c3 fix(web): add the missing nav tab for the Rotation & Durations page
The durations partial (/partials/durations) has existed as a route with no
nav tab and no content panel referencing it - an orphaned page. That made
the new rotation-order UI unreachable through the interface (caught by the
owner testing on the rig; my endpoint-level tests fetched the partial by
URL and never noticed the missing entry point).

- New "Rotation" tab (fa-rotate icon, verified present in the vendored
  FA 6.0.0 css) between Display and Backup & Restore, wired exactly like
  the other tabs (#durations-content + hx-get + loadtab; loadTabContent()
  is fully generic, so no JS changes needed).
- Page heading updated from "Display Durations" to "Rotation & Durations"
  to match its content since the rotation-order card landed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ
2026-07-16 12:01:03 -04:00

83 lines
3.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% import 'v3/partials/_macros.html' as ui %}
<div class="bg-white rounded-lg shadow p-6">
<div class="border-b border-gray-200 pb-4 mb-6">
<h2 class="text-lg font-semibold text-gray-900">Rotation &amp; Durations</h2>
<p class="mt-1 text-sm text-gray-600">Set the order plugins rotate on the display and how long each screen is shown. Durations are in seconds.</p>
</div>
{{ ui.settings_filter() }}
<form hx-post="/api/v3/config/main"
hx-ext="json-enc"
hx-headers='{"Content-Type": "application/json"}'
hx-swap="none"
hx-on:htmx:after-request="showNotification(event.detail.xhr.responseJSON?.message || 'Durations saved', event.detail.xhr.responseJSON?.status || 'success')"
class="space-y-6"
novalidate
onsubmit="fixInvalidNumberInputs(this); return true;">
<!-- Primary rotation order: drag to reorder which plugin shows first,
second, ... in the normal display rotation. Saved as
display.plugin_rotation_order and applied by the display
controller on startup and live plugin enable/disable. -->
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="text-md font-medium text-gray-900 mb-1">Rotation Order</h3>
<p class="text-sm text-gray-600 mb-3">Drag plugins to set the order they rotate on the display. Each plugin's screens keep their own order within its turn. Takes effect after saving and restarting the display.</p>
<div id="rotation_plugin_order" class="space-y-2 bg-white rounded-lg p-3 border border-gray-200">
<p class="text-sm text-gray-500 italic">Loading plugins…</p>
</div>
<input type="hidden" id="rotation_plugin_order_value" name="plugin_rotation_order"
value='{{ main_config.display.get("plugin_rotation_order", [])|tojson }}'>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{% for key, value in main_config.display.display_durations.items() %}
<div class="form-group" id="setting-durations-{{ key }}" data-setting-key="display.display_durations.{{ key }}">
<label for="duration_{{ key }}" class="block text-sm font-medium text-gray-700">
{{ key | replace('_', ' ') | title }}{{ ui.help_tip('How long the ' ~ (key | replace('_', ' ')) ~ ' screen stays on before rotating to the next one, in seconds.\nRange: 5600. Currently ' ~ value ~ 's.', key | replace('_', ' ') | title) }}
</label>
<input type="number"
id="duration_{{ key }}"
name="{{ key }}"
value="{{ value }}"
min="5"
max="600"
class="form-control">
</div>
{% endfor %}
</div>
<!-- Submit Button -->
<div class="flex justify-end">
<button type="submit"
class="btn bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md">
<i class="fas fa-save mr-2"></i>
Save Durations
</button>
</div>
</form>
</div>
<script>
(function () {
// Shared drag-and-drop plugin list (static/v3/js/widgets/plugin-order-list.js,
// same module the Vegas Scroll section uses).
function initRotationOrderList() {
if (!document.getElementById('rotation_plugin_order')) return;
if (!window.PluginOrderList) {
setTimeout(initRotationOrderList, 100);
return;
}
window.PluginOrderList.init({
containerId: 'rotation_plugin_order',
orderInputId: 'rotation_plugin_order_value'
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initRotationOrderList);
} else {
initRotationOrderList();
}
}());
</script>