feat(settings): gate collection management UI to owners (TASK-1103) (#417)

Settings → Collections currently shows "+ Create Collection" and clickable
edit cards to all roles. The server already enforces owner-only on create,
update, and delete (handlers_collections.go:48, :113, :164). UI now matches.

Changes:
- Collection cards remain clickable for owners (open EditCollectionModal);
  for non-owners they render as non-interactive divs with the same content
  visible. The "Edit" hint is hidden for non-owners.
- "+ Create Collection" button hidden entirely for non-owners.
- CreateCollectionModal / EditCollectionModal mount only for owners — a
  non-owner can't reach them via the UI.

Note: TASK-1103 spec floated "create gated to editor+", but the server is
owner-only. Aligned UI to server (server is the security boundary).

Parent: PLAN-1100.
This commit is contained in:
xarmian
2026-05-05 09:04:28 -04:00
committed by GitHub
parent 3524a5ed92
commit 0035a9dad9
@@ -683,7 +683,7 @@
<div class="coll-list">
{#each collections as coll (coll.id)}
{@const schema = parseSchema(coll)}
<button class="card coll-card coll-card-btn" onclick={() => (editingCollection = coll)}>
{#snippet collCardBody()}
<div class="coll-header">
<span class="coll-icon">{coll.icon || '#'}</span>
<span class="coll-name">{coll.name}</span>
@@ -692,7 +692,9 @@
{#if coll.is_default}
<span class="badge">default</span>
{/if}
<span class="edit-hint">Edit</span>
{#if isOwner}
<span class="edit-hint">Edit</span>
{/if}
</div>
{#if schema.fields.length > 0}
<div class="field-tags">
@@ -701,20 +703,37 @@
{/each}
</div>
{/if}
</button>
{/snippet}
<!-- Owner-only: card opens the edit modal. Non-owners see
the same card content but as a non-interactive div
(server requires owner role for collection update/delete
— handlers_collections.go:113, :164). -->
{#if isOwner}
<button class="card coll-card coll-card-btn" onclick={() => (editingCollection = coll)}>
{@render collCardBody()}
</button>
{:else}
<div class="card coll-card">
{@render collCardBody()}
</div>
{/if}
{/each}
</div>
{/if}
<button class="btn btn-create" onclick={() => (showCreateModal = true)}>
+ Create Collection
</button>
<CreateCollectionModal
open={showCreateModal}
{wsSlug}
oncreated={handleCollectionCreated}
onclose={() => (showCreateModal = false)}
/>
{#if editingCollection}
<!-- Server requires owner role for collection create
(handlers_collections.go:48). UI matches. -->
{#if isOwner}
<button class="btn btn-create" onclick={() => (showCreateModal = true)}>
+ Create Collection
</button>
<CreateCollectionModal
open={showCreateModal}
{wsSlug}
oncreated={handleCollectionCreated}
onclose={() => (showCreateModal = false)}
/>
{/if}
{#if editingCollection && isOwner}
<EditCollectionModal
open={true}
collection={editingCollection}