diff --git a/backend/onyx/connectors/salesforce/connector.py b/backend/onyx/connectors/salesforce/connector.py index 79df97e10e1..64bc1164173 100644 --- a/backend/onyx/connectors/salesforce/connector.py +++ b/backend/onyx/connectors/salesforce/connector.py @@ -438,7 +438,7 @@ def _full_sync( ) -> GenerateDocumentsOutput: type_to_processed: dict[str, int] = {} - logger.info("_fetch_from_salesforce starting.") + logger.info("_fetch_from_salesforce starting (full sync).") if not self._sf_client: raise RuntimeError("self._sf_client is None!") @@ -622,7 +622,7 @@ def _delta_sync( ) -> GenerateDocumentsOutput: type_to_processed: dict[str, int] = {} - logger.info("_fetch_from_salesforce starting.") + logger.info("_fetch_from_salesforce starting (delta sync).") if not self._sf_client: raise RuntimeError("self._sf_client is None!") @@ -936,12 +936,28 @@ def _make_context( child_types_all = sf_client.get_children_of_sf_type(parent_type) logger.debug(f"Found {len(child_types_all)} child types for {parent_type}") + logger.debug(f"child types: {child_types_all}") child_types_working = child_types_all.copy() if associations_config is not None: child_types_working = { k: v for k, v in child_types_all.items() if k in associations_config } + any_not_found = False + for k in associations_config: + if k not in child_types_working: + any_not_found = True + logger.warning(f"Association {k} not found in {parent_type}") + if any_not_found: + queryable_fields = sf_client.get_queryable_fields_by_type( + parent_type + ) + raise RuntimeError( + f"Associations {associations_config} not found in {parent_type} " + "make sure your parent-child associations are in the right order" + # f"with child objects {child_types_all}" + # f" and fields {queryable_fields}" + ) parent_to_child_relationships[parent_type] = set() parent_to_child_types[parent_type] = set() diff --git a/web/src/components/Field.tsx b/web/src/components/Field.tsx index c254c709478..26c2fed79df 100644 --- a/web/src/components/Field.tsx +++ b/web/src/components/Field.tsx @@ -38,6 +38,7 @@ import { transformLinkUri } from "@/lib/utils"; import FileInput from "@/app/admin/connectors/[connector]/pages/ConnectorInput/FileInput"; import { DatePicker } from "./ui/datePicker"; import { Textarea, TextareaProps } from "./ui/textarea"; +import { RichTextSubtext } from "./RichTextSubtext"; import { TypedFile, createTypedFile, @@ -92,6 +93,18 @@ export function SubLabel({ children }: { children: string | JSX.Element }) { // Add whitespace-pre-wrap for multiline descriptions (when children is a string with newlines) const hasNewlines = typeof children === "string" && children.includes("\n"); + // If children is a string, use RichTextSubtext to parse and render links + if (typeof children === "string") { + return ( +
+ +
+ ); + } + return (
{ + const elements: React.ReactNode[] = []; + + // Regex to match markdown links [text](url) and plain URLs + const combinedRegex = /(\[([^\]]+)\]\(([^)]+)\))|(https?:\/\/[^\s]+)/g; + + let lastIndex = 0; + let match; + let key = 0; + + while ((match = combinedRegex.exec(input)) !== null) { + // Add text before the match + if (match.index > lastIndex) { + elements.push( + + {input.slice(lastIndex, match.index)} + + ); + } + + if (match[1]) { + // Markdown-style link [text](url) + const linkText = match[2]; + const url = match[3]; + elements.push( + e.stopPropagation()} + > + {linkText} + + ); + } else if (match[4]) { + // Plain URL + const url = match[4]; + elements.push( + e.stopPropagation()} + > + {url} + + ); + } + + lastIndex = match.index + match[0].length; + } + + // Add remaining text after the last match + if (lastIndex < input.length) { + elements.push( + {input.slice(lastIndex)} + ); + } + + return elements; + }; + + return
{parseText(text)}
; +} diff --git a/web/src/lib/connectors/connectors.tsx b/web/src/lib/connectors/connectors.tsx index e8329aeaf64..835b43ad830 100644 --- a/web/src/lib/connectors/connectors.tsx +++ b/web/src/lib/connectors/connectors.tsx @@ -638,15 +638,12 @@ Example: "Account": { "fields": ["Id", "Name", "Industry"], "associations": { - "Contact": { - "fields": ["Id", "FirstName", "LastName", "Email"], - "associations": {} - } + "Contact": ["Id", "FirstName", "LastName", "Email"] } } } -See our docs for more details.`, +[See our docs](https://docs.onyx.app/connectors/salesforce) for more details.`, }, ], },