feat: Add toolset component utilities and refactor tool mode handling (#4946)

This commit is contained in:
Cristhian Zanforlin Lousa 2024-11-30 15:10:36 -03:00 • committed by GitHub
commit ce12ac096c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 55 additions and 13 deletions

View file

@ -615,6 +615,9 @@ async def custom_component_update(
component, component,
user_id=user.id, user_id=user.id,
) )
component_node["tool_mode"] = code_request.tool_mode
if hasattr(cc_instance, "set_attributes"): if hasattr(cc_instance, "set_attributes"):
template = code_request.get_template() template = code_request.get_template()
params = {} params = {}

View file

@ -204,6 +204,7 @@ class UpdateCustomComponentRequest(CustomComponentRequest):
field: str field: str
field_value: str | int | float | bool | dict | list | None = None field_value: str | int | float | bool | dict | list | None = None
template: dict template: dict
tool_mode: bool = False
def get_template(self): def get_template(self):
return dotdict(self.template) return dotdict(self.template)

View file

@ -396,10 +396,10 @@ class Component(CustomComponent):
def run_and_validate_update_outputs(self, frontend_node: dict, field_name: str, field_value: Any): def run_and_validate_update_outputs(self, frontend_node: dict, field_name: str, field_value: Any):
frontend_node = self.update_outputs(frontend_node, field_name, field_value) frontend_node = self.update_outputs(frontend_node, field_name, field_value)
if field_name == "tool_mode": if field_name == "tool_mode" or frontend_node.get("tool_mode"):
# Replace all outputs with the tool_output value if tool_mode is True is_tool_mode = field_value or frontend_node.get("tool_mode")
# else replace it with the original outputs frontend_node["outputs"] = [self._build_tool_output()] if is_tool_mode else frontend_node["outputs"]
frontend_node["outputs"] = [self._build_tool_output()] if field_value else frontend_node["outputs"]
return self._validate_frontend_node(frontend_node) return self._validate_frontend_node(frontend_node)
def _validate_frontend_node(self, frontend_node: dict): def _validate_frontend_node(self, frontend_node: dict):

View file

@ -49,6 +49,7 @@ export default function NodeInputField({
node: data.node!, node: data.node!,
nodeId: data.id, nodeId: data.id,
parameterId: name, parameterId: name,
tool_mode: data.node!.tool_mode ?? false,
}); });
const setFilterEdge = useFlowStore((state) => state.setFilterEdge); const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
const { handleNodeClass } = useHandleNodeClass(data.id); const { handleNodeClass } = useHandleNodeClass(data.id);

View file

@ -17,7 +17,10 @@ import { useShortcutsStore } from "../../stores/shortcuts";
import { useTypesStore } from "../../stores/typesStore"; import { useTypesStore } from "../../stores/typesStore";
import { OutputFieldType, VertexBuildTypeAPI } from "../../types/api"; import { OutputFieldType, VertexBuildTypeAPI } from "../../types/api";
import { NodeDataType } from "../../types/flow"; import { NodeDataType } from "../../types/flow";
import { scapedJSONStringfy } from "../../utils/reactflowUtils"; import {
checkHasToolMode,
scapedJSONStringfy,
} from "../../utils/reactflowUtils";
import { classNames, cn } from "../../utils/utils"; import { classNames, cn } from "../../utils/utils";
import { getNodeInputColors } from "../helpers/get-node-input-colors"; import { getNodeInputColors } from "../helpers/get-node-input-colors";
import { getNodeInputColorsName } from "../helpers/get-node-input-colors-name"; import { getNodeInputColorsName } from "../helpers/get-node-input-colors-name";
@ -332,9 +335,7 @@ export default function GenericNode({
return null; return null;
}; };
const hasToolMode = const hasToolMode = checkHasToolMode(data.node?.template ?? {});
data.node?.template &&
Object.values(data.node.template).some((field) => field.tool_mode);
return ( return (
<div className={cn(isOutdated && !isUserEdited ? "relative -mt-10" : "")}> <div className={cn(isOutdated && !isUserEdited ? "relative -mt-10" : "")}>

View file

@ -19,6 +19,7 @@ export const mutateTemplate = debounce(
>, >,
setErrorData, setErrorData,
parameterName?: string, parameterName?: string,
callback?: () => void,
) => { ) => {
try { try {
const newNode = cloneDeep(node); const newNode = cloneDeep(node);
@ -31,6 +32,7 @@ export const mutateTemplate = debounce(
newNode.outputs = newTemplate.outputs; newNode.outputs = newTemplate.outputs;
} }
setNodeClass(newNode); setNodeClass(newNode);
callback?.();
} catch (e) { } catch (e) {
const error = e as ResponseErrorDetailAPI; const error = e as ResponseErrorDetailAPI;
setErrorData({ setErrorData({

View file

@ -41,6 +41,7 @@ const useHandleOnNewValue = ({
parameterId: name, parameterId: name,
nodeId: nodeId, nodeId: nodeId,
node: node, node: node,
tool_mode: node.tool_mode ?? false,
}); });
const handleOnNewValue: handleOnNewValueType = async (changes, options?) => { const handleOnNewValue: handleOnNewValueType = async (changes, options?) => {

View file

@ -62,6 +62,8 @@ const CustomInputPopover = ({
} }
}; };
console.log(placeholder, value, id);
return ( return (
<Popover modal open={showOptions} onOpenChange={setShowOptions}> <Popover modal open={showOptions} onOpenChange={setShowOptions}>
<PopoverAnchor> <PopoverAnchor>

View file

@ -69,6 +69,7 @@ export default function InputGlobalComponent({
}); });
} }
} }
return ( return (
<InputComponent <InputComponent
nodeStyle nodeStyle

View file

@ -30,6 +30,7 @@ export function RefreshParameterComponent({
parameterId: name, parameterId: name,
nodeId: nodeId, nodeId: nodeId,
node: nodeClass, node: nodeClass,
tool_mode: nodeClass.tool_mode ?? false,
}); });
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);

View file

@ -10,12 +10,14 @@ import { UseRequestProcessor } from "../../services/request-processor";
interface IPostTemplateValue { interface IPostTemplateValue {
value: any; value: any;
tool_mode?: boolean;
} }
interface IPostTemplateValueParams { interface IPostTemplateValueParams {
node: APIClassType; node: APIClassType;
nodeId: string; nodeId: string;
parameterId: string; parameterId: string;
tool_mode: boolean;
} }
export const usePostTemplateValue: useMutationFunctionType< export const usePostTemplateValue: useMutationFunctionType<
@ -23,7 +25,7 @@ export const usePostTemplateValue: useMutationFunctionType<
IPostTemplateValue, IPostTemplateValue,
APIClassType, APIClassType,
ResponseErrorDetailAPI ResponseErrorDetailAPI
> = ({ parameterId, nodeId, node }, options?) => { > = ({ parameterId, nodeId, node, tool_mode }, options?) => {
const { mutate } = UseRequestProcessor(); const { mutate } = UseRequestProcessor();
const postTemplateValueFn = async ( const postTemplateValueFn = async (
@ -32,7 +34,6 @@ export const usePostTemplateValue: useMutationFunctionType<
const template = node.template; const template = node.template;
if (!template) return; if (!template) return;
const response = await api.post<APIClassType>( const response = await api.post<APIClassType>(
getURL("CUSTOM_COMPONENT", { update: "update" }), getURL("CUSTOM_COMPONENT", { update: "update" }),
{ {
@ -40,6 +41,7 @@ export const usePostTemplateValue: useMutationFunctionType<
template: template, template: template,
field: parameterId, field: parameterId,
field_value: payload.value, field_value: payload.value,
tool_mode: tool_mode,
}, },
); );

View file

@ -5,6 +5,7 @@ import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
import ShadTooltip from "@/components/common/shadTooltipComponent"; import ShadTooltip from "@/components/common/shadTooltipComponent";
import ToggleShadComponent from "@/components/core/parameterRenderComponent/components/toggleShadComponent"; import ToggleShadComponent from "@/components/core/parameterRenderComponent/components/toggleShadComponent";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { usePatchUpdateFlow } from "@/controllers/API/queries/flows/use-patch-update-flow";
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value"; import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
import { usePostRetrieveVertexOrder } from "@/controllers/API/queries/vertex"; import { usePostRetrieveVertexOrder } from "@/controllers/API/queries/vertex";
import useAddFlow from "@/hooks/flows/use-add-flow"; import useAddFlow from "@/hooks/flows/use-add-flow";
@ -32,6 +33,7 @@ import { useStoreStore } from "../../../../stores/storeStore";
import { nodeToolbarPropsType } from "../../../../types/components"; import { nodeToolbarPropsType } from "../../../../types/components";
import { FlowType } from "../../../../types/flow"; import { FlowType } from "../../../../types/flow";
import { import {
checkHasToolMode,
createFlowComponent, createFlowComponent,
downloadNode, downloadNode,
expandGroupNode, expandGroupNode,
@ -71,15 +73,20 @@ export default function NodeToolbarComponent({
const [openModal, setOpenModal] = useState(false); const [openModal, setOpenModal] = useState(false);
const isGroup = data.node?.flow ? true : false; const isGroup = data.node?.flow ? true : false;
const frozen = data.node?.frozen ?? false; const frozen = data.node?.frozen ?? false;
const currentFlow = useFlowStore((state) => state.currentFlow);
const addFlow = useAddFlow(); const addFlow = useAddFlow();
const { mutate: patchUpdateFlow } = usePatchUpdateFlow();
const isMinimal = countHandlesFn(data) <= 1 && numberOfOutputHandles <= 1; const isMinimal = countHandlesFn(data) <= 1 && numberOfOutputHandles <= 1;
function activateToolMode() { function activateToolMode() {
const newValue = !toolMode; const newValue = !toolMode;
setToolMode(newValue); setToolMode(newValue);
updateToolMode(data.id, newValue); updateToolMode(data.id, newValue);
data.node!.tool_mode = newValue;
mutateTemplate( mutateTemplate(
newValue, newValue,
data.node!, data.node!,
@ -87,7 +94,24 @@ export default function NodeToolbarComponent({
postToolModeValue, postToolModeValue,
setErrorData, setErrorData,
"tool_mode", "tool_mode",
() => {
const node = currentFlow?.data?.nodes.find(
(node) => node.id === data.id,
);
const index = currentFlow?.data?.nodes.indexOf(node!)!;
currentFlow!.data!.nodes[index]!.data.node.tool_mode = newValue;
patchUpdateFlow({
id: currentFlow?.id!,
name: currentFlow?.name!,
data: currentFlow?.data!,
description: currentFlow?.description!,
folder_id: currentFlow?.folder_id!,
endpoint_name: currentFlow?.endpoint_name!,
});
},
); );
updateNodeInternals(data.id); updateNodeInternals(data.id);
} }
function minimize() { function minimize() {
@ -145,9 +169,7 @@ export default function NodeToolbarComponent({
} }
// Check if any of the data.node.template fields have tool_mode as True // Check if any of the data.node.template fields have tool_mode as True
// if so we can show the tool mode button // if so we can show the tool mode button
const hasToolMode = const hasToolMode = checkHasToolMode(data.node?.template ?? {});
data.node?.template &&
Object.values(data.node.template).some((field) => field.tool_mode);
function openDocs() { function openDocs() {
if (data.node?.documentation) { if (data.node?.documentation) {
@ -370,6 +392,7 @@ export default function NodeToolbarComponent({
node: data.node!, node: data.node!,
nodeId: data.id, nodeId: data.id,
parameterId: "tool_mode", parameterId: "tool_mode",
tool_mode: data.node!.tool_mode ?? false,
}); });
return ( return (

View file

@ -1736,3 +1736,7 @@ export function someFlowTemplateFields(
}); });
}); });
} }
export function checkHasToolMode(template: APITemplateType) {
return template && Object.values(template).some((field) => field.tool_mode);
}