# T08a: Frontend DMS + Tags + Permissions UI — Implementation Briefing ## Task Implement frontend UI for DMS plugin (file browser, upload, preview, share, trash), Tags UI (assign, bulk, tag cloud), and Permissions UI (share links, permission display). ## Requirements - F-DMS-01–07: DMS file browser, folder tree, upload, preview, share, trash, search - F-FILEUI-01–06: File UI components (dropzone, preview modal, share dialog, bulk actions, trash view) - F-TAG-01–04: Tags UI (assign, bulk assign, tag cloud, tag picker) - F-PERM-03–05: Permissions UI (share links, permission display) - F-LINK-01–05: Entity links UI ## Acceptance Criteria (12 ACs) 1. DMS route /dms renders file browser with folder tree + file grid 2. DMS upload: drag file to dropzone → upload progress → file appears in list 3. DMS file preview modal opens with PDF.js for PDF files 4. DMS share dialog: select user/group, set permission, share created 5. DMS public share link: copy button generates URL, optional password+expiry fields 6. DMS bulk select → bulk-move or bulk-delete actions appear 7. DMS trash view: deleted files list, restore button per file 8. Mail: shared mailbox selector (DO NOT IMPLEMENT — belongs to T08c) 9. Tags: tag picker on company/contact detail → assign/unassign 10. Tags: bulk select entities → bulk-tag dialog 11. Plugin deactivate → plugin route+menu-item disappear from SPA 12. Plugin activate → plugin route+menu-item appear in SPA ## Backend API Endpoints (already implemented) ### DMS (/api/v1/dms) - GET /folders — list folder tree - POST /folders — create folder - PATCH /folders/{id} — rename/move folder - DELETE /folders/{id} — delete folder - POST /files/upload — upload file (multipart) - GET /files/{id} — get file detail - PATCH /files/{id} — update file (rename/move) - DELETE /files/{id} — soft-delete file - POST /files/{id}/restore — restore from trash - GET /files/{id}/preview — stream file for preview - POST /files/{id}/edit-session — create OnlyOffice edit session - POST /files/{id}/share — share file with user/group - DELETE /files/{id}/share — remove share - GET /search?q=text — search files - GET /shared-with-me — files shared with current user - POST /files/bulk-move — bulk move files - POST /files/bulk-delete — bulk delete files ### Tags (/api/v1/tags) - GET / — list tags - POST / — create tag - PATCH /{id} — update tag - DELETE /{id} — delete tag - POST /assign — assign tag to entity - DELETE /assign — unassign tag - POST /bulk-assign — bulk assign tags - GET /{id}/entities — list entities for tag ### Permissions (/api/v1/permissions) - GET /files/{id}/permissions — list permissions - POST /files/{id}/permissions — grant permission - DELETE /files/{id}/permissions/{user_id} — revoke permission - POST /files/{id}/share-link — create public share link - DELETE /share-links/{id} — revoke share link ## Frontend Architecture (follow existing patterns) - **Framework:** React + TypeScript + Vite - **Routing:** react-router-dom (createBrowserRouter, see src/routes/index.tsx) - **State:** TanStack Query (useQuery/useMutation) - **HTTP:** axios via src/api/client.ts (apiClient, baseURL /api/v1) - **API pattern:** See src/api/calendar.ts for plugin API client example - **UI components:** src/components/ui/ (Button, Card, Input, Modal, Table, Badge, ConfirmDialog, EmptyState, Pagination, Select, Skeleton, Toast) - **Shared components:** src/components/shared/ (DataGrid, SearchDropdown, Tabs, ActivityFeed) - **Store:** src/store/ (authStore, uiStore) - **Layout:** src/components/layout/AppShell (sidebar + main area) - **i18n:** src/i18n/ (add de.json + en.json keys for DMS/Tags) ## Files to Create - `src/api/dms.ts` — DMS API client (types + functions) - `src/api/tags.ts` — Tags API client - `src/api/permissions.ts` — Permissions API client - `src/pages/Dms.tsx` — DMS file browser page (folder tree + file grid) - `src/pages/DmsTrash.tsx` — DMS trash view - `src/components/dms/FolderTree.tsx` — folder tree sidebar - `src/components/dms/FileGrid.tsx` — file grid with icons - `src/components/dms/UploadDropzone.tsx` — drag-drop upload - `src/components/dms/FilePreviewModal.tsx` — file preview modal - `src/components/dms/ShareDialog.tsx` — share dialog - `src/components/dms/BulkActions.tsx` — bulk select actions - `src/components/tags/TagPicker.tsx` — tag assign/unassign picker - `src/components/tags/TagCloud.tsx` — tag cloud display - `src/components/tags/BulkTagDialog.tsx` — bulk tag assignment dialog - `src/__tests__/dms/DmsPage.test.tsx` — DMS page tests - `src/__tests__/dms/UploadDropzone.test.tsx` — upload tests - `src/__tests__/tags/TagPicker.test.tsx` — tag picker tests - `src/__tests__/tags/BulkTagDialog.test.tsx` — bulk tag tests - `src/__tests__/permissions/ShareDialog.test.tsx` — share dialog tests ## Files to Modify - `src/routes/index.tsx` — Add /dms, /dms/trash routes - `src/components/layout/AppShell.tsx` — Add DMS + Tags menu items to sidebar - `src/pages/CompanyDetail.tsx` — Add TagPicker component - `src/pages/ContactDetail.tsx` — Add TagPicker component - `src/i18n/locales/de.json` — Add DMS/Tags translations - `src/i18n/locales/en.json` — Add DMS/Tags translations ## Test Spec - Run: `cd /a0/usr/workdir/dev-projects/leocrm/frontend && npx vitest run src/__tests__/dms/ src/__tests__/tags/ src/__tests__/permissions/ --reporter=verbose` - Coverage: `npx vitest run src/__tests__/dms/ src/__tests__/tags/ --coverage` - Build: `npx vite build` - Type check: `npx tsc --noEmit` - Coverage target: 80% - Follow existing test pattern from src/__tests__/companies/ or src/__tests__/calendar/ ## Forbidden Patterns - No inline styles — use Tailwind classes - No any types — use proper TypeScript interfaces - No direct fetch() — use apiClient from src/api/client.ts - No hardcoded strings — use i18n (t() function) - No Lorem Ipsum — use realistic test data - No missing loading/error/empty states ## Estimated Size - ~600 lines code (pages + components + API clients) - ~300+ lines tests