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 }}> <script define:vars={{ slug, apiBase }}>
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (!token) { function renderLoginRequiredState() {
window.location.href = '/login'; 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) { function escapeHtml(str) {
@ -154,12 +214,23 @@ const { slug } = Astro.params;
const allowed = membership?.role === 'admin' || membership?.role === 'moderator'; const allowed = membership?.role === 'admin' || membership?.role === 'moderator';
if (!allowed) { if (!allowed) {
renderForbiddenState(community?.name || 'this community');
return;
}
if (!plugins || plugins.length === 0) {
container.innerHTML = ` container.innerHTML = `
<div class="error"> <div class="state-card ui-card">
<h2>Forbidden</h2> <p class="empty">No plugins available.</p>
<p>You must be an admin or moderator to manage plugins for ${escapeHtml(community.name)}.</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> </div>
`; `;
document.getElementById('retry-plugins-empty')?.addEventListener('click', load);
return; return;
} }
@ -353,9 +424,14 @@ const { slug } = Astro.params;
if (!container) return; if (!container) return;
try { try {
if (!token) {
renderLoginRequiredState();
return;
}
const community = await fetchCommunityBySlug(); const community = await fetchCommunityBySlug();
if (!community) { if (!community) {
container.innerHTML = '<div class="error">Community not found</div>'; renderNotFoundState();
return; return;
} }
@ -364,7 +440,14 @@ const { slug } = Astro.params;
renderPlugins(community, membership, plugins); renderPlugins(community, membership, plugins);
} catch (err) { } 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); color: var(--color-text-muted);
} }
.error { .plugins-error {
background: var(--color-error-muted); background: var(--color-error-muted);
border: 1px solid var(--color-error); border: 1px solid var(--color-error);
padding: 1rem; padding: 1rem;
border-radius: 12px; border-radius: 12px;
} }
.state-actions {
margin-top: 1.25rem;
display: flex;
gap: 0.75rem;
justify-content: center;
flex-wrap: wrap;
}
.settings-body-wrap { .settings-body-wrap {
padding-top: 0.5rem; padding-top: 0.5rem;
} }