Files
web-app-launcher/plans/phase-2-enhanced-features/CONTEXT.md
T
alexei.dolgolyov 5bb4fbcedf feat(phase2): per-board access control UI
- BoardAccessControl component with user/group autocomplete
- BoardShareDialog modal with copy link, guest toggle, quick add
- Board permissions REST API (GET/POST/DELETE)
- Access indicators on BoardCard (lock, globe, shared icons)
- Guest access toggle in board editor with status preview
- Enhanced PermissionEditor with search autocomplete
- i18n translations for all new strings (EN/RU)
2026-03-24 23:29:19 +03:00

6.9 KiB

Feature Context: Phase 2 — Enhanced Features

Current State

Phase 1 (OAuth/Authentik Integration) and Phase 2 (DnD) are complete. Installed openid-client v6.8.2. OAuth login flow uses PKCE and issues local JWT tokens. Login page conditionally shows OAuth button and/or local form based on authMode SystemSettings. Admin settings page has a working "Test Connection" button for OAuth configuration.

Temporary Workarounds

  • None yet

Cross-Phase Dependencies

  • Phase 1 (OAuth) is independent — touches auth system only
  • Phase 2 (DnD) is independent — touches board editor UI only
  • Phase 3 (Widgets) depends on existing widget system from MVP
  • Phase 4 (Access Control) depends on existing permission system from MVP
  • Phase 5 (Integration) depends on all prior phases

Implementation Notes

  • Big Bang strategy: intermediate phases may not build. Phase 6 is the convergence phase.
  • OAuth uses openid-client (already installed in MVP dependencies)
  • DnD uses svelte-dnd-action (installed in Phase 2)
  • New widget types extend the existing Widget model's type and config JSON fields

Phase 2 (DnD) — Completed

  • Installed svelte-dnd-action package
  • Created DraggableBoard.svelte, DraggableSection.svelte, DraggableWidget.svelte component hierarchy
  • Board edit page now uses DnD for section and widget reordering (including cross-section widget moves)
  • Added PUT /api/boards/[id]/reorder and PUT /api/boards/[id]/sections/[sid]/reorder endpoints
  • Extended boardService.ts with reorderSections(), reorderWidgets(), moveWidget() using Prisma transactions
  • Visual drag handles (grip dots) and dashed drop zone indicators added via Tailwind
  • Edit page actions (add/delete section/widget) use invalidateAll() for data refresh; DnD uses optimistic fetch

Phase 4 (Additional Widget Types) — Completed

  • Installed marked package for markdown rendering
  • WidgetType enum already had BOOKMARK, NOTE, EMBED, STATUS from MVP constants
  • Added per-type Zod config schemas in validators.ts: appWidgetConfigSchema, bookmarkWidgetConfigSchema, noteWidgetConfigSchema, embedWidgetConfigSchema, statusWidgetConfigSchema
  • Updated src/lib/types/widget.ts config interfaces to match spec (BookmarkWidgetConfig, NoteWidgetConfig, EmbedWidgetConfig, StatusWidgetConfig)
  • Created 4 new widget components:
    • BookmarkWidget.svelte — clickable card with icon, label, description, opens URL in new tab
    • NoteWidget.svelte — renders markdown via marked with basic HTML sanitization
    • EmbedWidget.svelte — iframe with configurable height, sandbox security, loading spinner
    • StatusWidget.svelte — aggregated status bar with online/offline/degraded/unknown counts, expandable per-app detail
  • Created WidgetRenderer.svelte — universal type-switch component dispatching to correct widget by type
  • Updated WidgetGrid.svelte to use WidgetRenderer; note/embed/status widgets span full grid width
  • Updated DraggableSection.svelte with widget type selector dropdown and type-specific config forms (app selector, bookmark URL/label/icon/desc, note textarea with format, embed URL/height, status multi-select apps)
  • onAddWidget callback changed from (sectionId, appId) to (sectionId, widgetDataJson) across DraggableBoard and edit page
  • Board view server ([boardId]/+page.server.ts) now loads all apps via appService.findAll() for StatusWidget
  • Plumbed allApps prop through Board -> Section -> WidgetGrid -> WidgetRenderer -> StatusWidget
  • Edit server action addWidget now handles configJson form field for non-app widget types

Phase 3 (Localization EN/RU) — Completed

  • Installed svelte-i18n package for i18n support
  • Created src/lib/i18n/en.json and src/lib/i18n/ru.json with ~180 translation keys covering all UI strings
  • Created src/lib/i18n/index.ts with locale detection (localStorage > browser navigator > fallback 'en') and storeLocale() helper
  • Created LanguageSwitcher.svelte — EN/RU toggle button added to Header, persists preference to localStorage key wal-locale
  • Root +layout.svelte imports $lib/i18n/index.js to initialize i18n before any component renders
  • Extracted all hardcoded strings from: layout (Header, Sidebar, MainLayout, ThemeToggle), auth pages (login, register), board/section/widget components, app components (AppForm, AppHealthBadge, AppIconPicker), admin pages (users, groups, settings, PermissionEditor), search components (SearchDialog, SearchTrigger), home page, and DnD components
  • Translation key structure uses dot-notation grouped by feature: nav.*, auth.*, board.*, section.*, widget.*, app.*, admin.*, search.*, common.*, status.*, theme.*, bg.*, sidebar.*, home.*
  • All status labels (online/offline/degraded/unknown) are now translated via $t('status.*') in AppHealthBadge
  • Phase 4 widget type form labels (bookmark, note, embed, status fields) are partially untranslated — can be addressed in Phase 6

Phase 5 (Per-Board Access Control UI) — Completed

  • Created src/lib/components/board/BoardAccessControl.svelte — self-contained board permission manager with search/autocomplete for users and groups, fetches permissions from /api/boards/[id]/permissions
  • Created src/lib/components/board/BoardShareDialog.svelte — modal dialog with copy link, guest access toggle, quick permission grant, and current access list
  • Created src/routes/api/boards/[id]/permissions/+server.ts — REST endpoint for GET (list), POST (grant), DELETE (revoke) board permissions with proper auth checks
  • Enhanced src/lib/components/admin/PermissionEditor.svelte — replaced plain select dropdowns with search/autocomplete inputs (onfocus/onblur managed dropdowns)
  • Updated src/lib/components/board/BoardCard.svelte — added globe icon for guest-accessible boards, lock icon for private boards, users icon for boards with shared permissions
  • Updated src/routes/boards/+page.server.ts — computes hasSharedPermissions flag per board for access indicators
  • Updated src/routes/boards/[boardId]/edit/+page.svelte — added dedicated "Guest Access" section with status preview and "Permissions" section with BoardAccessControl component
  • Updated src/routes/boards/[boardId]/edit/+page.server.ts — loads users and groups for permission editor, computes canManagePermissions flag
  • Updated src/lib/components/board/BoardHeader.svelte — added "Share" button that triggers share dialog callback
  • Updated src/routes/boards/[boardId]/+page.svelte — integrated BoardShareDialog with guest toggle via PATCH API
  • Updated src/routes/boards/[boardId]/+page.server.ts — loads users/groups for share dialog when user can edit
  • Added ~20 new i18n keys (board.access_*, board.share_*, board.guest_access_*, board.permissions_*, admin.perm_search_placeholder) to both en.json and ru.json
  • Big Bang strategy: no build/test verification performed — Phase 6 integration may be needed