refactor: global variables logic (#3144)

This commit is contained in:
Lucas Oliveira 2024-08-01 17:26:29 -03:00 • committed by GitHub
commit 83e48affb1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 130 additions and 258 deletions

View file

@ -1,4 +1,4 @@
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect } from "react";
import { Cookies } from "react-cookie"; import { Cookies } from "react-cookie";
import { ErrorBoundary } from "react-error-boundary"; import { ErrorBoundary } from "react-error-boundary";
import "reactflow/dist/style.css"; import "reactflow/dist/style.css";
@ -19,7 +19,6 @@ import {
useRefreshAccessToken, useRefreshAccessToken,
} from "./controllers/API/queries/auth"; } from "./controllers/API/queries/auth";
import { useGetHealthQuery } from "./controllers/API/queries/health"; import { useGetHealthQuery } from "./controllers/API/queries/health";
import { useGetGlobalVariables } from "./controllers/API/queries/variables";
import { useGetVersionQuery } from "./controllers/API/queries/version"; import { useGetVersionQuery } from "./controllers/API/queries/version";
import { setupAxiosDefaults } from "./controllers/API/utils"; import { setupAxiosDefaults } from "./controllers/API/utils";
import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path"; import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path";
@ -50,8 +49,6 @@ export default function App() {
useGetVersionQuery(); useGetVersionQuery();
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders); const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
const { mutate: mutateGetGlobalVariables } = useGetGlobalVariables();
const { mutate: mutateRefresh } = useRefreshAccessToken(); const { mutate: mutateRefresh } = useRefreshAccessToken();
const isLoginPage = location.pathname.includes("login"); const isLoginPage = location.pathname.includes("login");
@ -77,7 +74,6 @@ export default function App() {
if (user && user["access_token"]) { if (user && user["access_token"]) {
user["refresh_token"] = "auto"; user["refresh_token"] = "auto";
login(user["access_token"], "auto"); login(user["access_token"], "auto");
mutateGetGlobalVariables();
setUserData(user); setUserData(user);
setAutoLogin(true); setAutoLogin(true);
fetchAllData(); fetchAllData();

View file

@ -1,8 +1,11 @@
import { usePostGlobalVariables } from "@/controllers/API/queries/variables"; import {
import { useState } from "react"; useGetGlobalVariables,
usePostGlobalVariables,
} from "@/controllers/API/queries/variables";
import getUnavailableFields from "@/stores/globalVariablesStore/utils/get-unavailable-fields";
import { useEffect, useState } from "react";
import BaseModal from "../../modals/baseModal"; import BaseModal from "../../modals/baseModal";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
import { useTypesStore } from "../../stores/typesStore"; import { useTypesStore } from "../../stores/typesStore";
import { ResponseErrorDetailAPI } from "../../types/api"; import { ResponseErrorDetailAPI } from "../../types/api";
import ForwardedIconComponent from "../genericIconComponent"; import ForwardedIconComponent from "../genericIconComponent";
@ -28,26 +31,21 @@ export default function AddNewVariableButton({
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const componentFields = useTypesStore((state) => state.ComponentFields); const componentFields = useTypesStore((state) => state.ComponentFields);
const unavaliableFields = new Set(
Object.keys(
useGlobalVariablesStore((state) => state.unavaliableFields) ?? {},
),
);
const availableFields = () => {
const fields = Array.from(componentFields).filter(
(field) => !unavaliableFields.has(field),
);
return sortByName(fields);
};
const addGlobalVariable = useGlobalVariablesStore(
(state) => state.addGlobalVariable,
);
const { mutate: mutateAddGlobalVariable } = usePostGlobalVariables(); const { mutate: mutateAddGlobalVariable } = usePostGlobalVariables();
const { data: globalVariables } = useGetGlobalVariables();
const [availableFields, setAvailableFields] = useState<string[]>([]);
useEffect(() => {
if (globalVariables && componentFields.size > 0) {
const unavailableFields = getUnavailableFields(globalVariables);
const fields = Array.from(componentFields).filter(
(field) => !unavailableFields.hasOwnProperty(field),
);
setAvailableFields(sortByName(fields));
}
}, [globalVariables, componentFields]);
const setSuccessData = useAlertStore((state) => state.setSuccessData); const setSuccessData = useAlertStore((state) => state.setSuccessData);
function handleSaveVariable() { function handleSaveVariable() {
@ -65,8 +63,7 @@ export default function AddNewVariableButton({
mutateAddGlobalVariable(data, { mutateAddGlobalVariable(data, {
onSuccess: (res) => { onSuccess: (res) => {
const { name, id, type } = res.data; const { name } = res;
addGlobalVariable(name, id, type, fields);
setKey(""); setKey("");
setValue(""); setValue("");
setType(""); setType("");
@ -156,7 +153,7 @@ export default function AddNewVariableButton({
<InputComponent <InputComponent
setSelectedOptions={(value) => setFields(value)} setSelectedOptions={(value) => setFields(value)}
selectedOptions={fields} selectedOptions={fields}
options={availableFields()} options={availableFields}
password={false} password={false}
placeholder="Choose a field for the variable..." placeholder="Choose a field for the variable..."
id={"apply-to-fields"} id={"apply-to-fields"}

View file

@ -1,8 +1,10 @@
import { useDeleteGlobalVariables } from "@/controllers/API/queries/variables"; import {
useDeleteGlobalVariables,
useGetGlobalVariables,
} from "@/controllers/API/queries/variables";
import { useEffect } from "react"; import { useEffect } from "react";
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal"; import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
import { InputGlobalComponentType } from "../../types/components"; import { InputGlobalComponentType } from "../../types/components";
import { cn } from "../../utils/utils"; import { cn } from "../../utils/utils";
import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton"; import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton";
@ -17,33 +19,29 @@ export default function InputGlobalComponent({
data, data,
editNode = false, editNode = false,
}: InputGlobalComponentType): JSX.Element { }: InputGlobalComponentType): JSX.Element {
const globalVariablesEntries = useGlobalVariablesStore(
(state) => state.globalVariablesEntries,
);
const getVariableId = useGlobalVariablesStore((state) => state.getVariableId);
const removeGlobalVariable = useGlobalVariablesStore(
(state) => state.removeGlobalVariable,
);
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const { data: globalVariables } = useGetGlobalVariables();
const { mutate: mutateDeleteGlobalVariable } = useDeleteGlobalVariables(); const { mutate: mutateDeleteGlobalVariable } = useDeleteGlobalVariables();
useEffect(() => { useEffect(() => {
if (data && globalVariablesEntries) if (data && globalVariables)
if (data.load_from_db && !globalVariablesEntries.includes(data.value)) { if (
data.load_from_db &&
!globalVariables.find((variable) => variable.name === data.value)
) {
onChange("", false, true); onChange("", false, true);
} }
}, [globalVariablesEntries]); }, [globalVariables]);
async function handleDelete(key: string) { async function handleDelete(key: string) {
const id = getVariableId(key); if (!globalVariables) return;
const id = globalVariables.find((variable) => variable.name === key)?.id;
if (id !== undefined) { if (id !== undefined) {
mutateDeleteGlobalVariable( mutateDeleteGlobalVariable(
{ id }, { id },
{ {
onSuccess: () => { onSuccess: () => {
removeGlobalVariable(key);
if (data?.value === key && data?.load_from_db) { if (data?.value === key && data?.load_from_db) {
onChange("", false); onChange("", false);
} }
@ -70,7 +68,7 @@ export default function InputGlobalComponent({
disabled={disabled} disabled={disabled}
password={data.password ?? false} password={data.password ?? false}
value={data.value ?? ""} value={data.value ?? ""}
options={globalVariablesEntries} options={globalVariables?.map((variable) => variable.name) ?? []}
optionsPlaceholder={"Global Variables"} optionsPlaceholder={"Global Variables"}
optionsIcon="Globe" optionsIcon="Globe"
optionsButton={ optionsButton={
@ -113,8 +111,10 @@ export default function InputGlobalComponent({
)} )}
selectedOption={ selectedOption={
data?.load_from_db && data?.load_from_db &&
globalVariablesEntries && globalVariables &&
globalVariablesEntries.includes(data?.value ?? "") globalVariables
?.map((variable) => variable.name)
.includes(data?.value ?? "")
? data?.value ? data?.value
: "" : ""
} }

View file

@ -1,4 +1,3 @@
import { ColDef, ColGroupDef } from "ag-grid-community";
import { AxiosRequestConfig, AxiosResponse } from "axios"; import { AxiosRequestConfig, AxiosResponse } from "axios";
import { Edge, Node, ReactFlowJsonObject } from "reactflow"; import { Edge, Node, ReactFlowJsonObject } from "reactflow";
import { BASE_URL_API, MAX_BATCH_SIZE } from "../../constants/constants"; import { BASE_URL_API, MAX_BATCH_SIZE } from "../../constants/constants";
@ -8,21 +7,14 @@ import {
APITemplateType, APITemplateType,
Component, Component,
CustomComponentRequest, CustomComponentRequest,
LoginType,
ProfilePicturesTypeAPI,
Users, Users,
VertexBuildTypeAPI, VertexBuildTypeAPI,
VerticesOrderTypeAPI, VerticesOrderTypeAPI,
changeUser,
resetPasswordType,
sendAllProps, sendAllProps,
} from "../../types/api/index"; } from "../../types/api/index";
import { UserInputType } from "../../types/components";
import { FlowStyleType, FlowType } from "../../types/flow"; import { FlowStyleType, FlowType } from "../../types/flow";
import { Message } from "../../types/messages";
import { StoreComponentResponse } from "../../types/store"; import { StoreComponentResponse } from "../../types/store";
import { FlowPoolType } from "../../types/zustand/flow"; import { FlowPoolType } from "../../types/zustand/flow";
import { extractColumnsFromRows } from "../../utils/utils";
import { import {
APIClassType, APIClassType,
BuildStatusTypeAPI, BuildStatusTypeAPI,
@ -766,23 +758,6 @@ export async function requestLogout() {
} }
} }
export async function updateGlobalVariable(
name: string,
value: string,
id: string,
) {
try {
const response = api.patch(`${BASE_URL_API}variables/${id}`, {
name,
value,
});
return response;
} catch (error) {
throw error;
}
}
export async function getVerticesOrder( export async function getVerticesOrder(
flowId: string, flowId: string,
startNodeId?: string | null, startNodeId?: string | null,

View file

@ -12,7 +12,7 @@ export const useDeleteGlobalVariables: useMutationFunctionType<
undefined, undefined,
DeleteGlobalVariablesParams DeleteGlobalVariablesParams
> = (options?) => { > = (options?) => {
const { mutate } = UseRequestProcessor(); const { mutate, queryClient } = UseRequestProcessor();
const deleteGlobalVariables = async ({ const deleteGlobalVariables = async ({
id, id,
@ -25,7 +25,12 @@ export const useDeleteGlobalVariables: useMutationFunctionType<
DeleteGlobalVariablesParams, DeleteGlobalVariablesParams,
any, any,
DeleteGlobalVariablesParams DeleteGlobalVariablesParams
> = mutate(["useDeleteGlobalVariables"], deleteGlobalVariables, options); > = mutate(["useDeleteGlobalVariables"], deleteGlobalVariables, {
onSettled: () => {
queryClient.refetchQueries({ queryKey: ["useGetGlobalVariables"] });
},
...options,
});
return mutation; return mutation;
}; };

View file

@ -1,54 +1,37 @@
import { useGlobalVariablesStore } from "@/stores/globalVariablesStore/globalVariables"; import { useGlobalVariablesStore } from "@/stores/globalVariablesStore/globalVariables";
import { useMutationFunctionType } from "@/types/api"; import getUnavailableFields from "@/stores/globalVariablesStore/utils/get-unavailable-fields";
import { UseMutationResult } from "@tanstack/react-query"; import { useQueryFunctionType } from "@/types/api";
import { GlobalVariable } from "@/types/global_variables";
import { UseQueryResult } from "@tanstack/react-query";
import { api } from "../../api"; import { api } from "../../api";
import { getURL } from "../../helpers/constants"; import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor"; import { UseRequestProcessor } from "../../services/request-processor";
type GlobalVariable = { export const useGetGlobalVariables: useQueryFunctionType<
id: string; undefined,
type: string; GlobalVariable[]
default_fields: string[]; > = (options?) => {
name: string; const { query } = UseRequestProcessor();
};
export const useGetGlobalVariables: useMutationFunctionType<undefined, void> = ( const setGlobalVariablesEntries = useGlobalVariablesStore(
options?, (state) => state.setGlobalVariablesEntries,
) => { );
const { mutate } = UseRequestProcessor(); const setUnavailableFields = useGlobalVariablesStore(
(state) => state.setUnavailableFields,
const setGlobalVariables = useGlobalVariablesStore(
(state) => state.setGlobalVariables,
); );
const getGlobalVariables = async (): Promise<[GlobalVariable]> => { const getGlobalVariablesFn = async (): Promise<GlobalVariable[]> => {
const res = await api.get(`${getURL("VARIABLES")}/`); const res = await api.get(`${getURL("VARIABLES")}/`);
setGlobalVariablesEntries(res.data.map((entry) => entry.name));
setUnavailableFields(getUnavailableFields(res.data));
return res.data; return res.data;
}; };
const getGlobalVariablesFn = async (): Promise<{ const queryResult: UseQueryResult<GlobalVariable[], any> = query(
[key: string]: GlobalVariable;
}> => {
const data = await getGlobalVariables();
const globalVariables = {};
data?.forEach((element) => {
globalVariables[element.name] = {
id: element.id,
type: element.type,
default_fields: element.default_fields,
};
});
setGlobalVariables(globalVariables);
return globalVariables;
};
const mutation: UseMutationResult<any, any, any> = mutate(
["useGetGlobalVariables"], ["useGetGlobalVariables"],
getGlobalVariablesFn, getGlobalVariablesFn,
options, options,
); );
return mutation; return queryResult;
}; };

View file

@ -1,4 +1,4 @@
import { changeUser, useMutationFunctionType } from "@/types/api"; import { useMutationFunctionType } from "@/types/api";
import { UseMutationResult } from "@tanstack/react-query"; import { UseMutationResult } from "@tanstack/react-query";
import { api } from "../../api"; import { api } from "../../api";
import { getURL } from "../../helpers/constants"; import { getURL } from "../../helpers/constants";
@ -14,7 +14,7 @@ export const usePatchGlobalVariables: useMutationFunctionType<
undefined, undefined,
PatchGlobalVariablesParams PatchGlobalVariablesParams
> = (options?) => { > = (options?) => {
const { mutate } = UseRequestProcessor(); const { mutate, queryClient } = UseRequestProcessor();
async function patchGlobalVariables({ async function patchGlobalVariables({
name, name,
@ -32,7 +32,12 @@ export const usePatchGlobalVariables: useMutationFunctionType<
PatchGlobalVariablesParams, PatchGlobalVariablesParams,
any, any,
PatchGlobalVariablesParams PatchGlobalVariablesParams
> = mutate(["usePatchGlobalVariables"], patchGlobalVariables, options); > = mutate(["usePatchGlobalVariables"], patchGlobalVariables, {
onSettled: () => {
queryClient.refetchQueries({ queryKey: ["useGetGlobalVariables"] });
},
...options,
});
return mutation; return mutation;
}; };

View file

@ -16,7 +16,7 @@ export const usePostGlobalVariables: useMutationFunctionType<
undefined, undefined,
PostGlobalVariablesParams PostGlobalVariablesParams
> = (options?) => { > = (options?) => {
const { mutate } = UseRequestProcessor(); const { mutate, queryClient } = UseRequestProcessor();
const postGlobalVariablesFunction = async ({ const postGlobalVariablesFunction = async ({
name, name,
@ -24,17 +24,22 @@ export const usePostGlobalVariables: useMutationFunctionType<
type, type,
default_fields = [], default_fields = [],
}): Promise<AxiosResponse<{ name: string; id: string; type: string }>> => { }): Promise<AxiosResponse<{ name: string; id: string; type: string }>> => {
const res = await api.post(`${getURL("VARIABLES")}`, { const res = await api.post(`${getURL("VARIABLES")}/`, {
name, name,
value, value,
type, type,
default_fields: default_fields, default_fields: default_fields,
}); });
return res; return res.data;
}; };
const mutation: UseMutationResult<any, any, PostGlobalVariablesParams> = const mutation: UseMutationResult<any, any, PostGlobalVariablesParams> =
mutate(["usePostGlobalVariables"], postGlobalVariablesFunction, options); mutate(["usePostGlobalVariables"], postGlobalVariablesFunction, {
onSettled: () => {
queryClient.refetchQueries({ queryKey: ["useGetGlobalVariables"] });
},
...options,
});
return mutation; return mutation;
}; };

View file

@ -1,4 +1,5 @@
import { import {
QueryClient,
useMutation, useMutation,
UseMutationOptions, UseMutationOptions,
useQuery, useQuery,
@ -10,6 +11,7 @@ import { MutationFunctionType, QueryFunctionType } from "../../../types/api";
export function UseRequestProcessor(): { export function UseRequestProcessor(): {
query: QueryFunctionType; query: QueryFunctionType;
mutate: MutationFunctionType; mutate: MutationFunctionType;
queryClient: QueryClient;
} { } {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@ -41,5 +43,5 @@ export function UseRequestProcessor(): {
}); });
} }
return { query, mutate }; return { query, mutate, queryClient };
} }

View file

@ -1,5 +1,4 @@
import { useLoginUser } from "@/controllers/API/queries/auth"; import { useLoginUser } from "@/controllers/API/queries/auth";
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
import useFlowsManagerStore from "@/stores/flowsManagerStore"; import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { useFolderStore } from "@/stores/foldersStore"; import { useFolderStore } from "@/stores/foldersStore";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
@ -24,8 +23,6 @@ export default function LoginAdminPage() {
const { login } = useContext(AuthContext); const { login } = useContext(AuthContext);
const setLoading = useAlertStore((state) => state.setLoading); const setLoading = useAlertStore((state) => state.setLoading);
const { mutate: mutateGetGlobalVariables } = useGetGlobalVariables();
const setAllFlows = useFlowsManagerStore((state) => state.setAllFlows); const setAllFlows = useFlowsManagerStore((state) => state.setAllFlows);
const setSelectedFolder = useFolderStore((state) => state.setSelectedFolder); const setSelectedFolder = useFolderStore((state) => state.setSelectedFolder);
@ -51,11 +48,7 @@ export default function LoginAdminPage() {
setSelectedFolder(null); setSelectedFolder(null);
setLoading(true); setLoading(true);
login(res.access_token, "login"); login(res.access_token, "login");
mutateGetGlobalVariables();
navigate("/admin/");
}, },
onError: (error) => { onError: (error) => {
setErrorData({ setErrorData({

View file

@ -1,3 +1,4 @@
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
import { useEffect } from "react"; import { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import FlowToolbar from "../../components/chatComponent"; import FlowToolbar from "../../components/chatComponent";
@ -17,6 +18,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
const currentFlow = useFlowsManagerStore((state) => state.currentFlow); const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
const { id } = useParams(); const { id } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
useGetGlobalVariables();
const flows = useFlowsManagerStore((state) => state.flows); const flows = useFlowsManagerStore((state) => state.flows);

View file

@ -50,7 +50,6 @@ export default function LoginPage(): JSX.Element {
setLoading(true); setLoading(true);
login(data.access_token, "login"); login(data.access_token, "login");
navigate("/admin/");
}, },
onError: (error) => { onError: (error) => {
setErrorData({ setErrorData({

View file

@ -1,30 +1,21 @@
import IconComponent from "../../../../components/genericIconComponent"; import IconComponent from "../../../../components/genericIconComponent";
import { Button } from "../../../../components/ui/button"; import { Button } from "../../../../components/ui/button";
import { useDeleteGlobalVariables } from "@/controllers/API/queries/variables"; import {
useDeleteGlobalVariables,
useGetGlobalVariables,
} from "@/controllers/API/queries/variables";
import { ColDef, ColGroupDef, SelectionChangedEvent } from "ag-grid-community"; import { ColDef, ColGroupDef, SelectionChangedEvent } from "ag-grid-community";
import { useEffect, useState } from "react"; import { useState } from "react";
import AddNewVariableButton from "../../../../components/addNewVariableButtonComponent/addNewVariableButton"; import AddNewVariableButton from "../../../../components/addNewVariableButtonComponent/addNewVariableButton";
import Dropdown from "../../../../components/dropdownComponent"; import Dropdown from "../../../../components/dropdownComponent";
import ForwardedIconComponent from "../../../../components/genericIconComponent"; import ForwardedIconComponent from "../../../../components/genericIconComponent";
import TableComponent from "../../../../components/tableComponent"; import TableComponent from "../../../../components/tableComponent";
import { Badge } from "../../../../components/ui/badge"; import { Badge } from "../../../../components/ui/badge";
import useAlertStore from "../../../../stores/alertStore"; import useAlertStore from "../../../../stores/alertStore";
import { useGlobalVariablesStore } from "../../../../stores/globalVariablesStore/globalVariables";
export default function GlobalVariablesPage() { export default function GlobalVariablesPage() {
const globalVariablesEntries = useGlobalVariablesStore(
(state) => state.globalVariablesEntries,
);
const removeGlobalVariable = useGlobalVariablesStore(
(state) => state.removeGlobalVariable,
);
const globalVariables = useGlobalVariablesStore(
(state) => state.globalVariables,
);
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const getVariableId = useGlobalVariablesStore((state) => state.getVariableId);
const BadgeRenderer = (props) => { const BadgeRenderer = (props) => {
return props.value !== "" ? ( return props.value !== "" ? (
<div> <div>
@ -37,35 +28,6 @@ export default function GlobalVariablesPage() {
); );
}; };
const [rowData, setRowData] = useState<
{
type: string | undefined;
id: string;
name: string;
default_fields: string | undefined;
}[]
>([]);
useEffect(() => {
const rows: Array<{
type: string | undefined;
id: string;
name: string;
default_fields: string | undefined;
}> = [];
if (globalVariablesEntries === undefined) return;
globalVariablesEntries.forEach((entrie) => {
const globalVariableObj = globalVariables[entrie];
rows.push({
type: globalVariableObj.type,
id: globalVariableObj.id,
default_fields: (globalVariableObj.default_fields ?? []).join(", "),
name: entrie,
});
});
setRowData(rows);
}, [globalVariables]);
const DropdownEditor = ({ options, value, onValueChange }) => { const DropdownEditor = ({ options, value, onValueChange }) => {
return ( return (
<Dropdown options={options} value={value} onSelect={onValueChange}> <Dropdown options={options} value={value} onSelect={onValueChange}>
@ -108,17 +70,15 @@ export default function GlobalVariablesPage() {
const [selectedRows, setSelectedRows] = useState<string[]>([]); const [selectedRows, setSelectedRows] = useState<string[]>([]);
const { data: globalVariables } = useGetGlobalVariables();
const { mutate: mutateDeleteGlobalVariable } = useDeleteGlobalVariables(); const { mutate: mutateDeleteGlobalVariable } = useDeleteGlobalVariables();
async function removeVariables() { async function removeVariables() {
selectedRows.map(async (row) => { selectedRows.map(async (row) => {
const id = getVariableId(row); const id = globalVariables?.find((variable) => variable.name === row)?.id;
mutateDeleteGlobalVariable( mutateDeleteGlobalVariable(
{ id }, { id },
{ {
onSuccess: () => {
removeGlobalVariable(row);
},
onError: () => { onError: () => {
setErrorData({ setErrorData({
title: `Error deleting variable`, title: `Error deleting variable`,
@ -166,7 +126,7 @@ export default function GlobalVariablesPage() {
suppressRowClickSelection={true} suppressRowClickSelection={true}
pagination={true} pagination={true}
columnDefs={colDefs} columnDefs={colDefs}
rowData={rowData} rowData={globalVariables ?? []}
onDelete={removeVariables} onDelete={removeVariables}
/> />
</div> </div>

View file

@ -43,7 +43,6 @@ const useAuthStore = create<AuthStoreType>((set, get) => ({
// getUser: () => { // getUser: () => {
// const setLoading = useAlertStore.getState().setLoading; // const setLoading = useAlertStore.getState().setLoading;
// const getFoldersApi = useFolderStore.getState().getFoldersApi; // const getFoldersApi = useFolderStore.getState().getFoldersApi;
// const setGlobalVariables = useGlobalVariablesStore.getState().setGlobalVariables;
// const checkHasStore = useStoreStore.getState().checkHasStore; // const checkHasStore = useStoreStore.getState().checkHasStore;
// const fetchApiData = useStoreStore.getState().fetchApiData; // const fetchApiData = useStoreStore.getState().fetchApiData;
@ -51,8 +50,6 @@ const useAuthStore = create<AuthStoreType>((set, get) => ({
// .then(async (user) => { // .then(async (user) => {
// set({ userData: user, isAdmin: user.is_superuser }); // set({ userData: user, isAdmin: user.is_superuser });
// getFoldersApi(true, true); // getFoldersApi(true, true);
// const res = await getGlobalVariables();
// setGlobalVariables(res);
// checkHasStore(); // checkHasStore();
// fetchApiData(); // fetchApiData();
// }) // })

View file

@ -344,7 +344,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
updateGroupRecursion( updateGroupRecursion(
newNode, newNode,
selection.edges, selection.edges,
useGlobalVariablesStore.getState().unavaliableFields, useGlobalVariablesStore.getState().unavailableFields,
useGlobalVariablesStore.getState().globalVariablesEntries, useGlobalVariablesStore.getState().globalVariablesEntries,
); );

View file

@ -2,7 +2,6 @@ import { brokenEdgeMessage } from "@/utils/utils";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
import pDebounce from "p-debounce"; import pDebounce from "p-debounce";
import { useLocation } from "react-router-dom";
import { Edge, Node, Viewport, XYPosition } from "reactflow"; import { Edge, Node, Viewport, XYPosition } from "reactflow";
import { create } from "zustand"; import { create } from "zustand";
import { import {
@ -223,7 +222,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
updateGroupRecursion( updateGroupRecursion(
node, node,
flowData?.edges, flowData?.edges,
useGlobalVariablesStore.getState().unavaliableFields, useGlobalVariablesStore.getState().unavailableFields,
useGlobalVariablesStore.getState().globalVariablesEntries, useGlobalVariablesStore.getState().globalVariablesEntries,
); );
}); });

View file

@ -1,49 +1,15 @@
import { create } from "zustand"; import { create } from "zustand";
import { GlobalVariablesStore } from "../../types/zustand/globalVariables"; import { GlobalVariablesStore } from "../../types/zustand/globalVariables";
import getUnavailableFields from "./utils/get-unavailable-fields";
export const useGlobalVariablesStore = create<GlobalVariablesStore>( export const useGlobalVariablesStore = create<GlobalVariablesStore>(
(set, get) => ({ (set, get) => ({
unavaliableFields: undefined, unavailableFields: {},
setUnavaliableFields: (fields) => { setUnavailableFields: (fields) => {
set({ unavaliableFields: fields }); set({ unavailableFields: fields });
}, },
removeUnavaliableField: (field) => { globalVariablesEntries: [],
const newFields = get().unavaliableFields || {}; setGlobalVariablesEntries: (entries) => {
delete newFields[field]; set({ globalVariablesEntries: entries });
set({ unavaliableFields: newFields });
},
globalVariablesEntries: undefined,
globalVariables: {},
setGlobalVariables: (variables) => {
set({
globalVariables: variables,
globalVariablesEntries: Object.keys(variables) || [],
unavaliableFields: getUnavailableFields(variables),
});
},
addGlobalVariable: (name, id, type, default_fields) => {
const data = { id, type, default_fields };
const newVariables = { ...get().globalVariables, [name]: data };
set({
globalVariables: newVariables,
globalVariablesEntries: Object.keys(newVariables) || [],
unavaliableFields: getUnavailableFields(newVariables),
});
},
removeGlobalVariable: async (name) => {
const id = get().globalVariables[name]?.id;
if (id === undefined) return;
const newVariables = { ...get().globalVariables };
delete newVariables[name];
set({
globalVariables: newVariables,
globalVariablesEntries: Object.keys(newVariables) || [],
unavaliableFields: getUnavailableFields(newVariables),
});
},
getVariableId: (name) => {
return get().globalVariables[name]?.id;
}, },
}), }),
); );

View file

@ -1,11 +1,13 @@
export default function getUnavailableFields(variables: { import { GlobalVariable } from "@/types/global_variables";
[key: string]: { default_fields?: string[] };
}): { [name: string]: string } { export default function getUnavailableFields(variables: GlobalVariable[]): {
[name: string]: string;
} {
const unVariables: { [name: string]: string } = {}; const unVariables: { [name: string]: string } = {};
Object.keys(variables).forEach((key) => { variables.forEach((variable) => {
if (variables[key].default_fields) { if (variable.default_fields) {
variables[key].default_fields!.forEach((field) => { variable.default_fields!.forEach((field) => {
unVariables[field] = key; unVariables[field] = variable.name;
}); });
} }
}); });

View file

@ -0,0 +1,6 @@
export type GlobalVariable = {
id: string;
type: string;
default_fields: string[];
name: string;
};

View file

@ -1,31 +1,6 @@
export type GlobalVariablesStore = { export type GlobalVariablesStore = {
globalVariablesEntries: Array<string> | undefined; globalVariablesEntries: Array<string>;
globalVariables: { setGlobalVariablesEntries: (entries: Array<string>) => void;
[name: string]: { unavailableFields: { [name: string]: string };
id: string; setUnavailableFields: (fields: { [name: string]: string }) => void;
type?: string;
default_fields?: string[];
value?: string;
};
};
setGlobalVariables: (variables: {
[name: string]: {
id: string;
type?: string;
default_fields?: string[];
value?: string;
};
}) => void;
addGlobalVariable: (
name: string,
id: string,
type?: string,
default_fields?: string[],
value?: string,
) => void;
removeGlobalVariable: (name: string) => Promise<void>;
getVariableId: (name: string) => string | undefined;
unavaliableFields: { [name: string]: string } | undefined;
setUnavaliableFields: (fields: { [name: string]: string }) => void;
removeUnavaliableField: (field: string) => void;
}; };

View file

@ -43,14 +43,19 @@ test("should interact with global variables", async ({ page }) => {
.getByPlaceholder("Insert a value for the variable...") .getByPlaceholder("Insert a value for the variable...")
.fill("testtesttesttesttesttesttesttest"); .fill("testtesttesttesttesttesttesttest");
await page.getByTestId("popover-anchor-apply-to-fields").click(); await page.getByTestId("popover-anchor-apply-to-fields").click();
await page.waitForTimeout(2000);
await page.waitForTimeout(5000);
await page.getByPlaceholder("Search options...").fill("System Message"); await page.getByPlaceholder("Search options...").fill("System Message");
await page.waitForSelector("text=System Message", { timeout: 30000 });
await page.getByText("System Message").first().click(); await page.getByText("System Message").first().click();
await page.getByPlaceholder("Search options...").fill("openAI"); await page.getByPlaceholder("Search options...").fill("openAI");
await page.waitForSelector("text=OpenAI API Base", { timeout: 30000 });
await page.getByText("OpenAI API Base").first().click(); await page.getByText("OpenAI API Base").first().click();
await page.getByPlaceholder("Search options...").fill("llama"); await page.getByPlaceholder("Search options...").fill("llama");