Skip to content

Commit 030df2b

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 030df2b

1 file changed

Lines changed: 28 additions & 3 deletions

File tree

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,36 @@ 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+
* Paginated selectors drain in the background and the combobox filters
79+
* client-side, so a not-yet-drained option is genuinely absent from the list.
80+
* Saying "none found" there reads as "it does not exist" and sends users off to
81+
* enter the value by hand — say the list is still filling instead, and be honest
82+
* when the drain stopped early.
83+
*
84+
* `error` is checked first: the drain halts on a failed page but leaves
85+
* `hasMore` set, so a failure would otherwise claim to be loading forever.
86+
*/
87+
const emptyMessage = useMemo(() => {
88+
const noun = field.title.toLowerCase()
89+
if (error) return `Could not load ${noun} — enter the value directly`
90+
if (hasMore || isFetchingMore) return `Still loading ${noun}…`
91+
if (truncated) return `Too many ${noun} to list — enter the value directly`
92+
return `No ${noun} found`
93+
}, [field.title, error, hasMore, isFetchingMore, truncated])
94+
7095
const comboboxOptions = useMemo<ComboboxOption[]>(
7196
() => options.map((opt) => ({ label: opt.label, value: opt.id })),
7297
[options]
@@ -99,7 +124,7 @@ export function ConnectorSelectorField({
99124
: field.placeholder || `Select ${field.title.toLowerCase()}`
100125
}
101126
disabled={disabled || !credentialId || !depsResolved}
102-
emptyMessage={`No ${field.title.toLowerCase()} found`}
127+
emptyMessage={emptyMessage}
103128
/>
104129
)
105130
}
@@ -120,7 +145,7 @@ export function ConnectorSelectorField({
120145
: field.placeholder || `Select ${field.title.toLowerCase()}`
121146
}
122147
disabled={disabled || !credentialId || !depsResolved}
123-
emptyMessage={`No ${field.title.toLowerCase()} found`}
148+
emptyMessage={emptyMessage}
124149
/>
125150
)
126151
}

0 commit comments

Comments
 (0)