fix(platform): Fix unexpected connection clash on two dynamic pins link with the same keys (#8252)

pull/8276/head^2
Zamil Majdy 2024-10-09 23:29:13 +03:00 committed by GitHub
parent c582b5512a
commit dbc603c6eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 679 additions and 366 deletions

View File

@ -39,7 +39,7 @@
"@supabase/ssr": "^0.4.0", "@supabase/ssr": "^0.4.0",
"@supabase/supabase-js": "^2.45.0", "@supabase/supabase-js": "^2.45.0",
"@tanstack/react-table": "^8.20.5", "@tanstack/react-table": "^8.20.5",
"@xyflow/react": "^12.1.0", "@xyflow/react": "^12.3.1",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",

View File

@ -172,6 +172,7 @@ export function CustomNode({ data, id, width, height }: NodeProps<CustomNode>) {
<div key={propKey} onMouseOver={() => {}}> <div key={propKey} onMouseOver={() => {}}>
{!isConnected && ( {!isConnected && (
<NodeGenericInputField <NodeGenericInputField
nodeId={id}
className="mb-2 mt-1" className="mb-2 mt-1"
propKey={propKey} propKey={propKey}
propSchema={propSchema} propSchema={propSchema}
@ -231,6 +232,7 @@ export function CustomNode({ data, id, width, height }: NodeProps<CustomNode>) {
)} )}
{!isConnected && ( {!isConnected && (
<NodeGenericInputField <NodeGenericInputField
nodeId={id}
className="mb-2 mt-1" className="mb-2 mt-1"
propKey={propKey} propKey={propKey}
propSchema={propSchema} propSchema={propSchema}
@ -270,6 +272,7 @@ export function CustomNode({ data, id, width, height }: NodeProps<CustomNode>) {
)} )}
{!isConnected && ( {!isConnected && (
<NodeGenericInputField <NodeGenericInputField
nodeId={id}
className="mb-2 mt-1" className="mb-2 mt-1"
propKey={propKey} propKey={propKey}
propSchema={propSchema} propSchema={propSchema}

View File

@ -27,6 +27,7 @@ import { ConnectionData } from "./CustomNode";
import { CredentialsInput } from "./integrations/credentials-input"; import { CredentialsInput } from "./integrations/credentials-input";
type NodeObjectInputTreeProps = { type NodeObjectInputTreeProps = {
nodeId: string;
selfKey?: string; selfKey?: string;
schema: BlockIORootSchema | BlockIOObjectSubSchema; schema: BlockIORootSchema | BlockIOObjectSubSchema;
object?: { [key: string]: any }; object?: { [key: string]: any };
@ -39,6 +40,7 @@ type NodeObjectInputTreeProps = {
}; };
const NodeObjectInputTree: FC<NodeObjectInputTreeProps> = ({ const NodeObjectInputTree: FC<NodeObjectInputTreeProps> = ({
nodeId,
selfKey = "", selfKey = "",
schema, schema,
object, object,
@ -65,6 +67,7 @@ const NodeObjectInputTree: FC<NodeObjectInputTreeProps> = ({
{propSchema.title || beautifyString(propKey)} {propSchema.title || beautifyString(propKey)}
</span> </span>
<NodeGenericInputField <NodeGenericInputField
nodeId={nodeId}
key={propKey} key={propKey}
propKey={childKey} propKey={childKey}
propSchema={propSchema} propSchema={propSchema}
@ -85,6 +88,7 @@ const NodeObjectInputTree: FC<NodeObjectInputTreeProps> = ({
export default NodeObjectInputTree; export default NodeObjectInputTree;
export const NodeGenericInputField: FC<{ export const NodeGenericInputField: FC<{
nodeId: string;
propKey: string; propKey: string;
propSchema: BlockIOSubSchema; propSchema: BlockIOSubSchema;
currentValue?: any; currentValue?: any;
@ -95,6 +99,7 @@ export const NodeGenericInputField: FC<{
className?: string; className?: string;
displayName?: string; displayName?: string;
}> = ({ }> = ({
nodeId,
propKey, propKey,
propSchema, propSchema,
currentValue, currentValue,
@ -131,6 +136,7 @@ export const NodeGenericInputField: FC<{
if ("properties" in propSchema) { if ("properties" in propSchema) {
return ( return (
<NodeObjectInputTree <NodeObjectInputTree
nodeId={nodeId}
selfKey={propKey} selfKey={propKey}
schema={propSchema} schema={propSchema}
object={currentValue} object={currentValue}
@ -147,6 +153,7 @@ export const NodeGenericInputField: FC<{
if ("additionalProperties" in propSchema) { if ("additionalProperties" in propSchema) {
return ( return (
<NodeKeyValueInput <NodeKeyValueInput
nodeId={nodeId}
selfKey={propKey} selfKey={propKey}
schema={propSchema} schema={propSchema}
entries={currentValue} entries={currentValue}
@ -247,6 +254,7 @@ export const NodeGenericInputField: FC<{
case "array": case "array":
return ( return (
<NodeArrayInput <NodeArrayInput
nodeId={nodeId}
selfKey={propKey} selfKey={propKey}
schema={propSchema} schema={propSchema}
entries={currentValue} entries={currentValue}
@ -261,6 +269,7 @@ export const NodeGenericInputField: FC<{
case "object": case "object":
return ( return (
<NodeKeyValueInput <NodeKeyValueInput
nodeId={nodeId}
selfKey={propKey} selfKey={propKey}
schema={propSchema} schema={propSchema}
entries={currentValue} entries={currentValue}
@ -314,6 +323,7 @@ const NodeCredentialsInput: FC<{
}; };
const NodeKeyValueInput: FC<{ const NodeKeyValueInput: FC<{
nodeId: string;
selfKey: string; selfKey: string;
schema: BlockIOKVSubSchema; schema: BlockIOKVSubSchema;
entries?: { [key: string]: string } | { [key: string]: number }; entries?: { [key: string]: string } | { [key: string]: number };
@ -323,6 +333,7 @@ const NodeKeyValueInput: FC<{
className?: string; className?: string;
displayName?: string; displayName?: string;
}> = ({ }> = ({
nodeId,
selfKey, selfKey,
entries, entries,
schema, schema,
@ -333,18 +344,15 @@ const NodeKeyValueInput: FC<{
displayName, displayName,
}) => { }) => {
const getPairValues = useCallback(() => { const getPairValues = useCallback(() => {
let defaultEntries = new Map<string, any>(); // Map will preserve the order of entries.
const defaultEntries = new Map(
Object.entries(entries ?? schema.default ?? {}),
);
const prefix = getEntryKey("");
connections connections
.filter((c) => c.targetHandle.startsWith(`${selfKey}_`)) .filter((c) => c.targetHandle.startsWith(prefix))
.forEach((c) => { .map((c) => c.targetHandle.slice(prefix.length))
const key = c.targetHandle.slice(`${selfKey}_#_`.length); .forEach((k) => !defaultEntries.has(k) && defaultEntries.set(k, ""));
defaultEntries.set(key, "");
});
Object.entries(entries ?? schema.default ?? {}).forEach(([key, value]) => {
defaultEntries.set(key, value);
});
return Array.from(defaultEntries, ([key, value]) => ({ key, value })); return Array.from(defaultEntries, ([key, value]) => ({ key, value }));
}, [connections, entries, schema.default, selfKey]); }, [connections, entries, schema.default, selfKey]);
@ -380,7 +388,9 @@ const NodeKeyValueInput: FC<{
return `${selfKey}_#_${key}`; return `${selfKey}_#_${key}`;
} }
function isConnected(key: string): boolean { function isConnected(key: string): boolean {
return connections.some((c) => c.targetHandle === getEntryKey(key)); return connections.some(
(c) => c.targetHandle === getEntryKey(key) && c.target === nodeId,
);
} }
return ( return (
@ -388,7 +398,7 @@ const NodeKeyValueInput: FC<{
{displayName && <strong>{displayName}</strong>} {displayName && <strong>{displayName}</strong>}
<div> <div>
{keyValuePairs.map(({ key, value }, index) => ( {keyValuePairs.map(({ key, value }, index) => (
<div key={index}> <div key={getEntryKey(key)}>
{key && ( {key && (
<NodeHandle <NodeHandle
keyName={getEntryKey(key)} keyName={getEntryKey(key)}
@ -461,6 +471,7 @@ const NodeKeyValueInput: FC<{
}; };
const NodeArrayInput: FC<{ const NodeArrayInput: FC<{
nodeId: string;
selfKey: string; selfKey: string;
schema: BlockIOArraySubSchema; schema: BlockIOArraySubSchema;
entries?: string[]; entries?: string[];
@ -471,6 +482,7 @@ const NodeArrayInput: FC<{
className?: string; className?: string;
displayName?: string; displayName?: string;
}> = ({ }> = ({
nodeId,
selfKey, selfKey,
schema, schema,
entries, entries,
@ -491,7 +503,10 @@ const NodeArrayInput: FC<{
{entries.map((entry: any, index: number) => { {entries.map((entry: any, index: number) => {
const entryKey = `${selfKey}_$_${index}`; const entryKey = `${selfKey}_$_${index}`;
const isConnected = const isConnected =
connections && connections.some((c) => c.targetHandle === entryKey); connections &&
connections.some(
(c) => c.targetHandle === entryKey && c.target === nodeId,
);
return ( return (
<div key={entryKey} className="self-start"> <div key={entryKey} className="self-start">
<div className="mb-2 flex space-x-2"> <div className="mb-2 flex space-x-2">
@ -505,6 +520,7 @@ const NodeArrayInput: FC<{
{!isConnected && {!isConnected &&
(schema.items ? ( (schema.items ? (
<NodeGenericInputField <NodeGenericInputField
nodeId={nodeId}
propKey={entryKey} propKey={entryKey}
propSchema={schema.items} propSchema={schema.items}
currentValue={entry} currentValue={entry}

File diff suppressed because it is too large Load Diff