mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix(rnd): Fix jumping caret problem on builder input text field (#7917)
Issue 1: Input text field cursor keeps moving to the end of the text. Try to type "Hello World!" into the input text. Then try to type "some string" in the middle of the "Hello" and "World". Issue 2: History should only tracks on the input box onBlur/onLeave Try to type a "longcharacters" and try to undo it, the undo is removing 1 character at a time, polluting the history, and make the undo pretty much unusable. Issue 3: KeyValue & ArrayInput is non-undoable. Try to add key-value or add an entry to the list, it doesn't undo the value, but you need to click as many number of entries being added to make the undo work again
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
||||
BlockIONumberSubSchema,
|
||||
BlockIOBooleanSubSchema,
|
||||
} from "@/lib/autogpt-server-api/types";
|
||||
import { FC, useState } from "react";
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { Button } from "./ui/button";
|
||||
import { Switch } from "./ui/switch";
|
||||
import {
|
||||
@@ -296,23 +296,31 @@ const NodeKeyValueInput: FC<{
|
||||
className,
|
||||
displayName,
|
||||
}) => {
|
||||
let defaultEntries = new Map<string, any>();
|
||||
connections
|
||||
.filter((c) => c.targetHandle.startsWith(`${selfKey}_`))
|
||||
.forEach((c) => {
|
||||
const key = c.targetHandle.slice(`${selfKey}_#_`.length);
|
||||
defaultEntries.set(key, "");
|
||||
const getPairValues = () => {
|
||||
let defaultEntries = new Map<string, any>();
|
||||
|
||||
connections
|
||||
.filter((c) => c.targetHandle.startsWith(`${selfKey}_`))
|
||||
.forEach((c) => {
|
||||
const key = c.targetHandle.slice(`${selfKey}_#_`.length);
|
||||
defaultEntries.set(key, "");
|
||||
});
|
||||
|
||||
Object.entries(entries ?? schema.default ?? {}).forEach(([key, value]) => {
|
||||
defaultEntries.set(key, value);
|
||||
});
|
||||
Object.entries(entries ?? schema.default ?? {}).forEach(([key, value]) => {
|
||||
defaultEntries.set(key, value);
|
||||
});
|
||||
|
||||
return Array.from(defaultEntries, ([key, value]) => ({ key, value }));
|
||||
};
|
||||
|
||||
const [keyValuePairs, setKeyValuePairs] = useState<
|
||||
{
|
||||
key: string;
|
||||
value: string | number | null;
|
||||
}[]
|
||||
>(Array.from(defaultEntries, ([key, value]) => ({ key, value })));
|
||||
{ key: string; value: string | number | null }[]
|
||||
>([]);
|
||||
|
||||
useEffect(
|
||||
() => setKeyValuePairs(getPairValues()),
|
||||
[connections, entries, schema.default],
|
||||
);
|
||||
|
||||
function updateKeyValuePairs(newPairs: typeof keyValuePairs) {
|
||||
setKeyValuePairs(newPairs);
|
||||
@@ -373,7 +381,7 @@ const NodeKeyValueInput: FC<{
|
||||
type="text"
|
||||
placeholder="Value"
|
||||
value={value ?? ""}
|
||||
onChange={(e) =>
|
||||
onBlur={(e) =>
|
||||
updateKeyValuePairs(
|
||||
keyValuePairs.toSpliced(index, 1, {
|
||||
key: key,
|
||||
@@ -560,7 +568,7 @@ const NodeStringInput: FC<{
|
||||
placeholder={
|
||||
schema?.placeholder || `Enter ${beautifyString(displayName)}`
|
||||
}
|
||||
onChange={(e) => handleInputChange(selfKey, e.target.value)}
|
||||
onBlur={(e) => handleInputChange(selfKey, e.target.value)}
|
||||
className="pr-8 read-only:cursor-pointer read-only:text-gray-500"
|
||||
/>
|
||||
<Button
|
||||
@@ -605,9 +613,7 @@ const NodeNumberInput: FC<{
|
||||
type="number"
|
||||
id={selfKey}
|
||||
value={value}
|
||||
onChange={(e) =>
|
||||
handleInputChange(selfKey, parseFloat(e.target.value))
|
||||
}
|
||||
onBlur={(e) => handleInputChange(selfKey, parseFloat(e.target.value))}
|
||||
placeholder={
|
||||
schema.placeholder || `Enter ${beautifyString(displayName)}`
|
||||
}
|
||||
|
||||
@@ -6,7 +6,16 @@ export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
({ className, type, value, ...props }, ref) => {
|
||||
// This ref allows the `Input` component to be both controlled and uncontrolled.
|
||||
// The HTMLvalue will only be updated if the value prop changes, but the user can still type in the input.
|
||||
ref = ref || React.createRef<HTMLInputElement>();
|
||||
React.useEffect(() => {
|
||||
if (ref?.current?.value !== value) {
|
||||
console.log("Value changed from", ref?.current?.value, "to", value);
|
||||
ref.current.value = value;
|
||||
}
|
||||
}, [value]);
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
@@ -16,6 +25,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
defaultValue={value}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ class ExecutionScheduler(AppService):
|
||||
self.refresh_interval = refresh_interval
|
||||
|
||||
@property
|
||||
def execution_manager_client(self):
|
||||
def execution_manager_client(self) -> ExecutionManager:
|
||||
return get_service_client(ExecutionManager)
|
||||
|
||||
def run_service(self):
|
||||
@@ -49,15 +49,15 @@ class ExecutionScheduler(AppService):
|
||||
self.__execute_graph,
|
||||
CronTrigger.from_crontab(schedule.schedule),
|
||||
id=schedule.id,
|
||||
args=[schedule.graph_id, schedule.input_data],
|
||||
args=[schedule.graph_id, schedule.input_data, schedule.user_id],
|
||||
replace_existing=True,
|
||||
)
|
||||
|
||||
def __execute_graph(self, graph_id: str, input_data: dict):
|
||||
def __execute_graph(self, graph_id: str, input_data: dict, user_id: str):
|
||||
try:
|
||||
log(f"Executing recurring job for graph #{graph_id}")
|
||||
execution_manager = self.execution_manager_client
|
||||
execution_manager.add_execution(graph_id, input_data)
|
||||
execution_manager.add_execution(graph_id, input_data, user_id)
|
||||
except Exception as e:
|
||||
logger.exception(f"Error executing graph {graph_id}: {e}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user