updateTable component

This commit is contained in:
anovazzi1 2024-06-07 15:07:53 -03:00
commit 384977e156
14 changed files with 185 additions and 119 deletions

View file

@ -115,6 +115,7 @@ function CsvOutputComponent({
style={{ height: "100%", width: "100%" }}
>
<TableComponent
key={"csv-output"}
rowData={rowData}
columnDefs={colDefs}
defaultColDef={defaultColDef}

View file

@ -23,6 +23,7 @@ function RecordsOutputComponent({
return (
<TableComponent
key={"recordsOutputComponent"}
overlayNoRowsTemplate="No data available"
suppressRowClickSelection={true}
pagination={pagination}

View file

@ -0,0 +1,95 @@
import { cn } from "../../../../utils/utils";
import ShadTooltip from "../../../shadTooltipComponent";
import { Button } from "../../../ui/button";
import IconComponent from "../../../genericIconComponent";
export default function TableOptions({
resetGrid,
duplicateRow,
deleteRow,
hasSelection,
stateChange,
}: {
resetGrid: () => void;
duplicateRow?: () => void;
deleteRow?: () => void;
hasSelection: boolean;
stateChange: boolean;
}): JSX.Element {
return (
<div className={cn("absolute bottom-4 left-6")}>
<div className="flex items-center gap-2">
<div>
<ShadTooltip content="Reset Columns">
<Button
variant="none"
size="none"
onClick={() => {
resetGrid();
}}
disabled={!stateChange}
>
<IconComponent
name="RotateCcw"
className={cn("h-5 w-5 text-primary transition-all")}
/>
</Button>
</ShadTooltip>
</div>
{duplicateRow && (
<div>
<ShadTooltip
content={
!hasSelection ? (
<span>Select items to duplicate</span>
) : (
<span>Duplicate selected items</span>
)
}
>
<Button
variant="none"
size="none"
onClick={duplicateRow}
disabled={!hasSelection}
>
<IconComponent
name="Copy"
className={cn("h-5 w-5 text-primary transition-all")}
/>
</Button>
</ShadTooltip>
</div>
)}
{deleteRow && (
<div>
<ShadTooltip
content={
!hasSelection ? (
<span>Select items to delete</span>
) : (
<span>Delete selected items</span>
)
}
>
<Button
variant="none"
size="none"
onClick={deleteRow}
disabled={!hasSelection}
>
<IconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-primary transition-all",
!hasSelection ? "" : "hover:text-destructive",
)}
/>
</Button>
</ShadTooltip>
</div>
)}{" "}
</div>
</div>
);
}

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, useRef } from "react";
import { ElementRef, forwardRef, useRef, useState } from "react";
import {
DEFAULT_TABLE_ALERT_MSG,
DEFAULT_TABLE_ALERT_TITLE,
@ -11,7 +11,7 @@ import "../../style/ag-theme-shadcn.css"; // Custom CSS applied to the grid
import { cn, toTitleCase } from "../../utils/utils";
import ForwardedIconComponent from "../genericIconComponent";
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
import ResetColumns from "./components/ResetColumns";
import TableOptions from "./components/TableOptions";
import resetGrid from "./utils/reset-grid-columns";
import { useParams } from "react-router-dom";
@ -21,8 +21,8 @@ interface TableComponentProps extends AgGridReactProps {
alertTitle?: string;
alertDescription?: string;
editable?: boolean | string[];
onDelete?: (selectedRows: any) => void;
onDuplicate?: (selectedRows: any) => void;
onDelete?: () => void;
onDuplicate?: () => void;
}
const TableComponent = forwardRef<
@ -70,9 +70,12 @@ const TableComponent = forwardRef<
});
const gridRef = useRef(null);
// @ts-ignore
const realRef = ref?.current ? ref : gridRef;
const realRef: React.MutableRefObject<AgGridReact> = ref?.current
? ref
: gridRef;
const dark = useDarkStore((state) => state.dark);
const initialColumnDefs = useRef(colDef);
const [columnStateChange, setColumnStateChange] = useState(false);
const makeLastColumnNonResizable = (columnDefs) => {
columnDefs.forEach((colDef, index) => {
@ -88,6 +91,9 @@ const TableComponent = forwardRef<
params.api.setGridOption("columnDefs", updatedColumnDefs);
initialColumnDefs.current = params.api.getColumnDefs();
if (props.onGridReady) props.onGridReady(params);
setTimeout(() => {
setColumnStateChange(false);
}, 50);
};
const onColumnMoved = (params) => {
@ -132,8 +138,27 @@ const TableComponent = forwardRef<
pagination={true}
onGridReady={onGridReady}
onColumnMoved={onColumnMoved}
onStateUpdated={(e) => {
if (
e.sources.includes("columnVisibility") ||
e.sources.includes("columnOrder")
) {
setColumnStateChange(true);
}
}}
/>
<TableOptions
stateChange={columnStateChange}
hasSelection={realRef.current?.api.getSelectedRows().length > 0}
duplicateRow={props.onDuplicate ? props.onDuplicate : undefined}
deleteRow={props.onDelete ? props.onDelete : undefined}
resetGrid={() => {
resetGrid(realRef, initialColumnDefs);
setTimeout(() => {
setColumnStateChange(false);
}, 100);
}}
/>
<ResetColumns resetGrid={() => resetGrid(realRef, initialColumnDefs)} />
</div>
);
},

View file

@ -44,43 +44,23 @@ export default function SessionView({ rows }: { rows: Array<any> }) {
}
return (
<div className="flex h-full w-full flex-col justify-between gap-6">
<>
<div className="flex w-full items-center justify-end gap-4 space-y-0.5">
<div className="flex flex-shrink-0 items-center gap-2">
<Button
data-testid="api-key-button-store"
variant="primary"
className="group px-2"
disabled={selectedRows.length === 0}
onClick={handleRemoveMessages}
>
<ForwardedIconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-destructive group-disabled:text-primary",
)}
/>
</Button>
</div>
</div>
</>
<TableComponent
readOnlyEdit
onCellEditRequest={(event) => {
handleUpdateMessage(event);
}}
editable={["Sender Name", "Message"]}
overlayNoRowsTemplate="No data available"
onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(event.api.getSelectedRows().map((row) => row.index));
}}
rowSelection="multiple"
suppressRowClickSelection={true}
pagination={true}
columnDefs={columns}
rowData={rows}
/>
</div>
<TableComponent
key={"sessionView"}
onDelete={handleRemoveMessages}
readOnlyEdit
onCellEditRequest={(event) => {
handleUpdateMessage(event);
}}
editable={["Sender Name", "Message"]}
overlayNoRowsTemplate="No data available"
onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(event.api.getSelectedRows().map((row) => row.index));
}}
rowSelection="multiple"
suppressRowClickSelection={true}
pagination={true}
columnDefs={columns}
rowData={rows}
/>
);
}

View file

@ -36,25 +36,25 @@ export default function IOModal({
const allNodes = useFlowStore((state) => state.nodes);
const setMessages = useMessagesStore((state) => state.setMessages);
const inputs = useFlowStore((state) => state.inputs).filter(
(input) => input.type !== "ChatInput"
(input) => input.type !== "ChatInput",
);
const chatInput = useFlowStore((state) => state.inputs).find(
(input) => input.type === "ChatInput"
(input) => input.type === "ChatInput",
);
const outputs = useFlowStore((state) => state.outputs).filter(
(output) => output.type !== "ChatOutput"
(output) => output.type !== "ChatOutput",
);
const chatOutput = useFlowStore((state) => state.outputs).find(
(output) => output.type === "ChatOutput"
(output) => output.type === "ChatOutput",
);
const nodes = useFlowStore((state) => state.nodes).filter(
(node) =>
inputs.some((input) => input.id === node.id) ||
outputs.some((output) => output.id === node.id)
outputs.some((output) => output.id === node.id),
);
const haveChat = chatInput || chatOutput;
const [selectedTab, setSelectedTab] = useState(
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0,
);
const setErrorData = useAlertStore((state) => state.setErrorData);
const setSuccessData = useAlertStore((state) => state.setSuccessData);
@ -111,6 +111,9 @@ export default function IOModal({
setLockChat(false);
});
}
const { rows, columns } = await getMessagesTable("union", currentFlow!.id);
setMessages(rows);
setColumns(columns);
setLockChat(false);
if (chatInput) {
setNode(chatInput.id, (node: NodeType) => {
@ -124,7 +127,7 @@ export default function IOModal({
const { handleRemoveSession } = useRemoveSession(
setSuccessData,
setErrorData
setErrorData,
);
useEffect(() => {
@ -185,7 +188,7 @@ export default function IOModal({
<div className="flex-max-width h-full">
<div
className={cn(
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300"
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300",
)}
>
<Tabs
@ -212,11 +215,11 @@ export default function IOModal({
<TabsContent value={"1"} className="api-modal-tabs-content">
{nodes
.filter((node) =>
inputs.some((input) => input.id === node.id)
inputs.some((input) => input.id === node.id),
)
.map((node, index) => {
const input = inputs.find(
(input) => input.id === node.id
(input) => input.id === node.id,
)!;
return (
<div
@ -277,11 +280,11 @@ export default function IOModal({
<TabsContent value={"2"} className="api-modal-tabs-content">
{nodes
.filter((node) =>
outputs.some((output) => output.id === node.id)
outputs.some((output) => output.id === node.id),
)
.map((node, index) => {
const output = outputs.find(
(output) => output.id === node.id
(output) => output.id === node.id,
)!;
return (
<div
@ -381,7 +384,7 @@ export default function IOModal({
content={
flow_sessions.some(
(f_session) =>
f_session?.session_id === session
f_session?.session_id === session,
)
? "Active Session"
: "Inactive Session"
@ -392,10 +395,10 @@ export default function IOModal({
"h-2 w-2 rounded-full",
flow_sessions.some(
(f_session) =>
f_session?.session_id === session
f_session?.session_id === session,
)
? "bg-status-green"
: "bg-slate-500"
: "bg-slate-500",
)}
></div>
</ShadTooltip>
@ -413,7 +416,7 @@ export default function IOModal({
<div
className={cn(
"flex h-full w-full flex-col items-start gap-4 pt-4",
!selectedViewField ? "hidden" : ""
!selectedViewField ? "hidden" : "",
)}
>
<div className="font-xl flex items-center justify-center gap-3 font-semibold">
@ -432,7 +435,7 @@ export default function IOModal({
</div>
<div className="h-full w-full">
{inputs.some(
(input) => input.id === selectedViewField.id
(input) => input.id === selectedViewField.id,
) && (
<IOFieldView
type={InputOutput.INPUT}
@ -442,7 +445,7 @@ export default function IOModal({
/>
)}
{outputs.some(
(output) => output.id === selectedViewField.id
(output) => output.id === selectedViewField.id,
) && (
<IOFieldView
type={InputOutput.OUTPUT}
@ -452,12 +455,12 @@ export default function IOModal({
/>
)}
{sessions.some(
(session) => session === selectedViewField.id
(session) => session === selectedViewField.id,
) && (
<SessionView
rows={messages.filter(
(message) =>
message.session_id === selectedViewField.id
message.session_id === selectedViewField.id,
)}
/>
)}
@ -467,7 +470,7 @@ export default function IOModal({
<div
className={cn(
"flex h-full w-full",
selectedViewField ? "hidden" : ""
selectedViewField ? "hidden" : "",
)}
>
{haveChat ? (
@ -499,7 +502,7 @@ export default function IOModal({
"h-4 w-4",
isBuilding
? "animate-spin"
: "fill-current text-medium-indigo"
: "fill-current text-medium-indigo",
)}
/>
),

View file

@ -22,7 +22,7 @@ const EditNodeModal = forwardRef(
setOpen: (open: boolean) => void;
data: NodeDataType;
},
ref
ref,
) => {
const myData = useRef(data);
@ -43,7 +43,7 @@ const EditNodeModal = forwardRef(
data,
handleOnNewValue,
changeAdvanced,
open
open,
);
const [gridApi, setGridApi] = useState<GridApi | null>(null);
@ -92,6 +92,7 @@ const EditNodeModal = forwardRef(
<div className="h-full">
{nodeLength > 0 && (
<TableComponent
key={"editNode"}
onGridReady={(params) => {
setGridApi(params.api);
}}
@ -107,7 +108,7 @@ const EditNodeModal = forwardRef(
<BaseModal.Footer submit={{ label: "Save Changes" }} />
</BaseModal>
);
}
},
);
export default EditNodeModal;

View file

@ -86,6 +86,7 @@ export default function FlowLogsModal({
</TabsList>
</Tabs>
<TableComponent
key={activeTab}
readOnlyEdit
className="h-max-full h-full w-full"
pagination={rows.length === 0 ? false : true}

View file

@ -6,13 +6,11 @@ import { cn } from "../../../../../../utils/utils";
type ApiKeyHeaderComponentProps = {
selectedRows: string[];
handleDeleteKey: () => void;
fetchApiKeys: () => void;
userId: string;
};
const ApiKeyHeaderComponent = ({
selectedRows,
handleDeleteKey,
fetchApiKeys,
userId,
}: ApiKeyHeaderComponentProps) => {
@ -30,20 +28,6 @@ const ApiKeyHeaderComponent = ({
<p className="text-sm text-muted-foreground">{API_PAGE_PARAGRAPH}</p>
</div>
<div className="flex flex-shrink-0 items-center gap-2">
<Button
data-testid="api-key-button-store"
variant="primary"
className="group px-2"
disabled={selectedRows.length === 0}
onClick={handleDeleteKey}
>
<ForwardedIconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-destructive group-disabled:text-primary",
)}
/>
</Button>
<SecretKeyModal data={userId} onCloseModal={fetchApiKeys}>
<Button data-testid="api-key-button-store" variant="primary">
<ForwardedIconComponent name="Plus" className="mr-2 w-4" />

View file

@ -25,7 +25,7 @@ export default function ApiKeysPage() {
userData,
setLoadingKeys,
keysList,
setUserId
setUserId,
);
function resetFilter() {
@ -36,7 +36,7 @@ export default function ApiKeysPage() {
selectedRows,
resetFilter,
setSuccessData,
setErrorData
setErrorData,
);
const columnDefs = getColumnDefs();
@ -45,13 +45,14 @@ export default function ApiKeysPage() {
<div className="flex h-full w-full flex-col justify-between gap-6">
<ApiKeyHeaderComponent
selectedRows={selectedRows}
handleDeleteKey={handleDeleteKey}
fetchApiKeys={fetchApiKeys}
userId={userId}
/>
<div className="flex h-full w-full flex-col justify-between">
<TableComponent
key={"apiKeys"}
onDelete={handleDeleteKey}
overlayNoRowsTemplate="No data available"
onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(event.api.getSelectedRows().map((row) => row.id));

View file

@ -143,20 +143,6 @@ export default function GlobalVariablesPage() {
</p>
</div>
<div className="flex flex-shrink-0 items-center gap-2">
<Button
data-testid="api-key-button-store"
variant="primary"
className="group px-2"
disabled={selectedRows.length === 0}
onClick={removeVariables}
>
<IconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-destructive group-disabled:text-primary",
)}
/>
</Button>
<AddNewVariableButton>
<Button data-testid="api-key-button-store" variant="primary">
<IconComponent name="Plus" className="mr-2 w-4" />
@ -168,6 +154,7 @@ export default function GlobalVariablesPage() {
<div className="flex h-full w-full flex-col justify-between">
<TableComponent
key={"globalVariables"}
overlayNoRowsTemplate="No data available"
onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(event.api.getSelectedRows().map((row) => row.name));
@ -177,6 +164,7 @@ export default function GlobalVariablesPage() {
pagination={true}
columnDefs={colDefs}
rowData={rowData}
onDelete={removeVariables}
/>
</div>
</div>

View file

@ -113,6 +113,7 @@ export default function ShortcutsPage() {
</div>
<div className="flex h-full w-full flex-col justify-between">
<TableComponent
key={"shortcuts"}
pagination={false}
columnDefs={colDefs}
rowData={nodesRowData}

View file

@ -8,7 +8,6 @@ type HeaderMessagesComponentProps = {
};
const HeaderMessagesComponent = ({
selectedRows,
handleRemoveMessages,
}: HeaderMessagesComponentProps) => {
return (
<>
@ -26,22 +25,6 @@ const HeaderMessagesComponent = ({
behaviors.
</p>
</div>
<div className="flex flex-shrink-0 items-center gap-2">
<Button
data-testid="api-key-button-store"
variant="primary"
className="group px-2"
disabled={selectedRows.length === 0}
onClick={handleRemoveMessages}
>
<ForwardedIconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-destructive group-disabled:text-primary",
)}
/>
</Button>
</div>
</div>
</>
);

View file

@ -53,6 +53,8 @@ export default function MessagesPage() {
<div className="flex h-full w-full flex-col justify-between">
<TableComponent
key={"sessionView"}
onDelete={handleRemoveMessages}
readOnlyEdit
onCellEditRequest={(event) => {
handleUpdateMessage(event);