Merge remote-tracking branch 'origin/main-dev' into main-demo
This commit is contained in:
@@ -59,7 +59,6 @@ const DashboardEditor: React.FC = () => {
|
|||||||
peekUpdateCommonValue,
|
peekUpdateCommonValue,
|
||||||
peekUpdateDataValue,
|
peekUpdateDataValue,
|
||||||
peekUpdateDataSource,
|
peekUpdateDataSource,
|
||||||
|
|
||||||
} = simulationDashBoardStore();
|
} = simulationDashBoardStore();
|
||||||
|
|
||||||
const [editMode, setEditMode] = useState(false);
|
const [editMode, setEditMode] = useState(false);
|
||||||
@@ -209,6 +208,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
const elementToDrag = document.querySelector(`[data-element-id="${draggingElement}"]`) as HTMLElement;
|
const elementToDrag = document.querySelector(`[data-element-id="${draggingElement}"]`) as HTMLElement;
|
||||||
|
|
||||||
if (blockElement && elementToDrag) {
|
if (blockElement && elementToDrag) {
|
||||||
|
// Disable transitions during drag
|
||||||
|
elementToDrag.classList.add("no-transition");
|
||||||
|
|
||||||
const blockRect = blockElement.getBoundingClientRect();
|
const blockRect = blockElement.getBoundingClientRect();
|
||||||
const elementRect = elementToDrag.getBoundingClientRect();
|
const elementRect = elementToDrag.getBoundingClientRect();
|
||||||
const newX = e.clientX - blockRect.left - elementDragOffset.x;
|
const newX = e.clientX - blockRect.left - elementDragOffset.x;
|
||||||
@@ -233,6 +235,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
const blockToDrag = document.querySelector(`[data-block-id="${draggingBlock}"]`) as HTMLElement;
|
const blockToDrag = document.querySelector(`[data-block-id="${draggingBlock}"]`) as HTMLElement;
|
||||||
|
|
||||||
if (editorElement && blockToDrag) {
|
if (editorElement && blockToDrag) {
|
||||||
|
// Disable transitions during drag
|
||||||
|
blockToDrag.classList.add("no-transition");
|
||||||
|
|
||||||
const editorRect = editorElement.getBoundingClientRect();
|
const editorRect = editorElement.getBoundingClientRect();
|
||||||
const newX = e.clientX - editorRect.left - blockDragOffset.x;
|
const newX = e.clientX - editorRect.left - blockDragOffset.x;
|
||||||
const newY = e.clientY - editorRect.top - blockDragOffset.y;
|
const newY = e.clientY - editorRect.top - blockDragOffset.y;
|
||||||
@@ -248,6 +253,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
if (resizingElement && selectedBlock) {
|
if (resizingElement && selectedBlock) {
|
||||||
const elementToResize = document.querySelector(`[data-element-id="${resizingElement}"]`) as HTMLElement;
|
const elementToResize = document.querySelector(`[data-element-id="${resizingElement}"]`) as HTMLElement;
|
||||||
if (elementToResize) {
|
if (elementToResize) {
|
||||||
|
// Disable transitions during resize
|
||||||
|
elementToResize.classList.add("no-transition");
|
||||||
|
|
||||||
const deltaX = e.clientX - resizeStart.x;
|
const deltaX = e.clientX - resizeStart.x;
|
||||||
const deltaY = e.clientY - resizeStart.y;
|
const deltaY = e.clientY - resizeStart.y;
|
||||||
|
|
||||||
@@ -280,6 +288,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
} else if (resizingBlock) {
|
} else if (resizingBlock) {
|
||||||
const blockToResize = document.querySelector(`[data-block-id="${resizingBlock}"]`) as HTMLElement;
|
const blockToResize = document.querySelector(`[data-block-id="${resizingBlock}"]`) as HTMLElement;
|
||||||
if (blockToResize) {
|
if (blockToResize) {
|
||||||
|
// Disable transitions during resize
|
||||||
|
blockToResize.classList.add("no-transition");
|
||||||
|
|
||||||
const deltaX = e.clientX - resizeStart.x;
|
const deltaX = e.clientX - resizeStart.x;
|
||||||
const deltaY = e.clientY - resizeStart.y;
|
const deltaY = e.clientY - resizeStart.y;
|
||||||
|
|
||||||
@@ -328,6 +339,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
const elementToDrag = document.querySelector(`[data-element-id="${draggingElement}"]`) as HTMLElement;
|
const elementToDrag = document.querySelector(`[data-element-id="${draggingElement}"]`) as HTMLElement;
|
||||||
|
|
||||||
if (blockElement && elementToDrag) {
|
if (blockElement && elementToDrag) {
|
||||||
|
// Re-enable transitions
|
||||||
|
elementToDrag.classList.remove("no-transition");
|
||||||
|
|
||||||
const computedStyle = window.getComputedStyle(elementToDrag);
|
const computedStyle = window.getComputedStyle(elementToDrag);
|
||||||
const x = parseFloat(computedStyle.left);
|
const x = parseFloat(computedStyle.left);
|
||||||
const y = parseFloat(computedStyle.top);
|
const y = parseFloat(computedStyle.top);
|
||||||
@@ -341,6 +355,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
const blockToDrag = document.querySelector(`[data-block-id="${draggingBlock}"]`) as HTMLElement;
|
const blockToDrag = document.querySelector(`[data-block-id="${draggingBlock}"]`) as HTMLElement;
|
||||||
|
|
||||||
if (blockToDrag) {
|
if (blockToDrag) {
|
||||||
|
// Re-enable transitions
|
||||||
|
blockToDrag.classList.remove("no-transition");
|
||||||
|
|
||||||
const computedStyle = window.getComputedStyle(blockToDrag);
|
const computedStyle = window.getComputedStyle(blockToDrag);
|
||||||
const x = parseFloat(computedStyle.left);
|
const x = parseFloat(computedStyle.left);
|
||||||
const y = parseFloat(computedStyle.top);
|
const y = parseFloat(computedStyle.top);
|
||||||
@@ -355,6 +372,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
const blockElement = document.querySelector(`[data-block-id="${selectedBlock}"]`) as HTMLElement;
|
const blockElement = document.querySelector(`[data-block-id="${selectedBlock}"]`) as HTMLElement;
|
||||||
|
|
||||||
if (elementToResize && blockElement) {
|
if (elementToResize && blockElement) {
|
||||||
|
// Re-enable transitions
|
||||||
|
elementToResize.classList.remove("no-transition");
|
||||||
|
|
||||||
const computedStyle = window.getComputedStyle(elementToResize);
|
const computedStyle = window.getComputedStyle(elementToResize);
|
||||||
const width = parseFloat(computedStyle.width);
|
const width = parseFloat(computedStyle.width);
|
||||||
const height = parseFloat(computedStyle.height);
|
const height = parseFloat(computedStyle.height);
|
||||||
@@ -367,6 +387,9 @@ const DashboardEditor: React.FC = () => {
|
|||||||
// Update backend for block resize
|
// Update backend for block resize
|
||||||
const blockToResize = document.querySelector(`[data-block-id="${resizingBlock}"]`) as HTMLElement;
|
const blockToResize = document.querySelector(`[data-block-id="${resizingBlock}"]`) as HTMLElement;
|
||||||
if (blockToResize) {
|
if (blockToResize) {
|
||||||
|
// Re-enable transitions
|
||||||
|
blockToResize.classList.remove("no-transition");
|
||||||
|
|
||||||
const computedStyle = window.getComputedStyle(blockToResize);
|
const computedStyle = window.getComputedStyle(blockToResize);
|
||||||
const width = parseFloat(computedStyle.width);
|
const width = parseFloat(computedStyle.width);
|
||||||
const height = parseFloat(computedStyle.height);
|
const height = parseFloat(computedStyle.height);
|
||||||
@@ -638,7 +661,6 @@ const DashboardEditor: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,24 +14,10 @@ interface ElementComponentProps {
|
|||||||
handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void;
|
handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ElementComponent: React.FC<ElementComponentProps> = ({
|
const ElementComponent: React.FC<ElementComponentProps> = ({ element, blockId, editMode, selectedElement, handleElementClick, handleElementDragStart, handleElementResizeStart }) => {
|
||||||
element,
|
|
||||||
blockId,
|
|
||||||
editMode,
|
|
||||||
selectedElement,
|
|
||||||
handleElementClick,
|
|
||||||
handleElementDragStart,
|
|
||||||
handleElementResizeStart,
|
|
||||||
}) => {
|
|
||||||
const isSelected = selectedElement === element.elementUuid;
|
const isSelected = selectedElement === element.elementUuid;
|
||||||
|
|
||||||
const elementClasses = [
|
const elementClasses = ["element", element.positionType === "absolute" ? "absolute" : "", element.type === "graph" ? "graph" : "", editMode ? "edit-mode" : "", isSelected ? "selected" : ""]
|
||||||
"element",
|
|
||||||
element.positionType === "absolute" ? "absolute" : "",
|
|
||||||
element.type === "graph" ? "graph" : "",
|
|
||||||
editMode ? "edit-mode" : "",
|
|
||||||
isSelected ? "selected" : "",
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
@@ -43,8 +29,7 @@ const ElementComponent: React.FC<ElementComponentProps> = ({
|
|||||||
style={{
|
style={{
|
||||||
...element.style,
|
...element.style,
|
||||||
position: element.positionType || "relative",
|
position: element.positionType || "relative",
|
||||||
left:
|
left: element.positionType === "absolute" ? `${element.position?.x || 0}px` : "auto",
|
||||||
element.positionType === "absolute" ? `${element.position?.x || 0}px` : "auto",
|
|
||||||
top: element.positionType === "absolute" ? `${element.position?.y || 0}px` : "auto",
|
top: element.positionType === "absolute" ? `${element.position?.y || 0}px` : "auto",
|
||||||
width: element.size?.width || "auto",
|
width: element.size?.width || "auto",
|
||||||
height: element.size?.height || "auto",
|
height: element.size?.height || "auto",
|
||||||
@@ -55,16 +40,18 @@ const ElementComponent: React.FC<ElementComponentProps> = ({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleElementClick(blockId, element.elementUuid, e);
|
handleElementClick(blockId, element.elementUuid, e);
|
||||||
}}
|
}}
|
||||||
onMouseDown={(e) => handleElementDragStart(element.elementUuid, e)}
|
onMouseDown={(e) => {
|
||||||
|
// Only allow dragging for absolute positioned elements
|
||||||
|
if (element.positionType === "absolute") {
|
||||||
|
handleElementDragStart(element.elementUuid, e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ElementContent element={element} resolvedData={resolveElementValue(element)} />
|
<ElementContent element={element} resolvedData={resolveElementValue(element)} />
|
||||||
|
|
||||||
{editMode && (
|
{editMode && isSelected && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div className="resize-handle" onMouseDown={(e) => handleElementResizeStart(element.elementUuid, e)}>
|
||||||
className="resize-handle"
|
|
||||||
onMouseDown={(e) => handleElementResizeStart(element.elementUuid, e)}
|
|
||||||
>
|
|
||||||
<ResizeIcon />
|
<ResizeIcon />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
import React, { RefObject, useEffect, useState } from "react";
|
import React, { RefObject, useEffect, useState } from "react";
|
||||||
import DataSourceSelector from "../../../ui/inputs/DataSourceSelector";
|
import DataSourceSelector from "../../../ui/inputs/DataSourceSelector";
|
||||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
import {
|
import { AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, ArrowIcon, FlexColumnIcon, FlexRowIcon, FlexRowReverseIcon } from "../../../icons/ExportCommonIcons";
|
||||||
AlignJustifyIcon,
|
|
||||||
AlignLeftIcon,
|
|
||||||
AlignRightIcon,
|
|
||||||
ArrowIcon,
|
|
||||||
FlexColumnIcon,
|
|
||||||
FlexRowIcon,
|
|
||||||
FlexRowReverseIcon,
|
|
||||||
} from "../../../icons/ExportCommonIcons";
|
|
||||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import InputRange from "../../../ui/inputs/InputRange";
|
import InputRange from "../../../ui/inputs/InputRange";
|
||||||
import { getAlphaFromRgba, hexToRgba, rgbaToHex } from "../../functions/helpers/colorHandlers";
|
import { getAlphaFromRgba, hexToRgba, rgbaToHex } from "../../functions/helpers/colorHandlers";
|
||||||
@@ -25,35 +17,15 @@ interface ElementDesignProps {
|
|||||||
selectedBlock: string;
|
selectedBlock: string;
|
||||||
selectedElement: string;
|
selectedElement: string;
|
||||||
updateElementStyle: (blockId: string, elementId: string, style: ExtendedCSSProperties) => void;
|
updateElementStyle: (blockId: string, elementId: string, style: ExtendedCSSProperties) => void;
|
||||||
updateElementSize: (
|
updateElementSize: (blockId: string, elementId: string, size: { width: number; height: number }) => void;
|
||||||
blockId: string,
|
updateElementPosition: (blockId: string, elementId: string, position: { x: number; y: number }) => void;
|
||||||
elementId: string,
|
updateElementPositionType: (blockId: string, elementId: string, positionType: "relative" | "absolute" | "fixed") => void;
|
||||||
size: { width: number; height: number }
|
|
||||||
) => void;
|
|
||||||
updateElementPosition: (
|
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
position: { x: number; y: number }
|
|
||||||
) => void;
|
|
||||||
updateElementPositionType: (
|
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
positionType: "relative" | "absolute" | "fixed"
|
|
||||||
) => void;
|
|
||||||
updateElementZIndex: (blockId: string, elementId: string, zIndex: number) => void;
|
updateElementZIndex: (blockId: string, elementId: string, zIndex: number) => void;
|
||||||
updateElementData: (
|
updateElementData: (blockId: string, elementId: string, updates: Partial<ElementDataBinding>) => void;
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
updates: Partial<ElementDataBinding>
|
|
||||||
) => void;
|
|
||||||
updateGraphData: (blockId: string, elementId: string, newData: GraphDataPoint[]) => void;
|
updateGraphData: (blockId: string, elementId: string, newData: GraphDataPoint[]) => void;
|
||||||
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
|
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
|
||||||
updateGraphType: (blockId: string, elementId: string, type: GraphTypes) => void;
|
updateGraphType: (blockId: string, elementId: string, type: GraphTypes) => void;
|
||||||
updateDataType: (
|
updateDataType: (blockId: string, elementId: string, dataType: "single-machine" | "multiple-machine") => void;
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
dataType: "single-machine" | "multiple-machine"
|
|
||||||
) => void;
|
|
||||||
updateCommonValue: (blockId: string, elementId: string, commonValue: string) => void;
|
updateCommonValue: (blockId: string, elementId: string, commonValue: string) => void;
|
||||||
updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void;
|
updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void;
|
||||||
updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void;
|
updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void;
|
||||||
@@ -77,9 +49,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
const [color, setColor] = useState("#000000");
|
const [color, setColor] = useState("#000000");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setColor(
|
setColor(rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "#000000"));
|
||||||
rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "#000000")
|
|
||||||
);
|
|
||||||
}, [currentElement]);
|
}, [currentElement]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -96,11 +66,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
{ id: "radar", label: "Radar Chart" },
|
{ id: "radar", label: "Radar Chart" },
|
||||||
]}
|
]}
|
||||||
onSelect={(newValue) => {
|
onSelect={(newValue) => {
|
||||||
updateGraphType(
|
updateGraphType(selectedBlock, selectedElement, newValue.id as GraphTypes);
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
newValue.id as GraphTypes
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
showEyeDropper={false}
|
showEyeDropper={false}
|
||||||
/>
|
/>
|
||||||
@@ -113,15 +79,8 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
{["relative", "absolute"].map((position) => (
|
{["relative", "absolute"].map((position) => (
|
||||||
<div
|
<div
|
||||||
key={position}
|
key={position}
|
||||||
className={`type ${currentElement.positionType === position ? "active" : ""
|
className={`type ${currentElement.positionType === position ? "active" : ""}`}
|
||||||
}`}
|
onClick={() => updateElementPositionType(selectedBlock, selectedElement, position as "relative" | "absolute" | "fixed")}
|
||||||
onClick={() =>
|
|
||||||
updateElementPositionType(
|
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
position as "relative" | "absolute" | "fixed"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{position.charAt(0).toUpperCase() + position.slice(1)}
|
{position.charAt(0).toUpperCase() + position.slice(1)}
|
||||||
</div>
|
</div>
|
||||||
@@ -130,48 +89,16 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<div className="position-canvas">
|
<div className="position-canvas">
|
||||||
<div className="canvas">
|
<div className="canvas">
|
||||||
<div className="value padding-top">
|
<div className="value padding-top">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="value padding-right">
|
<div className="value padding-right">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="value padding-bottom">
|
<div className="value padding-bottom">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="value padding-left">
|
<div className="value padding-left">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -179,10 +106,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<div className="alignments-section">
|
<div className="alignments-section">
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div
|
<div
|
||||||
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "right"
|
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "right" ? "active" : ""}`}
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
@@ -192,11 +116,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<AlignRightIcon />
|
<AlignRightIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") ===
|
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "justify" ? "active" : ""}`}
|
||||||
"justify"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
textAlign: "justify",
|
textAlign: "justify",
|
||||||
@@ -206,10 +126,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<AlignJustifyIcon />
|
<AlignJustifyIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "left"
|
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "left" ? "active" : ""}`}
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
@@ -221,10 +138,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row"
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row" ? "active" : ""}`}
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
@@ -234,11 +148,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<FlexRowIcon />
|
<FlexRowIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") ===
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column" ? "active" : ""}`}
|
||||||
"column"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
@@ -248,11 +158,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<FlexColumnIcon />
|
<FlexColumnIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") ===
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row-reverse" ? "active" : ""}`}
|
||||||
"row-reverse"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "row-reverse",
|
flexDirection: "row-reverse",
|
||||||
@@ -262,11 +168,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<FlexRowReverseIcon />
|
<FlexRowReverseIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") ===
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column-reverse" ? "active" : ""}`}
|
||||||
"column-reverse"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "column-reverse",
|
flexDirection: "column-reverse",
|
||||||
@@ -283,22 +185,12 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
label="Layer"
|
label="Layer"
|
||||||
value={String(currentElement.zIndex || 1)}
|
value={String(currentElement.zIndex || 1)}
|
||||||
placeholder={"Layer"}
|
placeholder={"Layer"}
|
||||||
onChange={(newValue: string) =>
|
onChange={(newValue: string) => updateElementZIndex(selectedBlock, selectedElement, Number(newValue))}
|
||||||
updateElementZIndex(
|
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
Number(newValue)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="increase-z"
|
className="increase-z"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
updateElementZIndex(
|
updateElementZIndex(selectedBlock, selectedElement, Number(currentElement.zIndex ? currentElement.zIndex + 1 : 1));
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
Number(currentElement.zIndex ? currentElement.zIndex + 1 : 1)
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
@@ -306,11 +198,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<button
|
<button
|
||||||
className="decrease-z"
|
className="decrease-z"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
updateElementZIndex(
|
updateElementZIndex(selectedBlock, selectedElement, Number(currentElement.zIndex ? currentElement.zIndex - 1 : 1));
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
Number(currentElement.zIndex ? currentElement.zIndex - 1 : 1)
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
@@ -354,10 +242,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
/>
|
/>
|
||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
label="Width"
|
label="Width"
|
||||||
value={String(
|
value={String(currentElement.size?.width ?? (currentElement.type === "graph" ? 400 : 200))}
|
||||||
currentElement.size?.width ??
|
|
||||||
(currentElement.type === "graph" ? 400 : 200)
|
|
||||||
)}
|
|
||||||
placeholder={"Width"}
|
placeholder={"Width"}
|
||||||
onChange={(newValue: string) => {
|
onChange={(newValue: string) => {
|
||||||
updateElementSize(selectedBlock, selectedElement, {
|
updateElementSize(selectedBlock, selectedElement, {
|
||||||
@@ -368,10 +253,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
/>
|
/>
|
||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
label="Height"
|
label="Height"
|
||||||
value={String(
|
value={String(currentElement.size?.height ?? (currentElement.type === "graph" ? 200 : 60))}
|
||||||
currentElement.size?.height ??
|
|
||||||
(currentElement.type === "graph" ? 200 : 60)
|
|
||||||
)}
|
|
||||||
placeholder={"Height"}
|
placeholder={"Height"}
|
||||||
onChange={(newValue: string) => {
|
onChange={(newValue: string) => {
|
||||||
updateElementSize(selectedBlock, selectedElement, {
|
updateElementSize(selectedBlock, selectedElement, {
|
||||||
@@ -381,6 +263,17 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<InputRange
|
||||||
|
label={"Border Radius"}
|
||||||
|
min={0}
|
||||||
|
max={8}
|
||||||
|
value={parseInt(getCurrentElementStyleValue(currentElement, "borderRadius") || "") || 8}
|
||||||
|
onChange={(newValue: number) => {
|
||||||
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
|
borderRadius: Number(newValue),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="design-section element-color">
|
<div className="design-section element-color">
|
||||||
|
|||||||
@@ -187,6 +187,9 @@ function Analyzer() {
|
|||||||
// Track previous actions for ArmBots to detect cycle completion
|
// Track previous actions for ArmBots to detect cycle completion
|
||||||
const previousArmBotActionsRef = useRef<Record<string, string | undefined>>({});
|
const previousArmBotActionsRef = useRef<Record<string, string | undefined>>({});
|
||||||
|
|
||||||
|
// Track previous actions for Machines to detect cycle completion
|
||||||
|
const previousMachineActionsRef = useRef<Record<string, string | undefined>>({});
|
||||||
|
|
||||||
// Track previous action counts for Humans to detect completion from EventManager
|
// Track previous action counts for Humans to detect completion from EventManager
|
||||||
const previousHumanCountsRef = useRef<Record<string, Record<string, number>>>({});
|
const previousHumanCountsRef = useRef<Record<string, Record<string, number>>>({});
|
||||||
|
|
||||||
@@ -228,6 +231,7 @@ function Analyzer() {
|
|||||||
bottleneckEventsRef.current = {};
|
bottleneckEventsRef.current = {};
|
||||||
previousAssetStatesRef.current = {};
|
previousAssetStatesRef.current = {};
|
||||||
previousArmBotActionsRef.current = {};
|
previousArmBotActionsRef.current = {};
|
||||||
|
previousMachineActionsRef.current = {};
|
||||||
previousHumanCountsRef.current = {};
|
previousHumanCountsRef.current = {};
|
||||||
previousVehiclePhasesRef.current = {};
|
previousVehiclePhasesRef.current = {};
|
||||||
previousCranePhasesRef.current = {};
|
previousCranePhasesRef.current = {};
|
||||||
@@ -278,7 +282,7 @@ function Analyzer() {
|
|||||||
|
|
||||||
const calculateQualityMetrics = (assetId: string, totalOperations: number, defects: number, historicalData: any[] = []) => {
|
const calculateQualityMetrics = (assetId: string, totalOperations: number, defects: number, historicalData: any[] = []) => {
|
||||||
const errorCount = errorCountsRef.current[assetId] || 0;
|
const errorCount = errorCountsRef.current[assetId] || 0;
|
||||||
const firstPassYield = totalOperations > 0 ? ((totalOperations - defects) / totalOperations) * 100 : 100;
|
const firstPassYield = totalOperations > 0 ? ((totalOperations - defects) / totalOperations) * 100 : 0;
|
||||||
const defectRate = totalOperations > 0 ? (defects / totalOperations) * 100 : 0;
|
const defectRate = totalOperations > 0 ? (defects / totalOperations) * 100 : 0;
|
||||||
const scrapRate = defects > 0 ? defects * 0.1 : 0; // Assuming 10% scrap rate
|
const scrapRate = defects > 0 ? defects * 0.1 : 0; // Assuming 10% scrap rate
|
||||||
const reworkRate = defects > 0 ? defects * 0.9 : 0; // Assuming 90% rework
|
const reworkRate = defects > 0 ? defects * 0.9 : 0; // Assuming 90% rework
|
||||||
@@ -1722,8 +1726,8 @@ function Analyzer() {
|
|||||||
|
|
||||||
// Success rates
|
// Success rates
|
||||||
const liftAttempts = totalLifts + errorCount;
|
const liftAttempts = totalLifts + errorCount;
|
||||||
const liftSuccessRate = liftAttempts > 0 ? (totalLifts / liftAttempts) * 100 : 100;
|
const liftSuccessRate = liftAttempts > 0 ? (totalLifts / liftAttempts) * 100 : 0;
|
||||||
const positioningAccuracy = liftSuccessRate * 0.98; // Slightly lower than success rate
|
const positioningAccuracy = totalLifts > 0 ? liftSuccessRate * 1.0 : 0; // Slightly lower than success rate
|
||||||
|
|
||||||
// Load utilization
|
// Load utilization
|
||||||
const maxPickUpCount = crane.point?.actions?.[0]?.maxPickUpCount || 1;
|
const maxPickUpCount = crane.point?.actions?.[0]?.maxPickUpCount || 1;
|
||||||
@@ -2395,6 +2399,33 @@ function Analyzer() {
|
|||||||
});
|
});
|
||||||
}, [armBots, isPlaying]);
|
}, [armBots, isPlaying]);
|
||||||
|
|
||||||
|
// Monitor Machine action changes to track cycles
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return;
|
||||||
|
|
||||||
|
machines.forEach((machine) => {
|
||||||
|
const previousActionUuid = previousMachineActionsRef.current[machine.modelUuid];
|
||||||
|
const currentActionUuid = machine.currentAction?.actionUuid;
|
||||||
|
|
||||||
|
// Check if action completed (transition from an action to no action or different action)
|
||||||
|
if (previousActionUuid && previousActionUuid !== currentActionUuid) {
|
||||||
|
// Action completed - increment cycles
|
||||||
|
if (!completedActionsRef.current[machine.modelUuid]) {
|
||||||
|
completedActionsRef.current[machine.modelUuid] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[machine.modelUuid]++;
|
||||||
|
|
||||||
|
// Also update parts processed (assume 1 part per cycle)
|
||||||
|
if (!completedActionsRef.current[`${machine.modelUuid}_parts`]) {
|
||||||
|
completedActionsRef.current[`${machine.modelUuid}_parts`] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[`${machine.modelUuid}_parts`]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
previousMachineActionsRef.current[machine.modelUuid] = currentActionUuid;
|
||||||
|
});
|
||||||
|
}, [machines, isPlaying]);
|
||||||
|
|
||||||
// Monitor Human action changes from EventManager
|
// Monitor Human action changes from EventManager
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying || !humanEventManagerRef.current) return;
|
if (!isPlaying || !humanEventManagerRef.current) return;
|
||||||
@@ -2499,22 +2530,6 @@ function Analyzer() {
|
|||||||
const previousPhase = previousCranePhasesRef.current[crane.modelUuid];
|
const previousPhase = previousCranePhasesRef.current[crane.modelUuid];
|
||||||
const currentPhase = crane.currentPhase;
|
const currentPhase = crane.currentPhase;
|
||||||
|
|
||||||
// Check for transition from 'pickup-drop' to 'init' (Cycle completed)
|
|
||||||
if (previousPhase === "pickup-drop" && currentPhase === "init") {
|
|
||||||
// Increment cycles completed
|
|
||||||
if (!completedActionsRef.current[crane.modelUuid]) {
|
|
||||||
completedActionsRef.current[crane.modelUuid] = 0;
|
|
||||||
}
|
|
||||||
completedActionsRef.current[crane.modelUuid]++;
|
|
||||||
|
|
||||||
// Track loads handled (number of materials carried in this cycle)
|
|
||||||
const loadsInCycle = crane.currentMaterials?.length || 1;
|
|
||||||
if (!completedActionsRef.current[`${crane.modelUuid}_loads`]) {
|
|
||||||
completedActionsRef.current[`${crane.modelUuid}_loads`] = 0;
|
|
||||||
}
|
|
||||||
completedActionsRef.current[`${crane.modelUuid}_loads`] += loadsInCycle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track lifts (picking phase indicates a lift operation)
|
// Track lifts (picking phase indicates a lift operation)
|
||||||
if (previousPhase !== "picking" && currentPhase === "picking") {
|
if (previousPhase !== "picking" && currentPhase === "picking") {
|
||||||
if (!completedActionsRef.current[`${crane.modelUuid}_lifts`]) {
|
if (!completedActionsRef.current[`${crane.modelUuid}_lifts`]) {
|
||||||
@@ -2528,6 +2543,21 @@ function Analyzer() {
|
|||||||
completedActionsRef.current[`${crane.modelUuid}_lift_height`] = 0;
|
completedActionsRef.current[`${crane.modelUuid}_lift_height`] = 0;
|
||||||
}
|
}
|
||||||
completedActionsRef.current[`${crane.modelUuid}_lift_height`] += 5;
|
completedActionsRef.current[`${crane.modelUuid}_lift_height`] += 5;
|
||||||
|
|
||||||
|
// Track loads handled when picking (each pick is a load)
|
||||||
|
if (!completedActionsRef.current[`${crane.modelUuid}_loads`]) {
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_loads`] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_loads`]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track cycles completed when dropping is done (transition from 'dropping' to any other phase)
|
||||||
|
if (previousPhase === "dropping" && currentPhase !== "dropping") {
|
||||||
|
// Increment cycles completed
|
||||||
|
if (!completedActionsRef.current[crane.modelUuid]) {
|
||||||
|
completedActionsRef.current[crane.modelUuid] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[crane.modelUuid]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
previousCranePhasesRef.current[crane.modelUuid] = currentPhase;
|
previousCranePhasesRef.current[crane.modelUuid] = currentPhase;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function Simulation() {
|
|||||||
const { analysis } = analysisStore();
|
const { analysis } = analysisStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("analysis: ", analysis);
|
// console.log("analysis: ", analysis);
|
||||||
}, [analysis]);
|
}, [analysis]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
|
// Utility class to disable transitions during drag/resize
|
||||||
|
.no-transition,
|
||||||
|
.no-transition * {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
*> {
|
*> {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { useSceneContext } from "../../modules/scene/sceneContext";
|
|||||||
const KeyPressListener: React.FC = () => {
|
const KeyPressListener: React.FC = () => {
|
||||||
const { comparisonScene, clearComparisonState } = useSimulationState();
|
const { comparisonScene, clearComparisonState } = useSimulationState();
|
||||||
const { activeModule, setActiveModule } = useModuleStore();
|
const { activeModule, setActiveModule } = useModuleStore();
|
||||||
const { assetStore, versionStore } = useSceneContext();
|
const { assetStore, versionStore, simulationDashBoardStore } = useSceneContext();
|
||||||
const { selectedAssets } = assetStore();
|
const { selectedAssets } = assetStore();
|
||||||
const { setSubModule } = useSubModuleStore();
|
const { setSubModule } = useSubModuleStore();
|
||||||
const { setActiveSubTool } = useActiveSubTool();
|
const { setActiveSubTool } = useActiveSubTool();
|
||||||
@@ -46,6 +46,7 @@ const KeyPressListener: React.FC = () => {
|
|||||||
const { setSelectedComment } = useSelectedComment();
|
const { setSelectedComment } = useSelectedComment();
|
||||||
const { setDfxUploaded } = useDfxUpload();
|
const { setDfxUploaded } = useDfxUpload();
|
||||||
const isTextInput = (element: Element | null): boolean => element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element?.getAttribute("contenteditable") === "true";
|
const isTextInput = (element: Element | null): boolean => element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element?.getAttribute("contenteditable") === "true";
|
||||||
|
const { setSelectedBlock, setSelectedElement } = simulationDashBoardStore();
|
||||||
|
|
||||||
const handleModuleSwitch = (keyCombination: string) => {
|
const handleModuleSwitch = (keyCombination: string) => {
|
||||||
const modules: Record<string, string> = {
|
const modules: Record<string, string> = {
|
||||||
@@ -189,6 +190,8 @@ const KeyPressListener: React.FC = () => {
|
|||||||
setIsRenameMode(false);
|
setIsRenameMode(false);
|
||||||
setDfxUploaded([]);
|
setDfxUploaded([]);
|
||||||
setSelectedComment(null);
|
setSelectedComment(null);
|
||||||
|
setSelectedBlock(null);
|
||||||
|
setSelectedElement(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keyCombination || ["F5", "F11", "F12"].includes(event.key) || keyCombination === "Ctrl+R") return;
|
if (!keyCombination || ["F5", "F11", "F12"].includes(event.key) || keyCombination === "Ctrl+R") return;
|
||||||
|
|||||||
Reference in New Issue
Block a user