feat: plugin fault isolation notices + NUT managed mode fixes

Plugin failures:
- Track load-time failures in _FAILED_PLUGINS dict with human-readable reasons
- Inject plugin_failures into all templates via context processor
- Show admin-only warning banner in base.html when any plugin fails to load
- Show inline failure notice per plugin card in Settings → Plugins

NUT managed mode:
- entrypoint.sh: make nut_setup.py failure non-fatal so the container starts
  even if nut_ups_host isn't set yet (allows fixing config via UI)
- save_plugins: when nut_managed is enabled, auto-set nut_host=localhost so
  the plugin connects to the managed NUT instance without extra manual config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-23 18:04:53 -04:00
parent 56283df5a1
commit 8558d15eeb
6 changed files with 91 additions and 15 deletions
@@ -62,6 +62,20 @@
</label>
</div>
{# Failure notice — shown when this plugin failed to load #}
{% set fail_reason = plugin_failures.get(plugin._dir) %}
{% if fail_reason %}
<div style="display:flex;align-items:flex-start;gap:0.5rem;padding:0.5rem 0.75rem;
margin-top:0.6rem;background:color-mix(in srgb,var(--red) 10%,var(--bg));
border:1px solid color-mix(in srgb,var(--red) 30%,var(--border));
border-radius:5px;font-size:0.82rem;">
<span style="color:var(--red);flex-shrink:0;"></span>
<span><strong style="color:var(--red);">Failed to load</strong>
<span style="color:var(--text-muted);margin-left:0.3rem;">— {{ fail_reason }}</span>
</span>
</div>
{% endif %}
{# Config fields — only shown when there are config keys #}
{% if plugin.get('config') %}
<div style="border-top:1px solid var(--border);padding-top:1rem;display:grid;gap:0.6rem;">