Merge SessionManagement into SessionManagement
This commit is contained in:
commit
cd36ff8ad7
17 changed files with 179 additions and 73 deletions
|
|
@ -1,8 +1,7 @@
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
from uuid import UUID
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||||
|
|
||||||
from langflow.api.v1.schemas import MessageIds
|
|
||||||
from langflow.services.deps import get_monitor_service
|
from langflow.services.deps import get_monitor_service
|
||||||
from langflow.services.monitor.schema import (
|
from langflow.services.monitor.schema import (
|
||||||
MessageModelRequest,
|
MessageModelRequest,
|
||||||
|
|
@ -68,13 +67,13 @@ async def get_messages(
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
@router.post("/messages", status_code=204)
|
@router.delete("/messages", status_code=204)
|
||||||
async def delete_messages(
|
async def delete_messages(
|
||||||
message_ids: MessageIds,
|
message_ids: List[int],
|
||||||
monitor_service: MonitorService = Depends(get_monitor_service),
|
monitor_service: MonitorService = Depends(get_monitor_service),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
monitor_service.delete_messages(message_ids=message_ids.ids)
|
monitor_service.delete_messages(message_ids=message_ids)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
@ -87,9 +86,10 @@ async def update_message(
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
message_dict = message.model_dump(exclude_none=True)
|
message_dict = message.model_dump(exclude_none=True)
|
||||||
df = monitor_service.update_message(message_id=message_id, **message_dict)
|
message_dict.pop("index", None)
|
||||||
dicts = df.to_dict(orient="records")
|
monitor_service.update_message(message_id=message_id, **message_dict)
|
||||||
return [MessageModelResponse(**d) for d in dicts]
|
return MessageModelResponse(index=message_id, **message_dict)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,3 @@ class FlowDataRequest(BaseModel):
|
||||||
|
|
||||||
class ConfigResponse(BaseModel):
|
class ConfigResponse(BaseModel):
|
||||||
frontend_timeout: int
|
frontend_timeout: int
|
||||||
|
|
||||||
class MessageIds(BaseModel):
|
|
||||||
ids: List[int]
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ class MonitorService(Service):
|
||||||
valid: Optional[bool] = None,
|
valid: Optional[bool] = None,
|
||||||
order_by: Optional[str] = "timestamp",
|
order_by: Optional[str] = "timestamp",
|
||||||
):
|
):
|
||||||
query = "SELECT index,flow_id, valid, params, data, artifacts, timestamp FROM vertex_builds"
|
query = "SELECT id, index,flow_id, valid, params, data, artifacts, timestamp FROM vertex_builds"
|
||||||
conditions = []
|
conditions = []
|
||||||
if flow_id:
|
if flow_id:
|
||||||
conditions.append(f"flow_id = '{flow_id}'")
|
conditions.append(f"flow_id = '{flow_id}'")
|
||||||
|
|
@ -92,6 +92,8 @@ class MonitorService(Service):
|
||||||
with duckdb.connect(str(self.db_path)) as conn:
|
with duckdb.connect(str(self.db_path)) as conn:
|
||||||
df = conn.execute(query).df()
|
df = conn.execute(query).df()
|
||||||
|
|
||||||
|
print(query)
|
||||||
|
|
||||||
return df.to_dict(orient="records")
|
return df.to_dict(orient="records")
|
||||||
|
|
||||||
def delete_vertex_builds(self, flow_id: Optional[str] = None):
|
def delete_vertex_builds(self, flow_id: Optional[str] = None):
|
||||||
|
|
@ -113,7 +115,7 @@ class MonitorService(Service):
|
||||||
return self.exec_query(query)
|
return self.exec_query(query)
|
||||||
|
|
||||||
def update_message(self, message_id: int, **kwargs):
|
def update_message(self, message_id: int, **kwargs):
|
||||||
query = f"UPDATE messages SET {', '.join(f'{k} = {v}' for k, v in kwargs.items())} WHERE id = {message_id}"
|
query = f"""UPDATE messages SET {', '.join(f"{k} = '{v}'" for k, v in kwargs.items())} WHERE index = {message_id}"""
|
||||||
|
|
||||||
return self.exec_query(query)
|
return self.exec_query(query)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ import axios, { AxiosError, AxiosInstance } from "axios";
|
||||||
import { useContext, useEffect } from "react";
|
import { useContext, useEffect } from "react";
|
||||||
import { Cookies } from "react-cookie";
|
import { Cookies } from "react-cookie";
|
||||||
import { renewAccessToken } from ".";
|
import { renewAccessToken } from ".";
|
||||||
import { AUTHORIZED_DUPLICATE_REQUESTS } from "../../constants/constants";
|
|
||||||
import { BuildStatus } from "../../constants/enums";
|
import { BuildStatus } from "../../constants/enums";
|
||||||
import { AuthContext } from "../../contexts/authContext";
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
|
import { checkDuplicateRequestAndStoreRequest } from "./helpers/check-duplicate-requests";
|
||||||
|
|
||||||
// Create a new Axios instance
|
// Create a new Axios instance
|
||||||
const api: AxiosInstance = axios.create({
|
const api: AxiosInstance = axios.create({
|
||||||
|
|
@ -48,7 +48,7 @@ function ApiInterceptor() {
|
||||||
}
|
}
|
||||||
await clearBuildVerticesState(error);
|
await clearBuildVerticesState(error);
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const isAuthorizedURL = (url) => {
|
const isAuthorizedURL = (url) => {
|
||||||
|
|
@ -65,10 +65,10 @@ function ApiInterceptor() {
|
||||||
const parsedURL = new URL(url);
|
const parsedURL = new URL(url);
|
||||||
|
|
||||||
const isDomainAllowed = authorizedDomains.some(
|
const isDomainAllowed = authorizedDomains.some(
|
||||||
(domain) => parsedURL.origin === new URL(domain).origin
|
(domain) => parsedURL.origin === new URL(domain).origin,
|
||||||
);
|
);
|
||||||
const isEndpointAllowed = authorizedEndpoints.some((endpoint) =>
|
const isEndpointAllowed = authorizedEndpoints.some((endpoint) =>
|
||||||
parsedURL.pathname.includes(endpoint)
|
parsedURL.pathname.includes(endpoint),
|
||||||
);
|
);
|
||||||
|
|
||||||
return isDomainAllowed || isEndpointAllowed;
|
return isDomainAllowed || isEndpointAllowed;
|
||||||
|
|
@ -81,28 +81,12 @@ function ApiInterceptor() {
|
||||||
// Request interceptor to add access token to every request
|
// Request interceptor to add access token to every request
|
||||||
const requestInterceptor = api.interceptors.request.use(
|
const requestInterceptor = api.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
const lastUrl = localStorage.getItem("lastUrlCalled");
|
const checkRequest = checkDuplicateRequestAndStoreRequest(config);
|
||||||
const lastMethodCalled = localStorage.getItem("lastMethodCalled");
|
|
||||||
|
|
||||||
const isContained = AUTHORIZED_DUPLICATE_REQUESTS.some((request) =>
|
if (!checkRequest) {
|
||||||
config?.url!.includes(request),
|
return Promise.reject("Duplicate request.");
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
config?.url === lastUrl &&
|
|
||||||
!isContained &&
|
|
||||||
lastMethodCalled === config.method
|
|
||||||
) {
|
|
||||||
return Promise.reject("Duplicate request");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("lastUrlCalled", config.url ?? "");
|
|
||||||
localStorage.setItem("lastMethodCalled", config.method ?? "");
|
|
||||||
localStorage.setItem(
|
|
||||||
"lastRequestData",
|
|
||||||
JSON.stringify(config.data) ?? "",
|
|
||||||
);
|
|
||||||
|
|
||||||
const accessToken = cookies.get("access_token_lf");
|
const accessToken = cookies.get("access_token_lf");
|
||||||
if (accessToken && !isAuthorizedURL(config?.url)) {
|
if (accessToken && !isAuthorizedURL(config?.url)) {
|
||||||
config.headers["Authorization"] = `Bearer ${accessToken}`;
|
config.headers["Authorization"] = `Bearer ${accessToken}`;
|
||||||
|
|
@ -112,7 +96,7 @@ function ApiInterceptor() {
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -144,7 +128,7 @@ function ApiInterceptor() {
|
||||||
if (error?.config?.headers) {
|
if (error?.config?.headers) {
|
||||||
delete error.config.headers["Authorization"];
|
delete error.config.headers["Authorization"];
|
||||||
error.config.headers["Authorization"] = `Bearer ${cookies.get(
|
error.config.headers["Authorization"] = `Bearer ${cookies.get(
|
||||||
"access_token_lf"
|
"access_token_lf",
|
||||||
)}`;
|
)}`;
|
||||||
const response = await axios.request(error.config);
|
const response = await axios.request(error.config);
|
||||||
return response;
|
return response;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { AUTHORIZED_DUPLICATE_REQUESTS } from "../../../constants/constants";
|
||||||
|
|
||||||
|
export function checkDuplicateRequestAndStoreRequest(config) {
|
||||||
|
const lastUrl = localStorage.getItem("lastUrlCalled");
|
||||||
|
const lastMethodCalled = localStorage.getItem("lastMethodCalled");
|
||||||
|
const lastRequestTime = localStorage.getItem("lastRequestTime");
|
||||||
|
|
||||||
|
const currentTime = Date.now();
|
||||||
|
|
||||||
|
const isContained = AUTHORIZED_DUPLICATE_REQUESTS.some((request) =>
|
||||||
|
config?.url!.includes(request),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
config?.url === lastUrl &&
|
||||||
|
!isContained &&
|
||||||
|
lastMethodCalled === config.method &&
|
||||||
|
lastMethodCalled === "get" && // Assuming you want to check only for GET requests
|
||||||
|
lastRequestTime &&
|
||||||
|
currentTime - parseInt(lastRequestTime, 10) < 800
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem("lastUrlCalled", config.url ?? "");
|
||||||
|
localStorage.setItem("lastMethodCalled", config.method ?? "");
|
||||||
|
localStorage.setItem("lastRequestTime", currentTime.toString());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ import {
|
||||||
UploadFileTypeAPI,
|
UploadFileTypeAPI,
|
||||||
errorsTypeAPI,
|
errorsTypeAPI,
|
||||||
} from "./../../types/api/index";
|
} from "./../../types/api/index";
|
||||||
|
import { Message } from "../../types/messages";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all objects from the API endpoint.
|
* Fetches all objects from the API endpoint.
|
||||||
|
|
@ -1039,8 +1040,30 @@ export async function getMessagesTable(
|
||||||
return { rows: rows.data, columns };
|
return { rows: rows.data, columns };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteMessagesFn(ids: number[]) {
|
export async function getSessions(id?: string): Promise<Array<string>> {
|
||||||
return await api.post(`${BASE_URL_API}monitor/messages`, {
|
const config = {};
|
||||||
ids,
|
if (id) {
|
||||||
|
config["params"] = { flow_id: id };
|
||||||
|
}
|
||||||
|
const rows = await api.get(`${BASE_URL_API}monitor/messages`, config);
|
||||||
|
const sessions = new Set<string>();
|
||||||
|
rows.data.forEach((row) => {
|
||||||
|
sessions.add(row.session_id);
|
||||||
});
|
});
|
||||||
|
return Array.from(sessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteMessagesFn(ids: number[]) {
|
||||||
|
try {
|
||||||
|
return await api.delete(`${BASE_URL_API}monitor/messages`, {
|
||||||
|
data: ids,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting flows:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateMessageApi(data: Message) {
|
||||||
|
return await api.post(`${BASE_URL_API}monitor/messages/${data.index}`, data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
} from "../../../../components/ui/select";
|
||||||
import {
|
import {
|
||||||
CHAT_FIRST_INITIAL_TEXT,
|
CHAT_FIRST_INITIAL_TEXT,
|
||||||
CHAT_SECOND_INITIAL_TEXT,
|
CHAT_SECOND_INITIAL_TEXT,
|
||||||
|
|
@ -18,12 +24,6 @@ import { chatViewProps } from "../../../../types/components";
|
||||||
import { classNames } from "../../../../utils/utils";
|
import { classNames } from "../../../../utils/utils";
|
||||||
import ChatInput from "./chatInput";
|
import ChatInput from "./chatInput";
|
||||||
import ChatMessage from "./chatMessage";
|
import ChatMessage from "./chatMessage";
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
} from "../../../../components/ui/select";
|
|
||||||
|
|
||||||
export default function ChatView({
|
export default function ChatView({
|
||||||
sendMessage,
|
sendMessage,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import { cn } from "../../utils/utils";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
import IOFieldView from "./components/IOFieldView";
|
import IOFieldView from "./components/IOFieldView";
|
||||||
import ChatView from "./components/chatView";
|
import ChatView from "./components/chatView";
|
||||||
|
import { getSessions } from "../../controllers/API";
|
||||||
|
|
||||||
export default function IOModal({
|
export default function IOModal({
|
||||||
children,
|
children,
|
||||||
|
|
@ -78,6 +79,7 @@ export default function IOModal({
|
||||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||||
const setNode = useFlowStore((state) => state.setNode);
|
const setNode = useFlowStore((state) => state.setNode);
|
||||||
|
const [sessions, setSessions] = useState<string[]>([]);
|
||||||
|
|
||||||
async function updateVertices() {
|
async function updateVertices() {
|
||||||
return updateVerticesOrder(currentFlow!.id, null);
|
return updateVerticesOrder(currentFlow!.id, null);
|
||||||
|
|
@ -113,6 +115,11 @@ export default function IOModal({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedViewField(startView());
|
setSelectedViewField(startView());
|
||||||
|
// if (haveChat) {
|
||||||
|
// getSessions().then((sessions) => {
|
||||||
|
// setSessions(sessions);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -160,6 +167,9 @@ export default function IOModal({
|
||||||
{outputs.length > 0 && (
|
{outputs.length > 0 && (
|
||||||
<TabsTrigger value={"2"}>Outputs</TabsTrigger>
|
<TabsTrigger value={"2"}>Outputs</TabsTrigger>
|
||||||
)}
|
)}
|
||||||
|
{haveChat && (
|
||||||
|
<TabsTrigger value={"3"}>History</TabsTrigger>
|
||||||
|
)}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { getMessagesTable } from "../../../../../controllers/API";
|
import { getMessagesTable } from "../../../../../controllers/API";
|
||||||
|
import { useMessagesStore } from "../../../../../stores/messagesStore";
|
||||||
|
|
||||||
const useMessagesTable = (setColumns, setRows, setMessages) => {
|
const useMessagesTable = (setColumns) => {
|
||||||
|
const setMessages = useMessagesStore((state) => state.setMessages);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getMessagesTable("union", undefined, ["index"]);
|
const data = await getMessagesTable("union", undefined, ["index"]);
|
||||||
const { columns, rows } = data;
|
const { columns, rows } = data;
|
||||||
setColumns(columns);
|
setColumns(columns);
|
||||||
setRows(rows);
|
|
||||||
setMessages(rows);
|
setMessages(rows);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching messages:", error);
|
console.error("Error fetching messages:", error);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { deleteMessagesFn } from "../../../../../controllers/API";
|
||||||
import { useMessagesStore } from "../../../../../stores/messagesStore";
|
import { useMessagesStore } from "../../../../../stores/messagesStore";
|
||||||
|
|
||||||
const useRemoveMessages = (
|
const useRemoveMessages = (
|
||||||
setRows,
|
|
||||||
setSelectedRows,
|
setSelectedRows,
|
||||||
setSuccessData,
|
setSuccessData,
|
||||||
setErrorData,
|
setErrorData,
|
||||||
|
|
@ -12,22 +11,13 @@ const useRemoveMessages = (
|
||||||
|
|
||||||
const handleRemoveMessages = async () => {
|
const handleRemoveMessages = async () => {
|
||||||
try {
|
try {
|
||||||
// Call the deleteMessagesFn to perform the deletion
|
|
||||||
await deleteMessagesFn(selectedRows);
|
await deleteMessagesFn(selectedRows);
|
||||||
|
deleteMessages(selectedRows);
|
||||||
// Assuming deleteMessages is a separate function that updates state after deletion
|
|
||||||
const res = await deleteMessages(selectedRows);
|
|
||||||
setRows(res);
|
|
||||||
|
|
||||||
// Clear the selected rows
|
|
||||||
setSelectedRows([]);
|
setSelectedRows([]);
|
||||||
|
|
||||||
// Set success message
|
|
||||||
setSuccessData({
|
setSuccessData({
|
||||||
title: "Messages deleted successfully.",
|
title: "Messages deleted successfully.",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Set error message
|
|
||||||
setErrorData({
|
setErrorData({
|
||||||
title: "Error deleting messages.",
|
title: "Error deleting messages.",
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { useMessagesStore } from "../../../../../stores/messagesStore";
|
||||||
|
import { Message } from "../../../../../types/messages";
|
||||||
|
import { updateMessageApi } from "../../../../../controllers/API";
|
||||||
|
|
||||||
|
const useUpdateMessage = (setSuccessData, setErrorData) => {
|
||||||
|
const updateMessage = useMessagesStore((state) => state.updateMessage);
|
||||||
|
|
||||||
|
const handleUpdate = async (data: Message) => {
|
||||||
|
try {
|
||||||
|
await updateMessageApi(data);
|
||||||
|
|
||||||
|
updateMessage(data);
|
||||||
|
|
||||||
|
// Set success message
|
||||||
|
setSuccessData({
|
||||||
|
title: "Messages updated successfully.",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// Set error message
|
||||||
|
setErrorData({
|
||||||
|
title: "Error updating messages.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleUpdate };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useUpdateMessage;
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
import { ColDef, ColGroupDef, SelectionChangedEvent } from "ag-grid-community";
|
import {
|
||||||
|
CellEditRequestEvent,
|
||||||
|
ColDef,
|
||||||
|
ColGroupDef,
|
||||||
|
SelectionChangedEvent,
|
||||||
|
} from "ag-grid-community";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import TableComponent from "../../../../components/tableComponent";
|
import TableComponent from "../../../../components/tableComponent";
|
||||||
import { Card, CardContent } from "../../../../components/ui/card";
|
import { Card, CardContent } from "../../../../components/ui/card";
|
||||||
|
|
@ -7,12 +12,11 @@ import { useMessagesStore } from "../../../../stores/messagesStore";
|
||||||
import HeaderMessagesComponent from "./components/headerMessages";
|
import HeaderMessagesComponent from "./components/headerMessages";
|
||||||
import useMessagesTable from "./hooks/use-messages-table";
|
import useMessagesTable from "./hooks/use-messages-table";
|
||||||
import useRemoveMessages from "./hooks/use-remove-messages";
|
import useRemoveMessages from "./hooks/use-remove-messages";
|
||||||
|
import useUpdateMessage from "./hooks/use-updateMessage";
|
||||||
|
|
||||||
export default function MessagesPage() {
|
export default function MessagesPage() {
|
||||||
const setMessages = useMessagesStore((state) => state.setMessages);
|
|
||||||
|
|
||||||
const [columns, setColumns] = useState<Array<ColDef | ColGroupDef>>([]);
|
const [columns, setColumns] = useState<Array<ColDef | ColGroupDef>>([]);
|
||||||
const [rows, setRows] = useState<any>([]);
|
const messages = useMessagesStore((state) => state.messages);
|
||||||
|
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
|
|
@ -20,14 +24,26 @@ export default function MessagesPage() {
|
||||||
const [selectedRows, setSelectedRows] = useState<number[]>([]);
|
const [selectedRows, setSelectedRows] = useState<number[]>([]);
|
||||||
|
|
||||||
const { handleRemoveMessages } = useRemoveMessages(
|
const { handleRemoveMessages } = useRemoveMessages(
|
||||||
setRows,
|
|
||||||
setSelectedRows,
|
setSelectedRows,
|
||||||
setSuccessData,
|
setSuccessData,
|
||||||
setErrorData,
|
setErrorData,
|
||||||
selectedRows,
|
selectedRows,
|
||||||
);
|
);
|
||||||
|
|
||||||
useMessagesTable(setColumns, setRows, setMessages);
|
const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData);
|
||||||
|
|
||||||
|
useMessagesTable(setColumns);
|
||||||
|
|
||||||
|
function handleUpdateMessage(event: CellEditRequestEvent<any, string>) {
|
||||||
|
const newValue = event.newValue;
|
||||||
|
const field = event.column.getColId();
|
||||||
|
const row = event.data;
|
||||||
|
const data = {
|
||||||
|
...row,
|
||||||
|
[field]: newValue,
|
||||||
|
};
|
||||||
|
handleUpdate(data);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col justify-between gap-6">
|
<div className="flex h-full w-full flex-col justify-between gap-6">
|
||||||
|
|
@ -40,6 +56,10 @@ export default function MessagesPage() {
|
||||||
<Card x-chunk="dashboard-04-chunk-2" className="h-full pt-4">
|
<Card x-chunk="dashboard-04-chunk-2" className="h-full pt-4">
|
||||||
<CardContent className="h-full">
|
<CardContent className="h-full">
|
||||||
<TableComponent
|
<TableComponent
|
||||||
|
readOnlyEdit
|
||||||
|
onCellEditRequest={(event) => {
|
||||||
|
handleUpdateMessage(event);
|
||||||
|
}}
|
||||||
editable={["Sender", "Sender Name", "Message"]}
|
editable={["Sender", "Sender Name", "Message"]}
|
||||||
overlayNoRowsTemplate="No data available"
|
overlayNoRowsTemplate="No data available"
|
||||||
onSelectionChanged={(event: SelectionChangedEvent) => {
|
onSelectionChanged={(event: SelectionChangedEvent) => {
|
||||||
|
|
@ -51,7 +71,7 @@ export default function MessagesPage() {
|
||||||
suppressRowClickSelection={true}
|
suppressRowClickSelection={true}
|
||||||
pagination={true}
|
pagination={true}
|
||||||
columnDefs={columns}
|
columnDefs={columns}
|
||||||
rowData={rows}
|
rowData={messages}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export const useMessagesStore = create<MessagesStoreType>((set, get) => ({
|
||||||
updateMessage: (message) => {
|
updateMessage: (message) => {
|
||||||
set(() => ({
|
set(() => ({
|
||||||
messages: get().messages.map((msg) =>
|
messages: get().messages.map((msg) =>
|
||||||
msg.id === message.id ? message : msg,
|
msg.index === message.index ? message : msg,
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,5 @@ type Message = {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type { Message };
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,16 @@ export type FlowStoreType = {
|
||||||
onFlowPage: boolean;
|
onFlowPage: boolean;
|
||||||
setOnFlowPage: (onFlowPage: boolean) => void;
|
setOnFlowPage: (onFlowPage: boolean) => void;
|
||||||
flowPool: FlowPoolType;
|
flowPool: FlowPoolType;
|
||||||
inputs: Array<{ type: string; id: string; displayName: string }>;
|
inputs: Array<{
|
||||||
outputs: Array<{ type: string; id: string; displayName: string }>;
|
type: string;
|
||||||
|
id: string;
|
||||||
|
displayName: string;
|
||||||
|
}>;
|
||||||
|
outputs: Array<{
|
||||||
|
type: string;
|
||||||
|
id: string;
|
||||||
|
displayName: string;
|
||||||
|
}>;
|
||||||
hasIO: boolean;
|
hasIO: boolean;
|
||||||
setFlowPool: (flowPool: FlowPoolType) => void;
|
setFlowPool: (flowPool: FlowPoolType) => void;
|
||||||
addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => void;
|
addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => void;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { Message } from "../../messages";
|
||||||
|
|
||||||
export type MessagesStoreType = {
|
export type MessagesStoreType = {
|
||||||
messages: Message[];
|
messages: Message[];
|
||||||
setMessages: (messages: Message[]) => void;
|
setMessages: (messages: Message[]) => void;
|
||||||
|
|
@ -5,5 +7,5 @@ export type MessagesStoreType = {
|
||||||
removeMessage: (message: Message) => void;
|
removeMessage: (message: Message) => void;
|
||||||
updateMessage: (message: Message) => void;
|
updateMessage: (message: Message) => void;
|
||||||
clearMessages: () => void;
|
clearMessages: () => void;
|
||||||
removeMessages: (ids: number[]) => Promise<Message[]>;
|
removeMessages: (ids: number[]) => void;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,16 @@ export default function cloneFLowWithParent(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInputsAndOutputs(nodes: Node[]) {
|
export function getInputsAndOutputs(nodes: Node[]) {
|
||||||
let inputs: { type: string; id: string; displayName: string }[] = [];
|
let inputs: {
|
||||||
let outputs: { type: string; id: string; displayName: string }[] = [];
|
type: string;
|
||||||
|
id: string;
|
||||||
|
displayName: string;
|
||||||
|
}[] = [];
|
||||||
|
let outputs: {
|
||||||
|
type: string;
|
||||||
|
id: string;
|
||||||
|
displayName: string;
|
||||||
|
}[] = [];
|
||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
const nodeData: NodeDataType = node.data as NodeDataType;
|
const nodeData: NodeDataType = node.data as NodeDataType;
|
||||||
if (isOutputNode(nodeData)) {
|
if (isOutputNode(nodeData)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue