feat: Enhance DashboardEditor with element handling and selection management
This commit is contained in:
@@ -27,15 +27,20 @@ const DashboardEditor: React.FC = () => {
|
||||
const { activeModule } = useModuleStore();
|
||||
const {
|
||||
blocks,
|
||||
selectedBlock,
|
||||
setSelectedBlock,
|
||||
selectedElement,
|
||||
setSelectedElement,
|
||||
addBlock,
|
||||
setBlocks,
|
||||
updateBlockPosition,
|
||||
updateElementPosition,
|
||||
updateBlockSize,
|
||||
updateElementSize,
|
||||
addBlock,
|
||||
updateBlockStyle,
|
||||
updateBlockPositionType,
|
||||
updateBlockZIndex,
|
||||
addElement,
|
||||
updateElementStyle,
|
||||
updateElementPositionType,
|
||||
updateElementZIndex,
|
||||
@@ -50,8 +55,6 @@ const DashboardEditor: React.FC = () => {
|
||||
subscribe,
|
||||
} = simulationDashBoardStore();
|
||||
|
||||
const [selectedBlock, setSelectedBlock] = useState<string | null>(null);
|
||||
const [selectedElement, setSelectedElement] = useState<string | null>(null);
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const [draggingElement, setDraggingElement] = useState<string | null>(null);
|
||||
const [resizingElement, setResizingElement] = useState<string | null>(null);
|
||||
@@ -87,7 +90,6 @@ const DashboardEditor: React.FC = () => {
|
||||
useEffect(() => {
|
||||
if (!projectId || !selectedVersion) return;
|
||||
getDashBoardBlocksApi(projectId, selectedVersion.versionId).then((data) => {
|
||||
console.log("data: ", data);
|
||||
if (data.data?.blocks) {
|
||||
setBlocks(data.data.blocks);
|
||||
}
|
||||
@@ -107,7 +109,6 @@ const DashboardEditor: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const unsubscribe = subscribe(() => {
|
||||
if (!projectId || !selectedVersion) return;
|
||||
console.log("blocks: ", blocks);
|
||||
updateBackend(blocks);
|
||||
});
|
||||
|
||||
@@ -349,13 +350,16 @@ const DashboardEditor: React.FC = () => {
|
||||
<div className="block-grid-container">
|
||||
<BlockGrid
|
||||
blocks={blocks}
|
||||
handleAddElement={(blockId, type, graphType) => {
|
||||
addElement(blockId, type, graphType);
|
||||
}}
|
||||
editMode={editMode}
|
||||
selectedBlock={selectedBlock}
|
||||
selectedElement={selectedElement}
|
||||
showSwapUI={showSwapUI}
|
||||
swapSource={swapSource}
|
||||
calculateMinBlockSize={calculateMinBlockSize}
|
||||
handleBlockClick={(blockId, event) => handleBlockClick(blockId, event, editMode, setSelectedBlock, setSelectedElement, setShowSwapUI)}
|
||||
handleBlockClick={(blockId, event) => handleBlockClick(blockId, event, editMode, setSelectedBlock, setSelectedElement, setShowSwapUI, setShowElementDropdown, showElementDropdown)}
|
||||
handleElementClick={(blockId, elementId, event) =>
|
||||
handleElementClick(blockId, elementId, event, editMode, setSelectedElement, setSelectedBlock, setShowSwapUI, setShowElementDropdown)
|
||||
}
|
||||
@@ -369,7 +373,9 @@ const DashboardEditor: React.FC = () => {
|
||||
showElementDropdown={showElementDropdown}
|
||||
blockRef={blockRef}
|
||||
/>
|
||||
|
||||
{/* BlockEditor */}
|
||||
|
||||
{selectedBlock && editMode && !selectedElement && currentBlock && (
|
||||
<BlockEditor
|
||||
blockEditorRef={blockEditorRef}
|
||||
@@ -384,7 +390,7 @@ const DashboardEditor: React.FC = () => {
|
||||
const block = getBlockById(blockId);
|
||||
if (!block) return;
|
||||
deleteDashBoardBlocksApi({ projectId: projectId!, versionId: selectedVersion!.versionId, blocks: [block] }).then((data) => {
|
||||
if (data.blocks.length>0) {
|
||||
if (data.blocks.length > 0) {
|
||||
data.blocks.forEach((updatedBlock: any) => {
|
||||
if (updatedBlock.message === "Block deleted successfully") {
|
||||
removeBlock(updatedBlock.blockUuid);
|
||||
@@ -395,6 +401,7 @@ const DashboardEditor: React.FC = () => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedElement && editMode && selectedBlock && currentElement && (
|
||||
<ElementEditor
|
||||
elementEditorRef={elementEditorRef}
|
||||
|
||||
@@ -3,10 +3,10 @@ import { Block } from "../../../../types/exportedTypes";
|
||||
import ElementComponent from "../element/ElementComponent";
|
||||
import { ResizeIcon } from "../../../icons/ExportToolsIcons";
|
||||
import ElementDropdown from "../element/ElementDropdown";
|
||||
import { useSceneContext } from "../../../../modules/scene/sceneContext";
|
||||
|
||||
interface BlockComponentProps {
|
||||
block: Block;
|
||||
handleAddElement: (blockId: string, type: UIType, graphType?: GraphTypes) => void;
|
||||
editMode: boolean;
|
||||
selectedBlock: string | null;
|
||||
selectedElement: string | null;
|
||||
@@ -28,6 +28,7 @@ interface BlockComponentProps {
|
||||
|
||||
const BlockComponent: React.FC<BlockComponentProps> = ({
|
||||
block,
|
||||
handleAddElement,
|
||||
editMode,
|
||||
selectedBlock,
|
||||
selectedElement,
|
||||
@@ -46,9 +47,6 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
|
||||
blockRef,
|
||||
handleBlockDragStart,
|
||||
}) => {
|
||||
const { simulationDashBoardStore } = useSceneContext();
|
||||
const { addElement } = simulationDashBoardStore();
|
||||
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const minSize = calculateMinBlockSize(block);
|
||||
@@ -97,7 +95,7 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
|
||||
|
||||
<ElementDropdown
|
||||
showElementDropdown={showElementDropdown}
|
||||
addElement={(blockId, type, graphType) => addElement(blockId, type as UIType, graphType as GraphTypes)}
|
||||
handleAddElement={(blockId, type, graphType) => handleAddElement(blockId, type as UIType, graphType as GraphTypes)}
|
||||
dropdownRef={dropdownRef}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import BlockComponent from "./BlockComponent";
|
||||
// components/BlockGrid.tsx - Updated props
|
||||
interface BlockGridProps {
|
||||
blocks: Block[];
|
||||
handleAddElement: (blockId: string, type: UIType, graphType?: GraphTypes) => void;
|
||||
editMode: boolean;
|
||||
selectedBlock: string | null;
|
||||
selectedElement: string | null;
|
||||
@@ -26,6 +27,7 @@ interface BlockGridProps {
|
||||
|
||||
const BlockGrid: React.FC<BlockGridProps> = ({
|
||||
blocks,
|
||||
handleAddElement,
|
||||
editMode,
|
||||
selectedBlock,
|
||||
selectedElement,
|
||||
@@ -52,6 +54,7 @@ const BlockGrid: React.FC<BlockGridProps> = ({
|
||||
<BlockComponent
|
||||
key={block.blockUuid}
|
||||
block={block}
|
||||
handleAddElement={handleAddElement}
|
||||
editMode={editMode}
|
||||
selectedBlock={selectedBlock}
|
||||
selectedElement={selectedElement}
|
||||
|
||||
@@ -3,11 +3,11 @@ import React, { type RefObject } from "react";
|
||||
interface ElementDropdownProps {
|
||||
showElementDropdown: string | null;
|
||||
// dropDownPosition: { top: number; left: number };
|
||||
addElement: (blockId: string, type: string, graphType?: string | undefined) => void;
|
||||
handleAddElement: (blockId: string, type: string, graphType?: string | undefined) => void;
|
||||
dropdownRef: RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
const ElementDropdown: React.FC<ElementDropdownProps> = ({ showElementDropdown, addElement, dropdownRef }) => {
|
||||
const ElementDropdown: React.FC<ElementDropdownProps> = ({ showElementDropdown, handleAddElement, dropdownRef }) => {
|
||||
if (!showElementDropdown) return null;
|
||||
const elementTypes = [
|
||||
{ label: "Label-Value", type: "label-value" },
|
||||
@@ -21,12 +21,16 @@ const ElementDropdown: React.FC<ElementDropdownProps> = ({ showElementDropdown,
|
||||
];
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={dropdownRef}
|
||||
className="element-dropdown"
|
||||
>
|
||||
<div ref={dropdownRef} className="element-dropdown">
|
||||
{elementTypes.map((elementType) => (
|
||||
<button key={elementType.label} onClick={() => addElement(showElementDropdown, elementType.type, elementType.graphType)} className="dropdown-button">
|
||||
<button
|
||||
key={elementType.label}
|
||||
onClick={() => {
|
||||
handleAddElement(showElementDropdown, elementType.type, elementType.graphType);
|
||||
console.log('showElementDropdown: ', showElementDropdown);
|
||||
}}
|
||||
className="dropdown-button"
|
||||
>
|
||||
{elementType.label}
|
||||
</button>
|
||||
))}
|
||||
|
||||
@@ -92,11 +92,7 @@ export const handleSwapTarget = (
|
||||
event: React.MouseEvent,
|
||||
swapSource: string | null,
|
||||
selectedBlock: string | null,
|
||||
swapElements: (
|
||||
blockId: string,
|
||||
elementId1: string,
|
||||
elementId2: string,
|
||||
) => void,
|
||||
swapElements: (blockId: string, elementId1: string, elementId2: string) => void
|
||||
): void => {
|
||||
event.stopPropagation();
|
||||
if (swapSource && swapSource !== elementId && selectedBlock) {
|
||||
@@ -110,13 +106,19 @@ export const handleBlockClick = (
|
||||
editMode: boolean,
|
||||
setSelectedBlock: (blockId: string | null) => void,
|
||||
setSelectedElement: (elementId: string | null) => void,
|
||||
setShowSwapUI: (show: boolean) => void
|
||||
setShowSwapUI: (show: boolean) => void,
|
||||
setShowElementDropdown: (blockId: string | null) => void,
|
||||
showElementDropdown: string | null
|
||||
): void => {
|
||||
event.stopPropagation();
|
||||
if (editMode) {
|
||||
setSelectedBlock(blockId);
|
||||
setSelectedElement(null);
|
||||
setShowSwapUI(false);
|
||||
console.log('showElementDropdown: ', showElementDropdown);
|
||||
if (showElementDropdown && showElementDropdown !== blockId) {
|
||||
setShowElementDropdown(blockId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -135,6 +137,6 @@ export const handleElementClick = (
|
||||
setSelectedElement(elementId);
|
||||
setSelectedBlock(blockId);
|
||||
setShowSwapUI(false);
|
||||
setShowElementDropdown(null);
|
||||
// setShowElementDropdown(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,14 +6,18 @@ import { Block, UIElement, ExtendedCSSProperties } from "../../types/exportedTyp
|
||||
|
||||
interface SimulationDashboardStore {
|
||||
blocks: Block[];
|
||||
selectedBlockId: string | null;
|
||||
selectedElementId: string | null;
|
||||
selectedBlock: string | null;
|
||||
selectedElement: string | null;
|
||||
|
||||
// Subscription management
|
||||
subscribe: (callback: () => void) => () => void;
|
||||
_notifySubscribers: () => void;
|
||||
saveBlocks: () => void;
|
||||
|
||||
// Selection and hover management
|
||||
setSelectedBlock: (blockId: string | null) => void;
|
||||
setSelectedElement: (elementId: string | null) => void;
|
||||
|
||||
// Block operations
|
||||
addBlock: () => void;
|
||||
removeBlock: (blockId: string) => void;
|
||||
@@ -46,10 +50,6 @@ interface SimulationDashboardStore {
|
||||
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
|
||||
updateGraphType: (blockId: string, elementId: string, graphType: GraphTypes) => void;
|
||||
|
||||
// Selection and hover management
|
||||
setSelectedBlock: (blockId: string | null) => void;
|
||||
setSelectedElement: (elementId: string | null) => void;
|
||||
|
||||
// Element swapping
|
||||
swapElements: (blockId: string, elementId1: string, elementId2: string) => void;
|
||||
|
||||
@@ -68,8 +68,8 @@ export const createSimulationDashboardStore = () => {
|
||||
return create<SimulationDashboardStore>()(
|
||||
immer((set, get) => ({
|
||||
blocks: [],
|
||||
selectedBlockId: null,
|
||||
selectedElementId: null,
|
||||
selectedBlock: null,
|
||||
selectedElement: null,
|
||||
|
||||
subscribe: (callback: () => void) => {
|
||||
subscribers.add(callback);
|
||||
@@ -92,6 +92,23 @@ export const createSimulationDashboardStore = () => {
|
||||
get()._notifySubscribers();
|
||||
},
|
||||
|
||||
// Selection and hover management
|
||||
setSelectedBlock: (blockId) => {
|
||||
set((state) => {
|
||||
state.selectedBlock = blockId;
|
||||
// Clear element selection when selecting a block
|
||||
if (blockId) {
|
||||
state.selectedElement = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setSelectedElement: (elementId) => {
|
||||
set((state) => {
|
||||
state.selectedElement = elementId;
|
||||
});
|
||||
},
|
||||
|
||||
// Block operations
|
||||
addBlock: () => {
|
||||
set((state) => {
|
||||
@@ -120,8 +137,8 @@ export const createSimulationDashboardStore = () => {
|
||||
removeBlock: (blockId) => {
|
||||
set((state) => {
|
||||
state.blocks = state.blocks.filter((block) => block.blockUuid !== blockId);
|
||||
if (state.selectedBlockId === blockId) {
|
||||
state.selectedBlockId = null;
|
||||
if (state.selectedBlock === blockId) {
|
||||
state.selectedBlock = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -138,8 +155,8 @@ export const createSimulationDashboardStore = () => {
|
||||
clearBlocks: () => {
|
||||
set((state) => {
|
||||
state.blocks = [];
|
||||
state.selectedBlockId = null;
|
||||
state.selectedElementId = null;
|
||||
state.selectedBlock = null;
|
||||
state.selectedElement = null;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -329,8 +346,8 @@ export const createSimulationDashboardStore = () => {
|
||||
const block = state.blocks.find((b) => b.blockUuid === blockId);
|
||||
if (block) {
|
||||
block.elements = block.elements.filter((el) => el.elementUuid !== elementId);
|
||||
if (state.selectedElementId === elementId) {
|
||||
state.selectedElementId = null;
|
||||
if (state.selectedElement === elementId) {
|
||||
state.selectedElement = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -461,23 +478,6 @@ export const createSimulationDashboardStore = () => {
|
||||
});
|
||||
},
|
||||
|
||||
// Selection and hover management
|
||||
setSelectedBlock: (blockId) => {
|
||||
set((state) => {
|
||||
state.selectedBlockId = blockId;
|
||||
// Clear element selection when selecting a block
|
||||
if (blockId) {
|
||||
state.selectedElementId = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setSelectedElement: (elementId) => {
|
||||
set((state) => {
|
||||
state.selectedElementId = elementId;
|
||||
});
|
||||
},
|
||||
|
||||
// Element swapping
|
||||
swapElements: (blockId, elementId1, elementId2) => {
|
||||
set((state) => {
|
||||
@@ -509,16 +509,16 @@ export const createSimulationDashboardStore = () => {
|
||||
},
|
||||
|
||||
getSelectedBlock: () => {
|
||||
const { selectedBlockId, blocks } = get();
|
||||
return selectedBlockId ? blocks.find((b) => b.blockUuid === selectedBlockId) : undefined;
|
||||
const { selectedBlock, blocks } = get();
|
||||
return selectedBlock ? blocks.find((b) => b.blockUuid === selectedBlock) : undefined;
|
||||
},
|
||||
|
||||
getSelectedElement: () => {
|
||||
const { selectedElementId, selectedBlockId, blocks } = get();
|
||||
if (!selectedElementId || !selectedBlockId) return undefined;
|
||||
const { selectedElement, selectedBlock, blocks } = get();
|
||||
if (!selectedElement || !selectedBlock) return undefined;
|
||||
|
||||
const block = blocks.find((b) => b.blockUuid === selectedBlockId);
|
||||
return block?.elements.find((el) => el.elementUuid === selectedElementId);
|
||||
const block = blocks.find((b) => b.blockUuid === selectedBlock);
|
||||
return block?.elements.find((el) => el.elementUuid === selectedElement);
|
||||
},
|
||||
|
||||
hasBlock: (blockId) => {
|
||||
|
||||
Reference in New Issue
Block a user