This commit is contained in:
2025-11-29 01:36:07 +01:00
parent d932b832c1
commit 4fa9c97189
5 changed files with 427 additions and 59 deletions

View File

@@ -127,10 +127,8 @@ export default function ReportEditorPage() {
// Page state - track which page is currently being edited
const [currentPageId, setCurrentPageId] = useState<string>(defaultPage.id);
// Editor state
const [selectedElementId, setSelectedElementId] = useState<string | null>(
null,
);
// Editor state - support multiple selection
const [selectedElementIds, setSelectedElementIds] = useState<string[]>([]);
const [zoom, setZoom] = useState(isMobile ? 0.5 : 1);
const [showGrid, setShowGrid] = useState(true);
const [snapOptions, setSnapOptions] = useState<SnapOptions>({
@@ -256,8 +254,10 @@ export default function ReportEditorPage() {
elements: prev.elements.filter((el) => el.id !== message.itemId),
}));
// Clear selection if deleted element was selected
if (selectedElementId === message.itemId) {
setSelectedElementId(null);
if (selectedElementIds.includes(message.itemId)) {
setSelectedElementIds((prev) =>
prev.filter((id) => id !== message.itemId),
);
}
setTimeout(() => {
isApplyingRemoteChange.current = false;
@@ -396,18 +396,18 @@ export default function ReportEditorPage() {
}, [
collaboration,
historyActions,
selectedElementId,
selectedElementIds,
template,
queryClient,
id,
]);
// Send selection changes to collaborators
// Send selection changes to collaborators (send first selected element for compatibility)
useEffect(() => {
if (collaboration.isConnected && !isApplyingRemoteChange.current) {
collaboration.sendSelectionChanged(selectedElementId);
collaboration.sendSelectionChanged(selectedElementIds[0] || null);
}
}, [collaboration, selectedElementId]);
}, [collaboration, selectedElementIds]);
// Send view/page navigation to collaborators
useEffect(() => {
@@ -629,10 +629,14 @@ export default function ReportEditorPage() {
historyActions.redo();
}, [historyActions]);
// Get selected element
// Get selected element(s) - for single selection compatibility, use first selected
const selectedElementId = selectedElementIds[0] || null;
const selectedElement = selectedElementId
? template.elements.find((e) => e.id === selectedElementId)
: null;
const selectedElements = selectedElementIds
.map((id) => template.elements.find((e) => e.id === id))
.filter((e): e is AprtElement => e !== undefined);
// Dataset management
const handleAddDataset = useCallback((dataset: DatasetTypeDto) => {
@@ -682,7 +686,7 @@ export default function ReportEditorPage() {
// Switch to the new page
setCurrentPageId(newPageId);
setSelectedElementId(null);
setSelectedElementIds([]);
}, [template.pages.length, historyActions, collaboration]);
// Duplicate page with all its elements
@@ -717,7 +721,7 @@ export default function ReportEditorPage() {
// Switch to the new page
setCurrentPageId(newPageId);
setSelectedElementId(null);
setSelectedElementIds([]);
},
[template.pages, template.elements, historyActions],
);
@@ -749,7 +753,7 @@ export default function ReportEditorPage() {
if (newCurrentPage) {
setCurrentPageId(newCurrentPage.id);
}
setSelectedElementId(null);
setSelectedElementIds([]);
},
[template.pages, historyActions, collaboration],
);
@@ -796,7 +800,7 @@ export default function ReportEditorPage() {
// Select page
const handleSelectPage = useCallback((pageId: string) => {
setCurrentPageId(pageId);
setSelectedElementId(null); // Clear selection when switching pages
setSelectedElementIds([]); // Clear selection when switching pages
}, []);
// ============ END PAGE MANAGEMENT HANDLERS ============
@@ -851,7 +855,7 @@ export default function ReportEditorPage() {
...prev,
elements: [...prev.elements, newElement],
}));
setSelectedElementId(newElement.id);
setSelectedElementIds([newElement.id]);
// Send to collaborators
if (collaboration.isConnected && !isApplyingRemoteChange.current) {
@@ -958,7 +962,7 @@ export default function ReportEditorPage() {
...prev,
elements: [...prev.elements, newElement],
}));
setSelectedElementId(newElement.id);
setSelectedElementIds([newElement.id]);
},
[
selectedElementId,
@@ -991,7 +995,7 @@ export default function ReportEditorPage() {
...prev,
elements: prev.elements.filter((el) => el.id !== selectedElementId),
}));
setSelectedElementId(null);
setSelectedElementIds([]);
}, [selectedElementId, historyActions, collaboration]);
// Copy element
@@ -1011,7 +1015,7 @@ export default function ReportEditorPage() {
...prev,
elements: [...prev.elements, copy],
}));
setSelectedElementId(copy.id);
setSelectedElementIds([copy.id]);
}, [selectedElement, historyActions]);
// Toggle lock
@@ -1066,7 +1070,7 @@ export default function ReportEditorPage() {
// Handle context menu event from canvas
const handleContextMenu = useCallback((event: ContextMenuEvent) => {
if (event.elementId) {
setSelectedElementId(event.elementId);
setSelectedElementIds(event.elementId ? [event.elementId] : []);
}
setContextMenu({
open: true,
@@ -1113,7 +1117,7 @@ export default function ReportEditorPage() {
...prev,
elements: [...prev.elements, pastedElement],
}));
setSelectedElementId(pastedElement.id);
setSelectedElementIds([pastedElement.id]);
}, [clipboard, historyActions]);
// Duplicate element
@@ -1366,19 +1370,15 @@ export default function ReportEditorPage() {
// Selection operations
const handleSelectAll = useCallback(() => {
// For now, just show a message - multi-selection requires more work
if (template.elements.length > 0) {
setSelectedElementId(template.elements[template.elements.length - 1].id);
setSnackbar({
open: true,
message: "Selezione multipla non ancora implementata",
severity: "error",
});
// Select all elements on the current page
const pageElementIds = currentPageElements.map((e) => e.id);
if (pageElementIds.length > 0) {
setSelectedElementIds(pageElementIds);
}
}, [template.elements]);
}, [currentPageElements]);
const handleDeselectAll = useCallback(() => {
setSelectedElementId(null);
setSelectedElementIds([]);
}, []);
// Toggle visibility
@@ -1704,13 +1704,13 @@ export default function ReportEditorPage() {
onPrevPage={() => {
if (currentPageIndex > 0) {
setCurrentPageId(template.pages[currentPageIndex - 1].id);
setSelectedElementId(null);
setSelectedElementIds([]);
}
}}
onNextPage={() => {
if (currentPageIndex < template.pages.length - 1) {
setCurrentPageId(template.pages[currentPageIndex + 1].id);
setSelectedElementId(null);
setSelectedElementIds([]);
}
}}
// New props for enhanced toolbar
@@ -1764,11 +1764,11 @@ export default function ReportEditorPage() {
margins: currentPage?.margins || template.meta.margins,
},
}}
selectedElementId={selectedElementId}
onSelectElement={(id) => {
setSelectedElementId(id);
selectedElementIds={selectedElementIds}
onSelectElement={(ids) => {
setSelectedElementIds(ids);
// On mobile, auto-open properties when selecting element
if (isMobile && id) {
if (isMobile && ids.length > 0) {
setMobilePanel("properties");
}
}}
@@ -1973,7 +1973,7 @@ export default function ReportEditorPage() {
open={contextMenu.open}
position={contextMenu.position}
selectedElement={selectedElement || null}
selectedElements={selectedElement ? [selectedElement] : []}
selectedElements={selectedElements}
hasClipboard={clipboard !== null}
onClose={closeContextMenu}
// Clipboard actions