(RecordsOutputComponent): add support for dynamic column modes and rows

♻️ (TableComponent): remove unused useCallback import and add autoHeight
 (convert-to-table-rows): add helper function to convert objects to table rows
♻️ (SwitchOutputView): refactor to use new convertToTableRows helper and improve type checks
♻️ (OutputModal): change modal size to medium-log for better visualization
♻️ (IOFieldView): refactor to use new rows and columnMode props in RecordsOutputComponent

♻️ (baseModal): remove unnecessary comma in ReactElement type array
 (baseModal): add new size option "medium-log" for modal component
♻️ (textOutputView): simplify TextOutputView component props
♻️ (api): add params and messages to VertexBuildTypeAPI
♻️ (api): add type to logs in VertexDataTypeAPI
♻️ (api): make artifacts optional in VertexDataTypeAPI
♻️ (chat): make artifacts optional in FlowPoolObjectType
 (components): add playgroundDisabled to InputListComponentType
♻️ (components): fix formatting in various component types

♻️ (utils.ts): remove unused imports to clean up the code
 (utils.ts): add 'all' mode to extractColumnsFromRows for more flexibility
This commit is contained in:
cristhianzl 2024-05-30 14:34:32 -03:00
commit 5bdf80da65
12 changed files with 70 additions and 47 deletions

View file

@ -1,19 +1,22 @@
import { ColDef, ColGroupDef } from "ag-grid-community";
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid
import "ag-grid-community/styles/ag-theme-balham.css"; // Optional Theme applied to the grid
import { FlowPoolObjectType } from "../../types/chat";
import TableComponent from "../tableComponent";
import { extractColumnsFromRows } from "../../utils/utils";
import TableComponent from "../tableComponent";
function RecordsOutputComponent({
flowPoolObject,
pagination,
rows,
columnMode,
columnDefsRow,
}: {
flowPoolObject: FlowPoolObjectType;
pagination: boolean;
rows: any;
columnMode: "intersection" | "union" | "all";
columnDefsRow?: Array<Object>;
}) {
const rows = flowPoolObject?.data?.artifacts?.records ?? [];
const columns = extractColumnsFromRows(rows, "union");
const columns = extractColumnsFromRows(columnDefsRow ?? rows, columnMode);
const columnDefs = columns.map((col, idx) => ({
...col,
resizable: idx !== columns.length - 1,

View file

@ -1,7 +1,7 @@
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid
import "ag-grid-community/styles/ag-theme-quartz.css"; // Optional Theme applied to the grid
import { AgGridReact, AgGridReactProps } from "ag-grid-react";
import { ElementRef, forwardRef, useCallback } from "react";
import { ElementRef, forwardRef } from "react";
import {
DEFAULT_TABLE_ALERT_MSG,
DEFAULT_TABLE_ALERT_TITLE,
@ -59,7 +59,9 @@ const TableComponent = forwardRef<
className={cn(props.className, "custom-scroll")}
defaultColDef={{
minWidth: 100,
autoHeight: true,
}}
tooltipInteraction={true}
ref={ref}
/>
</div>

View file

@ -0,0 +1,4 @@
export const convertToTableRows = (obj: Object) => {
const tokensArray = [Object.values(obj)[0]];
return tokensArray;
};

View file

@ -2,23 +2,24 @@ import RecordsOutputComponent from "../../../../../../components/recordsOutputCo
import { Case } from "../../../../../../shared/components/caseComponent";
import TextOutputView from "../../../../../../shared/components/textOutputView";
import useFlowStore from "../../../../../../stores/flowStore";
import { convertToTableRows } from "./helpers/convert-to-table-rows";
export default function SwitchOutputView(nodeId): JSX.Element {
const nodes = useFlowStore((state) => state.nodes);
const setNode = useFlowStore((state) => state.setNode);
const flowPool = useFlowStore((state) => state.flowPool);
const node = nodes.find((node) => node?.id === nodeId?.nodeId);
const nodeIdentity = nodeId.nodeId;
const flowPoolNode = (flowPool[node!.id] ?? [])[
(flowPool[node!.id]?.length ?? 1) - 1
const nodes = useFlowStore((state) => state.nodes);
const flowPool = useFlowStore((state) => state.flowPool);
const node = nodes.find((node) => node?.id === nodeIdentity);
const flowPoolNode = (flowPool[nodeIdentity] ?? [])[
(flowPool[nodeIdentity]?.length ?? 1) - 1
];
const results = flowPoolNode?.data?.logs[0] ?? "";
const resultType = results?.type;
const resultMessage = results?.message;
const checkType = () => {
const typeOutput = typeof results;
return typeOutput;
};
console.log("results", resultMessage);
return (
<>
@ -26,14 +27,23 @@ export default function SwitchOutputView(nodeId): JSX.Element {
<div>NO OUTPUT</div>
</Case>
<Case condition={node && checkType() === "object"}>
<TextOutputView left={false} flowPool={flowPool} node={node} vaç />
<Case condition={node && resultType === "text"}>
<TextOutputView left={false} value={resultMessage} />
</Case>
<Case condition={node && Array.isArray(results)}>
<Case condition={resultType === "record"}>
<RecordsOutputComponent
flowPoolObject={flowPoolNode}
rows={[resultMessage] ?? []}
pagination={true}
columnMode="union"
/>
</Case>
<Case condition={resultType === "object"}>
<RecordsOutputComponent
rows={convertToTableRows(resultMessage)}
pagination={true}
columnMode="union"
/>
</Case>
</>

View file

@ -4,7 +4,7 @@ import SwitchOutputView from "./components/switchOutputView";
export default function OutputModal({ open, setOpen, nodeId }): JSX.Element {
return (
<BaseModal open={open} setOpen={setOpen} size="medium-h-full">
<BaseModal open={open} setOpen={setOpen} size="medium-log">
<BaseModal.Header description="Output Visualization">
<div className="flex items-center">
<span className="pr-2">Output View</span>

View file

@ -49,6 +49,8 @@ export default function IOFieldView({
(flowPool[node!.id] ?? [])[(flowPool[node!.id]?.length ?? 1) - 1]?.data
.results.result ?? "";
console.log(flowPoolNode?.data?.artifacts?.records);
function handleOutputType() {
if (!node) return <>"No node found!"</>;
switch (type) {
@ -161,14 +163,7 @@ export default function IOFieldView({
case InputOutput.OUTPUT:
switch (fieldType) {
case "TextOutput":
return (
<TextOutputView
left={left}
node={node}
flowPool={flowPool}
value={textOutputValue}
/>
);
return <TextOutputView left={left} value={textOutputValue} />;
case "PDFOutput":
return left ? (
<div>{PDFViewConstant}</div>
@ -256,8 +251,9 @@ export default function IOFieldView({
return (
<div className={left ? "h-56" : "h-full"}>
<RecordsOutputComponent
flowPoolObject={flowPoolNode}
pagination={!left}
rows={flowPoolNode?.data?.artifacts?.records ?? []}
columnMode="union"
/>
</div>
);

View file

@ -86,7 +86,8 @@ interface BaseModalProps {
| "medium-h-full"
| "md-thin"
| "sm-thin"
| "smaller-h-full";
| "smaller-h-full"
| "medium-log";
disable?: boolean;
onChangeOpenModal?: (open?: boolean) => void;
@ -172,8 +173,13 @@ function BaseModal({
case "large-h-full":
minWidth = "min-w-[80vw]";
height = "h-full max-h-[70vh]";
break;
case "medium-log":
minWidth = "min-w-[60vw]";
height = "h-[30vh]";
break;
default:
minWidth = "min-w-[80vw]";
height = "h-[80vh]";

View file

@ -1,16 +1,13 @@
import { Textarea } from "../../../components/ui/textarea";
const TextOutputView = ({ left, node, flowPool, value }) => {
const TextOutputView = ({ left, value }) => {
return (
<>
<Textarea
className={`w-full custom-scroll ${left ? " min-h-32" : " h-full"}`}
placeholder={"Empty"}
// update to real value on flowPool
value={
(flowPool[node.id] ?? [])[(flowPool[node.id]?.length ?? 1) - 1]?.data
.results.result ?? ""
}
value={value}
readOnly
/>
</>

View file

@ -1,6 +1,5 @@
import { Edge, Node, Viewport } from "reactflow";
import { ChatOutputType, chatInputType } from "../chat";
import { Log } from "../components";
import { FlowType } from "../flow";
//kind and class are just representative names to represent the actual structure of the object received by the API
export type APIDataType = { [key: string]: APIKindType };
@ -154,17 +153,20 @@ export type VertexBuildTypeAPI = {
valid: boolean;
data: VertexDataTypeAPI;
timestamp: string;
params: any;
messages: ChatOutputType[] | chatInputType[];
};
// data is the object received by the API
// it has results, artifacts, timedelta, duration
export type VertexDataTypeAPI = {
results: { [key: string]: string };
logs:{message:string}[];
results: { [key: string]: string };
logs: { message: string; type: string }[];
messages: ChatOutputType[] | chatInputType[];
inactive?: boolean;
timedelta?: number;
duration?: string;
artifacts?: any;
};
export type CodeErrorDataTypeAPI = {

View file

@ -31,6 +31,6 @@ export type FlowPoolObjectType = {
valid: boolean;
// list of chat outputs or list of chat inputs
messages: Array<ChatOutputType | chatInputType> | [];
data: { artifacts: any; results: any | ChatOutputType | chatInputType };
data: { artifacts?: any; results: any | ChatOutputType | chatInputType };
id: string;
};

View file

@ -76,6 +76,7 @@ export type InputListComponentType = {
disabled: boolean;
editNode?: boolean;
componentName?: string;
playgroundDisabled?: boolean;
};
export type InputGlobalComponentType = {

View file

@ -2,8 +2,6 @@ import { ColDef, ColGroupDef } from "ag-grid-community";
import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import TableAutoCellRender from "../components/tableAutoCellRender";
import { priorityFields } from "../constants/constants";
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants";
import { APIDataType, TemplateVariableType } from "../types/api";
import {
groupedObjType,
@ -353,7 +351,7 @@ export function isTimeStampString(str: string): boolean {
export function extractColumnsFromRows(
rows: object[],
mode: "intersection" | "union",
mode: "intersection" | "union" | "all",
): (ColDef<any> | ColGroupDef<any>)[] {
const columnsKeys: { [key: string]: ColDef<any> | ColGroupDef<any> } = {};
if (rows.length === 0) {
@ -366,7 +364,6 @@ export function extractColumnsFromRows(
field: key,
cellRenderer: TableAutoCellRender,
filter: true,
autoHeight: true,
};
}
for (const row of rows) {
@ -385,14 +382,19 @@ export function extractColumnsFromRows(
field: key,
filter: true,
cellRenderer: TableAutoCellRender,
suppressAutoSize: true,
tooltipField: key,
};
}
}
}
if (mode === "intersection") {
intersection();
} else {
} else if (mode === "union") {
union();
} else {
return rows;
}
return Object.values(columnsKeys);