feat: show update available when catalog version differs from installed
Catalog partial now compares catalog version vs installed plugin.yaml version. Gold border + "Update available — installed vX.Y.Z" badge when newer. Update button uses btn-warn styling. Route passes installed_versions dict. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -256,11 +256,13 @@ async def plugins_catalog():
|
|||||||
|
|
||||||
discovered = _discover_plugins()
|
discovered = _discover_plugins()
|
||||||
installed_names = {p["_dir"] for p in discovered}
|
installed_names = {p["_dir"] for p in discovered}
|
||||||
|
installed_versions = {p["_dir"]: p.get("version", "0.0.0") for p in discovered}
|
||||||
|
|
||||||
return await render_template(
|
return await render_template(
|
||||||
"settings/_catalog_partial.html",
|
"settings/_catalog_partial.html",
|
||||||
catalog=catalog,
|
catalog=catalog,
|
||||||
installed_names=installed_names,
|
installed_names=installed_names,
|
||||||
|
installed_versions=installed_versions,
|
||||||
loaded_names=_LOADED_PLUGINS,
|
loaded_names=_LOADED_PLUGINS,
|
||||||
error=error,
|
error=error,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,17 +12,27 @@
|
|||||||
{% for plugin in catalog %}
|
{% for plugin in catalog %}
|
||||||
{% set is_installed = plugin.name in installed_names %}
|
{% set is_installed = plugin.name in installed_names %}
|
||||||
{% set is_loaded = plugin.name in loaded_names %}
|
{% set is_loaded = plugin.name in loaded_names %}
|
||||||
<div class="card" style="margin-bottom:0;padding:1rem 1.25rem;">
|
{% set installed_ver = installed_versions.get(plugin.name, "") %}
|
||||||
|
{# update_available: catalog version is strictly newer than what's on disk #}
|
||||||
|
{% set update_available = is_installed and installed_ver and installed_ver != plugin.version %}
|
||||||
|
|
||||||
|
<div class="card" style="margin-bottom:0;padding:1rem 1.25rem;{% if update_available %}border-color:var(--gold);{% endif %}">
|
||||||
<div style="display:flex;align-items:flex-start;gap:1rem;">
|
<div style="display:flex;align-items:flex-start;gap:1rem;">
|
||||||
<div style="flex:1;min-width:0;">
|
<div style="flex:1;min-width:0;">
|
||||||
<div style="display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;">
|
<div style="display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;">
|
||||||
<span style="font-weight:600;color:var(--text);font-size:0.9rem;">{{ plugin.name }}</span>
|
<span style="font-weight:600;color:var(--text);font-size:0.9rem;">{{ plugin.name }}</span>
|
||||||
<span style="font-size:0.75rem;color:var(--text-muted);">v{{ plugin.version }}</span>
|
<span style="font-size:0.75rem;color:var(--text-muted);">v{{ plugin.version }}</span>
|
||||||
{% if is_loaded %}
|
|
||||||
|
{% if update_available %}
|
||||||
|
<span class="badge badge-gold" style="font-size:0.68rem;">
|
||||||
|
Update available — installed v{{ installed_ver }}
|
||||||
|
</span>
|
||||||
|
{% elif is_loaded %}
|
||||||
<span class="badge badge-green" style="font-size:0.68rem;">Active</span>
|
<span class="badge badge-green" style="font-size:0.68rem;">Active</span>
|
||||||
{% elif is_installed %}
|
{% elif is_installed %}
|
||||||
<span class="badge" style="background:var(--bg-elevated);color:var(--text-muted);font-size:0.68rem;">Installed</span>
|
<span class="badge" style="background:var(--bg-elevated);color:var(--text-muted);font-size:0.68rem;">Installed</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for tag in plugin.tags %}
|
{% for tag in plugin.tags %}
|
||||||
<span style="font-size:0.68rem;padding:0.1em 0.4em;background:var(--bg-elevated);color:var(--text-muted);border-radius:3px;">{{ tag }}</span>
|
<span style="font-size:0.68rem;padding:0.1em 0.4em;background:var(--bg-elevated);color:var(--text-muted);border-radius:3px;">{{ tag }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -46,8 +56,8 @@
|
|||||||
class="btn btn-ghost btn-sm" style="font-size:0.78rem;">Source</a>
|
class="btn btn-ghost btn-sm" style="font-size:0.78rem;">Source</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if is_loaded %}
|
{% if update_available %}
|
||||||
{# Already active — update available if versions differ #}
|
{# Installed but outdated — offer update (download + restart) #}
|
||||||
<form method="post"
|
<form method="post"
|
||||||
action="/settings/plugins/install/{{ plugin.name }}"
|
action="/settings/plugins/install/{{ plugin.name }}"
|
||||||
hx-post="/settings/plugins/install/{{ plugin.name }}"
|
hx-post="/settings/plugins/install/{{ plugin.name }}"
|
||||||
@@ -56,9 +66,12 @@
|
|||||||
style="margin:0;">
|
style="margin:0;">
|
||||||
<input type="hidden" name="download_url" value="{{ plugin.download_url }}">
|
<input type="hidden" name="download_url" value="{{ plugin.download_url }}">
|
||||||
<input type="hidden" name="checksum_sha256" value="{{ plugin.checksum_sha256 }}">
|
<input type="hidden" name="checksum_sha256" value="{{ plugin.checksum_sha256 }}">
|
||||||
<button type="submit" class="btn btn-ghost btn-sm" style="font-size:0.78rem;">Update</button>
|
<button type="submit" class="btn btn-warn btn-sm" style="font-size:0.78rem;">Update</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
{% elif is_loaded %}
|
||||||
|
{# Active and up to date — no action needed #}
|
||||||
|
|
||||||
{% elif is_installed %}
|
{% elif is_installed %}
|
||||||
{# Installed but not active — offer hot-reload #}
|
{# Installed but not active — offer hot-reload #}
|
||||||
<form method="post"
|
<form method="post"
|
||||||
|
|||||||
Reference in New Issue
Block a user