feat: Implement block and element removal functionality in DashboardEditor
- Added deleteDashBoardBlocksApi service to handle block deletion from the dashboard. - Integrated block removal functionality in DashboardEditor, allowing users to delete blocks. - Updated BlockEditor and ElementEditor components to include remove block and element handlers. - Enhanced Zustand store to manage block and element states effectively. - Updated exported types to accommodate new data structures for blocks and elements.
This commit is contained in:
@@ -18,6 +18,7 @@ import { handleBlockDragStart } from "./functions/block/handleBlockDragStart";
|
||||
|
||||
import { getDashBoardBlocksApi } from "../../services/visulization/dashBoard/getDashBoardBlocks";
|
||||
import { upsetDashBoardBlocksApi } from "../../services/visulization/dashBoard/upsertDashBoardBlocks";
|
||||
import { deleteDashBoardBlocksApi } from "../../services/visulization/dashBoard/deleteDashBoardBlocks";
|
||||
|
||||
const DashboardEditor: React.FC = () => {
|
||||
const { simulationDashBoardStore, versionStore } = useSceneContext();
|
||||
@@ -43,6 +44,9 @@ const DashboardEditor: React.FC = () => {
|
||||
updateGraphTitle,
|
||||
updateGraphType,
|
||||
swapElements,
|
||||
removeBlock,
|
||||
removeElement,
|
||||
getBlockById,
|
||||
subscribe,
|
||||
} = simulationDashBoardStore();
|
||||
|
||||
@@ -83,6 +87,7 @@ 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);
|
||||
}
|
||||
@@ -102,6 +107,7 @@ const DashboardEditor: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const unsubscribe = subscribe(() => {
|
||||
if (!projectId || !selectedVersion) return;
|
||||
console.log("blocks: ", blocks);
|
||||
updateBackend(blocks);
|
||||
});
|
||||
|
||||
@@ -374,6 +380,19 @@ const DashboardEditor: React.FC = () => {
|
||||
updateBlockPosition={(blockId, position) => updateBlockPosition(blockId, position)}
|
||||
updateBlockPositionType={(blockId, positionType) => updateBlockPositionType(blockId, positionType)}
|
||||
updateBlockZIndex={(blockId, zIndex) => updateBlockZIndex(blockId, zIndex)}
|
||||
handleRemoveBlock={(blockId) => {
|
||||
const block = getBlockById(blockId);
|
||||
if (!block) return;
|
||||
deleteDashBoardBlocksApi({ projectId: projectId!, versionId: selectedVersion!.versionId, blocks: [block] }).then((data) => {
|
||||
if (data.blocks.length>0) {
|
||||
data.blocks.forEach((updatedBlock: any) => {
|
||||
if (updatedBlock.message === "Block deleted successfully") {
|
||||
removeBlock(updatedBlock.blockUuid);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{selectedElement && editMode && selectedBlock && currentElement && (
|
||||
@@ -391,6 +410,7 @@ const DashboardEditor: React.FC = () => {
|
||||
updateGraphData={(blockId, elementId, newData) => updateGraphData(blockId, elementId, newData)}
|
||||
updateGraphTitle={(blockId, elementId, title) => updateGraphTitle(blockId, elementId, title)}
|
||||
updateGraphType={(blockId, elementId, type) => updateGraphType(blockId, elementId, type)}
|
||||
handleRemoveElement={(blockId, elementId) => removeElement(blockId, elementId)}
|
||||
setSwapSource={setSwapSource}
|
||||
setShowSwapUI={setShowSwapUI}
|
||||
dataModelManager={dataModelManager}
|
||||
|
||||
@@ -47,14 +47,14 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
|
||||
handleBlockDragStart,
|
||||
}) => {
|
||||
const { simulationDashBoardStore } = useSceneContext();
|
||||
const { addElement } = simulationDashBoardStore()
|
||||
const { addElement } = simulationDashBoardStore();
|
||||
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const minSize = calculateMinBlockSize(block);
|
||||
const isSelected = selectedBlock === block.blockUuid;
|
||||
const isDraggable = editMode && (block.positionType === "absolute" || block.positionType === "fixed");
|
||||
|
||||
|
||||
const handleMouseDown = (event: React.MouseEvent) => {
|
||||
if (isDraggable) {
|
||||
handleBlockDragStart(block.blockUuid, event);
|
||||
@@ -122,10 +122,11 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
|
||||
))}
|
||||
|
||||
{/* Block resize handle */}
|
||||
{editMode && isSelected &&
|
||||
{editMode && isSelected && (
|
||||
<div className="resize-handle" onMouseDown={(e) => handleBlockResizeStart(block.blockUuid, e)}>
|
||||
<ResizeIcon />
|
||||
</div>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Drag handle indicator for absolute/fixed blocks */}
|
||||
{isDraggable && editMode && (
|
||||
@@ -152,9 +153,6 @@ const BlockComponent: React.FC<BlockComponentProps> = ({
|
||||
⤣
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ interface BlockEditorProps {
|
||||
updateBlockPosition: (blockId: string, position: { x: number; y: number }) => void;
|
||||
updateBlockPositionType: (blockId: string, positionType: "relative" | "absolute" | "fixed") => void;
|
||||
updateBlockZIndex: (blockId: string, zIndex: number) => void;
|
||||
handleRemoveBlock: (blockId: string) => void;
|
||||
}
|
||||
|
||||
const BlockEditor: React.FC<BlockEditorProps> = ({
|
||||
@@ -29,12 +30,18 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
|
||||
updateBlockPosition,
|
||||
updateBlockPositionType,
|
||||
updateBlockZIndex,
|
||||
handleRemoveBlock,
|
||||
}) => {
|
||||
return (
|
||||
<div ref={blockEditorRef} className="panel block-editor-panel">
|
||||
<div className="header">
|
||||
<h4>Block Style</h4>
|
||||
<div className="delete icon">
|
||||
<div
|
||||
className="delete icon"
|
||||
onClick={() => {
|
||||
handleRemoveBlock(selectedBlock);
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,7 @@ interface ElementEditorProps {
|
||||
updateGraphData: (blockId: string, elementId: string, newData: GraphDataPoint[]) => void;
|
||||
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
|
||||
updateGraphType: (blockId: string, elementId: string, type: GraphTypes) => void;
|
||||
handleRemoveElement: (blockId: string, elementId: string) => void;
|
||||
setSwapSource: (source: string | null) => void;
|
||||
setShowSwapUI: (show: boolean) => void;
|
||||
dataModelManager: DataModelManager;
|
||||
@@ -37,6 +38,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
updateGraphData,
|
||||
updateGraphTitle,
|
||||
updateGraphType,
|
||||
handleRemoveElement,
|
||||
setSwapSource,
|
||||
setShowSwapUI,
|
||||
dataModelManager,
|
||||
@@ -52,10 +54,16 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
|
||||
return (
|
||||
<div ref={elementEditorRef} className="panel element-editor-panel">
|
||||
|
||||
<div className="header">
|
||||
<h4>Element Style</h4>
|
||||
<div className="delete icon"><DeleteIcon /></div>
|
||||
<div
|
||||
className="delete icon"
|
||||
onClick={() => {
|
||||
handleRemoveElement(selectedBlock, selectedElement);
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</div>
|
||||
</div>
|
||||
{currentElement.type === "label-value" && (
|
||||
<>
|
||||
@@ -352,11 +360,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
<>
|
||||
<div className="form-group">
|
||||
<label className="form-label">Chart Type: </label>
|
||||
<select
|
||||
value={currentElement.graphType || "line"}
|
||||
onChange={(e) => updateGraphType(selectedBlock, selectedElement, e.target.value as GraphTypes)}
|
||||
className="form-select"
|
||||
>
|
||||
<select value={currentElement.graphType || "line"} onChange={(e) => updateGraphType(selectedBlock, selectedElement, e.target.value as GraphTypes)} className="form-select">
|
||||
<option value="line">Line Chart</option>
|
||||
<option value="bar">Bar Chart</option>
|
||||
<option value="area">Area Chart</option>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Block } from "../../../types/exportedTypes";
|
||||
|
||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||
|
||||
export const deleteDashBoardBlocksApi = async ({ projectId, versionId, blocks }: { projectId: string; versionId: string; blocks: Block[] }) => {
|
||||
try {
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/V1/simulation/blocks`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
Authorization: "Bearer <access_token>",
|
||||
"Content-Type": "application/json",
|
||||
token: localStorage.getItem("token") || "",
|
||||
refresh_token: localStorage.getItem("refreshToken") || "",
|
||||
},
|
||||
body: JSON.stringify({ projectId, versionId, blocks }),
|
||||
});
|
||||
const newAccessToken = response.headers.get("x-access-token");
|
||||
if (newAccessToken) {
|
||||
localStorage.setItem("token", newAccessToken);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
echo.error("Failed to delete dashBoardBlocks");
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch {
|
||||
echo.error("Failed to delete dashBoardBlocks");
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,4 +27,33 @@ export type UIElement = {
|
||||
zIndex?: number;
|
||||
graphData?: GraphDataPoint[];
|
||||
size?: Size;
|
||||
};
|
||||
} & (
|
||||
| {
|
||||
type: "label-value";
|
||||
title: string;
|
||||
dataSource: string;
|
||||
dataValue: string;
|
||||
}
|
||||
| {
|
||||
type: "graph";
|
||||
dataType: "single-machine";
|
||||
title: string;
|
||||
dataSource: string;
|
||||
dataValue: string[];
|
||||
}
|
||||
| {
|
||||
type: "graph";
|
||||
dataType: "multiple-machine";
|
||||
title: string;
|
||||
dataSource: string[];
|
||||
commonValue: string;
|
||||
}
|
||||
| {
|
||||
type: Exclude<UIType, "label-value" | "graph">;
|
||||
title?: never;
|
||||
dataSource?: never;
|
||||
dataValue?: never;
|
||||
commonValue?: never;
|
||||
dataType?: never;
|
||||
}
|
||||
);
|
||||
|
||||
2
app/src/types/simulationDashboard.d.ts
vendored
2
app/src/types/simulationDashboard.d.ts
vendored
@@ -17,6 +17,8 @@ type DataModel = Record<string, DataModelValue>;
|
||||
|
||||
type UIType = "label-value" | "text" | "graph" | "icon";
|
||||
|
||||
type DataType = "single-machine" | "multiple-machine";
|
||||
|
||||
type Position = {
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
Reference in New Issue
Block a user