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
This commit is contained in:
anovazzi1 2023-09-25 22:04:50 -03:00
commit be69a216de
4 changed files with 57 additions and 24 deletions

View file

@ -71,7 +71,7 @@ export function AuthProvider({ children }): React.ReactElement {
setLoading(false); setLoading(false);
} }
}); });
}, []); }, [setUserData, setLoading, autoLogin, setIsAdmin]);
function getAuthentication() { function getAuthentication() {
const storedRefreshToken = cookies.get("refresh_token"); const storedRefreshToken = cookies.get("refresh_token");

View file

@ -1,3 +1,4 @@
import _ from "lodash";
import { import {
createContext, createContext,
ReactNode, ReactNode,
@ -11,7 +12,7 @@ import { APIKindType } from "../types/api";
import { localStorageUserType } from "../types/entities"; import { localStorageUserType } from "../types/entities";
import { NodeDataType } from "../types/flow"; import { NodeDataType } from "../types/flow";
import { typesContextType } from "../types/typesContext"; import { typesContextType } from "../types/typesContext";
import { checkLocalStorageKey } from "../utils/utils"; import { checkLocalStorageKey, IncrementObjectKey } from "../utils/utils";
import { alertContext } from "./alertContext"; import { alertContext } from "./alertContext";
import { AuthContext } from "./authContext"; import { AuthContext } from "./authContext";
@ -44,7 +45,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
const [data, setData] = useState({}); const [data, setData] = useState({});
const [fetchError, setFetchError] = useState(false); const [fetchError, setFetchError] = useState(false);
const { setLoading } = useContext(alertContext); const { setLoading } = useContext(alertContext);
const { getAuthentication } = useContext(AuthContext); const { getAuthentication, autoLogin, userData } = useContext(AuthContext);
const [getFilterEdge, setFilterEdge] = useState([]); const [getFilterEdge, setFilterEdge] = useState([]);
useEffect(() => { useEffect(() => {
@ -52,7 +53,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
if (getAuthentication() === true) { if (getAuthentication() === true) {
getTypes(); getTypes();
} }
}, [getAuthentication()]); }, [getAuthentication(), autoLogin, userData]);
async function getTypes(): Promise<void> { async function getTypes(): Promise<void> {
// We will keep a flag to handle the case where the component is unmounted before the API call resolves. // 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. // Make sure to only update the state if the component is still mounted.
if (isMounted && result?.status === 200) { if (isMounted && result?.status === 200) {
setLoading(false); 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( setTemplates(
Object.keys(result.data).reduce((acc, curr) => { Object.keys(data).reduce((acc, curr) => {
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => { Object.keys(data[curr]).forEach((c: keyof APIKindType) => {
acc[c] = result.data[curr][c]; acc[c] = data[curr][c];
}); });
return acc; 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. // Set the types by reducing over the keys of the result data and updating the accumulator.
setTypes( setTypes(
// Reverse the keys so the tool world does not overlap // Reverse the keys so the tool world does not overlap
Object.keys(result.data) Object.keys(data)
.reverse() .reverse()
.reduce((acc, curr) => { .reduce((acc, curr) => {
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => { Object.keys(data[curr]).forEach((c: keyof APIKindType) => {
acc[c] = curr; acc[c] = curr;
// Add the base classes to the accumulator as well. // 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; acc[b] = curr;
}); });
}); });
@ -90,6 +103,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
} }
} catch (error) { } catch (error) {
console.error("An error has occurred while fetching types."); console.error("An error has occurred while fetching types.");
console.log(error);
await getHealth().catch((e) => { await getHealth().catch((e) => {
setFetchError(true); setFetchError(true);
}); });
@ -108,15 +122,25 @@ export function TypesProvider({ children }: { children: ReactNode }) {
} }
function saveComponent(component: NodeDataType, id: string) { function saveComponent(component: NodeDataType, id: string) {
let savedComponentsJSON: localStorageUserType = { components: {} };
if (checkLocalStorageKey(id)) { if (checkLocalStorageKey(id)) {
let savedComponents = localStorage.getItem(id)!; let savedComponents = localStorage.getItem(id)!;
let savedComponentsJSON: localStorageUserType = savedComponentsJSON = JSON.parse(savedComponents);
JSON.parse(savedComponents); }
let components = savedComponentsJSON.components; let components = savedComponentsJSON.components;
components[component.type]; let key = component.type;
if (components[key] !== undefined) {
const { newKey, increment } = IncrementObjectKey(components, key);
key = newKey;
}
components[key] = component;
savedComponentsJSON.components = components; savedComponentsJSON.components = components;
localStorage.setItem(id, JSON.stringify(savedComponentsJSON)); localStorage.setItem(id, JSON.stringify(savedComponentsJSON));
} setData((prev) => {
let newData = { ...prev };
newData["custom_components"][key] = component.node;
return newData;
});
} }
return ( return (

View file

@ -10,6 +10,7 @@ import {
} from "../../../../components/ui/select-custom"; } from "../../../../components/ui/select-custom";
import { AuthContext } from "../../../../contexts/authContext"; import { AuthContext } from "../../../../contexts/authContext";
import { TabsContext } from "../../../../contexts/tabsContext"; import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
import EditNodeModal from "../../../../modals/EditNodeModal"; import EditNodeModal from "../../../../modals/EditNodeModal";
import { nodeToolbarPropsType } from "../../../../types/components"; import { nodeToolbarPropsType } from "../../../../types/components";
import { import {
@ -54,6 +55,7 @@ export default function NodeToolbarComponent({
} }
const isMinimal = canMinimize(); const isMinimal = canMinimize();
const { paste } = useContext(TabsContext); const { paste } = useContext(TabsContext);
const { saveComponent } = useContext(typesContext);
const reactFlowInstance = useReactFlow(); const reactFlowInstance = useReactFlow();
const [showModalAdvanced, setShowModalAdvanced] = useState(false); const [showModalAdvanced, setShowModalAdvanced] = useState(false);
const [selectedValue, setSelectedValue] = useState(""); const [selectedValue, setSelectedValue] = useState("");
@ -73,14 +75,8 @@ export default function NodeToolbarComponent({
break; break;
case "SaveAll": case "SaveAll":
if (isAuthenticated) { if (isAuthenticated) {
if (autoLogin) { saveComponent(data, autoLogin ? "auto" : userData?.id!);
console.log("save all");
} else {
} }
}
console.log(isAuthenticated);
console.log(userData);
console.log(autoLogin);
break; break;
} }
}; };

View file

@ -529,3 +529,16 @@ export function tabsArray(codes: string[], method: number) {
export function checkLocalStorageKey(key: string): boolean { export function checkLocalStorageKey(key: string): boolean {
return localStorage.getItem(key) !== null; 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 };
}