Skip to content

Commit 3f145fc

Browse files
committed
fix(connectors): stop the connector selector implying an option does not exist
The connector selector field ignored the drain state the shared selector hook already exposes. Paginated selectors fill in the background and the combobox filters client-side, so a not-yet-drained option is genuinely absent from the list — and the dropdown said "No spaces found", which reads as "this space does not exist" and sends users off to enter the value by hand. That is what happened with a Confluence space on a site with thousands of personal spaces. It now reports that the list is still filling, surfaces a failed drain instead of claiming to load forever, and is honest when the drain stops at its page cap.
1 parent c77300f commit 3f145fc

1 file changed

Lines changed: 33 additions & 3 deletions

File tree

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-selector-field/connector-selector-field.tsx

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,41 @@ export function ConnectorSelectorField({
6262
}, [field.dependsOn, sourceConfig, configFields, canonicalModes])
6363

6464
const isEnabled = !disabled && !!credentialId && depsResolved
65-
const { data: options = [], isLoading } = useSelectorOptions(field.selectorKey, {
65+
const {
66+
data: options = [],
67+
isLoading,
68+
hasMore,
69+
isFetchingMore,
70+
truncated,
71+
error,
72+
} = useSelectorOptions(field.selectorKey, {
6673
context,
6774
enabled: isEnabled,
6875
})
6976

77+
/**
78+
* Shown when the combobox has nothing to display. `isLoading` renders a spinner
79+
* instead until the first page lands, so by the time this is visible the list has
80+
* loaded at least once and is empty because the user's search matched none of the
81+
* options loaded *so far* — the wording is phrased for that case.
82+
*
83+
* Paginated selectors drain in the background and filter client-side, so an
84+
* option that has not drained yet is genuinely absent. A flat "none found" reads
85+
* as "it does not exist" and sends users off to enter the value by hand, which is
86+
* exactly what happened with a Confluence space on a site whose drain runs for
87+
* ~38s. Each branch instead explains why the list may still be incomplete.
88+
*
89+
* `error` is checked first: the drain halts on a failed page but leaves `hasMore`
90+
* set, so a failure would otherwise claim to be loading forever.
91+
*/
92+
const emptyMessage = useMemo(() => {
93+
const noun = field.title.toLowerCase()
94+
if (error) return `No match — could not load all ${noun}. Enter the value directly`
95+
if (hasMore || isFetchingMore) return `No match yet — still loading ${noun}…`
96+
if (truncated) return `No match in the ${noun} loaded — enter the value directly`
97+
return `No ${noun} found`
98+
}, [field.title, error, hasMore, isFetchingMore, truncated])
99+
70100
const comboboxOptions = useMemo<ComboboxOption[]>(
71101
() => options.map((opt) => ({ label: opt.label, value: opt.id })),
72102
[options]
@@ -99,7 +129,7 @@ export function ConnectorSelectorField({
99129
: field.placeholder || `Select ${field.title.toLowerCase()}`
100130
}
101131
disabled={disabled || !credentialId || !depsResolved}
102-
emptyMessage={`No ${field.title.toLowerCase()} found`}
132+
emptyMessage={emptyMessage}
103133
/>
104134
)
105135
}
@@ -120,7 +150,7 @@ export function ConnectorSelectorField({
120150
: field.placeholder || `Select ${field.title.toLowerCase()}`
121151
}
122152
disabled={disabled || !credentialId || !depsResolved}
123-
emptyMessage={`No ${field.title.toLowerCase()} found`}
153+
emptyMessage={emptyMessage}
124154
/>
125155
)
126156
}

0 commit comments

Comments
 (0)