477c0e4d52
- Add svelte-i18n with 224 translation keys (English + Russian) - Language switcher in header (EN/RU toggle, persists to localStorage) - Extract all hardcoded strings from 37 component/page files - Add 4 new widget types: Bookmark, Note (markdown), Embed (iframe), Status - WidgetRenderer dispatches by type, WidgetGrid supports full-width widgets - Type-specific config forms in board editor - Install marked for markdown rendering
4.9 KiB
4.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
typeandconfigJSON fields
Phase 2 (DnD) — Completed
- Installed
svelte-dnd-actionpackage - Created
DraggableBoard.svelte,DraggableSection.svelte,DraggableWidget.sveltecomponent hierarchy - Board edit page now uses DnD for section and widget reordering (including cross-section widget moves)
- Added
PUT /api/boards/[id]/reorderandPUT /api/boards/[id]/sections/[sid]/reorderendpoints - Extended
boardService.tswithreorderSections(),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
markedpackage 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.tsconfig 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 tabNoteWidget.svelte— renders markdown viamarkedwith basic HTML sanitizationEmbedWidget.svelte— iframe with configurable height, sandbox security, loading spinnerStatusWidget.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.svelteto use WidgetRenderer; note/embed/status widgets span full grid width - Updated
DraggableSection.sveltewith 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) onAddWidgetcallback changed from(sectionId, appId)to(sectionId, widgetDataJson)across DraggableBoard and edit page- Board view server (
[boardId]/+page.server.ts) now loads all apps viaappService.findAll()for StatusWidget - Plumbed
allAppsprop through Board -> Section -> WidgetGrid -> WidgetRenderer -> StatusWidget - Edit server action
addWidgetnow handlesconfigJsonform field for non-app widget types
Phase 3 (Localization EN/RU) — Completed
- Installed
svelte-i18npackage for i18n support - Created
src/lib/i18n/en.jsonandsrc/lib/i18n/ru.jsonwith ~180 translation keys covering all UI strings - Created
src/lib/i18n/index.tswith locale detection (localStorage > browser navigator > fallback 'en') andstoreLocale()helper - Created
LanguageSwitcher.svelte— EN/RU toggle button added to Header, persists preference to localStorage keywal-locale - Root
+layout.svelteimports$lib/i18n/index.jsto 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