fix: layer panel collapsible tree + element actions (visibility toggle, delete) + RenderEngine skips invisible elements

This commit is contained in:
2026-06-27 23:59:12 +02:00
parent affa6be151
commit a4371ca3ce
5 changed files with 91 additions and 44 deletions
+16
View File
@@ -331,6 +331,20 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
}
}, [layers, blocks, groups, bgConfig, syncHistory, drawingId, token, collab, activeLayerId]);
const handleToggleElementVisible = useCallback((id: string) => {
setElements((prev) => prev.map((e) => {
if (e.id === id) {
const newEl = { ...e, properties: { ...e.properties, visible: e.properties?.visible === false ? true : false } };
if (token) {
setSavedStatus("Speichert…");
updateElement(token, newEl.id, newEl).then(() => setSavedStatus("gespeichert")).catch(() => setSavedStatus("Fehler"));
}
return newEl;
}
return e;
}));
}, [token]);
const handleElementsDeleted = useCallback((ids: string[]) => {
setElements((prev) => {
const newElements = prev.filter((e) => !ids.includes(e.id));
@@ -980,6 +994,8 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
onRenameLayer={handleRenameLayer}
onDuplicateLayer={handleDuplicateLayer}
onToggleLock={handleToggleLock}
onElementsDeleted={handleElementsDeleted}
onToggleElementVisible={handleToggleElementVisible}
elements={elements}
onRenameBlock={handleRenameBlock}
onDuplicateBlock={handleDuplicateBlock}
+1 -1
View File
@@ -151,7 +151,7 @@ export class RenderEngine {
const layers = this.layerManager.getLayers();
for (const layer of layers) {
if (!layer.visible) continue;
const els = visibleElements.filter(e => e.layerId === layer.id);
const els = visibleElements.filter(e => e.layerId === layer.id && e.properties?.visible !== false);
for (const el of els) {
this.drawElement(el, layer);
}
+29 -3
View File
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';
import type { LayerPanelProps } from '../types/ui.types';
import type { CADLayer, CADElement } from '../types/cad.types';
import type { TreeNode } from '../types/ui.types';
@@ -67,6 +67,8 @@ const LayerPanel: React.FC<LayerPanelProps> = ({
onToggleLock,
onReorder,
onAddSubLayer,
onElementsDeleted,
onToggleElementVisible,
}) => {
const buildTree = (parentId: string | null): TreeNode[] => {
return layers
@@ -87,7 +89,7 @@ const LayerPanel: React.FC<LayerPanelProps> = ({
id: l.id,
name: l.name,
icon: layerIcon,
expanded: true,
expanded: false,
active: l.id === activeLayerId,
children: [...subLayerNodes, ...elementNodes],
count: layerElements.length > 0 ? layerElements.length : undefined,
@@ -132,7 +134,7 @@ const LayerPanel: React.FC<LayerPanelProps> = ({
renderIcon={(node) => node.icon}
renderActions={(node) => {
const layer = layers.find((l) => l.id === node.id);
if (!layer) return null;
if (layer) {
return (
<div style={{ display: 'flex', gap: '2px', opacity: 0.6 }}>
<button
@@ -172,6 +174,30 @@ const LayerPanel: React.FC<LayerPanelProps> = ({
</button>
</div>
);
}
const element = elements.find((el) => el.id === node.id);
if (element) {
const isVisible = element.properties?.visible !== false;
return (
<div style={{ display: 'flex', gap: '2px', opacity: 0.6 }}>
<button
onClick={(e) => { e.stopPropagation(); onToggleElementVisible?.(element.id); }}
title={isVisible ? 'Sichtbar' : 'Versteckt'}
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px', color: isVisible ? 'var(--text-color, #ccc)' : 'var(--text-muted, #666)' }}
>
{isVisible ? '👁' : '🚫'}
</button>
<button
onClick={(e) => { e.stopPropagation(); onElementsDeleted?.([element.id]); }}
title="Loschen"
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px', color: '#f44336' }}
>
</button>
</div>
);
}
return null;
}}
/>
)}
+2 -1
View File
@@ -17,6 +17,7 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
activeLayerId, onSelectLayer, onAddLayer, onToggleLayer,
onDeleteLayer, onRenameLayer, onDuplicateLayer, onToggleLock,
onReorder, onAddSubLayer,
onElementsDeleted, onToggleElementVisible,
elements,
onRenameBlock, onDuplicateBlock, onDeleteBlock, onSvgImport, onSaveGroupAsBlock,
onBlockCategoryChange, onBlockSearch, onDragBlock,
@@ -57,7 +58,7 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
}} />}
</div>
<div className={`rightbar-panel${activePanel === 'layer' ? ' active' : ''}`} data-panel-content="layer">
{activePanel === 'layer' && <LayerPanel layers={layers} elements={elements} activeLayerId={activeLayerId} onSelectLayer={onSelectLayer ?? (() => {})} onAddLayer={onAddLayer ?? (() => {})} onToggleLayer={onToggleLayer ?? (() => {})} onDeleteLayer={onDeleteLayer} onRenameLayer={onRenameLayer} onDuplicateLayer={onDuplicateLayer} onToggleLock={onToggleLock} onReorder={onReorder} onAddSubLayer={onAddSubLayer} />}
{activePanel === 'layer' && <LayerPanel layers={layers} elements={elements} onElementsDeleted={onElementsDeleted} onToggleElementVisible={onToggleElementVisible} activeLayerId={activeLayerId} onSelectLayer={onSelectLayer ?? (() => {})} onAddLayer={onAddLayer ?? (() => {})} onToggleLayer={onToggleLayer ?? (() => {})} onDeleteLayer={onDeleteLayer} onRenameLayer={onRenameLayer} onDuplicateLayer={onDuplicateLayer} onToggleLock={onToggleLock} onReorder={onReorder} onAddSubLayer={onAddSubLayer} />}
</div>
<div className={`rightbar-panel${activePanel === 'library' ? ' active' : ''}`} data-panel-content="library">
{activePanel === 'library' && <BlockLibrary blocks={blocks} category="Alle" onCategoryChange={onBlockCategoryChange ?? (() => {})} onSearch={onBlockSearch ?? (() => {})} onDragBlock={onDragBlock ?? (() => {})} onRenameBlock={onRenameBlock} onDuplicateBlock={onDuplicateBlock} onDeleteBlock={onDeleteBlock} onSvgImport={onSvgImport} onSaveGroupAsBlock={onSaveGroupAsBlock} />}
+4
View File
@@ -138,6 +138,8 @@ export interface RightSidebarProps {
onUpdateLayerLineType?: (id: string, lineType: 'solid' | 'dashed' | 'dotted') => void;
onUpdateLayerTransparency?: (id: string, transparency: number) => void;
onAddSubLayer?: (parentId: string) => void;
onElementsDeleted?: (ids: string[]) => void;
onToggleElementVisible?: (id: string) => void;
onRenameBlock?: (id: string, name: string) => void;
onDuplicateBlock?: (id: string) => void;
onDeleteBlock?: (id: string) => void;
@@ -176,6 +178,8 @@ export interface LayerPanelProps {
onUpdateLayerLineType?: (id: string, lineType: 'solid' | 'dashed' | 'dotted') => void;
onUpdateLayerTransparency?: (id: string, transparency: number) => void;
onAddSubLayer?: (parentId: string) => void;
onElementsDeleted?: (ids: string[]) => void;
onToggleElementVisible?: (id: string) => void;
}
export interface BlockLibraryProps {