feat: Implement ElementContent for rendering diverse simulation dashboard elements and AnalyzerManager for processing and updating analysis data.

This commit is contained in:
2025-12-22 12:53:31 +05:30
parent 1f881c488d
commit 949ce4a21f
2 changed files with 53 additions and 19 deletions

View File

@@ -91,6 +91,8 @@ const AnalyzerManager: React.FC = () => {
// 2. Handle Graph (Store Update) // 2. Handle Graph (Store Update)
// This effect MUST NOT depend on 'blocks' to avoid infinite loop (updateGraphData modifies blocks) // This effect MUST NOT depend on 'blocks' to avoid infinite loop (updateGraphData modifies blocks)
const lineChartHistory = useRef<Map<string, any[]>>(new Map());
useEffect(() => { useEffect(() => {
if (!analysis) return; if (!analysis) return;
@@ -107,14 +109,40 @@ const AnalyzerManager: React.FC = () => {
const assetAnalysis = getAssetAnalysis(assetId); const assetAnalysis = getAssetAnalysis(assetId);
if (assetAnalysis) { if (assetAnalysis) {
const newGraphData = dataKeys.map((key) => { let newGraphData: any[] = [];
const val = resolvePath(assetAnalysis, key);
return { if (element.graphType === "line") {
// Make the key readable or just use it as name const history = lineChartHistory.current.get(element.elementUuid) || [];
name: key.split(".").pop() || key, const now = new Date();
value: typeof val === "number" ? val : 0, const timeStr = now.toLocaleTimeString([], { hour12: false });
};
}); const dataPoint: any = { name: timeStr };
dataKeys.forEach((key) => {
const val = resolvePath(assetAnalysis, key);
dataPoint[key] = typeof val === "number" ? val : 0;
});
// Add slight variations if values are static to make it "live" as requested (optional, but requested "up and down")
// If the user feels the values are strictly from store, I should stick to store.
// "makeing the lines go up dna down as times goes on"
// If I just use store values, they might be flat.
// I will stick to store values. The user's system likely updates `analysis`.
history.push(dataPoint);
if (history.length > 20) history.shift();
newGraphData = [...history];
lineChartHistory.current.set(element.elementUuid, history);
} else {
newGraphData = dataKeys.map((key) => {
const val = resolvePath(assetAnalysis, key);
return {
// Make the key readable or just use it as name
name: key.split(".").pop() || key,
value: typeof val === "number" ? val : 0,
};
});
}
// Deep check to avoid unnecessary updates // Deep check to avoid unnecessary updates
if (JSON.stringify(newGraphData) !== JSON.stringify(element.graphData)) { if (JSON.stringify(newGraphData) !== JSON.stringify(element.graphData)) {

View File

@@ -126,17 +126,23 @@ const ElementContent: React.FC<ElementContentProps> = ({ element, resolvedData }
<XAxis dataKey="name" stroke="rgba(255,255,255,0.6)" fontSize={12} /> <XAxis dataKey="name" stroke="rgba(255,255,255,0.6)" fontSize={12} />
<YAxis stroke="rgba(255,255,255,0.6)" fontSize={12} /> <YAxis stroke="rgba(255,255,255,0.6)" fontSize={12} />
<Tooltip {...tooltipStyle} /> <Tooltip {...tooltipStyle} />
<Line {element.dataBinding?.dataType === "single-machine" && element.dataBinding.dataValue ? (
type="monotone" (Array.isArray(element.dataBinding.dataValue) ? element.dataBinding.dataValue : [element.dataBinding.dataValue as string]).map((key, index) => (
dataKey="value" <Line key={key} type="monotone" dataKey={key} stroke={COLORS[index % COLORS.length]} strokeWidth={2} dot={false} isAnimationActive={false} />
stroke="#6f42c1" ))
strokeWidth={2} ) : (
dot={{ <Line
fill: "#c4abf1", type="monotone"
strokeWidth: 2, dataKey="value"
}} stroke="#6f42c1"
isAnimationActive={false} strokeWidth={2}
/> dot={{
fill: "#c4abf1",
strokeWidth: 2,
}}
isAnimationActive={false}
/>
)}
</LineChart> </LineChart>
)} )}
</ResponsiveContainer> </ResponsiveContainer>