feat: folder permissions (ACLs) - share folders with users/groups, inherit to subfolders, permission dialog UI
This commit is contained in:
@@ -10,7 +10,8 @@ import {
|
||||
useMoveContactToFolder,
|
||||
} from '@/api/hooks';
|
||||
import { buildFolderTree, type ContactFolderTreeNode, type ContactFolder } from '@/api/contactFolders';
|
||||
import { ChevronRight, Folder, MoreVertical, Palette, Pencil, Pin, Plus, Tag, Trash2, Users } from 'lucide-react';
|
||||
import { ChevronRight, Folder, MoreVertical, Palette, Pencil, Pin, Plus, Shield, Tag, Trash2, Users } from 'lucide-react';
|
||||
import { FolderPermissionDialog } from './FolderPermissionDialog';
|
||||
|
||||
export type ContactFilter = 'all' | 'company' | 'person' | `tag:${string}` | `folder:${string}`;
|
||||
|
||||
@@ -74,6 +75,7 @@ function FolderDropdown({
|
||||
onDelete,
|
||||
onColor,
|
||||
onPin,
|
||||
onPermissions,
|
||||
}: {
|
||||
state: DropdownState;
|
||||
onClose: () => void;
|
||||
@@ -81,6 +83,7 @@ function FolderDropdown({
|
||||
onDelete: (id: string) => void;
|
||||
onColor: (id: string) => void;
|
||||
onPin: (id: string) => void;
|
||||
onPermissions: (id: string) => void;
|
||||
}) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -96,6 +99,7 @@ function FolderDropdown({
|
||||
{ label: 'Umbenennen', icon: Pencil, action: () => { onRename(state.folderId); onClose(); } },
|
||||
{ label: 'Farbe', icon: Palette, action: () => { onColor(state.folderId); onClose(); } },
|
||||
{ label: 'Anpinnen', icon: Pin, action: () => { onPin(state.folderId); onClose(); } },
|
||||
{ label: 'Rechte', icon: Shield, action: () => { onPermissions(state.folderId); onClose(); } },
|
||||
{ label: 'L\u00f6schen', icon: Trash2, action: () => { onDelete(state.folderId); onClose(); }, danger: true },
|
||||
];
|
||||
|
||||
@@ -268,6 +272,7 @@ export function ContactFolderTree({
|
||||
const [colorPicker, setColorPicker] = useState<{ folderId: string; color: string } | null>(null);
|
||||
const [dragOverFolderId, setDragOverFolderId] = useState<string | null>(null);
|
||||
const [multiSelectMode, setMultiSelectMode] = useState(false);
|
||||
const [permDialog, setPermDialog] = useState<{ folderId: string; folderName: string } | null>(null);
|
||||
|
||||
const { data: folders, isLoading: foldersLoading } = useContactFolders();
|
||||
const createFolderMut = useCreateContactFolder();
|
||||
@@ -329,6 +334,11 @@ export function ContactFolderTree({
|
||||
updateFolderMut.mutate({ id, data: { pinned: !pinned } as any });
|
||||
};
|
||||
|
||||
const handlePermissions = (id: string) => {
|
||||
const folder = folderList.find((f) => f.id === id);
|
||||
setPermDialog({ folderId: id, folderName: folder?.name || 'Ordner' });
|
||||
};
|
||||
|
||||
// Drag and Drop handlers
|
||||
const handleDragOver = (e: React.DragEvent, folderId: string) => {
|
||||
e.preventDefault();
|
||||
@@ -530,6 +540,15 @@ export function ContactFolderTree({
|
||||
onDelete={handleDelete}
|
||||
onColor={handleColor}
|
||||
onPin={handlePin}
|
||||
onPermissions={handlePermissions}
|
||||
/>
|
||||
)}
|
||||
|
||||
{permDialog && (
|
||||
<FolderPermissionDialog
|
||||
folderId={permDialog.folderId}
|
||||
folderName={permDialog.folderName}
|
||||
onClose={() => setPermDialog(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user