From 651a5ce92b1c5ea7227733a1f60ba78f7babcc8d Mon Sep 17 00:00:00 2001
From: Nicole Rappe <nicole.rappe@bunny-lab.io>
Date: Fri, 30 May 2025 05:03:32 -0600
Subject: [PATCH] Upgraded Array Index Extractor Node

---
 .../Node_Array_Index_Extractor.jsx            | 237 +++++++++---------
 1 file changed, 118 insertions(+), 119 deletions(-)

diff --git a/Data/Server/WebUI/src/nodes/Data Analysis & Manipulation/Node_Array_Index_Extractor.jsx b/Data/Server/WebUI/src/nodes/Data Analysis & Manipulation/Node_Array_Index_Extractor.jsx
index b8fc366..0ff675d 100644
--- a/Data/Server/WebUI/src/nodes/Data Analysis & Manipulation/Node_Array_Index_Extractor.jsx	
+++ b/Data/Server/WebUI/src/nodes/Data Analysis & Manipulation/Node_Array_Index_Extractor.jsx	
@@ -1,143 +1,142 @@
-////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: Node_Array_Index_Extractor.jsx
-
 import React, { useEffect, useRef, useState } from "react";
 import { Handle, Position, useReactFlow, useStore } from "reactflow";
 
+// Ensure Borealis shared memory exists
 if (!window.BorealisValueBus) window.BorealisValueBus = {};
 if (!window.BorealisUpdateRate) window.BorealisUpdateRate = 100;
 
 const ArrayIndexExtractorNode = ({ id, data }) => {
-    const edges = useStore((state) => state.edges);
-    const { setNodes } = useReactFlow();
+  const edges = useStore((state) => state.edges);
+  const { setNodes } = useReactFlow();
+  const [result, setResult] = useState("Line Does Not Exist");
+  const valueRef = useRef(result);
 
-    const [lineNumber, setLineNumber] = useState(data?.lineNumber || 1);
-    const [result, setResult] = useState("Line Does Not Exist");
+  // Use config field, always 1-based for UX, fallback to 1
+  const lineNumber = parseInt(data?.lineNumber, 10) || 1;
 
-    const valueRef = useRef(result);
+  useEffect(() => {
+    let intervalId = null;
+    let currentRate = window.BorealisUpdateRate;
 
-    const handleLineNumberChange = (e) => {
-        const num = parseInt(e.target.value, 10);
-        const clamped = isNaN(num) ? 1 : Math.max(1, num);
-        setLineNumber(clamped);
+    const runNodeLogic = () => {
+      const inputEdge = edges.find((e) => e.target === id);
+      if (!inputEdge) {
+        valueRef.current = "Line Does Not Exist";
+        setResult("Line Does Not Exist");
+        window.BorealisValueBus[id] = "Line Does Not Exist";
+        return;
+      }
 
-        setNodes((nds) =>
-            nds.map((n) =>
-                n.id === id ? { ...n, data: { ...n.data, lineNumber: clamped } } : n
-            )
-        );
+      const upstreamValue = window.BorealisValueBus[inputEdge.source];
+      if (!Array.isArray(upstreamValue)) {
+        valueRef.current = "Line Does Not Exist";
+        setResult("Line Does Not Exist");
+        window.BorealisValueBus[id] = "Line Does Not Exist";
+        return;
+      }
+
+      const index = Math.max(0, lineNumber - 1); // 1-based to 0-based
+      const selected = upstreamValue[index] ?? "Line Does Not Exist";
+
+      if (selected !== valueRef.current) {
+        valueRef.current = selected;
+        setResult(selected);
+        window.BorealisValueBus[id] = selected;
+      }
     };
 
-    useEffect(() => {
-        let intervalId = null;
-        let currentRate = window.BorealisUpdateRate;
-
-        const runNodeLogic = () => {
-            const inputEdge = edges.find((e) => e.target === id);
-            if (!inputEdge) {
-                valueRef.current = "Line Does Not Exist";
-                setResult("Line Does Not Exist");
-                window.BorealisValueBus[id] = "Line Does Not Exist";
-                return;
-            }
-
-            const upstreamValue = window.BorealisValueBus[inputEdge.source];
-            if (!Array.isArray(upstreamValue)) {
-                valueRef.current = "Line Does Not Exist";
-                setResult("Line Does Not Exist");
-                window.BorealisValueBus[id] = "Line Does Not Exist";
-                return;
-            }
-
-            const index = Math.max(0, lineNumber - 1); // Convert 1-based input to 0-based
-            const selected = upstreamValue[index] ?? "Line Does Not Exist";
-
-            if (selected !== valueRef.current) {
-                valueRef.current = selected;
-                setResult(selected);
-                window.BorealisValueBus[id] = selected;
-            }
-        };
+    intervalId = setInterval(runNodeLogic, currentRate);
 
+    // Monitor update rate live
+    const monitor = setInterval(() => {
+      const newRate = window.BorealisUpdateRate;
+      if (newRate !== currentRate) {
+        clearInterval(intervalId);
+        currentRate = newRate;
         intervalId = setInterval(runNodeLogic, currentRate);
+      }
+    }, 300);
 
-        const monitor = setInterval(() => {
-            const newRate = window.BorealisUpdateRate;
-            if (newRate !== currentRate) {
-                clearInterval(intervalId);
-                currentRate = newRate;
-                intervalId = setInterval(runNodeLogic, currentRate);
-            }
-        }, 300);
+    return () => {
+      clearInterval(intervalId);
+      clearInterval(monitor);
+    };
+  }, [id, edges, lineNumber]);
 
-        return () => {
-            clearInterval(intervalId);
-            clearInterval(monitor);
-        };
-    }, [id, edges, lineNumber]);
-
-    return (
-        <div className="borealis-node">
-            <Handle type="target" position={Position.Left} className="borealis-handle" />
-            <div className="borealis-node-header">Array Index Extractor</div>
-            <div className="borealis-node-content" style={{ fontSize: "9px" }}>
-                <div style={{ marginBottom: "6px", color: "#ccc" }}>
-                    Output a Specific Array Index's Value
-                </div>
-
-                <label style={{ display: "block", marginBottom: "2px" }}>
-                    Line Number (1 = First Line):
-                </label>
-                <input
-                    type="number"
-                    min="1"
-                    step="1"
-                    value={lineNumber}
-                    onChange={handleLineNumberChange}
-                    style={{
-                        width: "100%",
-                        fontSize: "9px",
-                        background: "#1e1e1e",
-                        color: "#ccc",
-                        border: "1px solid #444",
-                        borderRadius: "2px",
-                        padding: "3px",
-                        marginBottom: "6px"
-                    }}
-                />
-
-                <label style={{ display: "block", marginBottom: "2px" }}>
-                    Output:
-                </label>
-                <input
-                    type="text"
-                    value={result}
-                    disabled
-                    style={{
-                        width: "100%",
-                        fontSize: "9px",
-                        background: "#2a2a2a",
-                        color: "#ccc",
-                        border: "1px solid #444",
-                        borderRadius: "2px",
-                        padding: "3px"
-                    }}
-                />
-            </div>
-            <Handle type="source" position={Position.Right} className="borealis-handle" />
+  return (
+    <div className="borealis-node">
+      <Handle type="target" position={Position.Left} className="borealis-handle" />
+      <div className="borealis-node-header">
+        {data?.label || "Array Index Extractor"}
+      </div>
+      <div className="borealis-node-content" style={{ fontSize: "9px" }}>
+        <div style={{ marginBottom: "6px", color: "#ccc" }}>
+          Output a specific line from an upstream array.
         </div>
-    );
+        <div style={{ color: "#888", marginBottom: 4 }}>
+          Line Number: <b>{lineNumber}</b>
+        </div>
+        <label style={{ display: "block", marginBottom: "2px" }}>Output:</label>
+        <input
+          type="text"
+          value={result}
+          disabled
+          style={{
+            width: "100%",
+            fontSize: "9px",
+            background: "#2a2a2a",
+            color: "#ccc",
+            border: "1px solid #444",
+            borderRadius: "2px",
+            padding: "3px"
+          }}
+        />
+      </div>
+      <Handle type="source" position={Position.Right} className="borealis-handle" />
+    </div>
+  );
 };
 
+// ---- Node Registration Object with Sidebar Config & Markdown Docs ----
 export default {
-    type: "ArrayIndexExtractor",
-    label: "Array Index Extractor",
-    description: `
-Outputs a specific line from an upstream array (e.g., OCR multi-line output).
+  type: "ArrayIndexExtractor",
+  label: "Array Index Extractor",
+  description: `
+Outputs a specific line from an upstream array, such as the result of OCR multi-line extraction.
 
-- User specifies the line number (1-based index)
-- Outputs the value from that line if it exists
-- If the index is out of bounds, outputs "Line Does Not Exist"
+- Specify the **line number** (1 = first line)
+- Outputs the value at that index if present
+- If index is out of bounds, outputs "Line Does Not Exist"
 `.trim(),
-    content: "Output a Specific Array Index's Value",
-    component: ArrayIndexExtractorNode
+  content: "Output a Specific Array Index's Value",
+  component: ArrayIndexExtractorNode,
+  config: [
+    {
+      key: "lineNumber",
+      label: "Line Number (1 = First Line)",
+      type: "text",
+      defaultValue: "1"
+    }
+  ],
+  usage_documentation: `
+### Array Index Extractor Node
+
+This node allows you to extract a specific line or item from an upstream array value.
+
+**Typical Use:**
+- Used after OCR or any node that outputs an array of lines or items.
+- Set the **Line Number** (1-based, so "1" = first line).
+
+**Behavior:**
+- If the line exists, outputs the value at that position.
+- If not, outputs: \`Line Does Not Exist\`.
+
+**Input:**
+- Connect an upstream node that outputs an array (such as OCR Text Extraction).
+
+**Sidebar Config:**
+- Set the desired line number from the configuration sidebar for live updates.
+
+---
+`.trim()
 };