fix: Refactor messages API and session view (#2577)

* feat: create boilerplate code for messages api

* centering functionality on one component

* refactor useGetMessages

* update to new type format

* refactor Session view and get messages logic

* update to session view to useGetMessageQuery

* remove old api call

* feat: create boilerplate code for messages api

* centering functionality on one component

* refactor useGetMessages

* update to new type format

* refactor Session view and get messages logic

* update to session view to useGetMessageQuery

* remove old api call

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Cristhian Zanforlin Lousa <72977554+Cristhianzl@users.noreply.github.com>
This commit is contained in:
anovazzi1 2024-07-08 18:05:31 -03:00 committed by GitHub
commit ca3367d8e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 103 additions and 153 deletions

View file

@ -5,6 +5,7 @@ export const URLs = {
API_KEY: `api_key`,
FILES: `files`,
VERSION: `version`,
MESSAGES: `monitor/messages`,
} as const;
export function getURL(key: keyof typeof URLs, params: any = {}) {

View file

@ -1071,31 +1071,6 @@ export async function getTransactionTable(
return { rows: rows.data, columns };
}
export async function getMessagesTable(
mode: "intersection" | "union",
id?: string,
excludedFields?: string[],
params = {},
): Promise<{ rows: Array<Message>; columns: Array<ColDef | ColGroupDef> }> {
const config = {};
if (id) {
config["params"] = { flow_id: id };
}
if (params) {
config["params"] = { ...config["params"], ...params };
}
const rows = await api.get(`${BASE_URL_API}monitor/messages`, config);
const rowsOrganized = rows.data;
const columns = extractColumnsFromRows(rowsOrganized, mode, excludedFields);
const sessions = new Set<string>();
rowsOrganized.forEach((row) => {
sessions.add(row.session_id);
});
return { rows: rowsOrganized, columns };
}
export async function deleteMessagesFn(ids: string[]) {
try {
return await api.delete(`${BASE_URL_API}monitor/messages`, {

View file

@ -0,0 +1,3 @@
export * from "./use-delete-messages";
export * from "./use-get-messages";
export * from "./use-update-messages";

View file

@ -0,0 +1,53 @@
import { useMessagesStore } from "@/stores/messagesStore";
import { keepPreviousData } from "@tanstack/react-query";
import { ColDef, ColGroupDef } from "ag-grid-community";
import { useQueryFunctionType } from "../../../../types/api";
import { extractColumnsFromRows } from "../../../../utils/utils";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";
interface MessagesQueryParams {
id?: string;
mode: "intersection" | "union";
excludedFields?: string[];
params?: object;
}
interface MessagesResponse {
rows: Array<object>;
columns: Array<ColDef | ColGroupDef>;
}
export const useGetMessagesQuery: useQueryFunctionType<
MessagesQueryParams,
MessagesResponse
> = ({ id, mode, excludedFields, params }, options) => {
const { query } = UseRequestProcessor();
const getMessagesFn = async (id?: string, params = {}) => {
const config = {};
if (id) {
config["params"] = { flow_id: id };
}
if (params) {
config["params"] = { ...config["params"], ...params };
}
return await api.get<any>(`${getURL("MESSAGES")}`, config);
};
const responseFn = async () => {
const data = await getMessagesFn(id, params);
const columns = extractColumnsFromRows(data.data, mode, excludedFields);
useMessagesStore.getState().setMessages(data.data);
useMessagesStore.getState().setColumns(columns);
return { rows: data, columns };
};
const queryResult = query(["useGetMessagesQuery", { id }], responseFn, {
placeholderData: keepPreviousData,
...options,
});
return queryResult;
};

View file

@ -1,3 +1,6 @@
import Loading from "@/components/ui/loading";
import { useGetMessagesQuery } from "@/controllers/API/queries/messages";
import { useIsFetching } from "@tanstack/react-query";
import {
CellEditRequestEvent,
NewValueParams,
@ -12,11 +15,22 @@ import useAlertStore from "../../../../stores/alertStore";
import { useMessagesStore } from "../../../../stores/messagesStore";
import { messagesSorter } from "../../../../utils/utils";
export default function SessionView({ rows }: { rows: Array<any> }) {
export default function SessionView({
session,
id,
}: {
session?: string;
id?: string;
}) {
const columns = useMessagesStore((state) => state.columns);
const messages = useMessagesStore((state) => state.messages);
const setErrorData = useAlertStore((state) => state.setErrorData);
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const isFetching = useIsFetching({
queryKey: ["useGetMessagesQuery"],
exact: false,
});
const [selectedRows, setSelectedRows] = useState<string[]>([]);
const { handleRemoveMessages } = useRemoveMessages(
@ -42,7 +56,17 @@ export default function SessionView({ rows }: { rows: Array<any> }) {
});
}
return (
let filteredMessages = session
? messages.filter((message) => message.session_id === session)
: messages;
filteredMessages = id
? filteredMessages.filter((message) => message.flow_id === id)
: filteredMessages;
return isFetching > 0 ? (
<div className="flex h-full w-full items-center justify-center align-middle">
<Loading></Loading>
</div>
) : (
<TableComponent
key={"sessionView"}
onDelete={handleRemoveMessages}
@ -58,7 +82,7 @@ export default function SessionView({ rows }: { rows: Array<any> }) {
suppressRowClickSelection={true}
pagination={true}
columnDefs={columns.sort(messagesSorter)}
rowData={rows}
rowData={filteredMessages}
/>
);
}

View file

@ -1,3 +1,5 @@
import { useGetMessagesQuery } from "@/controllers/API/queries/messages";
import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import AccordionComponent from "../../components/accordionComponent";
import IconComponent from "../../components/genericIconComponent";
@ -12,14 +14,12 @@ import {
} from "../../components/ui/tabs";
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
import { InputOutput } from "../../constants/enums";
import { getMessagesTable } from "../../controllers/API";
import useAlertStore from "../../stores/alertStore";
import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useMessagesStore } from "../../stores/messagesStore";
import { IOModalPropsType } from "../../types/components";
import { NodeDataType, NodeType } from "../../types/flow";
import { updateVerticesOrder } from "../../utils/buildUtils";
import { cn } from "../../utils/utils";
import BaseModal from "../baseModal";
import IOFieldView from "./components/IOFieldView";
@ -34,7 +34,6 @@ export default function IOModal({
disable,
}: IOModalPropsType): JSX.Element {
const allNodes = useFlowStore((state) => state.nodes);
const setMessages = useMessagesStore((state) => state.setMessages);
const inputs = useFlowStore((state) => state.inputs).filter(
(input) => input.type !== "ChatInput",
);
@ -85,9 +84,13 @@ export default function IOModal({
const setNode = useFlowStore((state) => state.setNode);
const [sessions, setSessions] = useState<string[]>([]);
const messages = useMessagesStore((state) => state.messages);
const setColumns = useMessagesStore((state) => state.setColumns);
const flowPool = useFlowStore((state) => state.flowPool);
const { refetch } = useGetMessagesQuery({
mode: "union",
id: currentFlow?.id,
});
async function sendMessage({
repeat = 1,
files,
@ -111,12 +114,7 @@ export default function IOModal({
setLockChat(false);
});
}
const { rows, columns } = await getMessagesTable("union", currentFlow!.id, [
"index",
"flow_id",
]);
setMessages(rows);
setColumns(columns);
refetch();
setLockChat(false);
if (chatInput) {
setNode(chatInput.id, (node: NodeType) => {
@ -147,23 +145,13 @@ export default function IOModal({
}
});
useEffect(() => {
setSelectedViewField(startView());
if (haveChat) {
getMessagesTable("union", currentFlow!.id, ["index", "flow_id"]).then(
({ rows, columns }) => {
setMessages(rows);
setColumns(columns);
},
);
}
}, [open]);
useEffect(() => {
const sessions = new Set<string>();
messages.forEach((row) => {
sessions.add(row.session_id);
});
messages
.filter((message) => message.flow_id === currentFlow!.id)
.forEach((row) => {
sessions.add(row.session_id);
});
setSessions(Array.from(sessions));
sessions;
}, [messages]);
@ -480,10 +468,8 @@ export default function IOModal({
(session) => session === selectedViewField.id,
) && (
<SessionView
rows={messages.filter(
(message) =>
message.session_id === selectedViewField.id,
)}
session={selectedViewField.id}
id={currentFlow!.id}
/>
)}
</div>

View file

@ -1,27 +0,0 @@
import { ColDef, ColGroupDef } from "ag-grid-community";
import { useEffect } from "react";
import { getMessagesTable } from "../../../../../controllers/API";
import { useMessagesStore } from "../../../../../stores/messagesStore";
const useMessagesTable = (
setColumns: (data: Array<ColDef | ColGroupDef>) => void,
) => {
const setMessages = useMessagesStore((state) => state.setMessages);
useEffect(() => {
const fetchData = async () => {
try {
const data = await getMessagesTable("union", undefined, ["index"]);
const { columns, rows } = data;
setColumns(columns);
setMessages(rows);
} catch (error) {
console.error("Error fetching messages:", error);
}
};
fetchData();
}, []);
return null;
};
export default useMessagesTable;

View file

@ -1,80 +1,15 @@
import {
CellEditRequestEvent,
ColDef,
ColGroupDef,
SelectionChangedEvent,
} from "ag-grid-community";
import { cloneDeep } from "lodash";
import { useState } from "react";
import TableComponent from "../../../../components/tableComponent";
import useAlertStore from "../../../../stores/alertStore";
import { useMessagesStore } from "../../../../stores/messagesStore";
import { messagesSorter } from "../../../../utils/utils";
import { useGetMessagesQuery } from "@/controllers/API/queries/messages";
import SessionView from "@/modals/IOModal/components/SessionView";
import HeaderMessagesComponent from "./components/headerMessages";
import useMessagesTable from "./hooks/use-messages-table";
import useRemoveMessages from "./hooks/use-remove-messages";
import useUpdateMessage from "./hooks/use-updateMessage";
export default function MessagesPage() {
const [columns, setColumns] = useState<Array<ColDef | ColGroupDef>>([]);
const messages = useMessagesStore((state) => state.messages);
const setErrorData = useAlertStore((state) => state.setErrorData);
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const [selectedRows, setSelectedRows] = useState<string[]>([]);
const { handleRemoveMessages } = useRemoveMessages(
setSelectedRows,
setSuccessData,
setErrorData,
selectedRows,
);
const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData);
useMessagesTable(setColumns);
function handleUpdateMessage(event: CellEditRequestEvent<any, string>) {
const newValue = event.newValue;
const field = event.column.getColId();
const row = cloneDeep(event.data);
const data = {
...row,
[field]: newValue,
};
handleUpdate(data);
}
useGetMessagesQuery({ mode: "union" });
return (
<div className="flex h-full w-full flex-col justify-between gap-6">
<HeaderMessagesComponent />
<div className="flex h-full w-full flex-col justify-between">
<TableComponent
key={"sessionView"}
onDelete={handleRemoveMessages}
readOnlyEdit
onCellEditRequest={(event) => {
handleUpdateMessage(event);
}}
editable={[
{
field: "text",
onUpdate: handleUpdateMessage,
editableCell: false,
},
]}
overlayNoRowsTemplate="No data available"
onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(event.api.getSelectedRows().map((row) => row.id));
}}
rowSelection="multiple"
suppressRowClickSelection={true}
pagination={true}
columnDefs={columns.sort(messagesSorter)}
rowData={messages}
/>
<SessionView />
</div>
</div>
);