@salesforce/webapp-template-app-react-sample-b2x-experimental 1.112.7 → 1.112.9
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/dist/CHANGELOG.md +19 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/package.json +6 -5
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/graphql-operations-types.ts +12058 -214
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/graphqlClient.ts +18 -15
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/{propertyListingGraphQL.ts → properties/propertyListingGraphQL.ts} +1 -1
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/appLayout.tsx +4 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{TopBar.tsx → layout/TopBar.tsx} +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{MaintenanceRequestList.tsx → maintenanceRequests/MaintenanceRequestList.tsx} +4 -4
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{MaintenanceRequestListItem.tsx → maintenanceRequests/MaintenanceRequestListItem.tsx} +3 -3
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/maintenanceRequests/MaintenanceSummaryDetailsModal.tsx +87 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{PropertyListingCard.tsx → properties/PropertyListingCard.tsx} +1 -1
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/{features/global-search/components/search/SearchPagination.tsx → components/properties/PropertyListingSearchPagination.tsx} +20 -28
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/constants/propertyListing.ts +4 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/api/accountSearchService.ts +46 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/api/query/distinctAccountIndustries.graphql +19 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/api/query/distinctAccountTypes.graphql +19 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/api/query/getAccountDetail.graphql +121 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/api/query/searchAccounts.graphql +51 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/pages/AccountObjectDetailPage.tsx +357 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/pages/AccountSearch.tsx +303 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/__examples__/pages/Home.tsx +34 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/api/objectSearchService.ts +84 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/ActiveFilters.tsx +89 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/FilterContext.tsx +73 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/ObjectBreadcrumb.tsx +66 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/PaginationControls.tsx +109 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/SearchBar.tsx +41 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/SortControl.tsx +143 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/BooleanFilter.tsx +74 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/DateFilter.tsx +121 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/DateRangeFilter.tsx +69 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/MultiSelectFilter.tsx +98 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/NumericRangeFilter.tsx +85 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/SearchFilter.tsx +37 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/SelectFilter.tsx +93 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/components/filters/TextFilter.tsx +74 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/hooks/useAsyncData.ts +54 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/hooks/useCachedAsyncData.ts +184 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/hooks/useObjectSearchParams.ts +247 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/utils/debounce.ts +22 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/utils/fieldUtils.ts +29 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/utils/filterUtils.ts +372 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/object-search/utils/sortUtils.ts +38 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useMaintenanceRequests.ts +1 -1
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyAddresses.ts +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyDetail.ts +1 -1
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyListingAmenities.ts +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyListingSearch.ts +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyMapMarkers.ts +3 -3
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyPrimaryImages.ts +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Application.tsx +3 -3
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Dashboard.tsx +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Home.tsx +4 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Maintenance.tsx +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertyDetails.tsx +1 -1
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertySearch.tsx +12 -10
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/routes.tsx +6 -18
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/propertyListingPaginationUtils.ts +18 -0
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/dist/scripts/graphql-search.sh +69 -17
- package/package.json +1 -1
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/MaintenanceDetailsModal.tsx +0 -128
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/api/objectDetailService.ts +0 -102
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/api/objectInfoGraphQLService.ts +0 -137
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/api/objectInfoService.ts +0 -95
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/api/recordListGraphQLService.ts +0 -364
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/DetailFields.tsx +0 -55
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/DetailForm.tsx +0 -146
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/DetailHeader.tsx +0 -34
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/DetailLayoutSections.tsx +0 -80
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/Section.tsx +0 -108
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/SectionRow.tsx +0 -20
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/UiApiDetailForm.tsx +0 -140
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/formatted/FieldValueDisplay.tsx +0 -73
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/formatted/FormattedAddress.tsx +0 -29
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/formatted/FormattedEmail.tsx +0 -17
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/formatted/FormattedPhone.tsx +0 -24
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/formatted/FormattedText.tsx +0 -11
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/detail/formatted/FormattedUrl.tsx +0 -29
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/filters/FilterField.tsx +0 -54
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/filters/FilterInput.tsx +0 -55
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/filters/FilterSelect.tsx +0 -72
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/filters/FiltersPanel.tsx +0 -380
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/forms/filters-form.tsx +0 -114
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/forms/submit-button.tsx +0 -47
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/search/GlobalSearchInput.tsx +0 -114
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/search/ResultCardFields.tsx +0 -71
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/search/SearchHeader.tsx +0 -31
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/search/SearchResultCard.tsx +0 -138
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/search/SearchResultsPanel.tsx +0 -197
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/components/shared/LoadingFallback.tsx +0 -61
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/constants.ts +0 -39
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/filters/FilterInput.tsx +0 -55
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/filters/FilterSelect.tsx +0 -72
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/hooks/form.tsx +0 -209
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/hooks/useObjectInfoBatch.ts +0 -72
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/hooks/useObjectSearchData.ts +0 -174
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/hooks/useRecordDetailLayout.ts +0 -137
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/hooks/useRecordListGraphQL.ts +0 -135
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/pages/DetailPage.tsx +0 -109
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/pages/GlobalSearch.tsx +0 -235
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/types/filters/filters.ts +0 -121
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/types/filters/picklist.ts +0 -6
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/types/objectInfo/objectInfo.ts +0 -49
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/types/recordDetail/recordDetail.ts +0 -61
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/types/schema.d.ts +0 -200
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/apiUtils.ts +0 -59
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/cacheUtils.ts +0 -76
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/debounce.ts +0 -90
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/fieldUtils.ts +0 -354
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/fieldValueExtractor.ts +0 -67
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/filterUtils.ts +0 -32
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/formDataTransformUtils.ts +0 -260
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/formUtils.ts +0 -142
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/graphQLNodeFieldUtils.ts +0 -186
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +0 -77
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/graphQLRecordAdapter.ts +0 -90
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/layoutTransformUtils.ts +0 -236
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/linkUtils.ts +0 -14
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/paginationUtils.ts +0 -49
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/recordUtils.ts +0 -159
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/utils/sanitizationUtils.ts +0 -50
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyListingPriceRange.ts +0 -64
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/index.ts +0 -120
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/About.tsx +0 -8
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/HelpCenter.tsx +0 -29
- package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertyListings.tsx +0 -100
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/{applicationApi.ts → applications/applicationApi.ts} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/{maintenanceRequestApi.ts → maintenanceRequests/maintenanceRequestApi.ts} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/{propertyDetailGraphQL.ts → properties/propertyDetailGraphQL.ts} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{WeatherWidget.tsx → dashboard/WeatherWidget.tsx} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{NavMenu.tsx → layout/VerticalNav.tsx} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{MaintenanceRequestIcon.tsx → maintenanceRequests/MaintenanceRequestIcon.tsx} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{StatusBadge.tsx → maintenanceRequests/StatusBadge.tsx} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{PropertyMap.tsx → properties/PropertyMap.tsx} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/{PropertySearchFilters.tsx → properties/PropertySearchFilters.tsx} +0 -0
- /package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/{features/global-search/types/search → types}/searchResults.ts +0 -0
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transforms UI API record + object info into detail form shape: Reference fields get
|
|
3
|
-
* relationshipField, compound fields get constituents, metadata gets editable flag.
|
|
4
|
-
* Aligns with LWC detailForm _calculateFormData and uiApiDataTransformHelper.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { FieldValue } from "../types/search/searchResults";
|
|
8
|
-
|
|
9
|
-
/** Field metadata from object info API (subset used by form transform). */
|
|
10
|
-
export interface ObjectInfoFieldMetadata {
|
|
11
|
-
compound?: boolean;
|
|
12
|
-
compoundFieldName?: string;
|
|
13
|
-
compoundComponentName?: string;
|
|
14
|
-
dataType?: string;
|
|
15
|
-
relationshipName?: string;
|
|
16
|
-
updateable?: boolean;
|
|
17
|
-
calculated?: boolean;
|
|
18
|
-
polymorphicForeignKey?: boolean;
|
|
19
|
-
apiName?: string;
|
|
20
|
-
label?: string;
|
|
21
|
-
[name: string]: unknown;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Minimal UI API object info (metadata) for form data transform. */
|
|
25
|
-
export interface ObjectInfoMetadata {
|
|
26
|
-
apiName?: string;
|
|
27
|
-
fields?: Record<string, ObjectInfoFieldMetadata>;
|
|
28
|
-
[name: string]: unknown;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** Transformed field value: base FieldValue + relationshipField (Reference) and constituents (compound). */
|
|
32
|
-
export interface TransformedFieldValue extends FieldValue {
|
|
33
|
-
relationshipField?: FieldValue;
|
|
34
|
-
constituents?: Record<string, TransformedFieldValue & { metadata?: ObjectInfoFieldMetadata }>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type TransformedDataFields = Record<string, TransformedFieldValue>;
|
|
38
|
-
|
|
39
|
-
/** Form values keyed by record context id (e.g. record.id). */
|
|
40
|
-
export type FormValues = Record<string, TransformedDataFields>;
|
|
41
|
-
|
|
42
|
-
/** Form metadata keyed by metadata context (e.g. object apiName). */
|
|
43
|
-
export type FormMetadata = Record<string, ObjectInfoMetadata>;
|
|
44
|
-
|
|
45
|
-
/** Contexts: recordId -> objectApiName. */
|
|
46
|
-
export type FormContexts = Record<string, string>;
|
|
47
|
-
|
|
48
|
-
/** Result of calculateFormData (single record). */
|
|
49
|
-
export interface FormData {
|
|
50
|
-
formValues: FormValues;
|
|
51
|
-
formMetadata: FormMetadata;
|
|
52
|
-
formContexts: FormContexts;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** Fields never editable per UI API (platform convention). */
|
|
56
|
-
const NON_EDITABLE_FIELDS = ["OwnerId", "RecordTypeId"];
|
|
57
|
-
|
|
58
|
-
/** Created By / Last Modified By: synthetic compound from Id + Date (modstampMetadataTransform). */
|
|
59
|
-
const SYSTEM_FIELDS = [
|
|
60
|
-
{
|
|
61
|
-
fieldName: "CreatedBy",
|
|
62
|
-
idFieldName: "CreatedById",
|
|
63
|
-
dateFieldName: "CreatedDate",
|
|
64
|
-
apiName: "CreatedBy",
|
|
65
|
-
compound: true,
|
|
66
|
-
dataType: "String",
|
|
67
|
-
label: "Created By",
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
fieldName: "LastModifiedBy",
|
|
71
|
-
idFieldName: "LastModifiedById",
|
|
72
|
-
dateFieldName: "LastModifiedDate",
|
|
73
|
-
apiName: "LastModifiedBy",
|
|
74
|
-
compound: true,
|
|
75
|
-
dataType: "String",
|
|
76
|
-
label: "Last Modified By",
|
|
77
|
-
},
|
|
78
|
-
];
|
|
79
|
-
|
|
80
|
-
function modstampMetadataTransform(metadata: ObjectInfoMetadata): ObjectInfoMetadata {
|
|
81
|
-
const fields = { ...metadata.fields };
|
|
82
|
-
if (!fields) return metadata;
|
|
83
|
-
|
|
84
|
-
SYSTEM_FIELDS.forEach((systemField) => {
|
|
85
|
-
const field = systemField.fieldName;
|
|
86
|
-
const idField = systemField.idFieldName;
|
|
87
|
-
const dateField = systemField.dateFieldName;
|
|
88
|
-
if (idField in fields && dateField in fields && metadata.fields) {
|
|
89
|
-
fields[field] = { ...metadata.fields[idField], ...systemField };
|
|
90
|
-
fields[idField] = {
|
|
91
|
-
...(metadata.fields[idField] ?? {}),
|
|
92
|
-
compoundComponentName: "Id",
|
|
93
|
-
compoundFieldName: field,
|
|
94
|
-
};
|
|
95
|
-
fields[dateField] = {
|
|
96
|
-
...(metadata.fields[dateField] ?? {}),
|
|
97
|
-
compoundComponentName: "Date",
|
|
98
|
-
compoundFieldName: field,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
return { ...metadata, fields };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function metaDataTransform(metadata: ObjectInfoMetadata): ObjectInfoMetadata {
|
|
106
|
-
const newMetadata = modstampMetadataTransform(metadata);
|
|
107
|
-
const fields: Record<string, ObjectInfoFieldMetadata> = {};
|
|
108
|
-
const metaFields = newMetadata.fields ?? {};
|
|
109
|
-
Object.keys(metaFields).forEach((fieldName) => {
|
|
110
|
-
const fieldRep = metaFields[fieldName];
|
|
111
|
-
const isCalculated = Boolean(fieldRep.calculated);
|
|
112
|
-
const isUpdateable = Boolean(fieldRep.updateable);
|
|
113
|
-
const isPolymorphicLookup = Boolean(fieldRep.polymorphicForeignKey);
|
|
114
|
-
fields[fieldName] = {
|
|
115
|
-
...fieldRep,
|
|
116
|
-
editable:
|
|
117
|
-
!isCalculated &&
|
|
118
|
-
isUpdateable &&
|
|
119
|
-
!isPolymorphicLookup &&
|
|
120
|
-
!NON_EDITABLE_FIELDS.includes(fieldName),
|
|
121
|
-
} as ObjectInfoFieldMetadata;
|
|
122
|
-
});
|
|
123
|
-
return { ...newMetadata, fields };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export function getConstituentMap(
|
|
127
|
-
dataFields: Record<string, FieldValue>,
|
|
128
|
-
fieldMetadata: Record<string, ObjectInfoFieldMetadata>,
|
|
129
|
-
): Record<string, Record<string, TransformedFieldValue & { metadata?: ObjectInfoFieldMetadata }>> {
|
|
130
|
-
const constituentMap: Record<
|
|
131
|
-
string,
|
|
132
|
-
Record<string, TransformedFieldValue & { metadata?: ObjectInfoFieldMetadata }>
|
|
133
|
-
> = {};
|
|
134
|
-
Object.keys(fieldMetadata).forEach((fieldApiName) => {
|
|
135
|
-
const { compoundFieldName } = fieldMetadata[fieldApiName];
|
|
136
|
-
if (compoundFieldName && dataFields[fieldApiName]) {
|
|
137
|
-
const constituentFields =
|
|
138
|
-
constituentMap[compoundFieldName] ??
|
|
139
|
-
({} as Record<string, TransformedFieldValue & { metadata?: ObjectInfoFieldMetadata }>);
|
|
140
|
-
const raw = dataFields[fieldApiName] as TransformedFieldValue;
|
|
141
|
-
constituentFields[fieldApiName] = {
|
|
142
|
-
...raw,
|
|
143
|
-
metadata: fieldMetadata[fieldApiName],
|
|
144
|
-
};
|
|
145
|
-
constituentMap[compoundFieldName] = constituentFields;
|
|
146
|
-
|
|
147
|
-
const compoundMeta = fieldMetadata[compoundFieldName];
|
|
148
|
-
if (
|
|
149
|
-
compoundMeta?.dataType === "Address" &&
|
|
150
|
-
(fieldApiName.endsWith("StateCode") || fieldApiName.endsWith("CountryCode"))
|
|
151
|
-
) {
|
|
152
|
-
const nonPicklistName = fieldApiName.replace("Code", "");
|
|
153
|
-
if (fieldMetadata[nonPicklistName] && dataFields[nonPicklistName]) {
|
|
154
|
-
constituentFields[nonPicklistName] = {
|
|
155
|
-
...(dataFields[nonPicklistName] as TransformedFieldValue),
|
|
156
|
-
metadata: fieldMetadata[nonPicklistName],
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
if (constituentMap.Name) {
|
|
163
|
-
const constituentApiNames = Object.keys(constituentMap.Name);
|
|
164
|
-
if (constituentApiNames.length === 1 && constituentApiNames[0] === "Name") {
|
|
165
|
-
delete constituentMap.Name;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return constituentMap;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export function objectInfoFieldsTransform(
|
|
172
|
-
dataFields: Record<string, FieldValue>,
|
|
173
|
-
metadata: ObjectInfoMetadata,
|
|
174
|
-
): TransformedDataFields {
|
|
175
|
-
const fieldMetadata = metadata.fields ?? {};
|
|
176
|
-
const transformedDataFields: TransformedDataFields = { ...dataFields };
|
|
177
|
-
|
|
178
|
-
Object.keys(fieldMetadata).forEach((field) => {
|
|
179
|
-
const meta = fieldMetadata[field];
|
|
180
|
-
if (meta.dataType === "Reference" && meta.relationshipName != null) {
|
|
181
|
-
const existing = dataFields[field];
|
|
182
|
-
const relField = dataFields[meta.relationshipName];
|
|
183
|
-
transformedDataFields[field] = {
|
|
184
|
-
...(existing ?? {}),
|
|
185
|
-
relationshipField: {
|
|
186
|
-
...(relField ?? {}),
|
|
187
|
-
value: null,
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
Object.keys(fieldMetadata).forEach((field) => {
|
|
194
|
-
const meta = fieldMetadata[field];
|
|
195
|
-
const { compound, dataType } = meta;
|
|
196
|
-
const existing = dataFields[field];
|
|
197
|
-
if (dataType === "Reference") return;
|
|
198
|
-
if (compound) {
|
|
199
|
-
transformedDataFields[field] = { ...(existing ?? {}) };
|
|
200
|
-
} else if (existing) {
|
|
201
|
-
transformedDataFields[field] = existing as TransformedFieldValue;
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const constituentMap = getConstituentMap(transformedDataFields, fieldMetadata);
|
|
206
|
-
Object.keys(constituentMap).forEach((field) => {
|
|
207
|
-
if (transformedDataFields[field]) {
|
|
208
|
-
transformedDataFields[field] = {
|
|
209
|
-
...transformedDataFields[field],
|
|
210
|
-
constituents: constituentMap[field],
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
return transformedDataFields;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export function multiRecordMetadataTransform(
|
|
218
|
-
metadata: Record<string, ObjectInfoMetadata>,
|
|
219
|
-
): FormMetadata {
|
|
220
|
-
const result: FormMetadata = {};
|
|
221
|
-
Object.keys(metadata).forEach((metadataContext) => {
|
|
222
|
-
result[metadataContext] = metaDataTransform(metadata[metadataContext]);
|
|
223
|
-
});
|
|
224
|
-
return result;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export function multiRecordValuesTransform(
|
|
228
|
-
values: Record<string, Record<string, FieldValue>>,
|
|
229
|
-
metadata: FormMetadata,
|
|
230
|
-
contexts: FormContexts,
|
|
231
|
-
): FormValues {
|
|
232
|
-
const result: FormValues = {};
|
|
233
|
-
Object.keys(values).forEach((recordContext) => {
|
|
234
|
-
const metadataContext = contexts[recordContext];
|
|
235
|
-
if (metadataContext && metadata[metadataContext]) {
|
|
236
|
-
result[recordContext] = objectInfoFieldsTransform(
|
|
237
|
-
values[recordContext],
|
|
238
|
-
metadata[metadataContext],
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
return result;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export function calculateFormData(
|
|
246
|
-
record: { id: string; apiName: string; fields: Record<string, FieldValue> },
|
|
247
|
-
metadata: ObjectInfoMetadata | null | undefined,
|
|
248
|
-
): FormData {
|
|
249
|
-
const formValues: FormValues = {};
|
|
250
|
-
const formMetadata: FormMetadata = {};
|
|
251
|
-
const formContexts: FormContexts = { [record.id]: record.apiName };
|
|
252
|
-
|
|
253
|
-
if (!metadata?.fields) {
|
|
254
|
-
return { formValues, formMetadata, formContexts };
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
formMetadata[record.apiName] = metaDataTransform(metadata);
|
|
258
|
-
formValues[record.id] = objectInfoFieldsTransform(record.fields, formMetadata[record.apiName]);
|
|
259
|
-
return { formValues, formMetadata, formContexts };
|
|
260
|
-
}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Form Utilities
|
|
3
|
-
*
|
|
4
|
-
* Utility functions for form validation and error handling.
|
|
5
|
-
* These utilities are framework-agnostic and can be used with any form library.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Form error structure from TanStack Form
|
|
10
|
-
* Errors can be objects with a message property or strings
|
|
11
|
-
*/
|
|
12
|
-
export interface FormError {
|
|
13
|
-
message: string;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Type guard to check if an error has a message property
|
|
19
|
-
* @param error - The error to check
|
|
20
|
-
* @returns true if the error has a message property
|
|
21
|
-
*/
|
|
22
|
-
export function isFormError(error: unknown): error is FormError {
|
|
23
|
-
return (
|
|
24
|
-
typeof error === "object" &&
|
|
25
|
-
error !== null &&
|
|
26
|
-
"message" in error &&
|
|
27
|
-
typeof (error as FormError).message === "string"
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Extracts unique errors by message, filtering out duplicates
|
|
33
|
-
* Handles both Error objects and string errors
|
|
34
|
-
* Converts FormError objects to Error instances for compatibility with UI components
|
|
35
|
-
*
|
|
36
|
-
* @param errors - Array of error objects or strings from form libraries
|
|
37
|
-
* @returns Array of unique Error objects (compatible with FieldError component)
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```tsx
|
|
41
|
-
* const uniqueErrors = getUniqueErrors(formErrors);
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export function getUniqueErrors(errors: unknown[]): Error[] {
|
|
45
|
-
const errorMap = new Map<string, Error>();
|
|
46
|
-
|
|
47
|
-
for (const error of errors) {
|
|
48
|
-
if (isFormError(error)) {
|
|
49
|
-
// Use message as key to deduplicate
|
|
50
|
-
if (!errorMap.has(error.message)) {
|
|
51
|
-
// Convert FormError to Error for compatibility
|
|
52
|
-
const errorObj = new Error(error.message);
|
|
53
|
-
// Preserve additional properties if needed
|
|
54
|
-
Object.assign(errorObj, error);
|
|
55
|
-
errorMap.set(error.message, errorObj);
|
|
56
|
-
}
|
|
57
|
-
} else if (typeof error === "string") {
|
|
58
|
-
// Handle string errors
|
|
59
|
-
if (!errorMap.has(error)) {
|
|
60
|
-
errorMap.set(error, new Error(error));
|
|
61
|
-
}
|
|
62
|
-
} else if (error instanceof Error) {
|
|
63
|
-
// Handle Error objects directly
|
|
64
|
-
if (!errorMap.has(error.message)) {
|
|
65
|
-
errorMap.set(error.message, error);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return Array.from(errorMap.values());
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Validates that min value is less than or equal to max value for range filters
|
|
75
|
-
* This utility can be used in form validation logic
|
|
76
|
-
*
|
|
77
|
-
* @param minValue - Minimum value (string or number)
|
|
78
|
-
* @param maxValue - Maximum value (string or number)
|
|
79
|
-
* @returns Error message if validation fails, null if valid
|
|
80
|
-
*
|
|
81
|
-
* @remarks
|
|
82
|
-
* - If both values are empty, validation passes
|
|
83
|
-
* - Only validates if both values can be parsed as numbers
|
|
84
|
-
* - Returns null if values cannot be parsed (lets other validators handle it)
|
|
85
|
-
*
|
|
86
|
-
* @example
|
|
87
|
-
* ```tsx
|
|
88
|
-
* // In form validation
|
|
89
|
-
* const minError = validateRangeValues(minFieldValue, maxFieldValue);
|
|
90
|
-
* if (minError) {
|
|
91
|
-
* setFieldError('minField', minError);
|
|
92
|
-
* }
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
export function validateRangeValues(
|
|
96
|
-
minValue: string | number | null | undefined,
|
|
97
|
-
maxValue: string | number | null | undefined,
|
|
98
|
-
): string | null {
|
|
99
|
-
// If both are empty, validation passes
|
|
100
|
-
if (!minValue && !maxValue) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Parse values to numbers if possible
|
|
105
|
-
const parseValue = (val: string | number | null | undefined): number | null => {
|
|
106
|
-
if (!val) {
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
if (typeof val === "number") {
|
|
110
|
-
return val;
|
|
111
|
-
}
|
|
112
|
-
const parsed = parseInt(val, 10);
|
|
113
|
-
return isNaN(parsed) ? null : parsed;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const minNum = parseValue(minValue);
|
|
117
|
-
const maxNum = parseValue(maxValue);
|
|
118
|
-
|
|
119
|
-
// If one is not a number, skip numeric validation (let other validators handle it)
|
|
120
|
-
if (minNum === null || maxNum === null) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Validate min <= max
|
|
125
|
-
if (minNum > maxNum) {
|
|
126
|
-
return "Minimum value must be less than or equal to maximum value";
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function getFormValueByPath(record: Record<string, unknown>, fieldPath: string): string {
|
|
133
|
-
if (!fieldPath) return "";
|
|
134
|
-
const parts = fieldPath.split(".");
|
|
135
|
-
let current: Record<string, unknown> = record;
|
|
136
|
-
for (const part of parts) {
|
|
137
|
-
if (current == null || typeof current !== "object") return "";
|
|
138
|
-
current = (current as Record<string, unknown>)[part] as unknown as Record<string, unknown>;
|
|
139
|
-
}
|
|
140
|
-
if (current === undefined || current === null) return "";
|
|
141
|
-
return "" + current;
|
|
142
|
-
}
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GraphQL record node → display values for detail view.
|
|
3
|
-
*
|
|
4
|
-
* getGraphQLNodeValue: primitive by field path. getDisplayValueForDetailFieldFromNode: single field,
|
|
5
|
-
* uses metadata to show relationship name instead of Id. getDisplayValueForLayoutItemFromNode:
|
|
6
|
-
* single or compound (address, modstamp). getGraphQLRecordDisplayName: record title from nameFields.
|
|
7
|
-
*
|
|
8
|
-
* @module utils/graphQLNodeFieldUtils
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { FieldValue } from "../types/search/searchResults";
|
|
12
|
-
import type { GraphQLRecordNode } from "../api/recordListGraphQLService";
|
|
13
|
-
import type { ObjectInfoMetadata } from "./formDataTransformUtils";
|
|
14
|
-
import { getDisplayValueForLayoutItem, type LayoutItemDisplayResult } from "./fieldUtils";
|
|
15
|
-
|
|
16
|
-
/** Metadata from getObjectInfoBatch (object metadata) used to resolve reference fields by relationshipName. */
|
|
17
|
-
export type ObjectMetadataForDisplay = ObjectInfoMetadata | null | undefined;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Gets a primitive value from a GraphQL node by field path.
|
|
21
|
-
* - "Id" -> node.Id (scalar)
|
|
22
|
-
* - "Name" -> node.Name?.value
|
|
23
|
-
* - "Owner.Alias" -> node.Owner?.Alias?.value
|
|
24
|
-
*/
|
|
25
|
-
export function getGraphQLNodeValue(
|
|
26
|
-
node: GraphQLRecordNode | null | undefined,
|
|
27
|
-
fieldPath: string,
|
|
28
|
-
): string | number | boolean | null {
|
|
29
|
-
if (!node || !fieldPath) return null;
|
|
30
|
-
const parts = fieldPath.split(".");
|
|
31
|
-
let current: unknown = node;
|
|
32
|
-
for (let i = 0; i < parts.length; i++) {
|
|
33
|
-
if (current == null || typeof current !== "object") return null;
|
|
34
|
-
current = (current as Record<string, unknown>)[parts[i]];
|
|
35
|
-
}
|
|
36
|
-
if (current == null) return null;
|
|
37
|
-
if (typeof current === "object" && current !== null && "value" in current) {
|
|
38
|
-
const v = (current as { value: unknown }).value;
|
|
39
|
-
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
40
|
-
return v;
|
|
41
|
-
}
|
|
42
|
-
if (v === null) return null;
|
|
43
|
-
return v as string;
|
|
44
|
-
}
|
|
45
|
-
if (typeof current === "string" || typeof current === "number" || typeof current === "boolean") {
|
|
46
|
-
return current as string | number | boolean;
|
|
47
|
-
}
|
|
48
|
-
// Relationship/lookup objects: try DisplayValue (scalar or object), Name.value, then Id
|
|
49
|
-
if (typeof current === "object" && current !== null) {
|
|
50
|
-
const obj = current as Record<string, unknown>;
|
|
51
|
-
const displayVal = obj.DisplayValue ?? obj.displayValue;
|
|
52
|
-
if (displayVal != null) {
|
|
53
|
-
if (
|
|
54
|
-
typeof displayVal === "string" ||
|
|
55
|
-
typeof displayVal === "number" ||
|
|
56
|
-
typeof displayVal === "boolean"
|
|
57
|
-
) {
|
|
58
|
-
return displayVal;
|
|
59
|
-
}
|
|
60
|
-
if (typeof displayVal === "object" && "value" in displayVal) {
|
|
61
|
-
const v = (displayVal as { value: unknown }).value;
|
|
62
|
-
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") return v;
|
|
63
|
-
if (v === null) return null;
|
|
64
|
-
return v as string;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const nameObj = obj.Name ?? obj.name;
|
|
68
|
-
if (nameObj != null && typeof nameObj === "object" && "value" in nameObj) {
|
|
69
|
-
const v = (nameObj as { value: unknown }).value;
|
|
70
|
-
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") return v;
|
|
71
|
-
if (v === null) return null;
|
|
72
|
-
return v as string;
|
|
73
|
-
}
|
|
74
|
-
const idVal = obj.Id ?? obj.id;
|
|
75
|
-
if (
|
|
76
|
-
idVal != null &&
|
|
77
|
-
(typeof idVal === "string" || typeof idVal === "number" || typeof idVal === "boolean")
|
|
78
|
-
) {
|
|
79
|
-
return idVal;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Builds a minimal Record<string, FieldValue> from node for the given api names (for reuse with fieldUtils formatters). */
|
|
86
|
-
function nodeToConstituentFields(
|
|
87
|
-
node: GraphQLRecordNode,
|
|
88
|
-
componentApiNames: string[],
|
|
89
|
-
metadata?: ObjectMetadataForDisplay,
|
|
90
|
-
): Record<string, FieldValue> {
|
|
91
|
-
const fields: Record<string, FieldValue> = {};
|
|
92
|
-
for (const apiName of componentApiNames) {
|
|
93
|
-
const v = getDisplayValueForDetailFieldFromNode(node, apiName, metadata);
|
|
94
|
-
const displayValue = v as string | null;
|
|
95
|
-
fields[apiName] = { displayValue, value: v };
|
|
96
|
-
}
|
|
97
|
-
return fields;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Resolves display value for a layout item from a GraphQL node (single or multiple components).
|
|
102
|
-
* Reuses address/modstamp formatting from fieldUtils by building minimal constituent fields from the node.
|
|
103
|
-
* Pass metadata from getObjectInfoBatch so reference fields show the relationship's name instead of Id.
|
|
104
|
-
*/
|
|
105
|
-
export function getDisplayValueForLayoutItemFromNode(
|
|
106
|
-
node: GraphQLRecordNode | null | undefined,
|
|
107
|
-
componentApiNames: string[],
|
|
108
|
-
metadata?: ObjectMetadataForDisplay,
|
|
109
|
-
): LayoutItemDisplayResult {
|
|
110
|
-
if (!node || componentApiNames.length === 0) {
|
|
111
|
-
return { value: null };
|
|
112
|
-
}
|
|
113
|
-
if (componentApiNames.length === 1) {
|
|
114
|
-
const apiName = componentApiNames[0];
|
|
115
|
-
const value = getDisplayValueForDetailFieldFromNode(node, apiName, metadata);
|
|
116
|
-
const dataType = metadata?.fields?.[apiName]?.dataType;
|
|
117
|
-
return { value, dataType };
|
|
118
|
-
}
|
|
119
|
-
const constituents = nodeToConstituentFields(node, componentApiNames, metadata);
|
|
120
|
-
const result = getDisplayValueForLayoutItem(constituents, componentApiNames);
|
|
121
|
-
return { value: result.value, dataType: result.dataType };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Resolves display value for a single detail field from a GraphQL node.
|
|
126
|
-
* When metadata from getObjectInfoBatch is provided and the field is a Reference (dataType === "Reference")
|
|
127
|
-
* with a relationshipName, shows the related record's display value (e.g. Owner.Name) instead of the Id.
|
|
128
|
-
*/
|
|
129
|
-
/** Treat dataType as Reference regardless of casing (e.g. REFERENCE from GraphQL). */
|
|
130
|
-
function isReferenceDataType(dataType: string | undefined): boolean {
|
|
131
|
-
return dataType != null && dataType.toLowerCase() === "reference";
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function getDisplayValueForDetailFieldFromNode(
|
|
135
|
-
node: GraphQLRecordNode | null | undefined,
|
|
136
|
-
apiName: string,
|
|
137
|
-
metadata?: ObjectMetadataForDisplay,
|
|
138
|
-
): string | number | boolean | null {
|
|
139
|
-
if (!node || !apiName) return null;
|
|
140
|
-
const fieldMeta = metadata?.fields?.[apiName];
|
|
141
|
-
if (
|
|
142
|
-
fieldMeta &&
|
|
143
|
-
isReferenceDataType(fieldMeta.dataType) &&
|
|
144
|
-
fieldMeta.relationshipName != null &&
|
|
145
|
-
fieldMeta.relationshipName !== ""
|
|
146
|
-
) {
|
|
147
|
-
const displayValue = getGraphQLNodeValue(node, fieldMeta.relationshipName);
|
|
148
|
-
if (displayValue !== null && displayValue !== undefined && displayValue !== "") {
|
|
149
|
-
return displayValue;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return getGraphQLNodeValue(node, apiName);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** Fallback field names for record display name when nameFields are not available. */
|
|
156
|
-
const DISPLAY_FIELD_CANDIDATES = [
|
|
157
|
-
"Name",
|
|
158
|
-
"CaseNumber",
|
|
159
|
-
"Subject",
|
|
160
|
-
"Title",
|
|
161
|
-
"DeveloperName",
|
|
162
|
-
"ContractNumber",
|
|
163
|
-
] as const;
|
|
164
|
-
|
|
165
|
-
/** Minimal metadata for record display name. */
|
|
166
|
-
export type GraphQLRecordDisplayNameMetadata = { nameFields?: string[] } | null;
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Resolves a display name for a record from a GraphQL node.
|
|
170
|
-
* Tries metadata.nameFields first, then DISPLAY_FIELD_CANDIDATES, then node.Id.
|
|
171
|
-
*/
|
|
172
|
-
export function getGraphQLRecordDisplayName(
|
|
173
|
-
node: GraphQLRecordNode | null | undefined,
|
|
174
|
-
metadata?: GraphQLRecordDisplayNameMetadata,
|
|
175
|
-
): string {
|
|
176
|
-
if (!node) return "";
|
|
177
|
-
const id = (node.Id as string) ?? "";
|
|
178
|
-
const candidates = [...(metadata?.nameFields ?? []), ...DISPLAY_FIELD_CANDIDATES];
|
|
179
|
-
for (const fieldPath of candidates) {
|
|
180
|
-
const v = getGraphQLNodeValue(node, fieldPath);
|
|
181
|
-
if (v !== null && v !== undefined && v !== "") {
|
|
182
|
-
return v as string;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return id;
|
|
186
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GraphQL objectInfos → REST-compatible object info and picklist.
|
|
3
|
-
*
|
|
4
|
-
* graphQLObjectInfoToObjectInfoResult / graphQLObjectInfosToBatchResponse: used by objectInfoService
|
|
5
|
-
* after getObjectInfosGraphQL. extractPicklistValuesFromGraphQLObjectInfo: used for getPicklistValues.
|
|
6
|
-
* Normalizes casing and adds synthetic compound fields (e.g. BillingAddress) for layout/dataType.
|
|
7
|
-
*
|
|
8
|
-
* @module utils/graphQLObjectInfoAdapter
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type {
|
|
12
|
-
ObjectInfoBatchResponse,
|
|
13
|
-
GetObjectInfosQueryObjectInfos,
|
|
14
|
-
GetPicklistValuesQueryObjectInfo,
|
|
15
|
-
GetPicklistValuesQueryField,
|
|
16
|
-
GetObjectInfosQueryObjectInfo,
|
|
17
|
-
ObjectInfoResult,
|
|
18
|
-
PicklistValue as GraphQLPicklistValue,
|
|
19
|
-
} from "../types/objectInfo/objectInfo";
|
|
20
|
-
import type { PicklistValue } from "../types/filters/picklist";
|
|
21
|
-
|
|
22
|
-
export function graphQLObjectInfoToObjectInfoResult(
|
|
23
|
-
objectInfo: GetObjectInfosQueryObjectInfo,
|
|
24
|
-
): ObjectInfoResult {
|
|
25
|
-
const { fields, ...rest } = objectInfo;
|
|
26
|
-
const fieldsRecord = Object.fromEntries((fields ?? []).map((field) => [field?.ApiName, field]));
|
|
27
|
-
return {
|
|
28
|
-
...rest,
|
|
29
|
-
fields: fieldsRecord,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Convert GraphQL objectInfos array to ObjectInfoBatchResponse (REST shape). */
|
|
34
|
-
export function graphQLObjectInfosToBatchResponse(
|
|
35
|
-
objectInfos: GetObjectInfosQueryObjectInfos,
|
|
36
|
-
_requestedApiNames: string[],
|
|
37
|
-
): ObjectInfoBatchResponse {
|
|
38
|
-
const results = objectInfos.map((objectInfo) => ({
|
|
39
|
-
result: graphQLObjectInfoToObjectInfoResult(objectInfo!),
|
|
40
|
-
statusCode: 200,
|
|
41
|
-
}));
|
|
42
|
-
return { results };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Extract picklist values for a field from a GraphQL ObjectInfo node (raw response).
|
|
47
|
-
* Uses picklistValuesByRecordTypeIDs; prefers the given recordTypeId or first available.
|
|
48
|
-
*/
|
|
49
|
-
export function extractPicklistValuesFromGraphQLObjectInfo(
|
|
50
|
-
objectInfo: NonNullable<GetPicklistValuesQueryObjectInfo>,
|
|
51
|
-
fieldName: string,
|
|
52
|
-
recordTypeId?: string,
|
|
53
|
-
): PicklistValue[] {
|
|
54
|
-
const fields = objectInfo.fields;
|
|
55
|
-
if (fields == null) return [];
|
|
56
|
-
const fieldMap: Record<string, GetPicklistValuesQueryField> = Object.fromEntries(
|
|
57
|
-
fields.map((field) => {
|
|
58
|
-
return [field?.ApiName, field];
|
|
59
|
-
}),
|
|
60
|
-
);
|
|
61
|
-
const field = fieldMap[fieldName];
|
|
62
|
-
if (!field) return [];
|
|
63
|
-
const picklistData =
|
|
64
|
-
"picklistValuesByRecordTypeIDs" in field ? field.picklistValuesByRecordTypeIDs : undefined;
|
|
65
|
-
if (!picklistData) return [];
|
|
66
|
-
const rtId = recordTypeId ?? "012000000000000AAA";
|
|
67
|
-
const byRecordType = picklistData.find((p) => p!.recordTypeID === rtId) ?? picklistData[0];
|
|
68
|
-
return mapPicklistValues(byRecordType?.picklistValues ?? []);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function mapPicklistValues(values: GraphQLPicklistValue[]): PicklistValue[] {
|
|
72
|
-
return values.map((item) => ({
|
|
73
|
-
...item,
|
|
74
|
-
value: item.value ?? "",
|
|
75
|
-
label: item.label ?? "",
|
|
76
|
-
}));
|
|
77
|
-
}
|