feat: Refactor ElementEditor and DataSourceSelector for improved data handling and UI integration

This commit is contained in:
2025-12-17 17:02:45 +05:30
parent 4a0c39faa3
commit d014b3f87e
5 changed files with 381 additions and 284 deletions

View File

@@ -225,7 +225,7 @@ const DashboardEditor: React.FC = () => {
}
};
document.addEventListener("mousedown", handleClickOutside);
// document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};

View File

@@ -0,0 +1,262 @@
import React, { RefObject } from "react";
import DataSourceSelector from "../../../ui/inputs/DataSourceSelector";
import RenameInput from "../../../ui/inputs/RenameInput";
import { AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, FlexColumnIcon, FlexRowIcon, FlexRowReverseIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import InputRange from "../../../ui/inputs/InputRange";
import { getAlphaFromRgba, hexToRgba, rgbaToHex } from "../../functions/helpers/colorHandlers";
import { ExtendedCSSProperties, UIElement } from "../../../../types/exportedTypes";
import { getCurrentElementStyleValue } from "../../functions/helpers/getCurrentElementStyleValue";
interface ElementDesignProps {
element: UIElement | undefined;
elementEditorRef: RefObject<HTMLDivElement>;
currentElement: UIElement;
selectedBlock: string;
selectedElement: string;
updateElementStyle: (blockId: string, elementId: string, style: ExtendedCSSProperties) => void;
updateElementSize: (blockId: string, elementId: string, 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;
updateElementData: (blockId: string, elementId: string, updates: Partial<DataBinding>) => void;
updateGraphData: (blockId: string, elementId: string, newData: GraphDataPoint[]) => void;
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
updateGraphType: (blockId: string, elementId: string, type: GraphTypes) => void;
updateDataType: (blockId: string, elementId: string, dataType: "single-machine" | "multiple-machine") => void;
updateCommonValue: (blockId: string, elementId: string, commonValue: string) => void;
updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void;
updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void;
handleRemoveElement: (blockId: string, elementId: string) => void;
setSwapSource: (source: string | null) => void;
setShowSwapUI: (show: boolean) => void;
}
const ElementDesign: React.FC<ElementDesignProps> = ({
element,
elementEditorRef,
currentElement,
selectedBlock,
selectedElement,
updateElementStyle,
updateElementSize,
updateElementPosition,
updateElementPositionType,
updateElementZIndex,
updateElementData,
updateGraphData,
updateGraphTitle,
updateGraphType,
updateDataType,
updateCommonValue,
updateDataValue,
updateDataSource,
handleRemoveElement,
setSwapSource,
setShowSwapUI,
}) => {
return (
<div>
{element?.type === "graph" && (
<div className="design-section">
<DataSourceSelector
label={"Chart Type"}
options={[
{ id: "line", label: "Line Chart" },
{ id: "bar", label: "Bar Chart" },
{ id: "pie", label: "Pie Chart" },
{ id: "area", label: "Area Chart" },
{ id: "radar", label: "Radar Chart" },
]}
onSelect={(newValue) => {
updateGraphType(selectedBlock, selectedElement, newValue.id as GraphTypes);
}}
showEyeDropper={false}
/>
</div>
)}
<div className="design-section">
<div className="section-header">Position</div>
<div className="select-type">
{["relative", "absolute"].map((position) => (
<div
key={position}
className={`type ${currentElement.positionType === position ? "active" : ""}`}
onClick={() => updateElementPositionType(selectedBlock, selectedElement, position as "relative" | "absolute" | "fixed")}
>
{position.charAt(0).toUpperCase() + position.slice(1)}
</div>
))}
</div>
<div className="position-canvas">
<div className="canvas">
<div className="value padding-top">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
<div className="value padding-right">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
<div className="value padding-bottom">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
<div className="value padding-left">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
</div>
</div>
<div className="alignments-section">
<div className="section">
<div
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "right" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { textAlign: "right" })}
>
<AlignRightIcon />
</div>
<div
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "justify" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { textAlign: "justify" })}
>
<AlignJustifyIcon />
</div>
<div
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "left" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { textAlign: "left" })}
>
<AlignLeftIcon />
</div>
</div>
<div className="section">
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "row" })}
>
<FlexRowIcon />
</div>
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "column" })}
>
<FlexColumnIcon />
</div>
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row-reverse" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "row-reverse" })}
>
<FlexRowReverseIcon />
</div>
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column-reverse" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "column-reverse" })}
>
<FlexRowReverseIcon />
</div>
</div>
</div>
<div className="design-section-footer">
<InputWithDropDown
label="Layer"
value={String(currentElement.zIndex || 1)}
placeholder={"Layer"}
onChange={(newValue: string) => updateElementZIndex(selectedBlock, selectedElement, Number(newValue))}
/>
<InputRange
label={"Blur"}
min={0}
max={40}
value={parseInt(getCurrentElementStyleValue(currentElement, "backdropFilter")?.match(/\d+/)?.[0] || "0")}
onChange={(value: number) => updateElementStyle(selectedBlock, selectedElement, { backdropFilter: `blur(${Number(value)}px)` })}
/>
<InputRange
label={"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 appearance">
<div className="section-header">Appearance</div>
<div className="design-datas-wrapper">
<InputWithDropDown
label="X-Position"
value={String(currentElement.position?.x ?? 0)}
placeholder={"X"}
onChange={(newValue: string) => {
updateElementPosition(selectedBlock, selectedElement, {
...(currentElement.position || { x: 0, y: 0 }),
x: Number(newValue),
});
}}
/>
<InputWithDropDown
label="Y-Position"
value={String(currentElement.position?.y ?? 0)}
placeholder={"Y"}
onChange={(newValue: string) => {
updateElementPosition(selectedBlock, selectedElement, {
...(currentElement.position || { x: 0, y: 0 }),
y: Number(newValue),
});
}}
/>
<InputWithDropDown
label="Width"
value={String(currentElement.size?.width ?? (currentElement.type === "graph" ? 400 : 200))}
placeholder={"Width"}
onChange={(newValue: string) => {
updateElementSize(selectedBlock, selectedElement, {
...(currentElement.size || { width: 0, height: 0 }),
width: Number(newValue),
});
}}
/>
<InputWithDropDown
label="Height"
value={String(currentElement.size?.height ?? (currentElement.type === "graph" ? 200 : 60))}
placeholder={"Height"}
onChange={(newValue: string) => {
updateElementSize(selectedBlock, selectedElement, {
...(currentElement.size || { width: 0, height: 0 }),
height: Number(newValue),
});
}}
/>
</div>
</div>
<div className="design-section element-color">
<div className="section-header">Element Color</div>
<div className="data-picker">
<div className="label">Color</div>
<div className="left">
<input
type="color"
value={rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "rgba(50,50,50,1)")}
onChange={(e) => {
const currentBg = getCurrentElementStyleValue(currentElement, "backgroundColor") || "rgba(50,50,50,1)";
const currentAlpha = getAlphaFromRgba(currentBg);
const newBg = hexToRgba(e.target.value, currentAlpha);
updateElementStyle(selectedBlock, selectedElement, { backgroundColor: newBg });
}}
/>
<div className="colorValue">{rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "rgba(50,50,50,1)")}</div>
</div>
</div>
</div>
<div className="footer">Swap with Another Element</div>
</div>
);
};
export default ElementDesign;

View File

@@ -1,4 +1,4 @@
import { useCallback, useState, type RefObject } from "react";
import { useCallback, useEffect, useMemo, useState, type RefObject } from "react";
import { ExtendedCSSProperties, UIElement } from "../../../../types/exportedTypes";
import { getCurrentElementStyleValue } from "../../functions/helpers/getCurrentElementStyleValue";
import type { DataModelManager } from "../../data/dataModel";
@@ -11,6 +11,7 @@ import { AddIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, DeviceIcon, F
import { getAlphaFromRgba, rgbaToHex, hexToRgba } from "../../functions/helpers/colorHandlers";
import DataDetailedDropdown from "../../../ui/inputs/DataDetailedDropdown";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import ElementDesign from "./ElementDesign";
interface ElementEditorProps {
elementEditorRef: RefObject<HTMLDivElement>;
@@ -65,14 +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("singleMachine");
const [singleFields, setSingleFields] = useState<Array<{ id: string; label: string; showEyeDropper?: boolean }>>([
{ id: "data-source", label: "Data Source", showEyeDropper: true },
{ id: "input-1", label: "Input 1", showEyeDropper: false },
{ id: "input-2", label: "Input 2", showEyeDropper: false },
]);
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" },
@@ -306,26 +302,55 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
return commonItems;
}, []);
const addField = () => {
if (selectDataMapping === "singleMachine") {
setSingleFields((prev) => [
...prev,
{
id: `input-${Date.now()}`,
label: `Input ${prev.filter((f) => f.label.startsWith("Input")).length + 1}`,
showEyeDropper: false,
},
]);
return;
const singleSourceFields = useMemo(
() => [{ id: "data-source", label: "Data Source", showEyeDropper: true, options: getAssetDropdownItems().map((item) => ({ id: item.id, label: item.label })) }],
[getAssetDropdownItems]
);
const singleValueFields = useMemo(() => {
if (element?.type === "graph" && element.dataType === "single-machine") {
// Get the dataValue array - ensure it's always an array
const dataValues = Array.isArray(element.dataValue) ? element.dataValue : [];
// Generate dropdown options based on the selected data source
const valueOptions = element.dataSource ? getLableValueDropdownItems(element.dataSource).flatMap((section) => section.items.map((item) => ({ id: item.id, label: item.label }))) : [];
// Create fields based on the number of data values in the element
return dataValues.map((value, index) => ({
id: `data-value-${index}`,
label: `Data Value ${index + 1}`,
showEyeDropper: true,
options: valueOptions,
}));
}
setMultipleFields((prev) => [
...prev,
// Return default field if not a graph with single-machine data type
return [
{
id: `data-${Date.now()}`,
label: "Data Source",
id: "data-value",
label: "Data Value",
showEyeDropper: false,
options: [],
},
]);
];
}, [element, getLableValueDropdownItems]);
const addField = () => {
if (selectDataMapping === "singleMachine" && element?.type === "graph" && element.dataType === "single-machine") {
// For single machine, add new data value field
const currentDataValue = Array.isArray(element.dataValue) ? element.dataValue : [];
const newDataValue = [...currentDataValue, ""]; // Add empty string for new field
// Update the element's dataValue
updateDataValue(selectedBlock, selectedElement, newDataValue);
} else if (selectDataMapping === "multipleMachine" && element?.type === "graph") {
// 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
// Update the element's dataSource
updateDataSource(selectedBlock, selectedElement, newDataSource);
}
};
return (
@@ -354,227 +379,35 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
)}
{selectType === "design" && (
<>
{element?.type === "graph" && (
<div className="design-section">
<DataSourceSelector
label={"Chart Type"}
options={[
{ id: "line", label: "Line Chart" },
{ id: "bar", label: "Bar Chart" },
{ id: "pie", label: "Pie Chart" },
{ id: "area", label: "Area Chart" },
{ id: "radar", label: "Radar Chart" },
]}
onSelect={(newValue) => {
if (newValue === "Line Chart") {
updateGraphType(selectedBlock, selectedElement, "line");
return;
} else if (newValue === "Bar Chart") {
updateGraphType(selectedBlock, selectedElement, "bar");
return;
} else if (newValue === "Pie Chart") {
updateGraphType(selectedBlock, selectedElement, "pie");
return;
} else if (newValue === "Area Chart") {
updateGraphType(selectedBlock, selectedElement, "area");
return;
} else if (newValue === "Radar Chart") {
updateGraphType(selectedBlock, selectedElement, "radar");
return;
}
}}
showEyeDropper={false}
/>
</div>
)}
<div className="design-section">
<div className="section-header">Position</div>
<div className="select-type">
{["relative", "absolute"].map((position) => (
<div
key={position}
className={`type ${currentElement.positionType === position ? "active" : ""}`}
onClick={() => updateElementPositionType(selectedBlock, selectedElement, position as "relative" | "absolute" | "fixed")}
>
{position.charAt(0).toUpperCase() + position.slice(1)}
</div>
))}
</div>
<div className="position-canvas">
<div className="canvas">
<div className="value padding-top">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
<div className="value padding-right">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
<div className="value padding-bottom">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
<div className="value padding-left">
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
</div>
</div>
</div>
<div className="alignments-section">
<div className="section">
<div
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "right" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { textAlign: "right" })}
>
<AlignRightIcon />
</div>
<div
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "justify" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { textAlign: "justify" })}
>
<AlignJustifyIcon />
</div>
<div
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "left" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { textAlign: "left" })}
>
<AlignLeftIcon />
</div>
</div>
<div className="section">
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "row" })}
>
<FlexRowIcon />
</div>
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "column" })}
>
<FlexColumnIcon />
</div>
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row-reverse" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "row-reverse" })}
>
<FlexRowReverseIcon />
</div>
<div
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column-reverse" ? "active" : ""}`}
onClick={() => updateElementStyle(selectedBlock, selectedElement, { flexDirection: "column-reverse" })}
>
<FlexRowReverseIcon />
</div>
</div>
</div>
<div className="design-section-footer">
<InputWithDropDown
label="Layer"
value={String(currentElement.zIndex || 1)}
placeholder={"Layer"}
onChange={(newValue: string) => updateElementZIndex(selectedBlock, selectedElement, Number(newValue))}
/>
<InputRange
label={"Blur"}
min={0}
max={40}
value={parseInt(getCurrentElementStyleValue(currentElement, "backdropFilter")?.match(/\d+/)?.[0] || "0")}
onChange={(value: number) => updateElementStyle(selectedBlock, selectedElement, { backdropFilter: `blur(${Number(value)}px)` })}
/>
<InputRange
label={"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 appearance">
<div className="section-header">Appearance</div>
<div className="design-datas-wrapper">
<InputWithDropDown
label="X-Position"
value={String(currentElement.position?.x ?? 0)}
placeholder={"X"}
onChange={(newValue: string) => {
updateElementPosition(selectedBlock, selectedElement, {
...(currentElement.position || { x: 0, y: 0 }),
x: Number(newValue),
});
}}
/>
<InputWithDropDown
label="Y-Position"
value={String(currentElement.position?.y ?? 0)}
placeholder={"Y"}
onChange={(newValue: string) => {
updateElementPosition(selectedBlock, selectedElement, {
...(currentElement.position || { x: 0, y: 0 }),
y: Number(newValue),
});
}}
/>
<InputWithDropDown
label="Width"
value={String(currentElement.size?.width ?? (currentElement.type === "graph" ? 400 : 200))}
placeholder={"Width"}
onChange={(newValue: string) => {
updateElementSize(selectedBlock, selectedElement, {
...(currentElement.size || { width: 0, height: 0 }),
width: Number(newValue),
});
}}
/>
<InputWithDropDown
label="Height"
value={String(currentElement.size?.height ?? (currentElement.type === "graph" ? 200 : 60))}
placeholder={"Height"}
onChange={(newValue: string) => {
updateElementSize(selectedBlock, selectedElement, {
...(currentElement.size || { width: 0, height: 0 }),
height: Number(newValue),
});
}}
/>
</div>
</div>
<div className="design-section element-color">
<div className="section-header">Element Color</div>
<div className="data-picker">
<div className="label">Color</div>
<div className="left">
<input
type="color"
value={rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "rgba(50,50,50,1)")}
onChange={(e) => {
const currentBg = getCurrentElementStyleValue(currentElement, "backgroundColor") || "rgba(50,50,50,1)";
const currentAlpha = getAlphaFromRgba(currentBg);
const newBg = hexToRgba(e.target.value, currentAlpha);
updateElementStyle(selectedBlock, selectedElement, { backgroundColor: newBg });
}}
/>
<div className="colorValue">{rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "rgba(50,50,50,1)")}</div>
</div>
</div>
</div>
<div className="footer">Swap with Another Element</div>
</>
<ElementDesign
element={element}
elementEditorRef={elementEditorRef}
currentElement={currentElement}
selectedBlock={selectedBlock}
selectedElement={selectedElement}
updateElementStyle={updateElementStyle}
updateElementSize={updateElementSize}
updateElementPosition={updateElementPosition}
updateElementPositionType={updateElementPositionType}
updateElementZIndex={updateElementZIndex}
updateElementData={updateElementData}
updateGraphData={updateGraphData}
updateGraphTitle={updateGraphTitle}
updateGraphType={updateGraphType}
updateDataType={updateDataType}
updateCommonValue={updateCommonValue}
updateDataValue={updateDataValue}
updateDataSource={updateDataSource}
handleRemoveElement={handleRemoveElement}
setSwapSource={setSwapSource}
setShowSwapUI={setShowSwapUI}
/>
)}
{selectType === "data" && (
<div className="data-details">
{element?.type === "label-value" && (
<div className="data-wrapper">
<InputWithDropDown label="Title" value={`title`} placeholder={"Label 1"} min={0.1} step={0.1} max={2} onChange={() => { }} />
<InputWithDropDown label="Title" value={`title`} placeholder={"Label 1"} min={0.1} step={0.1} max={2} onChange={() => {}} />
<div className="data">
<DataDetailedDropdown
title="Data Source"
@@ -626,23 +459,47 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
<div className={`type ${selectDataMapping === "singleMachine" ? "active" : ""}`} onClick={() => setSelectDataMapping("singleMachine")}>
Single Machine
</div>
<div className={`type ${selectDataMapping === "multipleeMachine" ? "active" : ""}`} onClick={() => setSelectDataMapping("multipleeMachine")}>
<div className={`type ${selectDataMapping === "multipleMachine" ? "active" : ""}`} onClick={() => setSelectDataMapping("multipleMachine")}>
Multiple Machine
</div>
</div>
{selectDataMapping === "singleMachine" && (
{selectDataMapping === "singleMachine" && element.dataType === "single-machine" && (
<div className="fields-wrapper">
{singleFields.map((field) => (
<DataSourceSelector
key={field.id}
label={field.label}
options={[
{ id: "global", label: "Global" }
]}
onSelect={() => { }} showEyeDropper={!!field.showEyeDropper}
/>
))}
<>
{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 : [];
// Create a new array with the updated value at the correct index
const newDataValue = [...currentDataValue];
newDataValue[index] = value.id;
// Update the entire array
updateDataValue(selectedBlock, selectedElement, newDataValue);
}}
showEyeDropper={!!field.showEyeDropper}
/>
))}
</>
<div className="add-field" onClick={addField}>
<div className="icon">
@@ -653,17 +510,15 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
</div>
)}
{selectDataMapping === "multipleeMachine" && (
{selectDataMapping === "multipleMachine" && (
<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={() => { }}
options={[{ id: "global", label: "Global" }]}
onSelect={() => {}}
showEyeDropper={field.label !== "Common Value"}
/>
</div>

View File

@@ -1,5 +1,4 @@
import React, { useState } from "react";
import RegularDropDown from "./RegularDropDown";
import { EyeDroperIcon } from "../../icons/ExportCommonIcons";
import RegularDropDownID from "./RegularDropDownID";
@@ -10,18 +9,12 @@ type DataSourceSelectorProps = {
label: string;
}[];
selected?: string;
onSelect: (value: string) => void;
onSelect: (value: { id: string; label: string }) => void;
eyeDropperActive?: boolean; // initial state
showEyeDropper?: boolean;
};
const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({
label = "Data Source",
options,
selected,
onSelect,
showEyeDropper = true,
}) => {
const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({ label = "Data Source", options, selected, onSelect, showEyeDropper = true }) => {
// Local state to toggle EyeDropper
const [isEyeActive, setIsEyeActive] = useState(false);
@@ -30,19 +23,10 @@ const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({
<div className="datas__label">{label}</div>
<div className="datas__class">
<RegularDropDownID
header={selected || "Select value"}
options={options}
onSelect={onSelect}
search={false}
/>
<RegularDropDownID header={selected || "Select value"} options={options} onSelect={onSelect} search={false} />
{showEyeDropper && (
<div
className={`icon ${isEyeActive ? "active" : ""}`}
onClick={() => setIsEyeActive(!isEyeActive)}
style={{ cursor: "pointer" }}
>
<div className={`icon ${isEyeActive ? "active" : ""}`} onClick={() => setIsEyeActive(!isEyeActive)} style={{ cursor: "pointer" }}>
{/* Pass the local state here */}
<EyeDroperIcon isActive={isEyeActive} />
</div>
@@ -53,7 +37,3 @@ const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({
};
export default DataSourceSelector;

View File

@@ -9,7 +9,7 @@ interface DropdownOption {
interface DropdownProps {
header: string;
options: DropdownOption[];
onSelect: (optionId: string) => void;
onSelect: (value: DropdownOption) => void;
search?: boolean;
onClick?: () => void;
onChange?: () => void;
@@ -63,7 +63,7 @@ const RegularDropDownID: React.FC<DropdownProps> = ({
const handleOptionClick = (opt: DropdownOption) => {
setSelectedOption(opt.label);
onSelect(opt.id);
onSelect(opt);
setIsOpen(false);
};