feat: click-drag drawing, layer tree, settings modal, UI improvements
- interaction: click-drag drawing for 2-point tools (line, rect, circle, dimension, leader) - interaction: preview rendering during drag with setPreviewElement - interaction: handleDrawDown only sets phase=drawing on first point - CanvasArea: sync activeLayerId to LayerManager - CanvasArea: callback refresh useEffect prevents stale closures - App.tsx: functional setElements updates for handleElementCreated/Deleted/Modified - LayerPanel: tree structure with sub-layers (onReorder, onAddSubLayer) - TreeView: drag-and-drop reordering support - RightSidebar: onReorder, onAddSubLayer, onUpdateElement props - PropertiesPanel: onUpdateElement prop - SettingsModal: personal/password/language/theme/users/plugins/AI tabs - styles.css: extensive UI styling additions - types: updated RightSidebarProps, CanvasAreaProps, LayerPanelProps
This commit is contained in:
+10
-24
@@ -36,18 +36,13 @@ import { Register } from './pages/Register';
|
||||
import { Dashboard } from './pages/Dashboard';
|
||||
|
||||
// ─── Mock Data ──────────────────────────────────────────────
|
||||
function makeInitialLayers(): CADLayer[] {
|
||||
const ts = Date.now();
|
||||
return [
|
||||
{ id: `layer-${ts}-0`, name: 'Wände', visible: true, locked: false, color: '#e74c3c', lineType: 'solid', transparency: 0, sortOrder: 0, parentId: null },
|
||||
{ id: `layer-${ts}-1`, name: 'Türen', visible: true, locked: false, color: '#3498db', lineType: 'solid', transparency: 0, sortOrder: 1, parentId: null },
|
||||
{ id: `layer-${ts}-2`, name: 'Bestuhlung', visible: true, locked: false, color: '#2ecc71', lineType: 'solid', transparency: 0, sortOrder: 2, parentId: null },
|
||||
{ id: `layer-${ts}-3`, name: 'Bühne', visible: true, locked: false, color: '#f39c12', lineType: 'solid', transparency: 0, sortOrder: 3, parentId: null },
|
||||
{ id: `layer-${ts}-4`, name: 'Hintergrund', visible: true, locked: true, color: '#95a5a6', lineType: 'dotted', transparency: 50, sortOrder: 4, parentId: null },
|
||||
];
|
||||
}
|
||||
|
||||
const initialLayers: CADLayer[] = makeInitialLayers();
|
||||
const initialLayers: CADLayer[] = [
|
||||
{ id: 'layer-0', name: 'Wände', visible: true, locked: false, color: '#e74c3c', lineType: 'solid', transparency: 0, sortOrder: 0, parentId: null },
|
||||
{ id: 'layer-1', name: 'Türen', visible: true, locked: false, color: '#3498db', lineType: 'solid', transparency: 0, sortOrder: 1, parentId: null },
|
||||
{ id: 'layer-2', name: 'Bestuhlung', visible: true, locked: false, color: '#2ecc71', lineType: 'solid', transparency: 0, sortOrder: 2, parentId: null },
|
||||
{ id: 'layer-3', name: 'Bühne', visible: true, locked: false, color: '#f39c12', lineType: 'solid', transparency: 0, sortOrder: 3, parentId: null },
|
||||
{ id: 'layer-4', name: 'Hintergrund', visible: true, locked: true, color: '#95a5a6', lineType: 'dotted', transparency: 50, sortOrder: 4, parentId: null },
|
||||
];
|
||||
|
||||
const initialBlocks: BlockDefinition[] = createDefaultBlocks();
|
||||
|
||||
@@ -115,7 +110,7 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
||||
const [activeRightPanel, setActiveRightPanel] = useState<RightPanel>('tool');
|
||||
const [selectedElement, setSelectedElement] = useState<CADElement | null>(null);
|
||||
const [layers, setLayers] = useState<CADLayer[]>(initialLayers);
|
||||
const [activeLayerId, setActiveLayerId] = useState<string>(initialLayers[0].id);
|
||||
const [activeLayerId, setActiveLayerId] = useState<string>('layer-0');
|
||||
const [blocks, setBlocks] = useState<BlockDefinition[]>(initialBlocks);
|
||||
const [blockCategory, setBlockCategory] = useState('Alle');
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<string | null>(null);
|
||||
@@ -257,14 +252,9 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
||||
if (data.blocks.length > 0) setBlocks(data.blocks);
|
||||
// Save initial layers to backend if backend has none
|
||||
if (data.layers.length === 0 && data.drawing) {
|
||||
const freshLayers = makeInitialLayers();
|
||||
setLayers(freshLayers);
|
||||
setActiveLayerId(freshLayers[0].id);
|
||||
for (const layer of freshLayers) {
|
||||
for (const layer of initialLayers) {
|
||||
createLayerTyped(token, data.drawing.id, layer).catch(() => {});
|
||||
}
|
||||
} else {
|
||||
setActiveLayerId(data.layers[0]?.id ?? initialLayers[0].id);
|
||||
}
|
||||
setSavedStatus('gespeichert');
|
||||
setDataLoaded(true);
|
||||
@@ -692,7 +682,6 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
||||
setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Suche: Befehlszeile verwenden (Strg+F)', type: 'info' }]);
|
||||
return;
|
||||
}
|
||||
if (action === 'plugins') { setActiveRightPanel('plugins'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Plugin-Manager geöffnet', type: 'info' }]); return; }
|
||||
if (action === 'history') { setHistoryPanelOpen((prev) => !prev); return; }
|
||||
|
||||
// ─── Background ───
|
||||
@@ -921,7 +910,7 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
||||
handleKISend(suggestion.label);
|
||||
}, [handleKISend]);
|
||||
|
||||
const activeLayerName = layers.find((l) => l.id === activeLayerId)?.name ?? '—';
|
||||
const activeLayerName = layers.find((l) => l.id === 'layer-0')?.name ?? '—';
|
||||
|
||||
// ─── Render ─────────────────────────────────────────────
|
||||
return (
|
||||
@@ -991,9 +980,6 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
||||
onRenameLayer={handleRenameLayer}
|
||||
onDuplicateLayer={handleDuplicateLayer}
|
||||
onToggleLock={handleToggleLock}
|
||||
onUpdateLayerColor={handleUpdateLayerColor}
|
||||
onUpdateLayerLineType={handleUpdateLayerLineType}
|
||||
onUpdateLayerTransparency={handleUpdateLayerTransparency}
|
||||
onRenameBlock={handleRenameBlock}
|
||||
onDuplicateBlock={handleDuplicateBlock}
|
||||
onDeleteBlock={handleDeleteBlock}
|
||||
|
||||
Reference in New Issue
Block a user