ux: improve community plugins states

This commit is contained in:
Marco Allegretti 2026-02-06 17:38:41 +01:00
parent e084c0d235
commit c8f7150fac

View file

@ -28,8 +28,68 @@ const { slug } = Astro.params;
<script define:vars={{ slug, apiBase }}>
const token = localStorage.getItem('token');
if (!token) {
window.location.href = '/login';
function renderLoginRequiredState() {
const container = document.getElementById('plugins-content');
if (!container) return;
container.innerHTML = `
<div class="state-card ui-card">
<p class="empty">Login required.</p>
<p class="hint">Sign in to manage community plugins.</p>
<div class="state-actions">
<a class="ui-btn ui-btn-primary" href="/login">Login</a>
<a class="ui-btn ui-btn-secondary" href="/communities/${encodeURIComponent(String(slug || ''))}">Back to community</a>
</div>
</div>
`;
}
function renderNotFoundState() {
const container = document.getElementById('plugins-content');
if (!container) return;
container.innerHTML = `
<div class="state-card ui-card">
<p class="error">Community not found.</p>
<p class="hint">It may have been deleted, or the link is incorrect.</p>
<div class="state-actions">
<a class="ui-btn ui-btn-primary" href="/communities">Back to communities</a>
</div>
</div>
`;
}
function renderForbiddenState(communityName) {
const container = document.getElementById('plugins-content');
if (!container) return;
container.innerHTML = `
<div class="state-card ui-card">
<p class="error">Not allowed.</p>
<p class="hint">You must be an admin or moderator to manage plugins for ${escapeHtml(communityName)}.</p>
<div class="state-actions">
<a class="ui-btn ui-btn-primary" href="/communities/${encodeURIComponent(String(slug || ''))}">Back to community</a>
</div>
</div>
`;
}
function renderPluginsErrorState(message) {
const container = document.getElementById('plugins-content');
if (!container) return;
container.innerHTML = `
<div class="state-card ui-card">
<p class="error">${escapeHtml(message || 'Failed to load plugins.')}</p>
<p class="hint">Check your connection and try again.</p>
<div class="state-actions">
<button type="button" class="ui-btn ui-btn-primary" id="retry-plugins">Retry</button>
<a class="ui-btn ui-btn-secondary" href="/communities/${encodeURIComponent(String(slug || ''))}">Back to community</a>
</div>
</div>
`;
document.getElementById('retry-plugins')?.addEventListener('click', load);
}
function escapeHtml(str) {
@ -154,12 +214,23 @@ const { slug } = Astro.params;
const allowed = membership?.role === 'admin' || membership?.role === 'moderator';
if (!allowed) {
renderForbiddenState(community?.name || 'this community');
return;
}
if (!plugins || plugins.length === 0) {
container.innerHTML = `
<div class="error">
<h2>Forbidden</h2>
<p>You must be an admin or moderator to manage plugins for ${escapeHtml(community.name)}.</p>
<div class="state-card ui-card">
<p class="empty">No plugins available.</p>
<p class="hint">If this seems wrong, try reloading the page.</p>
<div class="state-actions">
<button type="button" class="ui-btn ui-btn-primary" id="retry-plugins-empty">Retry</button>
<a class="ui-btn ui-btn-secondary" href="/communities/${encodeURIComponent(String(slug || ''))}">Back to community</a>
</div>
</div>
`;
document.getElementById('retry-plugins-empty')?.addEventListener('click', load);
return;
}
@ -353,9 +424,14 @@ const { slug } = Astro.params;
if (!container) return;
try {
if (!token) {
renderLoginRequiredState();
return;
}
const community = await fetchCommunityBySlug();
if (!community) {
container.innerHTML = '<div class="error">Community not found</div>';
renderNotFoundState();
return;
}
@ -364,7 +440,14 @@ const { slug } = Astro.params;
renderPlugins(community, membership, plugins);
} catch (err) {
container.innerHTML = `<div class="error">${escapeHtml(err?.message || 'Failed to load')}</div>`;
const msg = err?.message || 'Failed to load plugins.';
if (String(msg || '').toLowerCase().includes('unauthorized') || String(msg || '').includes('401')) {
renderLoginRequiredState();
return;
}
renderPluginsErrorState(msg);
}
}
@ -478,13 +561,21 @@ const { slug } = Astro.params;
color: var(--color-text-muted);
}
.error {
.plugins-error {
background: var(--color-error-muted);
border: 1px solid var(--color-error);
padding: 1rem;
border-radius: 12px;
}
.state-actions {
margin-top: 1.25rem;
display: flex;
gap: 0.75rem;
justify-content: center;
flex-wrap: wrap;
}
.settings-body-wrap {
padding-top: 0.5rem;
}