Skip to content

Commit

Permalink
refactor: update template api, handleonnewvalue and handlenodeclass h…
Browse files Browse the repository at this point in the history
…ooks (#2628)

* Added Custom Component URL

* Added Post Template Value mutation

* Changed HandleOnNewValue hook to ParameterValue mutation

* refactored some states

* Added NumberInput component to replace input type=number. Added logic to maintain cursor at the same place when editing

* Refactored post-template-value to remove all logic

* Removed hooks from custom hook and removed mutation definition from parametercomponent

* Added mutate-template helper to call debounced mutation

* Changed handle new value to use the created function and update as requested.

* Removed pDebounce from imports

* Refactored FetchDataOnMount to only call mutateTemplate

* Refactored ParameterComponent to use the new MutateTemplate and the loading from the mutation

* removed handle refresh button

* Changed handleOnNewValue to change the value of any parameter of a template field

* Changed hooks to receive node instead of data, added HandleOnNewValue hook on tableNodeCellRender

* added SetNodeClass to update internal table state of EditNodeModal

* Removed other handle new value and node class, updated every component to use the same one

* Updated parameter component to use the same nodeclass hook

* FIxed hook to only assign value if code is present

* Fixed type attribution on useHandleNodeClass
  • Loading branch information
lucaseduoli authored Jul 19, 2024
1 parent f701d86 commit b3c1b94
Show file tree
Hide file tree
Showing 19 changed files with 964 additions and 435 deletions.
602 changes: 600 additions & 2 deletions src/frontend/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.2",
"private": true,
"dependencies": {
"@chakra-ui/number-input": "^2.1.2",
"@headlessui/react": "^2.0.4",
"@hookform/resolvers": "^3.6.0",
"@million/lint": "^1.0.0-rc.26",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { mutateTemplate } from "@/CustomNodes/helpers/mutate-template";
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
import useAlertStore from "@/stores/alertStore";
import { cloneDeep } from "lodash";
import { ReactNode, useEffect, useRef, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
Expand Down Expand Up @@ -27,10 +31,6 @@ import { useShortcutsStore } from "../../../../stores/shortcuts";
import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType } from "../../../../types/api";
import { ParameterComponentType } from "../../../../types/components";
import {
debouncedHandleUpdateValues,
handleUpdateValues,
} from "../../../../utils/parameterUtils";
import {
convertObjToArray,
convertValuesToNumbers,
Expand All @@ -48,8 +48,6 @@ import {
} from "../../../../utils/utils";
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
import useHandleNodeClass from "../../../hooks/use-handle-node-class";
import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons";
import OutputComponent from "../OutputComponent";
import HandleRenderComponent from "../handleRenderComponent";
import OutputModal from "../outputModal";
Expand Down Expand Up @@ -81,7 +79,12 @@ export default function ParameterComponent({
const setNode = useFlowStore((state) => state.setNode);
const myData = useTypesStore((state) => state.data);
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
const [isLoading, setIsLoading] = useState(false);
const postTemplateValue = usePostTemplateValue({
node: data.node!,
nodeId: data.id,
parameterId: name,
});
const isLoading = postTemplateValue.isPending;
const updateNodeInternals = useUpdateNodeInternals();
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
Expand Down Expand Up @@ -131,29 +134,25 @@ export default function ParameterComponent({
}
}

const setErrorData = useAlertStore((state) => state.setErrorData);

const output = useShortcutsStore((state) => state.output);
useHotkeys(output, handleOutputWShortcut, { preventDefault });

const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue(
data,
name,
takeSnapshot,
handleUpdateValues,
debouncedHandleUpdateValues,
setNode,
setIsLoading,
);

const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
data,
name,
takeSnapshot,
setNode,
updateNodeInternals,
data.id,
);

const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
useHandleRefreshButtonPress(setIsLoading, setNode);
const handleRefreshButtonPress = () =>
mutateTemplate(
data.node?.template[name]?.value,
data.node!,
handleNodeClass,
postTemplateValue,
setErrorData,
);

let disabled =
edges.some(
Expand All @@ -167,28 +166,36 @@ export default function ParameterComponent({
edge.sourceHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
) ?? false;

const handleRefreshButtonPress = async (name, data) => {
handleRefreshButtonPressHook(name, data);
};

useFetchDataOnMount(data, name, handleUpdateValues, setNode, setIsLoading);
const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue({
node: data.node!,
nodeId: data.id,
name,
});

const handleOnNewValue = async (
newValue: string | string[] | boolean | Object[],
const handleOnNewValue = (
value: any,
dbValue?: boolean,
skipSnapshot: boolean | undefined = false,
): Promise<void> => {
handleOnNewValueHook(newValue, dbValue, skipSnapshot);
skipSnapshot?: boolean,
) => {
handleOnNewValueHook(
{
value,
load_from_db: dbValue,
},
{ skipSnapshot },
);
};

const handleNodeClass = (
newNodeClass: APIClassType,
code?: string,
type?: string,
): void => {
handleNodeClassHook(newNodeClass, code, type);
handleNodeClassHook(newNodeClass, name, code, type);
};

useFetchDataOnMount(data.node!, handleNodeClass, name, postTemplateValue);

useEffect(() => {
// @ts-ignore
infoHtml.current = (
Expand Down Expand Up @@ -614,7 +621,7 @@ export default function ParameterComponent({
<Case condition={left === true && type === "int"}>
<div className="mt-2 w-full">
<IntComponent
rangeSpec={data.node?.template[name]?.rangeSpec}
rangeSpec={data.node?.template[name]?.range_spec}
disabled={disabled}
value={data.node?.template[name]?.value ?? ""}
onChange={handleOnNewValue}
Expand Down
44 changes: 44 additions & 0 deletions src/frontend/src/CustomNodes/helpers/mutate-template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
ERROR_UPDATING_COMPONENT,
SAVE_DEBOUNCE_TIME,
TITLE_ERROR_UPDATING_COMPONENT,
} from "@/constants/constants";
import {
APIClassType,
APITemplateType,
ResponseErrorDetailAPI,
} from "@/types/api";
import { UseMutationResult } from "@tanstack/react-query";
import { cloneDeep, debounce } from "lodash";

export const mutateTemplate = debounce(
async (
newValue,
node: APIClassType,
setNodeClass,
postTemplateValue: UseMutationResult<
APITemplateType | undefined,
ResponseErrorDetailAPI,
any
>,
setErrorData,
) => {
try {
const newNode = cloneDeep(node);
const newTemplate = await postTemplateValue.mutateAsync({
value: newValue,
});
if (newTemplate) {
newNode.template = newTemplate;
}
setNodeClass(newNode);
} catch (e) {
const error = e as ResponseErrorDetailAPI;
setErrorData({
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [error.response?.data?.detail || ERROR_UPDATING_COMPONENT],
});
}
},
SAVE_DEBOUNCE_TIME,
);
63 changes: 24 additions & 39 deletions src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,40 @@
import { cloneDeep } from "lodash";
import { useEffect } from "react";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
APIClassType,
APITemplateType,
ResponseErrorDetailAPI,
} from "@/types/api";
import { UseMutationResult } from "@tanstack/react-query";
import { useEffect } from "react";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorDetailAPI } from "../../types/api";
import { NodeDataType } from "../../types/flow";
import { mutateTemplate } from "../helpers/mutate-template";

const useFetchDataOnMount = (
data: NodeDataType,
node: APIClassType,
setNodeClass: (node: APIClassType) => void,
name: string,
handleUpdateValues: (name: string, data: NodeDataType) => Promise<any>,
setNode: (id: string, callback: (oldNode: any) => any) => void,
setIsLoading: (value: boolean) => void,
postTemplateValue: UseMutationResult<
APITemplateType | undefined,
ResponseErrorDetailAPI,
any
>,
) => {
const setErrorData = useAlertStore((state) => state.setErrorData);

useEffect(() => {
async function fetchData() {
const template = node.template[name];
if (
(data.node?.template[name]?.real_time_refresh ||
data.node?.template[name]?.refresh_button) &&
(template?.real_time_refresh || template?.refresh_button) &&
// options can be undefined but not an empty array
(data.node?.template[name]?.options?.length ?? 0) === 0
(template?.options?.length ?? 0) === 0
) {
setIsLoading(true);
try {
let newTemplate = await handleUpdateValues(name, data);

if (newTemplate) {
setNode(data.id, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
};
newNode.data.node.template = newTemplate;
return newNode;
});
}
} catch (error) {
let responseError = error as ResponseErrorDetailAPI;

setErrorData({
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
],
});
}
setIsLoading(false);
mutateTemplate(
template?.value,
node,
setNodeClass,
postTemplateValue,
setErrorData,
);
}
}
fetchData();
Expand Down
Loading

0 comments on commit b3c1b94

Please sign in to comment.