@salesforce/templates 66.13.5 → 66.13.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/templates/project/angularextapp/CHANGELOG.md +258 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/angular.json +1 -1
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/eslint-plugin-angular-graphql.js +148 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/eslint.config.js +9 -1
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package-lock.json +680 -408
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package.json +2 -2
- package/lib/templates/project/angularextapp/package.json +1 -1
- package/lib/templates/project/angularextapp/scripts/org-setup-config-schema.mjs +17 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-utils.mjs +33 -3
- package/lib/templates/project/angularextapp/scripts/org-setup.mjs +535 -3
- package/lib/templates/project/angularintapp/CHANGELOG.md +266 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/angular.json +1 -1
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/eslint-plugin-angular-graphql.js +148 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/eslint.config.js +9 -1
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package-lock.json +690 -418
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package.json +2 -2
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/agentforce/agentforce-embed.service.ts +6 -1
- package/lib/templates/project/angularintapp/package.json +1 -1
- package/lib/templates/project/angularintapp/scripts/org-setup-config-schema.mjs +17 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-utils.mjs +33 -3
- package/lib/templates/project/angularintapp/scripts/org-setup.mjs +535 -3
- package/lib/templates/project/reactexternalapp/CHANGELOG.md +1409 -0
- package/lib/templates/project/reactexternalapp/PRD.md +38 -0
- package/lib/templates/project/reactexternalapp/README.md +14 -10
- package/lib/templates/project/reactexternalapp/_p_/_m_/_ps_/reactexternalapp_Guest_User_Api_Access.permissionset-meta.xml +25 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package-lock.json +953 -714
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package.json +9 -7
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/scripts/get-graphql-schema.mjs +8 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/LanguageSwitcher.tsx +116 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/__examples__/language-switcher-example.tsx +36 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/__examples__/vite-config-site-example.ts +44 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/buildLanguageUrl.ts +158 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/index.ts +28 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/languages.ts +46 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/components/SocialLogin.tsx +141 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Login.tsx +2 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +246 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/apiUtils.ts +56 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/orgApiVersionService.ts +37 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +116 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/channelResolver.ts +40 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +97 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeSessionCache.ts +134 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +38 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/hooks/useSearchableContentTypes.ts +128 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +54 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/parseResponse.ts +65 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +15 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/types.ts +66 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/registry.ts +38 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/index.ts +19 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/parseResponse.ts +56 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/queryFragment.ts +141 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +101 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/distinctValuesService.ts +84 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/searchService.ts +136 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/GlobalSearchBox.tsx +98 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +294 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/Search.tsx +203 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +88 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +187 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/PaginationControls.tsx +185 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/ScopeSelector.tsx +107 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SearchBar.tsx +55 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SortControl.tsx +62 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/ActiveFilters.tsx +61 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +125 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_/components → search/components/filters}/FilterContext.tsx +7 -20
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/BooleanFilter.tsx +50 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/DateRangeFilter.tsx +160 -0
- package/lib/templates/project/{reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters → reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs}/FilterFieldWrapper.tsx +11 -6
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/MultiSelectFilter.tsx +89 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/NumericRangeFilter.tsx +108 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/SelectFilter.tsx +46 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/TextFilter.tsx +52 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/CmsResultRow.tsx +101 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/DefaultResultRow.tsx +109 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/resolveResultRenderer.ts +49 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/config.json +88 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/constants.ts +8 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_ → search}/hooks/useAsyncData.ts +3 -10
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useDistinctValues.ts +59 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +966 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/index.ts +115 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/loadConfig.ts +14 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/queryBuilder.ts +100 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/types.ts +376 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/debounce.ts +17 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/fieldUtils.ts +14 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +285 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/sortUtils.ts +34 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/graphqlClient.ts +24 -8
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/appLayout.tsx +7 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/CustomerWebClientChat.tsx +74 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/components → components}/ObjectBreadcrumb.tsx +7 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ui/button.tsx +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ui/datePicker.tsx +2 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ui/table.tsx +9 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/index.ts +8 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +53 -18
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +3 -27
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/TestChatPage.tsx +26 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +21 -8
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/types/chat.ts +36 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/types/globals.d.ts +23 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/utils/fieldUtils.ts → utils/accountFields.ts} +9 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/tsconfig.json +2 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls +133 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls-meta.xml +5 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls +101 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls-meta.xml +5 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/package.xml +4 -0
- package/lib/templates/project/reactexternalapp/package.json +8 -2
- package/lib/templates/project/reactexternalapp/scripts/org-setup-config-schema.mjs +120 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup-dev.mjs +87 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup-utils.mjs +569 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup-xml.mjs +182 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup.config.json +6 -2
- package/lib/templates/project/reactexternalapp/scripts/org-setup.mjs +1509 -328
- package/lib/templates/project/reactexternalapp/scripts/validate-org-setup-config.mjs +38 -0
- package/lib/templates/project/reactinternalapp/CHANGELOG.md +1223 -0
- package/lib/templates/project/reactinternalapp/PRD.md +35 -0
- package/lib/templates/project/reactinternalapp/README.md +14 -10
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package-lock.json +813 -538
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package.json +10 -9
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +246 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/apiUtils.ts +56 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/orgApiVersionService.ts +37 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +116 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/channelResolver.ts +40 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +97 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeSessionCache.ts +134 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +38 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/hooks/useSearchableContentTypes.ts +128 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +54 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/parseResponse.ts +65 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +15 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/types.ts +66 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/registry.ts +38 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/index.ts +19 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/parseResponse.ts +56 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/queryFragment.ts +141 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +101 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/distinctValuesService.ts +84 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/searchService.ts +136 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/GlobalSearchBox.tsx +98 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +294 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/Search.tsx +203 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +88 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +187 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/PaginationControls.tsx +185 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/ScopeSelector.tsx +107 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SearchBar.tsx +55 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SortControl.tsx +62 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/ActiveFilters.tsx +61 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +125 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_/components → search/components/filters}/FilterContext.tsx +7 -20
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/BooleanFilter.tsx +50 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/DateRangeFilter.tsx +160 -0
- package/lib/templates/project/{reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters → reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs}/FilterFieldWrapper.tsx +11 -6
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/MultiSelectFilter.tsx +89 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/NumericRangeFilter.tsx +108 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/SelectFilter.tsx +46 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/TextFilter.tsx +52 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/CmsResultRow.tsx +101 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/DefaultResultRow.tsx +109 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/resolveResultRenderer.ts +49 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/config.json +88 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/constants.ts +8 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_ → search}/hooks/useAsyncData.ts +3 -10
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useDistinctValues.ts +59 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +966 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/index.ts +115 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/loadConfig.ts +14 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/queryBuilder.ts +100 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/types.ts +376 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/debounce.ts +17 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/fieldUtils.ts +14 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +285 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/sortUtils.ts +34 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/AgentforceConversationClient.tsx +16 -132
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/components → components}/ObjectBreadcrumb.tsx +7 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/button.tsx +1 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/datePicker.tsx +2 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/table.tsx +9 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +49 -16
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +3 -27
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +12 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/utils/fieldUtils.ts → utils/accountFields.ts} +9 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/tsconfig.json +2 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -0
- package/lib/templates/project/reactinternalapp/package.json +4 -2
- package/lib/templates/project/reactinternalapp/scripts/org-setup-config-schema.mjs +24 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup-dev.mjs +87 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup-utils.mjs +569 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup-xml.mjs +182 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup.mjs +1162 -214
- package/lib/templates/uiBundles/angularbasic/angular.json +1 -1
- package/lib/templates/uiBundles/angularbasic/eslint-plugin-angular-graphql.js +148 -0
- package/lib/templates/uiBundles/angularbasic/eslint.config.js +9 -1
- package/lib/templates/uiBundles/angularbasic/package-lock.json +680 -408
- package/lib/templates/uiBundles/angularbasic/package.json +2 -2
- package/lib/templates/uiBundles/reactbasic/package-lock.json +738 -440
- package/lib/utils/template-placeholders.js +14 -0
- package/lib/utils/template-placeholders.js.map +1 -1
- package/lib/utils/uiBundleTemplateUtils.d.ts +5 -1
- package/lib/utils/uiBundleTemplateUtils.js +7 -1
- package/lib/utils/uiBundleTemplateUtils.js.map +1 -1
- package/package.json +7 -7
- package/lib/templates/project/reactexternalapp/AGENT.md +0 -252
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/accountSearchService.ts +0 -46
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountIndustries.graphql +0 -19
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountTypes.graphql +0 -19
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/getAccountDetail.graphql +0 -121
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/searchAccounts.graphql +0 -51
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountObjectDetailPage.tsx +0 -355
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +0 -304
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/Home.tsx +0 -34
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/api/objectSearchService.ts +0 -82
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/ActiveFilters.tsx +0 -89
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/PaginationControls.tsx +0 -109
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SearchBar.tsx +0 -41
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SortControl.tsx +0 -143
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +0 -78
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +0 -128
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +0 -70
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +0 -97
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +0 -167
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +0 -52
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +0 -97
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +0 -93
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +0 -34
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +0 -254
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +0 -25
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +0 -404
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/sortUtils.ts +0 -38
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +0 -46
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +0 -19
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +0 -19
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +0 -51
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/graphql-operations-types.ts +0 -11260
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +0 -297
- package/lib/templates/project/reactexternalapp/scripts/prepare-import-unique-fields.js +0 -122
- package/lib/templates/project/reactinternalapp/AGENT.md +0 -252
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/accountSearchService.ts +0 -46
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountIndustries.graphql +0 -19
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountTypes.graphql +0 -19
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/getAccountDetail.graphql +0 -121
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/searchAccounts.graphql +0 -51
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountObjectDetailPage.tsx +0 -355
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +0 -304
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/Home.tsx +0 -34
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/api/objectSearchService.ts +0 -82
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/ActiveFilters.tsx +0 -89
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/PaginationControls.tsx +0 -109
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SearchBar.tsx +0 -41
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SortControl.tsx +0 -143
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +0 -78
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +0 -128
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +0 -70
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +0 -97
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +0 -167
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +0 -52
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +0 -97
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +0 -93
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +0 -34
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +0 -254
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +0 -25
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +0 -404
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/sortUtils.ts +0 -38
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +0 -46
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +0 -19
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +0 -19
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +0 -51
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/graphql-operations-types.ts +0 -11260
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +0 -297
- package/lib/templates/project/reactinternalapp/scripts/prepare-import-unique-fields.js +0 -122
- /package/lib/templates/project/angularextapp/_p_/_m_/{permissionsets → _ps_}/angularextapp_Guest_User_Api_Access.permissionset-meta.xml +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/{permissionsets → _ps_}/angularintapp_Access.permissionset-meta.xml +0 -0
- /package/lib/templates/project/reactinternalapp/_p_/_m_/{permissionsets → _ps_}/reactinternalapp_Access.permissionset-meta.xml +0 -0
package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter primitives for search.
|
|
3
|
+
*
|
|
4
|
+
* Two responsibilities:
|
|
5
|
+
* 1. Build a GraphQL `where` clause from a list of active filter values.
|
|
6
|
+
* 2. Serialize/deserialize active filters to/from URLSearchParams under a
|
|
7
|
+
* per-source namespace prefix (so multiple sources can coexist on one URL).
|
|
8
|
+
*
|
|
9
|
+
* The URL helpers are namespaced: each source declares its key, and filter
|
|
10
|
+
* params are written as `s.<key>.f.<field>=...`. Sort uses
|
|
11
|
+
* `s.<key>.sort=<field>&s.<key>.dir=ASC|DESC`. Page size and page index use
|
|
12
|
+
* `s.<key>.ps=<size>` and `s.<key>.page=<n>`.
|
|
13
|
+
*
|
|
14
|
+
* The global search term `q=...` is **not** scoped to a source — it's broadcast
|
|
15
|
+
* to every source's `searchableFields` by the query builder.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { SortState } from "./sortUtils";
|
|
19
|
+
|
|
20
|
+
export type FilterFieldType =
|
|
21
|
+
| "text"
|
|
22
|
+
| "picklist"
|
|
23
|
+
| "numeric"
|
|
24
|
+
| "boolean"
|
|
25
|
+
| "date"
|
|
26
|
+
| "daterange"
|
|
27
|
+
| "datetime"
|
|
28
|
+
| "datetimerange"
|
|
29
|
+
| "multipicklist";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Which comparison UI a date/datetime filter exposes:
|
|
33
|
+
* - `"range"`: a single Between control (two date inputs, lower–upper bound).
|
|
34
|
+
* - `"comparison"`: an After / Before selector with one date input.
|
|
35
|
+
* - `"both"`: a Between / After / Before selector that switches between the two.
|
|
36
|
+
*
|
|
37
|
+
* Applies only to the date-family `type`s (`date`, `daterange`, `datetime`,
|
|
38
|
+
* `datetimerange`); ignored for other field types. Defaults to `"comparison"`.
|
|
39
|
+
*/
|
|
40
|
+
export type DateFilterMode = "range" | "comparison" | "both";
|
|
41
|
+
|
|
42
|
+
export type FilterFieldConfig<TFieldName extends string = string> = {
|
|
43
|
+
field: TFieldName;
|
|
44
|
+
label: string;
|
|
45
|
+
type: FilterFieldType;
|
|
46
|
+
placeholder?: string;
|
|
47
|
+
/** Required for picklist / multipicklist. */
|
|
48
|
+
options?: Array<{ value: string; label: string }>;
|
|
49
|
+
/** Date-family only — see {@link DateFilterMode}. Defaults to `"comparison"`. */
|
|
50
|
+
dateMode?: DateFilterMode;
|
|
51
|
+
helpText?: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type ActiveFilterValue<TFieldName extends string = string> = {
|
|
55
|
+
field: TFieldName;
|
|
56
|
+
label: string;
|
|
57
|
+
type: FilterFieldType;
|
|
58
|
+
value?: string;
|
|
59
|
+
min?: string;
|
|
60
|
+
max?: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// URL serialization (per-source namespace)
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
const SOURCE_PREFIX = "s.";
|
|
68
|
+
const FILTER_INFIX = ".f.";
|
|
69
|
+
const SORT_SUFFIX = ".sort";
|
|
70
|
+
const DIR_SUFFIX = ".dir";
|
|
71
|
+
const PAGE_SIZE_SUFFIX = ".ps";
|
|
72
|
+
const PAGE_SUFFIX = ".page";
|
|
73
|
+
|
|
74
|
+
/** Global search term key (not source-scoped). */
|
|
75
|
+
export const GLOBAL_QUERY_KEY = "q";
|
|
76
|
+
|
|
77
|
+
function filterKey(sourceKey: string, field: string, suffix?: string) {
|
|
78
|
+
return `${SOURCE_PREFIX}${sourceKey}${FILTER_INFIX}${field}${suffix ? `.${suffix}` : ""}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The source's own default sort / page size. When a source's current state
|
|
83
|
+
* matches these, the corresponding URL params are omitted so the query string
|
|
84
|
+
* only ever reflects an *explicit* user choice — resetting filters or returning
|
|
85
|
+
* a source to its defaults yields a clean URL instead of one littered with the
|
|
86
|
+
* defaults. The read path falls back to these same defaults when the params are
|
|
87
|
+
* absent, so the round-trip is lossless.
|
|
88
|
+
*/
|
|
89
|
+
export interface SourceParamDefaults {
|
|
90
|
+
sort?: SortState | null;
|
|
91
|
+
pageSize?: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function sortMatchesDefault(sort: SortState, defaultSort: SortState | null | undefined): boolean {
|
|
95
|
+
return (
|
|
96
|
+
!!defaultSort && sort.field === defaultSort.field && sort.direction === defaultSort.direction
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function writeSourceParams(
|
|
101
|
+
params: URLSearchParams,
|
|
102
|
+
sourceKey: string,
|
|
103
|
+
filters: ActiveFilterValue[],
|
|
104
|
+
sort: SortState | null,
|
|
105
|
+
pageSize?: number,
|
|
106
|
+
pageIndex?: number,
|
|
107
|
+
defaults?: SourceParamDefaults,
|
|
108
|
+
): void {
|
|
109
|
+
for (const filter of filters) {
|
|
110
|
+
if (filter.value !== undefined && filter.value !== "") {
|
|
111
|
+
params.set(filterKey(sourceKey, filter.field), filter.value);
|
|
112
|
+
}
|
|
113
|
+
if (filter.min !== undefined && filter.min !== "") {
|
|
114
|
+
params.set(filterKey(sourceKey, filter.field, "min"), filter.min);
|
|
115
|
+
}
|
|
116
|
+
if (filter.max !== undefined && filter.max !== "") {
|
|
117
|
+
params.set(filterKey(sourceKey, filter.field, "max"), filter.max);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Only serialize sort when it differs from the source default — otherwise
|
|
121
|
+
// the URL would carry the default the user never chose.
|
|
122
|
+
if (sort && !sortMatchesDefault(sort, defaults?.sort)) {
|
|
123
|
+
params.set(`${SOURCE_PREFIX}${sourceKey}${SORT_SUFFIX}`, sort.field);
|
|
124
|
+
params.set(`${SOURCE_PREFIX}${sourceKey}${DIR_SUFFIX}`, sort.direction);
|
|
125
|
+
}
|
|
126
|
+
if (pageSize !== undefined && pageSize !== defaults?.pageSize) {
|
|
127
|
+
params.set(`${SOURCE_PREFIX}${sourceKey}${PAGE_SIZE_SUFFIX}`, String(pageSize));
|
|
128
|
+
}
|
|
129
|
+
if (pageIndex !== undefined && pageIndex > 0) {
|
|
130
|
+
params.set(`${SOURCE_PREFIX}${sourceKey}${PAGE_SUFFIX}`, String(pageIndex + 1));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface ReadSourceParamsResult {
|
|
135
|
+
filters: ActiveFilterValue[];
|
|
136
|
+
sort: SortState | null;
|
|
137
|
+
pageSize: number | undefined;
|
|
138
|
+
pageIndex: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function readSourceParams(
|
|
142
|
+
params: URLSearchParams,
|
|
143
|
+
sourceKey: string,
|
|
144
|
+
configs: FilterFieldConfig[],
|
|
145
|
+
): ReadSourceParamsResult {
|
|
146
|
+
const filters: ActiveFilterValue[] = [];
|
|
147
|
+
for (const config of configs) {
|
|
148
|
+
const { field, label, type } = config;
|
|
149
|
+
const value = params.get(filterKey(sourceKey, field)) ?? undefined;
|
|
150
|
+
const min = params.get(filterKey(sourceKey, field, "min")) ?? undefined;
|
|
151
|
+
const max = params.get(filterKey(sourceKey, field, "max")) ?? undefined;
|
|
152
|
+
|
|
153
|
+
const hasValue = value !== undefined && value !== "";
|
|
154
|
+
const hasRange = (min !== undefined && min !== "") || (max !== undefined && max !== "");
|
|
155
|
+
if (hasValue || hasRange) {
|
|
156
|
+
filters.push({ field, label, type, value, min, max });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let sort: SortState | null = null;
|
|
161
|
+
const sortField = params.get(`${SOURCE_PREFIX}${sourceKey}${SORT_SUFFIX}`);
|
|
162
|
+
const sortDir = params.get(`${SOURCE_PREFIX}${sourceKey}${DIR_SUFFIX}`);
|
|
163
|
+
if (sortField) {
|
|
164
|
+
sort = { field: sortField, direction: sortDir === "DESC" ? "DESC" : "ASC" };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const pageSizeRaw = params.get(`${SOURCE_PREFIX}${sourceKey}${PAGE_SIZE_SUFFIX}`);
|
|
168
|
+
const pageSize = pageSizeRaw ? parseInt(pageSizeRaw, 10) : undefined;
|
|
169
|
+
const pageRaw = params.get(`${SOURCE_PREFIX}${sourceKey}${PAGE_SUFFIX}`);
|
|
170
|
+
const page = pageRaw ? parseInt(pageRaw, 10) : 1;
|
|
171
|
+
const pageIndex = !isNaN(page) && page > 1 ? page - 1 : 0;
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
filters,
|
|
175
|
+
sort,
|
|
176
|
+
pageSize: pageSize && !isNaN(pageSize) ? pageSize : undefined,
|
|
177
|
+
pageIndex,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
// GraphQL filter building
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Combines active filter values into a GraphQL `where` clause for one source.
|
|
187
|
+
* Returns `undefined` when no constraints are active.
|
|
188
|
+
*/
|
|
189
|
+
export function buildFilter(filters: ActiveFilterValue[], configs: FilterFieldConfig[]): unknown {
|
|
190
|
+
const configMap = new Map(configs.map((c) => [c.field, c]));
|
|
191
|
+
const clauses: unknown[] = [];
|
|
192
|
+
for (const filter of filters) {
|
|
193
|
+
const clause = buildSingleFilter(filter, configMap.get(filter.field));
|
|
194
|
+
if (clause) clauses.push(clause);
|
|
195
|
+
}
|
|
196
|
+
if (clauses.length === 0) return undefined;
|
|
197
|
+
if (clauses.length === 1) return clauses[0];
|
|
198
|
+
return { and: clauses };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function toStartOfDay(d: string) {
|
|
202
|
+
return `${d}T00:00:00.000Z`;
|
|
203
|
+
}
|
|
204
|
+
function toEndOfDay(d: string) {
|
|
205
|
+
return `${d}T23:59:59.999Z`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function buildSingleFilter(filter: ActiveFilterValue, _config?: FilterFieldConfig): unknown {
|
|
209
|
+
const { field, type, value, min, max } = filter;
|
|
210
|
+
switch (type) {
|
|
211
|
+
case "text": {
|
|
212
|
+
if (!value) return null;
|
|
213
|
+
return { [field]: { like: `%${value}%` } };
|
|
214
|
+
}
|
|
215
|
+
case "picklist": {
|
|
216
|
+
if (!value) return null;
|
|
217
|
+
return { [field]: { eq: value } };
|
|
218
|
+
}
|
|
219
|
+
case "numeric": {
|
|
220
|
+
if (!min && !max) return null;
|
|
221
|
+
const ops: Record<string, number> = {};
|
|
222
|
+
if (min) ops.gte = Number(min);
|
|
223
|
+
if (max) ops.lte = Number(max);
|
|
224
|
+
return { [field]: ops };
|
|
225
|
+
}
|
|
226
|
+
case "boolean": {
|
|
227
|
+
if (value === undefined || value === "") return null;
|
|
228
|
+
return { [field]: { eq: value === "true" } };
|
|
229
|
+
}
|
|
230
|
+
case "multipicklist": {
|
|
231
|
+
if (!value) return null;
|
|
232
|
+
const values = value.split(",").filter(Boolean);
|
|
233
|
+
if (values.length === 0) return null;
|
|
234
|
+
if (values.length === 1) return { [field]: { eq: values[0] } };
|
|
235
|
+
return { [field]: { in: values } };
|
|
236
|
+
}
|
|
237
|
+
case "date": {
|
|
238
|
+
if (!min && !max) return null;
|
|
239
|
+
const op = min ? "gte" : "lte";
|
|
240
|
+
const dateStr = min ?? max;
|
|
241
|
+
return { [field]: { [op]: { value: dateStr } } };
|
|
242
|
+
}
|
|
243
|
+
case "daterange": {
|
|
244
|
+
if (!min && !max) return null;
|
|
245
|
+
const clauses: unknown[] = [];
|
|
246
|
+
if (min) clauses.push({ [field]: { gte: { value: min } } });
|
|
247
|
+
if (max) clauses.push({ [field]: { lte: { value: max } } });
|
|
248
|
+
return clauses.length === 1 ? clauses[0] : { and: clauses };
|
|
249
|
+
}
|
|
250
|
+
case "datetime": {
|
|
251
|
+
if (!min && !max) return null;
|
|
252
|
+
const op = min ? "gte" : "lte";
|
|
253
|
+
const dateStr = min ?? max;
|
|
254
|
+
const isoStr = op === "gte" ? toStartOfDay(dateStr!) : toEndOfDay(dateStr!);
|
|
255
|
+
return { [field]: { [op]: { value: isoStr } } };
|
|
256
|
+
}
|
|
257
|
+
case "datetimerange": {
|
|
258
|
+
if (!min && !max) return null;
|
|
259
|
+
const clauses: unknown[] = [];
|
|
260
|
+
if (min) clauses.push({ [field]: { gte: { value: toStartOfDay(min) } } });
|
|
261
|
+
if (max) clauses.push({ [field]: { lte: { value: toEndOfDay(max) } } });
|
|
262
|
+
return clauses.length === 1 ? clauses[0] : { and: clauses };
|
|
263
|
+
}
|
|
264
|
+
default:
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Builds a global-q `or` clause across the source's searchable fields.
|
|
271
|
+
* Returns `undefined` when q is empty or the source has no searchable fields.
|
|
272
|
+
*/
|
|
273
|
+
export function buildGlobalQueryClause(q: string, searchableFields: string[]): unknown {
|
|
274
|
+
const trimmed = q.trim();
|
|
275
|
+
if (!trimmed || searchableFields.length === 0) return undefined;
|
|
276
|
+
const clauses = searchableFields.map((path) => {
|
|
277
|
+
const parts = path.split(".");
|
|
278
|
+
let clause: Record<string, unknown> = { like: `%${trimmed}%` };
|
|
279
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
280
|
+
clause = { [parts[i]]: clause };
|
|
281
|
+
}
|
|
282
|
+
return clause;
|
|
283
|
+
});
|
|
284
|
+
return clauses.length === 1 ? clauses[0] : { or: clauses };
|
|
285
|
+
}
|
package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/sortUtils.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort state and order-by builder for search.
|
|
3
|
+
*
|
|
4
|
+
* The order-by output shape matches the Salesforce uiapi GraphQL convention:
|
|
5
|
+
* { [field]: { order: ASC|DESC, nulls: LAST } }
|
|
6
|
+
*
|
|
7
|
+
* The constants are stringly-typed here (rather than imported from codegen)
|
|
8
|
+
* because search builds its query at runtime and isn't tied to a
|
|
9
|
+
* specific generated schema.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type SortFieldConfig<TFieldName extends string = string> = {
|
|
13
|
+
field: TFieldName;
|
|
14
|
+
label: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type SortState<TFieldName extends string = string> = {
|
|
18
|
+
field: TFieldName;
|
|
19
|
+
direction: "ASC" | "DESC";
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const ORDER_ASC = "ASC";
|
|
23
|
+
const ORDER_DESC = "DESC";
|
|
24
|
+
const NULLS_LAST = "LAST";
|
|
25
|
+
|
|
26
|
+
export function buildOrderBy(sort: SortState | null): unknown {
|
|
27
|
+
if (!sort) return undefined;
|
|
28
|
+
return {
|
|
29
|
+
[sort.field]: {
|
|
30
|
+
order: sort.direction === "ASC" ? ORDER_ASC : ORDER_DESC,
|
|
31
|
+
nulls: NULLS_LAST,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -6,59 +6,21 @@
|
|
|
6
6
|
|
|
7
7
|
import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
|
|
8
8
|
import type { AgentforceClientConfig } from "@salesforce/agentforce-conversation-client";
|
|
9
|
+
import { createAccEmbedder } from "@salesforce/agentforce-conversation-client/ui-bundle";
|
|
9
10
|
import { useEffect, useMemo, useRef } from "react";
|
|
10
|
-
import type {
|
|
11
|
-
ResolvedEmbedOptions,
|
|
12
|
-
AgentforceConversationClientProps,
|
|
13
|
-
} from "../types/conversation";
|
|
11
|
+
import type { AgentforceConversationClientProps } from "../types/conversation";
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
initialized: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface WindowWithAgentforceSingleton extends Window {
|
|
24
|
-
[SINGLETON_KEY]?: AgentforceConversationClientSingleton;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
type GlobalWithSfdcEnv = typeof globalThis & {
|
|
28
|
-
SFDC_ENV?: {
|
|
29
|
-
orgUrl?: string;
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
function getSingleton(): AgentforceConversationClientSingleton {
|
|
34
|
-
const win = window as WindowWithAgentforceSingleton;
|
|
35
|
-
if (!win[SINGLETON_KEY]) {
|
|
36
|
-
win[SINGLETON_KEY] = {
|
|
37
|
-
initialized: false,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
return win[SINGLETON_KEY]!;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function getOrCreateGlobalHost(): HTMLDivElement {
|
|
44
|
-
let host = document.getElementById(GLOBAL_HOST_ID) as HTMLDivElement | null;
|
|
45
|
-
if (!host) {
|
|
46
|
-
host = document.createElement("div");
|
|
47
|
-
host.id = GLOBAL_HOST_ID;
|
|
48
|
-
document.body.appendChild(host);
|
|
49
|
-
}
|
|
50
|
-
return host;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function getDefaultEmbedOptions(): ResolvedEmbedOptions {
|
|
54
|
-
const sfdcEnv = (globalThis as GlobalWithSfdcEnv).SFDC_ENV;
|
|
55
|
-
return { salesforceOrigin: sfdcEnv?.orgUrl };
|
|
56
|
-
}
|
|
13
|
+
// The embed orchestration (window singleton, global host, dev frontdoor fetch,
|
|
14
|
+
// SFDC_ENV default, partial-embed cleanup) lives in the shared, framework-agnostic
|
|
15
|
+
// @salesforce/agentforce-conversation-client/ui-bundle glue. We hand it the
|
|
16
|
+
// low-level embed function via dependency injection.
|
|
17
|
+
const embedder = createAccEmbedder<AgentforceClientConfig>(embedAgentforceClient);
|
|
57
18
|
|
|
58
19
|
/**
|
|
59
20
|
* React wrapper that embeds the Agentforce Conversation Client (copilot/agent UI)
|
|
60
21
|
* using Lightning Out. Requires a valid Salesforce session for the given org.
|
|
61
|
-
*
|
|
22
|
+
* Flat props are normalized into an `AgentforceClientConfig` and passed through
|
|
23
|
+
* to the shared embedder as-is.
|
|
62
24
|
*/
|
|
63
25
|
export function AgentforceConversationClient({
|
|
64
26
|
agentId,
|
|
@@ -109,96 +71,18 @@ export function AgentforceConversationClient({
|
|
|
109
71
|
const inline = normalizedAgentforceClientConfig?.renderingConfig?.mode === "inline";
|
|
110
72
|
|
|
111
73
|
useEffect(() => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const singleton = getSingleton();
|
|
120
|
-
if (singleton.initialized || singleton.initPromise) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (inline && !containerRef.current) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const initialize = (options: ResolvedEmbedOptions) => {
|
|
129
|
-
if (singleton.initialized) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
const existingEmbed = document.querySelector('lightning-out-application[data-lo="acc"]');
|
|
133
|
-
if (existingEmbed) {
|
|
134
|
-
singleton.initialized = true;
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
const host = inline ? containerRef.current! : getOrCreateGlobalHost();
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
embedAgentforceClient({
|
|
141
|
-
container: host,
|
|
142
|
-
salesforceOrigin: salesforceOrigin ?? options.salesforceOrigin,
|
|
143
|
-
frontdoorUrl: frontdoorUrl ?? options.frontdoorUrl,
|
|
144
|
-
agentforceClientConfig: normalizedAgentforceClientConfig,
|
|
145
|
-
onReady,
|
|
146
|
-
onError,
|
|
147
|
-
});
|
|
148
|
-
singleton.initialized = true;
|
|
149
|
-
} catch (err) {
|
|
150
|
-
// Strip a partially-created LO element so the next mount can retry.
|
|
151
|
-
const partialEmbed = document.querySelector('lightning-out-application[data-lo="acc"]');
|
|
152
|
-
partialEmbed?.remove();
|
|
153
|
-
console.error("AgentforceConversationClient: initialization failed", err);
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const safeInitialize = (options: ResolvedEmbedOptions) => {
|
|
158
|
-
try {
|
|
159
|
-
initialize(options);
|
|
160
|
-
} catch (initErr) {
|
|
161
|
-
console.error("AgentforceConversationClient: initialization failed", initErr);
|
|
162
|
-
singleton.initialized = false;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const shouldFetchFrontdoor = window.location.hostname === "localhost";
|
|
167
|
-
|
|
168
|
-
if (shouldFetchFrontdoor) {
|
|
169
|
-
singleton.initPromise = fetch("/__lo/frontdoor")
|
|
170
|
-
.then(async (res) => {
|
|
171
|
-
if (!res.ok) {
|
|
172
|
-
console.error("frontdoor fetch failed");
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
const { frontdoorUrl: resolvedFrontdoorUrl } = await res.json();
|
|
176
|
-
safeInitialize({ frontdoorUrl: resolvedFrontdoorUrl });
|
|
177
|
-
})
|
|
178
|
-
.catch((err) => {
|
|
179
|
-
console.error("AgentforceConversationClient: failed to fetch frontdoor URL", err);
|
|
180
|
-
})
|
|
181
|
-
.finally(() => {
|
|
182
|
-
singleton.initPromise = undefined;
|
|
183
|
-
});
|
|
184
|
-
} else {
|
|
185
|
-
singleton.initPromise = Promise.resolve()
|
|
186
|
-
.then(() => {
|
|
187
|
-
safeInitialize(getDefaultEmbedOptions());
|
|
188
|
-
})
|
|
189
|
-
.catch((err) => {
|
|
190
|
-
console.error("AgentforceConversationClient: failed to embed Agentforce client", err);
|
|
191
|
-
})
|
|
192
|
-
.finally(() => {
|
|
193
|
-
singleton.initPromise = undefined;
|
|
194
|
-
});
|
|
195
|
-
}
|
|
74
|
+
embedder.embedAcc(
|
|
75
|
+
normalizedAgentforceClientConfig,
|
|
76
|
+
{ salesforceOrigin, frontdoorUrl },
|
|
77
|
+
containerRef.current,
|
|
78
|
+
{ onReady, onError },
|
|
79
|
+
);
|
|
196
80
|
|
|
197
81
|
return () => {
|
|
198
82
|
// Intentionally no cleanup:
|
|
199
83
|
// This component guarantees a single LO initialization per window.
|
|
200
84
|
};
|
|
201
|
-
}, [salesforceOrigin, frontdoorUrl, normalizedAgentforceClientConfig,
|
|
85
|
+
}, [salesforceOrigin, frontdoorUrl, normalizedAgentforceClientConfig, onReady, onError]);
|
|
202
86
|
|
|
203
87
|
if (!inline) {
|
|
204
88
|
return null;
|
|
@@ -6,9 +6,14 @@ import {
|
|
|
6
6
|
BreadcrumbLink,
|
|
7
7
|
BreadcrumbSeparator,
|
|
8
8
|
BreadcrumbPage,
|
|
9
|
-
} from "
|
|
10
|
-
import { Skeleton } from "
|
|
9
|
+
} from "./ui/breadcrumb";
|
|
10
|
+
import { Skeleton } from "./ui/skeleton";
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Home → List → Record breadcrumb for object pages. Previously imported from
|
|
14
|
+
* feature-react-object-search; inlined here so the app no longer depends on
|
|
15
|
+
* that feature.
|
|
16
|
+
*/
|
|
12
17
|
interface ObjectBreadcrumbProps {
|
|
13
18
|
listPath: string;
|
|
14
19
|
listLabel: string;
|
|
@@ -17,7 +17,7 @@ const buttonVariants = cva(
|
|
|
17
17
|
ghost:
|
|
18
18
|
'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
|
|
19
19
|
destructive:
|
|
20
|
-
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
|
|
20
|
+
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-red-700 dark:text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
|
|
21
21
|
link: 'text-primary underline-offset-4 hover:underline',
|
|
22
22
|
},
|
|
23
23
|
size: {
|
package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/datePicker.tsx
CHANGED
|
@@ -38,7 +38,7 @@ function DatePickerTrigger({
|
|
|
38
38
|
data-slot="date-picker-trigger"
|
|
39
39
|
data-empty={!date}
|
|
40
40
|
className={cn(
|
|
41
|
-
'w-[280px] justify-start text-left font-normal data-[empty=true]:text-
|
|
41
|
+
'w-[280px] justify-start text-left font-normal data-[empty=true]:text-gray-600',
|
|
42
42
|
className
|
|
43
43
|
)}
|
|
44
44
|
{...props}
|
|
@@ -87,7 +87,7 @@ function DatePickerRangeTrigger({
|
|
|
87
87
|
data-slot="date-picker-range-trigger"
|
|
88
88
|
data-empty={!hasDate}
|
|
89
89
|
className={cn(
|
|
90
|
-
'justify-start text-left font-normal data-[empty=true]:text-
|
|
90
|
+
'justify-start text-left font-normal data-[empty=true]:text-gray-600',
|
|
91
91
|
className
|
|
92
92
|
)}
|
|
93
93
|
{...props}
|
|
@@ -2,11 +2,18 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
4
|
|
|
5
|
-
function Table({
|
|
5
|
+
function Table({
|
|
6
|
+
className,
|
|
7
|
+
'aria-label': ariaLabel = 'Table',
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<'table'>) {
|
|
6
10
|
return (
|
|
7
11
|
<div
|
|
8
12
|
data-slot="table-container"
|
|
9
|
-
|
|
13
|
+
role="region"
|
|
14
|
+
aria-label={ariaLabel}
|
|
15
|
+
tabIndex={0}
|
|
16
|
+
className="relative w-full overflow-x-auto focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-purple"
|
|
10
17
|
>
|
|
11
18
|
<table
|
|
12
19
|
data-slot="table"
|
package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx
CHANGED
|
@@ -3,18 +3,10 @@ import { useParams, useNavigate } from "react-router";
|
|
|
3
3
|
import { createDataSDK } from "@salesforce/platform-sdk";
|
|
4
4
|
import { AlertCircle, ChevronDown, ChevronRight, FileQuestion } from "lucide-react";
|
|
5
5
|
import GET_ACCOUNT_DETAIL from "../api/account/query/getAccountDetail.graphql?raw";
|
|
6
|
-
import type {
|
|
7
|
-
GetAccountDetailQuery,
|
|
8
|
-
GetAccountDetailQueryVariables,
|
|
9
|
-
} from "../api/graphql-operations-types";
|
|
10
6
|
import { Alert, AlertTitle, AlertDescription } from "../components/ui/alert";
|
|
11
7
|
import { Button } from "../components/ui/button";
|
|
12
8
|
import { Card, CardContent } from "../components/ui/card";
|
|
13
|
-
import {
|
|
14
|
-
fieldValue,
|
|
15
|
-
getAddressFieldLines,
|
|
16
|
-
formatDateTimeField,
|
|
17
|
-
} from "../features/object-search/utils/fieldUtils";
|
|
9
|
+
import { fieldValue, getAddressFieldLines, formatDateTimeField } from "../utils/accountFields";
|
|
18
10
|
import {
|
|
19
11
|
Collapsible,
|
|
20
12
|
CollapsibleTrigger,
|
|
@@ -23,17 +15,58 @@ import {
|
|
|
23
15
|
import { Separator } from "../components/ui/separator";
|
|
24
16
|
import { Skeleton } from "../components/ui/skeleton";
|
|
25
17
|
import { useAsyncData } from "../hooks/useAsyncData";
|
|
26
|
-
import { ObjectBreadcrumb } from "../
|
|
18
|
+
import { ObjectBreadcrumb } from "../components/ObjectBreadcrumb";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A uiapi scalar field as returned with `@optional { value displayValue }`.
|
|
22
|
+
* Typed locally so this page no longer depends on the generated
|
|
23
|
+
* `graphql-operations-types` that shipped with feature-react-object-search.
|
|
24
|
+
*/
|
|
25
|
+
type FieldValue = { value?: unknown; displayValue?: string | null } | null;
|
|
26
|
+
type NameHolder = { Name?: FieldValue } | null;
|
|
27
|
+
|
|
28
|
+
interface AccountNode {
|
|
29
|
+
Id?: string;
|
|
30
|
+
Name?: FieldValue;
|
|
31
|
+
Owner?: NameHolder;
|
|
32
|
+
Phone?: FieldValue;
|
|
33
|
+
Fax?: FieldValue;
|
|
34
|
+
Parent?: NameHolder;
|
|
35
|
+
Website?: FieldValue;
|
|
36
|
+
Type?: FieldValue;
|
|
37
|
+
NumberOfEmployees?: FieldValue;
|
|
38
|
+
Industry?: FieldValue;
|
|
39
|
+
AnnualRevenue?: FieldValue;
|
|
40
|
+
Description?: FieldValue;
|
|
41
|
+
BillingStreet?: FieldValue;
|
|
42
|
+
BillingCity?: FieldValue;
|
|
43
|
+
BillingState?: FieldValue;
|
|
44
|
+
BillingPostalCode?: FieldValue;
|
|
45
|
+
BillingCountry?: FieldValue;
|
|
46
|
+
ShippingStreet?: FieldValue;
|
|
47
|
+
ShippingCity?: FieldValue;
|
|
48
|
+
ShippingState?: FieldValue;
|
|
49
|
+
ShippingPostalCode?: FieldValue;
|
|
50
|
+
ShippingCountry?: FieldValue;
|
|
51
|
+
CreatedBy?: NameHolder;
|
|
52
|
+
CreatedDate?: FieldValue;
|
|
53
|
+
LastModifiedBy?: NameHolder;
|
|
54
|
+
LastModifiedDate?: FieldValue;
|
|
55
|
+
}
|
|
27
56
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
57
|
+
interface GetAccountDetailResponse {
|
|
58
|
+
uiapi?: {
|
|
59
|
+
query?: {
|
|
60
|
+
Account?: {
|
|
61
|
+
edges?: Array<{ node?: AccountNode } | null> | null;
|
|
62
|
+
} | null;
|
|
63
|
+
} | null;
|
|
64
|
+
} | null;
|
|
65
|
+
}
|
|
33
66
|
|
|
34
67
|
async function fetchAccountDetail(recordId: string): Promise<AccountNode | null | undefined> {
|
|
35
68
|
const data = await createDataSDK();
|
|
36
|
-
const result = await data.graphql!.query<
|
|
69
|
+
const result = await data.graphql!.query<GetAccountDetailResponse, { id: string }>({
|
|
37
70
|
query: GET_ACCOUNT_DETAIL,
|
|
38
71
|
variables: { id: recordId },
|
|
39
72
|
});
|
|
@@ -1,34 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useNavigate } from "react-router";
|
|
3
|
-
import { SearchBar } from "../features/object-search/components/SearchBar";
|
|
4
|
-
import { Button } from "../components/ui/button";
|
|
1
|
+
import { GlobalSearchBox } from "../features/search";
|
|
5
2
|
|
|
6
3
|
export default function HomePage() {
|
|
7
|
-
const navigate = useNavigate();
|
|
8
|
-
const [text, setText] = useState("");
|
|
9
|
-
|
|
10
|
-
const handleSubmit = (e: React.SyntheticEvent<HTMLFormElement>) => {
|
|
11
|
-
e.preventDefault();
|
|
12
|
-
const params = text ? `?q=${encodeURIComponent(text)}` : "";
|
|
13
|
-
navigate(`/accounts${params}`);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
4
|
return (
|
|
17
5
|
<div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
<Button variant="outline" size="sm" onClick={() => navigate("/accounts")}>
|
|
21
|
-
Browse All Accounts
|
|
22
|
-
</Button>
|
|
23
|
-
</div>
|
|
24
|
-
<form onSubmit={handleSubmit} className="flex gap-2">
|
|
25
|
-
<SearchBar
|
|
26
|
-
placeholder="Search by name, phone, or industry..."
|
|
27
|
-
value={text}
|
|
28
|
-
handleChange={setText}
|
|
29
|
-
/>
|
|
30
|
-
<Button type="submit">Search</Button>
|
|
31
|
-
</form>
|
|
6
|
+
<h1 className="text-2xl font-bold mb-6">Home</h1>
|
|
7
|
+
<GlobalSearchBox placeholder="Search accounts, contacts, opportunities..." />
|
|
32
8
|
</div>
|
|
33
9
|
);
|
|
34
10
|
}
|