feat: Update ElementEditor and DashboardEditor to enhance data handling and UI responsiveness
This commit is contained in:
@@ -620,7 +620,7 @@ const DashboardEditor: React.FC = () => {
|
||||
const updatedBlocks = peekRemoveElement(blockId, elementId);
|
||||
const updatedBlock = getBlockFromPeekedBlocks(updatedBlocks, blockId);
|
||||
if (updatedBlock) {
|
||||
await updateBackend(updatedBlock);
|
||||
// await updateBackend(updatedBlock);
|
||||
}
|
||||
}}
|
||||
setSwapSource={setSwapSource}
|
||||
|
||||
@@ -66,16 +66,9 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
const product = getProductById(selectedProduct.productUuid);
|
||||
const { getElementById } = simulationDashBoardStore();
|
||||
const element = getElementById(selectedBlock, selectedElement);
|
||||
console.log("element: ", element);
|
||||
const [selectType, setSelectType] = useState("design");
|
||||
const [selectDataMapping, setSelectDataMapping] = useState(element?.type === "graph" && element.dataType === "multiple-machine" ? "multipleMachine" : "singleMachine");
|
||||
|
||||
const [multipleFields, setMultipleFields] = useState<Array<{ id: string; label: string }>>([
|
||||
{ id: "common-value", label: "Common Value" },
|
||||
{ id: "data-source-1", label: "Data Source" },
|
||||
{ id: "data-source-2", label: "Data Source" },
|
||||
]);
|
||||
|
||||
// Get asset dropdown items from product
|
||||
const getAssetDropdownItems = useCallback(() => {
|
||||
if (!product?.eventDatas) return [];
|
||||
@@ -268,26 +261,6 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
[product]
|
||||
);
|
||||
|
||||
// Get value dropdown items for a specific asset
|
||||
const getValueDropdownItems = useCallback(
|
||||
(assetId: string | undefined) => {
|
||||
if (!product || !assetId || assetId === "global") return [];
|
||||
|
||||
const assetAnalysis = product?.eventDatas.find((e) => e.modelUuid === assetId);
|
||||
if (!assetAnalysis) return [];
|
||||
|
||||
// Return all available metrics for the asset
|
||||
return getLableValueDropdownItems(assetId).flatMap((section) =>
|
||||
section.items.map((item) => ({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
icon: item.icon,
|
||||
}))
|
||||
);
|
||||
},
|
||||
[product, getLableValueDropdownItems]
|
||||
);
|
||||
|
||||
// Get common value dropdown items (available across all assets)
|
||||
const getCommonValueDropdownItems = useCallback(() => {
|
||||
const commonItems = [
|
||||
@@ -319,7 +292,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
return dataValues.map((value, index) => ({
|
||||
id: `data-value-${index}`,
|
||||
label: `Data Value ${index + 1}`,
|
||||
showEyeDropper: true,
|
||||
showEyeDropper: false,
|
||||
options: valueOptions,
|
||||
}));
|
||||
}
|
||||
@@ -335,6 +308,44 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
];
|
||||
}, [element, getLableValueDropdownItems]);
|
||||
|
||||
const multipleSourceFields = useMemo(() => {
|
||||
if (element?.type === "graph" && element.dataType === "multiple-machine") {
|
||||
const dataSources = Array.isArray(element.dataSource) ? element.dataSource : [];
|
||||
|
||||
return dataSources.map((_, index) => ({
|
||||
id: `data-source-${index}`,
|
||||
label: `Data Source ${index + 1}`,
|
||||
showEyeDropper: true,
|
||||
options: getAssetDropdownItems().map((item) => ({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
})),
|
||||
}));
|
||||
}
|
||||
|
||||
return [];
|
||||
}, [element, getAssetDropdownItems]);
|
||||
|
||||
const multipleValueFields = useMemo(
|
||||
() => [{ id: "data-value", label: "Data Value", showEyeDropper: false, options: getCommonValueDropdownItems().map((item) => ({ id: item.id, label: item.label })) }],
|
||||
[getCommonValueDropdownItems]
|
||||
);
|
||||
|
||||
const handleDataTypeSwitch = (newDataType: "singleMachine" | "multipleMachine") => {
|
||||
if (!element || element.type !== "graph") return;
|
||||
|
||||
setSelectDataMapping(newDataType);
|
||||
|
||||
// Convert the element data type when switching
|
||||
if (newDataType === "singleMachine" && element.dataType === "multiple-machine") {
|
||||
// Convert from multiple-machine to single-machine
|
||||
updateDataType(selectedBlock, selectedElement, "single-machine");
|
||||
} else if (newDataType === "multipleMachine" && element.dataType === "single-machine") {
|
||||
// Convert from single-machine to multiple-machine
|
||||
updateDataType(selectedBlock, selectedElement, "multiple-machine");
|
||||
}
|
||||
};
|
||||
|
||||
const addField = () => {
|
||||
if (selectDataMapping === "singleMachine" && element?.type === "graph" && element.dataType === "single-machine") {
|
||||
// For single machine, add new data value field
|
||||
@@ -343,7 +354,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
|
||||
// Update the element's dataValue
|
||||
updateDataValue(selectedBlock, selectedElement, newDataValue);
|
||||
} else if (selectDataMapping === "multipleMachine" && element?.type === "graph") {
|
||||
} else if (selectDataMapping === "multipleMachine" && element?.type === "graph" && element.dataType === "multiple-machine") {
|
||||
// For multiple machine, add new data source field
|
||||
const currentDataSource = Array.isArray(element.dataSource) ? element.dataSource : [];
|
||||
const newDataSource = [...currentDataSource, ""]; // Add empty string for new field
|
||||
@@ -456,50 +467,46 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
<div className="heading">Data Mapping</div>
|
||||
|
||||
<div className="type-switch">
|
||||
<div className={`type ${selectDataMapping === "singleMachine" ? "active" : ""}`} onClick={() => setSelectDataMapping("singleMachine")}>
|
||||
<div className={`type ${selectDataMapping === "singleMachine" ? "active" : ""}`} onClick={() => handleDataTypeSwitch("singleMachine")}>
|
||||
Single Machine
|
||||
</div>
|
||||
<div className={`type ${selectDataMapping === "multipleMachine" ? "active" : ""}`} onClick={() => setSelectDataMapping("multipleMachine")}>
|
||||
<div className={`type ${selectDataMapping === "multipleMachine" ? "active" : ""}`} onClick={() => handleDataTypeSwitch("multipleMachine")}>
|
||||
Multiple Machine
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectDataMapping === "singleMachine" && element.dataType === "single-machine" && (
|
||||
<div className="fields-wrapper">
|
||||
<>
|
||||
{singleSourceFields.map((field) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={getEventByModelUuid(selectedProduct.productUuid, element.dataSource)?.modelName ?? ""}
|
||||
onSelect={(value) => {
|
||||
updateDataSource(selectedBlock, selectedElement, value.id);
|
||||
}}
|
||||
showEyeDropper={!!field.showEyeDropper}
|
||||
/>
|
||||
))}
|
||||
{singleValueFields.map((field, index) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={field.options.find((option) => option.id === element.dataValue?.[index])?.label ?? ""}
|
||||
onSelect={(value) => {
|
||||
// Get current dataValue array
|
||||
const currentDataValue = Array.isArray(element.dataValue) ? element.dataValue : [];
|
||||
{singleSourceFields.map((field) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={getEventByModelUuid(selectedProduct.productUuid, element.dataSource)?.modelName ?? ""}
|
||||
onSelect={(value) => {
|
||||
updateDataSource(selectedBlock, selectedElement, value.id);
|
||||
}}
|
||||
showEyeDropper={field.showEyeDropper}
|
||||
/>
|
||||
))}
|
||||
|
||||
// Create a new array with the updated value at the correct index
|
||||
const newDataValue = [...currentDataValue];
|
||||
newDataValue[index] = value.id;
|
||||
{singleValueFields.map((field, index) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={field.options.find((option) => option.id === element.dataValue?.[index])?.label ?? ""}
|
||||
onSelect={(value) => {
|
||||
const currentDataValue = Array.isArray(element.dataValue) ? element.dataValue : [];
|
||||
|
||||
// Update the entire array
|
||||
updateDataValue(selectedBlock, selectedElement, newDataValue);
|
||||
}}
|
||||
showEyeDropper={!!field.showEyeDropper}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
const newDataValue = [...currentDataValue];
|
||||
newDataValue[index] = value.id;
|
||||
|
||||
updateDataValue(selectedBlock, selectedElement, newDataValue);
|
||||
}}
|
||||
showEyeDropper={field.showEyeDropper}
|
||||
/>
|
||||
))}
|
||||
|
||||
<div className="add-field" onClick={addField}>
|
||||
<div className="icon">
|
||||
@@ -510,19 +517,37 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectDataMapping === "multipleMachine" && (
|
||||
{selectDataMapping === "multipleMachine" && element.dataType === "multiple-machine" && (
|
||||
<div className="fields-wrapper">
|
||||
{multipleFields.map((field) => (
|
||||
<div className="datas" key={field.id}>
|
||||
<div className="datas__class">
|
||||
<DataSourceSelector
|
||||
label={field.label}
|
||||
options={[{ id: "global", label: "Global" }]}
|
||||
onSelect={() => {}}
|
||||
showEyeDropper={field.label !== "Common Value"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{multipleValueFields.map((field) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={field.options.find((o) => o.id === element.commonValue)?.label ?? ""}
|
||||
onSelect={(value) => {
|
||||
updateCommonValue(selectedBlock, selectedElement, value.id);
|
||||
}}
|
||||
showEyeDropper={field.showEyeDropper}
|
||||
/>
|
||||
))}
|
||||
|
||||
{multipleSourceFields.map((field, index) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={getEventByModelUuid(selectedProduct.productUuid, element.dataSource?.[index])?.modelName ?? ""}
|
||||
onSelect={(value) => {
|
||||
const current = Array.isArray(element.dataSource) ? element.dataSource : [];
|
||||
|
||||
const next = [...current];
|
||||
next[index] = value.id;
|
||||
|
||||
updateDataSource(selectedBlock, selectedElement, next);
|
||||
}}
|
||||
showEyeDropper={field.showEyeDropper}
|
||||
/>
|
||||
))}
|
||||
|
||||
<div className="add-field" onClick={addField}>
|
||||
|
||||
@@ -301,7 +301,7 @@ export const createSimulationDashboardStore = () => {
|
||||
...baseGraphProps,
|
||||
dataType: "multiple-machine" as const,
|
||||
title: "Multi Machine Chart",
|
||||
dataSource: ["", "", ""],
|
||||
dataSource: [],
|
||||
commonValue: "",
|
||||
};
|
||||
} else {
|
||||
@@ -310,7 +310,7 @@ export const createSimulationDashboardStore = () => {
|
||||
dataType: "single-machine" as const,
|
||||
title: "Single Machine Chart",
|
||||
dataSource: "",
|
||||
dataValue: ["", "", ""],
|
||||
dataValue: [],
|
||||
};
|
||||
}
|
||||
break;
|
||||
@@ -668,7 +668,7 @@ export const createSimulationDashboardStore = () => {
|
||||
...baseGraphProps,
|
||||
dataType: "multiple-machine" as const,
|
||||
title: "Multi Machine Chart",
|
||||
dataSource: ["", "", ""],
|
||||
dataSource: [],
|
||||
commonValue: "",
|
||||
};
|
||||
} else {
|
||||
@@ -677,7 +677,7 @@ export const createSimulationDashboardStore = () => {
|
||||
dataType: "single-machine" as const,
|
||||
title: "Single Machine Chart",
|
||||
dataSource: "",
|
||||
dataValue: ["", "", ""],
|
||||
dataValue: [],
|
||||
};
|
||||
}
|
||||
break;
|
||||
@@ -853,13 +853,39 @@ export const createSimulationDashboardStore = () => {
|
||||
|
||||
peekUpdateDataType: (blockId, elementId, dataType) => {
|
||||
const blocks = cloneBlocks(get().blocks);
|
||||
|
||||
const block = blocks.find((b) => b.blockUuid === blockId);
|
||||
if (block) {
|
||||
const element = block.elements.find((el) => el.elementUuid === elementId);
|
||||
if (element && element.type === "graph") {
|
||||
element.dataType = dataType;
|
||||
}
|
||||
if (!block) return blocks;
|
||||
|
||||
const index = block.elements.findIndex((el) => el.elementUuid === elementId);
|
||||
if (index === -1) return blocks;
|
||||
|
||||
const element = block.elements[index];
|
||||
if (element.type !== "graph" || element.dataType === dataType) return blocks;
|
||||
|
||||
let newElement: UIElement;
|
||||
|
||||
if (dataType === "single-machine") {
|
||||
const { commonValue, ...rest } = element as Extract<UIElement, { type: "graph"; dataType: "multiple-machine" }>;
|
||||
|
||||
newElement = {
|
||||
...rest,
|
||||
dataType: "single-machine",
|
||||
dataSource: "",
|
||||
dataValue: [],
|
||||
};
|
||||
} else {
|
||||
const { dataValue, ...rest } = element as Extract<UIElement, { type: "graph"; dataType: "single-machine" }>;
|
||||
|
||||
newElement = {
|
||||
...rest,
|
||||
dataType: "multiple-machine",
|
||||
dataSource: [],
|
||||
commonValue: "",
|
||||
};
|
||||
}
|
||||
|
||||
block.elements[index] = newElement;
|
||||
return blocks;
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user