From be69a216de9ec89606c3f688bb9dc1ab4aede349 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Mon, 25 Sep 2023 22:04:50 -0300 Subject: [PATCH] fix(authContext.tsx): update useEffect dependencies to include setUserData, setLoading, autoLogin, and setIsAdmin to prevent unnecessary re-renders and ensure proper functionality feat(authContext.tsx): add support for autoLogin and userData in the TypesProvider component to retrieve and save custom components based on user data fix(typesContext.tsx): update useEffect dependencies to include autoLogin and userData to ensure proper functionality and prevent unnecessary re-renders fix(typesContext.tsx): handle error when fetching types and log the error for debugging purposes feat(typesContext.tsx): add saveComponent function to save custom components to localStorage and update the data state with the new component fix(nodeToolbarComponent/index.tsx): import typesContext from typesContext file to use the saveComponent function feat(nodeToolbarComponent/index.tsx): call saveComponent function from typesContext to save the current node data as a custom component feat(utils.ts): add IncrementObjectKey function to increment the key of an object if it already exists, to avoid overwriting existing keys in localStorage --- src/frontend/src/contexts/authContext.tsx | 2 +- src/frontend/src/contexts/typesContext.tsx | 56 +++++++++++++------ .../components/nodeToolbarComponent/index.tsx | 10 +--- src/frontend/src/utils/utils.ts | 13 +++++ 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/frontend/src/contexts/authContext.tsx b/src/frontend/src/contexts/authContext.tsx index c917b4ef9..93ac65779 100644 --- a/src/frontend/src/contexts/authContext.tsx +++ b/src/frontend/src/contexts/authContext.tsx @@ -71,7 +71,7 @@ export function AuthProvider({ children }): React.ReactElement { setLoading(false); } }); - }, []); + }, [setUserData, setLoading, autoLogin, setIsAdmin]); function getAuthentication() { const storedRefreshToken = cookies.get("refresh_token"); diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index da7eca216..e8136999a 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -1,3 +1,4 @@ +import _ from "lodash"; import { createContext, ReactNode, @@ -11,7 +12,7 @@ import { APIKindType } from "../types/api"; import { localStorageUserType } from "../types/entities"; import { NodeDataType } from "../types/flow"; import { typesContextType } from "../types/typesContext"; -import { checkLocalStorageKey } from "../utils/utils"; +import { checkLocalStorageKey, IncrementObjectKey } from "../utils/utils"; import { alertContext } from "./alertContext"; import { AuthContext } from "./authContext"; @@ -44,7 +45,7 @@ export function TypesProvider({ children }: { children: ReactNode }) { const [data, setData] = useState({}); const [fetchError, setFetchError] = useState(false); const { setLoading } = useContext(alertContext); - const { getAuthentication } = useContext(AuthContext); + const { getAuthentication, autoLogin, userData } = useContext(AuthContext); const [getFilterEdge, setFilterEdge] = useState([]); useEffect(() => { @@ -52,7 +53,7 @@ export function TypesProvider({ children }: { children: ReactNode }) { if (getAuthentication() === true) { getTypes(); } - }, [getAuthentication()]); + }, [getAuthentication(), autoLogin, userData]); async function getTypes(): Promise { // We will keep a flag to handle the case where the component is unmounted before the API call resolves. @@ -62,11 +63,23 @@ export function TypesProvider({ children }: { children: ReactNode }) { // Make sure to only update the state if the component is still mounted. if (isMounted && result?.status === 200) { setLoading(false); - setData(result.data); + let { data } = _.cloneDeep(result); + const savedComponents = autoLogin + ? localStorage.getItem("auto") + : localStorage.getItem(userData?.id!); + if (savedComponents !== null) { + const { components }: localStorageUserType = JSON.parse( + savedComponents! + ); + Object.keys(components).forEach((key) => { + data["custom_components"][key] = components[key].node!; + }); + } + setData(data); setTemplates( - Object.keys(result.data).reduce((acc, curr) => { - Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => { - acc[c] = result.data[curr][c]; + Object.keys(data).reduce((acc, curr) => { + Object.keys(data[curr]).forEach((c: keyof APIKindType) => { + acc[c] = data[curr][c]; }); return acc; }, {}) @@ -74,13 +87,13 @@ export function TypesProvider({ children }: { children: ReactNode }) { // Set the types by reducing over the keys of the result data and updating the accumulator. setTypes( // Reverse the keys so the tool world does not overlap - Object.keys(result.data) + Object.keys(data) .reverse() .reduce((acc, curr) => { - Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => { + Object.keys(data[curr]).forEach((c: keyof APIKindType) => { acc[c] = curr; // Add the base classes to the accumulator as well. - result.data[curr][c].base_classes?.forEach((b) => { + data[curr][c].base_classes?.forEach((b) => { acc[b] = curr; }); }); @@ -90,6 +103,7 @@ export function TypesProvider({ children }: { children: ReactNode }) { } } catch (error) { console.error("An error has occurred while fetching types."); + console.log(error); await getHealth().catch((e) => { setFetchError(true); }); @@ -108,15 +122,25 @@ export function TypesProvider({ children }: { children: ReactNode }) { } function saveComponent(component: NodeDataType, id: string) { + let savedComponentsJSON: localStorageUserType = { components: {} }; if (checkLocalStorageKey(id)) { let savedComponents = localStorage.getItem(id)!; - let savedComponentsJSON: localStorageUserType = - JSON.parse(savedComponents); - let components = savedComponentsJSON.components; - components[component.type]; - savedComponentsJSON.components = components; - localStorage.setItem(id, JSON.stringify(savedComponentsJSON)); + savedComponentsJSON = JSON.parse(savedComponents); } + let components = savedComponentsJSON.components; + let key = component.type; + if (components[key] !== undefined) { + const { newKey, increment } = IncrementObjectKey(components, key); + key = newKey; + } + components[key] = component; + savedComponentsJSON.components = components; + localStorage.setItem(id, JSON.stringify(savedComponentsJSON)); + setData((prev) => { + let newData = { ...prev }; + newData["custom_components"][key] = component.node; + return newData; + }); } return ( diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 2132a134e..43e0f7887 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -10,6 +10,7 @@ import { } from "../../../../components/ui/select-custom"; import { AuthContext } from "../../../../contexts/authContext"; import { TabsContext } from "../../../../contexts/tabsContext"; +import { typesContext } from "../../../../contexts/typesContext"; import EditNodeModal from "../../../../modals/EditNodeModal"; import { nodeToolbarPropsType } from "../../../../types/components"; import { @@ -54,6 +55,7 @@ export default function NodeToolbarComponent({ } const isMinimal = canMinimize(); const { paste } = useContext(TabsContext); + const { saveComponent } = useContext(typesContext); const reactFlowInstance = useReactFlow(); const [showModalAdvanced, setShowModalAdvanced] = useState(false); const [selectedValue, setSelectedValue] = useState(""); @@ -73,14 +75,8 @@ export default function NodeToolbarComponent({ break; case "SaveAll": if (isAuthenticated) { - if (autoLogin) { - console.log("save all"); - } else { - } + saveComponent(data, autoLogin ? "auto" : userData?.id!); } - console.log(isAuthenticated); - console.log(userData); - console.log(autoLogin); break; } }; diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index 19f70aaf5..34f3e0393 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -529,3 +529,16 @@ export function tabsArray(codes: string[], method: number) { export function checkLocalStorageKey(key: string): boolean { return localStorage.getItem(key) !== null; } + +export function IncrementObjectKey( + object: object, + key: string +): { newKey: string; increment: number } { + let count = 1; + let newKey = key; + while (object[newKey]) { + newKey = key + " " + `(${count})`; + count++; + } + return { newKey, increment: count }; +}