From b5e1a3ab8eee5e7134e05816f78a8bc34d74be89 Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 14:48:14 -0600 Subject: [PATCH 01/13] Refactor ControlSelect to fix custom string input --- .../src/components/ControlSelect.tsx | 148 +++++++++++++----- 1 file changed, 107 insertions(+), 41 deletions(-) diff --git a/packages/connect-react/src/components/ControlSelect.tsx b/packages/connect-react/src/components/ControlSelect.tsx index 97092e79876c8..8fb94a499201b 100644 --- a/packages/connect-react/src/components/ControlSelect.tsx +++ b/packages/connect-react/src/components/ControlSelect.tsx @@ -1,4 +1,7 @@ -import { useMemo } from "react"; +import { + useEffect, + useMemo, useState, +} from "react"; import Select, { Props as ReactSelectProps, components, } from "react-select"; @@ -28,6 +31,26 @@ export function ControlSelect({ const { select, theme, } = useCustomize(); + const [ + selectOptions, + setSelectOptions, + ] = useState(options); + const [ + rawValue, + setRawValue, + ] = useState(value); + + useEffect(() => { + setSelectOptions(options) + }, [ + options, + ]) + + useEffect(() => { + setRawValue(value) + }, [ + value, + ]) const baseSelectProps: BaseReactSelectProps = { styles: { @@ -40,8 +63,15 @@ export function ControlSelect({ }; const selectValue = useMemo(() => { - let ret = value; + let ret = rawValue; if (ret != null) { + // if (!options || !options.length) { + // // Options would not be available when reloading the component + // return { + // label: value, + // value: value, + // } + // } if (Array.isArray(ret)) { // if simple, make lv (XXX combine this with other place this happens) if (typeof ret[0] !== "object") { @@ -65,7 +95,7 @@ export function ControlSelect({ const lvOptions = options?.[0] && typeof options[0] === "object"; if (lvOptions) { for (const item of options) { - if (item.value === value) { + if (item.value === rawValue) { ret = item; break; } @@ -77,7 +107,7 @@ export function ControlSelect({ } return ret; }, [ - value, + rawValue, options, ]); @@ -105,12 +135,78 @@ export function ControlSelect({ } const handleCreate = (inputValue: string) => { - options.unshift({ - label: inputValue, - value: inputValue, - }) + const createOption = (input: unknown) => { + if (typeof input === "object") return input + return { + label: input, + value: input, + } + } + const newOption = createOption(inputValue) + let newRawValue = newOption + const newSelectOptions = selectOptions + ? [ + newOption, + ...selectOptions, + ] + : [ + newOption, + ] + setSelectOptions(newSelectOptions); + if (prop.type.endsWith("[]")) { + if (Array.isArray(rawValue)) { + newRawValue = [ + ...rawValue.map(createOption), + newOption, + ] + } else { + newRawValue = [ + newOption, + ] + } + } + setRawValue(newRawValue) + handleChange(newRawValue) }; + const handleChange = (o: unknown) => { + if (o) { + if (Array.isArray(o)) { + if (typeof o[0] === "object" && "value" in o[0]) { + const vs = []; + for (const _o of o) { + if (prop.withLabel) { + vs.push(_o); + } else { + vs.push(_o.value); + } + } + onChange(vs); + } else { + onChange(o); + } + } else if (typeof o === "object" && "value" in o) { + if (prop.withLabel) { + onChange({ + __lv: o, + }); + } else { + onChange(o.value); + } + } else { + throw new Error("unhandled option type"); // TODO + } + } else { + onChange(undefined); + } + } + + const additionalProps = { + onCreateOption: prop.remoteOptions + ? handleCreate + : undefined, + } + const MaybeCreatableSelect = isCreatable ? CreatableSelect : Select; @@ -118,45 +214,15 @@ export function ControlSelect({ { - if (o) { - if (Array.isArray(o)) { - if (typeof o[0] === "object" && "value" in o[0]) { - const vs = []; - for (const _o of o) { - if (prop.withLabel) { - vs.push(_o); - } else { - vs.push(_o.value); - } - } - onChange(vs); - } else { - onChange(o); - } - } else if (typeof o === "object" && "value" in o) { - if (prop.withLabel) { - onChange({ - __lv: o, - }); - } else { - onChange(o.value); - } - } else { - throw new Error("unhandled option type"); // TODO - } - } else { - onChange(undefined); - } - }} + {...additionalProps} + onChange={handleChange} /> ); } From 640f2d3af77ea45ebd0a86f51b82db27c986868e Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 15:08:08 -0600 Subject: [PATCH 02/13] Fix custom string input state update --- .../connect-react/src/components/ControlSelect.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/connect-react/src/components/ControlSelect.tsx b/packages/connect-react/src/components/ControlSelect.tsx index 8fb94a499201b..cac483add22d5 100644 --- a/packages/connect-react/src/components/ControlSelect.tsx +++ b/packages/connect-react/src/components/ControlSelect.tsx @@ -63,6 +63,7 @@ export function ControlSelect({ }; const selectValue = useMemo(() => { + console.log("rawValue: ", rawValue) let ret = rawValue; if (ret != null) { // if (!options || !options.length) { @@ -81,7 +82,7 @@ export function ControlSelect({ label: o, value: o, } - for (const item of options) { + for (const item of selectOptions) { if (item.value === o) { obj = item; break; @@ -92,9 +93,9 @@ export function ControlSelect({ ret = lvs; } } else if (typeof ret !== "object") { - const lvOptions = options?.[0] && typeof options[0] === "object"; + const lvOptions = selectOptions?.[0] && typeof selectOptions[0] === "object"; if (lvOptions) { - for (const item of options) { + for (const item of selectOptions) { if (item.value === rawValue) { ret = item; break; @@ -108,7 +109,7 @@ export function ControlSelect({ return ret; }, [ rawValue, - options, + selectOptions, ]); const LoadMore = ({ @@ -165,6 +166,8 @@ export function ControlSelect({ ] } } + console.log("newRawValue: ", newRawValue) + console.log("newSelectOptions: ", newSelectOptions) setRawValue(newRawValue) handleChange(newRawValue) }; From 5c320a75ae3cba453755841ffc43606ee3bdb3bb Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 15:20:04 -0600 Subject: [PATCH 03/13] Populate prev value of remote options on page load --- .../connect-react/src/components/ControlSelect.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/connect-react/src/components/ControlSelect.tsx b/packages/connect-react/src/components/ControlSelect.tsx index cac483add22d5..c9a104e33c8de 100644 --- a/packages/connect-react/src/components/ControlSelect.tsx +++ b/packages/connect-react/src/components/ControlSelect.tsx @@ -66,13 +66,6 @@ export function ControlSelect({ console.log("rawValue: ", rawValue) let ret = rawValue; if (ret != null) { - // if (!options || !options.length) { - // // Options would not be available when reloading the component - // return { - // label: value, - // value: value, - // } - // } if (Array.isArray(ret)) { // if simple, make lv (XXX combine this with other place this happens) if (typeof ret[0] !== "object") { @@ -101,6 +94,11 @@ export function ControlSelect({ break; } } + } else { + ret = { + label: rawValue, + value: rawValue, + } } } else if (ret.__lv) { ret = ret.__lv From b9f775b21b179f7787db23e1e4b2c418a5920b1d Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 15:20:30 -0600 Subject: [PATCH 04/13] Pass prevValues to RemoteOptionsContainer --- .../connect-react/src/components/RemoteOptionsContainer.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/connect-react/src/components/RemoteOptionsContainer.tsx b/packages/connect-react/src/components/RemoteOptionsContainer.tsx index d606bee52f6c0..d391d696ec455 100644 --- a/packages/connect-react/src/components/RemoteOptionsContainer.tsx +++ b/packages/connect-react/src/components/RemoteOptionsContainer.tsx @@ -8,9 +8,12 @@ import { ControlSelect } from "./ControlSelect"; export type RemoteOptionsContainerProps = { queryEnabled?: boolean; + prevValues?: never; }; -export function RemoteOptionsContainer({ queryEnabled }: RemoteOptionsContainerProps) { +export function RemoteOptionsContainer({ + queryEnabled, prevValues, +}: RemoteOptionsContainerProps) { const client = useFrontendClient(); const { userId, From e426ed61edc530288f0fadbdbb08fdfb842c7b4c Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 15:20:46 -0600 Subject: [PATCH 05/13] Update package --- .../examples/nextjs/package-lock.json | 2 +- pnpm-lock.yaml | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/connect-react/examples/nextjs/package-lock.json b/packages/connect-react/examples/nextjs/package-lock.json index 2190193a49061..b9b2f2471f8a8 100644 --- a/packages/connect-react/examples/nextjs/package-lock.json +++ b/packages/connect-react/examples/nextjs/package-lock.json @@ -23,7 +23,7 @@ }, "../..": { "name": "@pipedream/connect-react", - "version": "1.0.0-preview.22", + "version": "1.0.0-preview.23", "license": "MIT", "dependencies": { "@pipedream/sdk": "workspace:^", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a55bc744e4c8f..33c1996281eff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -997,8 +997,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/azure_api_for_fhir: - specifiers: {} + components/azure_api_for_fhir: {} components/azure_devops: dependencies: @@ -3416,8 +3415,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/exist: - specifiers: {} + components/exist: {} components/expedy: dependencies: @@ -4746,8 +4744,7 @@ importers: components/hasura: {} - components/have_i_been_pwned: - specifiers: {} + components/have_i_been_pwned: {} components/heartbeat: {} @@ -6612,8 +6609,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/mindbody: - specifiers: {} + components/mindbody: {} components/mindmeister: {} @@ -7668,8 +7664,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/paylocity: - specifiers: {} + components/paylocity: {} components/paymo: dependencies: @@ -12083,8 +12078,7 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/yext: - specifiers: {} + components/yext: {} components/yoast_seo: {} From 3eacf9b531fcd4926f77e46d80aac4426e0977fc Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 15:21:12 -0600 Subject: [PATCH 06/13] Pass prevValues to RemoteOptionsContainer --- packages/connect-react/src/components/Control.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/connect-react/src/components/Control.tsx b/packages/connect-react/src/components/Control.tsx index 23007e459a417..ebb0424c33a71 100644 --- a/packages/connect-react/src/components/Control.tsx +++ b/packages/connect-react/src/components/Control.tsx @@ -24,14 +24,14 @@ export function Control } = props; const { queryDisabledIdx } = form; const { - prop, idx, + prop, idx, value, } = field; const app = "app" in field.extra ? field.extra.app : undefined; if (prop.remoteOptions || prop.type === "$.discord.channel") { - return = idx} />; + return = idx} />; } if ("options" in prop && prop.options) { From 838b18980e2a435c0db3e597dd68c17f84d419f3 Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 17:00:55 -0600 Subject: [PATCH 07/13] Ensure propsNeedConfiguring is updated after field registration --- packages/connect-react/src/hooks/form-context.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/connect-react/src/hooks/form-context.tsx b/packages/connect-react/src/hooks/form-context.tsx index 6c0634a15918a..6bc735a1cd58c 100644 --- a/packages/connect-react/src/hooks/form-context.tsx +++ b/packages/connect-react/src/hooks/form-context.tsx @@ -365,6 +365,9 @@ export const FormContextProvider = ({ } } // propsNeedConfiguring.splice(0, propsNeedConfiguring.length, ..._propsNeedConfiguring) + // For some reason registerField is called in recursive loop if an empty + // propsNeedConfiguring is set to an empty _propsNeedConfiguring + if (!propsNeedConfiguring.length && !_propsNeedConfiguring.length) return setPropsNeedConfiguring(_propsNeedConfiguring) } @@ -373,6 +376,7 @@ export const FormContextProvider = ({ fields[field.prop.name] = field return fields }); + checkPropsNeedConfiguring() }; // console.log("***", configurableProps, configuredProps) From 34ca0dab863427add1423059a2e2026e5e995656 Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 17:14:14 -0600 Subject: [PATCH 08/13] Remove checkPropsNeedConfiguring call --- packages/connect-react/src/hooks/form-context.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/connect-react/src/hooks/form-context.tsx b/packages/connect-react/src/hooks/form-context.tsx index 6bc735a1cd58c..6c0634a15918a 100644 --- a/packages/connect-react/src/hooks/form-context.tsx +++ b/packages/connect-react/src/hooks/form-context.tsx @@ -365,9 +365,6 @@ export const FormContextProvider = ({ } } // propsNeedConfiguring.splice(0, propsNeedConfiguring.length, ..._propsNeedConfiguring) - // For some reason registerField is called in recursive loop if an empty - // propsNeedConfiguring is set to an empty _propsNeedConfiguring - if (!propsNeedConfiguring.length && !_propsNeedConfiguring.length) return setPropsNeedConfiguring(_propsNeedConfiguring) } @@ -376,7 +373,6 @@ export const FormContextProvider = ({ fields[field.prop.name] = field return fields }); - checkPropsNeedConfiguring() }; // console.log("***", configurableProps, configuredProps) From 324d958a87a493ff6fd2791b241d2bff013bca5e Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 17:15:41 -0600 Subject: [PATCH 09/13] Cleanup --- packages/connect-react/src/components/ControlSelect.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/connect-react/src/components/ControlSelect.tsx b/packages/connect-react/src/components/ControlSelect.tsx index c9a104e33c8de..1543c99f54144 100644 --- a/packages/connect-react/src/components/ControlSelect.tsx +++ b/packages/connect-react/src/components/ControlSelect.tsx @@ -63,7 +63,6 @@ export function ControlSelect({ }; const selectValue = useMemo(() => { - console.log("rawValue: ", rawValue) let ret = rawValue; if (ret != null) { if (Array.isArray(ret)) { From acc6b47c4450664c863a3b82bda6cd7b774c3903 Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 17:18:30 -0600 Subject: [PATCH 10/13] Cleanup --- packages/connect-react/src/components/ControlSelect.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/connect-react/src/components/ControlSelect.tsx b/packages/connect-react/src/components/ControlSelect.tsx index 1543c99f54144..b7f1be6ae704d 100644 --- a/packages/connect-react/src/components/ControlSelect.tsx +++ b/packages/connect-react/src/components/ControlSelect.tsx @@ -163,8 +163,6 @@ export function ControlSelect({ ] } } - console.log("newRawValue: ", newRawValue) - console.log("newSelectOptions: ", newSelectOptions) setRawValue(newRawValue) handleChange(newRawValue) }; From 3a44c770a3a46efae0d3e08b4cbfcfc6f863f72d Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 17:22:27 -0600 Subject: [PATCH 11/13] Update version and changelog --- packages/connect-react/CHANGELOG.md | 6 ++++++ packages/connect-react/package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/connect-react/CHANGELOG.md b/packages/connect-react/CHANGELOG.md index f648366d74be0..af8ac173e64a3 100644 --- a/packages/connect-react/CHANGELOG.md +++ b/packages/connect-react/CHANGELOG.md @@ -1,6 +1,12 @@ # Changelog +# [1.0.0-preview.24] - 2025-01-24 + +- Fix the bug where inputting multiple strings into an array prop would merge the strings into one +- Fix custom string input for remote options +- Fix the reloading of a previously selected remote option when re-rendering the form component + # [1.0.0-preview.23] - 2025-01-22 - Show the prop label instead of the value after selecting from a dropdown for string array props diff --git a/packages/connect-react/package.json b/packages/connect-react/package.json index 15dfa2f466b1b..b4c52d6571bd7 100644 --- a/packages/connect-react/package.json +++ b/packages/connect-react/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/connect-react", - "version": "1.0.0-preview.23", + "version": "1.0.0-preview.24", "description": "Pipedream Connect library for React", "files": [ "dist" From 238bfea6e1e528e51fd8fdc7c1b0769f502795f7 Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Fri, 24 Jan 2025 17:23:40 -0600 Subject: [PATCH 12/13] Commit pnpm-lock.yaml --- pnpm-lock.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3183cb0fdb21a..09d98effc5dfb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9279,8 +9279,7 @@ importers: specifier: 3.0.1 version: 3.0.1 - components/seen: - specifiers: {} + components/seen: {} components/segment: dependencies: From 3803fdb8904dd0740259a74c7f46db287d40e5a8 Mon Sep 17 00:00:00 2001 From: Biz Melesse Date: Mon, 27 Jan 2025 13:00:44 -0600 Subject: [PATCH 13/13] Remove unused prevValue --- packages/connect-react/examples/nextjs/package-lock.json | 2 +- packages/connect-react/src/components/Control.tsx | 4 ++-- .../connect-react/src/components/RemoteOptionsContainer.tsx | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/connect-react/examples/nextjs/package-lock.json b/packages/connect-react/examples/nextjs/package-lock.json index b9b2f2471f8a8..9d9ef59557722 100644 --- a/packages/connect-react/examples/nextjs/package-lock.json +++ b/packages/connect-react/examples/nextjs/package-lock.json @@ -23,7 +23,7 @@ }, "../..": { "name": "@pipedream/connect-react", - "version": "1.0.0-preview.23", + "version": "1.0.0-preview.24", "license": "MIT", "dependencies": { "@pipedream/sdk": "workspace:^", diff --git a/packages/connect-react/src/components/Control.tsx b/packages/connect-react/src/components/Control.tsx index ebb0424c33a71..23007e459a417 100644 --- a/packages/connect-react/src/components/Control.tsx +++ b/packages/connect-react/src/components/Control.tsx @@ -24,14 +24,14 @@ export function Control } = props; const { queryDisabledIdx } = form; const { - prop, idx, value, + prop, idx, } = field; const app = "app" in field.extra ? field.extra.app : undefined; if (prop.remoteOptions || prop.type === "$.discord.channel") { - return = idx} />; + return = idx} />; } if ("options" in prop && prop.options) { diff --git a/packages/connect-react/src/components/RemoteOptionsContainer.tsx b/packages/connect-react/src/components/RemoteOptionsContainer.tsx index d391d696ec455..d606bee52f6c0 100644 --- a/packages/connect-react/src/components/RemoteOptionsContainer.tsx +++ b/packages/connect-react/src/components/RemoteOptionsContainer.tsx @@ -8,12 +8,9 @@ import { ControlSelect } from "./ControlSelect"; export type RemoteOptionsContainerProps = { queryEnabled?: boolean; - prevValues?: never; }; -export function RemoteOptionsContainer({ - queryEnabled, prevValues, -}: RemoteOptionsContainerProps) { +export function RemoteOptionsContainer({ queryEnabled }: RemoteOptionsContainerProps) { const client = useFrontendClient(); const { userId,