mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix(frontend/builder): make Google Drive file inputs chainable (#12274)
Resolves: OPEN-3018
Google Drive picker fields on INPUT blocks were missing connection
handles, making them non-chainable in the new builder.
### Changes 🏗️
- **Render `TitleFieldTemplate` with `InputNodeHandle`** — uses
`getHandleId()` with `fieldPathId.$id` (which correctly resolves to e.g.
`agpt_%_spreadsheet`), fixing the previous `_@_` handle error caused by
using `idSchema.$id` (undefined for custom RJSF FieldProps)
- **Override `showHandles: !!nodeId`** in uiOptions — the INPUT block's
`generate-ui-schema.ts` sets `showHandles: false`, but Google Drive
fields need handles to be chainable
- **Hide picker content when handle is connected** — uses
`useEdgeStore.isInputConnected()` to detect wired connections and
conditionally hides the picker/placeholder UI
### Checklist 📋
#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
- [x] Add a Google Drive file input block to a graph in the new builder
- [x] Verify the connection handle appears on the input
- [x] Connect another block's output to the Google Drive input handle
- [x] Verify the picker UI hides when connected and reappears when
disconnected
- [x] Verify the Google Drive picker still works normally on non-INPUT
block nodes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes input-handle ID generation and conditional rendering for
Google Drive fields in the builder; regressions could break edge
connections or hide the picker unexpectedly on some nodes.
>
> **Overview**
> Google Drive picker fields now render a proper RJSF
`TitleFieldTemplate` (and thus input handles) using a computed
`handleId` derived from `fieldPathId.$id`, and force `showHandles` on
when a `nodeId` is present.
>
> The picker/placeholder UI is now conditionally hidden when
`useEdgeStore.isInputConnected()` reports the input handle is connected,
preventing duplicate input UI when the value comes from an upstream
node.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1f1df53a38. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: abhi1992002 <abhimanyu1992002@gmail.com>
Co-authored-by: Abhimanyu Yadav <122007096+Abhi1992002@users.noreply.github.com>
This commit is contained in:
@@ -1,32 +1,60 @@
|
||||
import { BlockUIType } from "@/app/(platform)/build/components/types";
|
||||
import { GoogleDrivePickerInput } from "@/components/contextual/GoogleDrivePicker/GoogleDrivePickerInput";
|
||||
import { GoogleDrivePickerConfig } from "@/lib/autogpt-server-api";
|
||||
import { FieldProps, getUiOptions } from "@rjsf/utils";
|
||||
import { FieldProps, getTemplate, getUiOptions, titleId } from "@rjsf/utils";
|
||||
import { cleanUpHandleId, getHandleId, updateUiOption } from "../../helpers";
|
||||
import { useEdgeStore } from "@/app/(platform)/build/stores/edgeStore";
|
||||
|
||||
export const GoogleDrivePickerField = (props: FieldProps) => {
|
||||
const { schema, uiSchema, onChange, fieldPathId, formData, registry } = props;
|
||||
const uiOptions = getUiOptions(uiSchema);
|
||||
const config: GoogleDrivePickerConfig = schema.google_drive_picker_config;
|
||||
|
||||
const { nodeId } = registry.formContext;
|
||||
const uiType = registry.formContext?.uiType;
|
||||
|
||||
const TitleFieldTemplate = getTemplate("TitleFieldTemplate", registry);
|
||||
|
||||
const handleId = getHandleId({ uiOptions, id: fieldPathId.$id, schema });
|
||||
const updatedUiSchema = updateUiOption(uiSchema, {
|
||||
handleId,
|
||||
showHandles: !!nodeId,
|
||||
});
|
||||
|
||||
const { isInputConnected } = useEdgeStore();
|
||||
const isConnected = isInputConnected(nodeId, cleanUpHandleId(handleId));
|
||||
|
||||
if (uiType === BlockUIType.INPUT) {
|
||||
return (
|
||||
<div className="rounded-3xl border border-gray-200 p-2 pl-4 text-xs text-gray-500 hover:cursor-not-allowed">
|
||||
Select files when you run the graph
|
||||
<div className="flex flex-col gap-2">
|
||||
{!isConnected && (
|
||||
<div className="rounded-3xl border border-gray-200 p-2 pl-4 text-xs text-gray-500 hover:cursor-not-allowed">
|
||||
Select files when you run the graph
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<GoogleDrivePickerInput
|
||||
config={config}
|
||||
value={formData}
|
||||
onChange={(value) => onChange(value, fieldPathId.path)}
|
||||
className={uiOptions.className}
|
||||
showRemoveButton={true}
|
||||
<div className="flex flex-col gap-2">
|
||||
<TitleFieldTemplate
|
||||
id={titleId(fieldPathId.$id)}
|
||||
title={schema.title || ""}
|
||||
required={false}
|
||||
schema={schema}
|
||||
uiSchema={updatedUiSchema}
|
||||
registry={registry}
|
||||
/>
|
||||
{!isConnected && (
|
||||
<GoogleDrivePickerInput
|
||||
config={config}
|
||||
value={formData}
|
||||
onChange={(value) => onChange(value, fieldPathId.path)}
|
||||
className={uiOptions.className}
|
||||
showRemoveButton={true}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -44,9 +44,19 @@ export function generateUiSchemaForCustomFields(
|
||||
const customFieldId = findCustomFieldId(propSchema);
|
||||
|
||||
if (customFieldId) {
|
||||
const hasAnyOfOrOneOf =
|
||||
propSchema.anyOf || propSchema.oneOf ? true : false;
|
||||
uiSchema[key] = {
|
||||
...(uiSchema[key] as object),
|
||||
"ui:field": customFieldId,
|
||||
...(hasAnyOfOrOneOf && {
|
||||
"ui:options": {
|
||||
...((uiSchema[key] as Record<string, unknown>)?.[
|
||||
"ui:options"
|
||||
] as object),
|
||||
fieldReplacesAnyOrOneOf: true,
|
||||
},
|
||||
}),
|
||||
};
|
||||
// Skip further processing for custom fields
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user