0962f3a961
- DMS file browser: folder tree + file grid + upload dropzone + search + preview modal - DMS share dialog: user/group share + public share links with password+expiry - DMS bulk actions: bulk move + bulk delete with confirm dialogs - DMS trash view: deleted files list with restore button - Tags: TagPicker on company/contact detail pages (new tabs tab) - Tags: TagCloud + BulkTagDialog for bulk tag assignment - Permissions: share link creation, permission display, copy-link button - API clients: dms.ts, tags.ts, permissions.ts - Routes: /dms, /dms/trash added to router - Sidebar: DMS nav link updated - i18n: de.json + en.json translations for DMS/Tags/Permissions - 33 new tests (5 test files), full regression 276/276 pass - tsc --noEmit: 0 errors, vite build: 252 modules
6.0 KiB
6.0 KiB
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)
- DMS route /dms renders file browser with folder tree + file grid
- DMS upload: drag file to dropzone → upload progress → file appears in list
- DMS file preview modal opens with PDF.js for PDF files
- DMS share dialog: select user/group, set permission, share created
- DMS public share link: copy button generates URL, optional password+expiry fields
- DMS bulk select → bulk-move or bulk-delete actions appear
- DMS trash view: deleted files list, restore button per file
- Mail: shared mailbox selector (DO NOT IMPLEMENT — belongs to T08c)
- Tags: tag picker on company/contact detail → assign/unassign
- Tags: bulk select entities → bulk-tag dialog
- Plugin deactivate → plugin route+menu-item disappear from SPA
- 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 clientsrc/api/permissions.ts— Permissions API clientsrc/pages/Dms.tsx— DMS file browser page (folder tree + file grid)src/pages/DmsTrash.tsx— DMS trash viewsrc/components/dms/FolderTree.tsx— folder tree sidebarsrc/components/dms/FileGrid.tsx— file grid with iconssrc/components/dms/UploadDropzone.tsx— drag-drop uploadsrc/components/dms/FilePreviewModal.tsx— file preview modalsrc/components/dms/ShareDialog.tsx— share dialogsrc/components/dms/BulkActions.tsx— bulk select actionssrc/components/tags/TagPicker.tsx— tag assign/unassign pickersrc/components/tags/TagCloud.tsx— tag cloud displaysrc/components/tags/BulkTagDialog.tsx— bulk tag assignment dialogsrc/__tests__/dms/DmsPage.test.tsx— DMS page testssrc/__tests__/dms/UploadDropzone.test.tsx— upload testssrc/__tests__/tags/TagPicker.test.tsx— tag picker testssrc/__tests__/tags/BulkTagDialog.test.tsx— bulk tag testssrc/__tests__/permissions/ShareDialog.test.tsx— share dialog tests
Files to Modify
src/routes/index.tsx— Add /dms, /dms/trash routessrc/components/layout/AppShell.tsx— Add DMS + Tags menu items to sidebarsrc/pages/CompanyDetail.tsx— Add TagPicker componentsrc/pages/ContactDetail.tsx— Add TagPicker componentsrc/i18n/locales/de.json— Add DMS/Tags translationssrc/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