feat: standalone buttons for all plugin pages + window system for modals

Standalone buttons:
- Add ExternalLink button to Dms, Calendar, Mail, ContactsList toolbars
- Create standalone pages for each (no sidebar, full screen)
- Add standalone routes outside ProtectedRoute

Window system for modals:
- AppointmentModal -> AppointmentEditForm + openWindow()
- ComposeModal -> MailComposeForm + openWindow()
- FilePreviewModal -> FilePreviewContent + openWindow()
- Calendar, Mail, Dms use openWindow() instead of modal state
This commit is contained in:
Agent Zero
2026-07-25 00:21:37 +02:00
parent 2f6c3175a3
commit 868bb274ef
12 changed files with 1220 additions and 124 deletions
+33 -14
View File
@@ -20,11 +20,12 @@ import { SourceTree } from '@/components/dms/SourceTree';
import { FileExplorer, type ViewMode, type SortBy, type SortOrder } from '@/components/dms/FileExplorer';
import { FileDetails } from '@/components/dms/FileDetails';
import { UploadDropzone } from '@/components/dms/UploadDropzone';
import { FilePreviewModal } from '@/components/dms/FilePreviewModal';
import { FilePreviewContent } from '@/components/dms/FilePreviewContent';
import { useWindowStore } from '@/store/windowStore';
import { ShareDialog } from '@/components/dms/ShareDialog';
import { BulkActions } from '@/components/dms/BulkActions';
import { usePluginToolbarStore } from '@/store/pluginToolbarStore';
import { ArrowRight, ChevronLeft, ChevronRight, Info, Plus, Trash2, Upload } from 'lucide-react';
import { ArrowRight, ChevronLeft, ChevronRight, ExternalLink, Info, Plus, Trash2, Upload } from 'lucide-react';
import {
fetchFolders,
createFolder,
@@ -72,7 +73,7 @@ export function DmsPage() {
// Modal state
const [showUpload, setShowUpload] = useState(false);
const [showNewFolder, setShowNewFolder] = useState(false);
const [previewFile, setPreviewFile] = useState<DmsFile | null>(null);
const openWindow = useWindowStore((s) => s.openWindow);
const [shareFile, setShareFile] = useState<DmsFile | null>(null);
const [deleteTarget, setDeleteTarget] = useState<DmsFile | null>(null);
const [submittingFolder, setSubmittingFolder] = useState(false);
@@ -195,8 +196,15 @@ export function DmsPage() {
// Handle file double click (open preview)
const handleFileDoubleClick = useCallback((file: DmsFile) => {
setPreviewFile(file);
}, []);
openWindow({
title: file.name,
type: 'file-preview',
component: FilePreviewContent,
componentProps: {
file,
},
});
}, [openWindow]);
// Handle file share
const handleFileShare = useCallback((file: DmsFile) => {
@@ -210,8 +218,15 @@ export function DmsPage() {
// Handle file preview
const handleFilePreview = useCallback((file: DmsFile) => {
setPreviewFile(file);
}, []);
openWindow({
title: file.name,
type: 'file-preview',
component: FilePreviewContent,
componentProps: {
file,
},
});
}, [openWindow]);
// Handle toggle select
const handleToggleSelect = useCallback((fileId: string) => {
@@ -439,6 +454,17 @@ export function DmsPage() {
),
onClick: () => setShowDetails((v) => !v),
},
{
id: 'open-standalone',
plugin: 'dms',
label: 'In neuem Fenster',
type: 'button' as const,
group: 'actions',
icon: (
<ExternalLink className="w-3.5 h-3.5" strokeWidth={2} />
),
onClick: () => window.open('/dms-standalone', '_blank', 'width=1200,height=800'),
},
];
// Add bulk actions when files are selected
@@ -706,13 +732,6 @@ export function DmsPage() {
onCancel={() => setDeleteTarget(null)}
/>
{/* File preview modal */}
<FilePreviewModal
open={!!previewFile}
file={previewFile}
onClose={() => setPreviewFile(null)}
/>
{/* Share dialog */}
<ShareDialog
open={!!shareFile}