@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,209 +0,0 @@
|
|
|
1
|
-
import React, { useId } from "react";
|
|
2
|
-
import { createFormHookContexts, createFormHook } from "@tanstack/react-form";
|
|
3
|
-
import {
|
|
4
|
-
Field,
|
|
5
|
-
FieldDescription,
|
|
6
|
-
FieldError,
|
|
7
|
-
FieldLabel,
|
|
8
|
-
} from "../../../components/ui/field";
|
|
9
|
-
import { Input } from "../../../components/ui/input";
|
|
10
|
-
import {
|
|
11
|
-
Select,
|
|
12
|
-
SelectContent,
|
|
13
|
-
SelectItem,
|
|
14
|
-
SelectTrigger,
|
|
15
|
-
SelectValue,
|
|
16
|
-
} from "../../../components/ui/select";
|
|
17
|
-
import { cn } from "../../../lib/utils";
|
|
18
|
-
import type { PicklistValue } from "../types/filters/picklist";
|
|
19
|
-
import { getUniqueErrors } from "../utils/formUtils";
|
|
20
|
-
|
|
21
|
-
export type { FormError } from "../utils/formUtils";
|
|
22
|
-
export { validateRangeValues } from "../utils/formUtils";
|
|
23
|
-
|
|
24
|
-
export const { fieldContext, formContext, useFieldContext, useFormContext } =
|
|
25
|
-
createFormHookContexts();
|
|
26
|
-
|
|
27
|
-
interface FilterTextFieldProps extends Omit<
|
|
28
|
-
React.ComponentProps<typeof Input>,
|
|
29
|
-
"name" | "value" | "onBlur" | "onChange" | "aria-invalid"
|
|
30
|
-
> {
|
|
31
|
-
label: string;
|
|
32
|
-
description?: React.ReactNode;
|
|
33
|
-
placeholder?: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function FilterTextField({
|
|
37
|
-
label,
|
|
38
|
-
id: providedId,
|
|
39
|
-
description,
|
|
40
|
-
placeholder,
|
|
41
|
-
type = "text",
|
|
42
|
-
...props
|
|
43
|
-
}: FilterTextFieldProps) {
|
|
44
|
-
const field = useFieldContext<string>();
|
|
45
|
-
const generatedId = useId();
|
|
46
|
-
const id = providedId ?? generatedId;
|
|
47
|
-
const descriptionId = `${id}-description`;
|
|
48
|
-
const errorId = `${id}-error`;
|
|
49
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
50
|
-
|
|
51
|
-
const uniqueErrors = getUniqueErrors(field.state.meta.errors);
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Field data-invalid={isInvalid}>
|
|
55
|
-
<FieldLabel htmlFor={id}>{label}</FieldLabel>
|
|
56
|
-
{description && <FieldDescription id={descriptionId}>{description}</FieldDescription>}
|
|
57
|
-
<Input
|
|
58
|
-
id={id}
|
|
59
|
-
name={field.name as string}
|
|
60
|
-
type={type}
|
|
61
|
-
value={field.state.value ?? ""}
|
|
62
|
-
onBlur={field.handleBlur}
|
|
63
|
-
onChange={(e: React.ChangeEvent<HTMLInputElement>) => field.handleChange(e.target.value)}
|
|
64
|
-
placeholder={placeholder}
|
|
65
|
-
aria-invalid={isInvalid}
|
|
66
|
-
aria-describedby={cn(description && descriptionId, isInvalid && errorId)}
|
|
67
|
-
{...props}
|
|
68
|
-
/>
|
|
69
|
-
{isInvalid && uniqueErrors.length > 0 && <FieldError errors={uniqueErrors} />}
|
|
70
|
-
</Field>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
interface FilterSelectFieldProps {
|
|
75
|
-
label: string;
|
|
76
|
-
id?: string;
|
|
77
|
-
description?: React.ReactNode;
|
|
78
|
-
placeholder?: string;
|
|
79
|
-
options: PicklistValue[];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function FilterSelectField({
|
|
83
|
-
label,
|
|
84
|
-
id: providedId,
|
|
85
|
-
description,
|
|
86
|
-
placeholder = "Select...",
|
|
87
|
-
options,
|
|
88
|
-
}: FilterSelectFieldProps) {
|
|
89
|
-
const field = useFieldContext<string>();
|
|
90
|
-
const generatedId = useId();
|
|
91
|
-
const id = providedId ?? generatedId;
|
|
92
|
-
const descriptionId = `${id}-description`;
|
|
93
|
-
const errorId = `${id}-error`;
|
|
94
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
95
|
-
|
|
96
|
-
const uniqueErrors = getUniqueErrors(field.state.meta.errors);
|
|
97
|
-
|
|
98
|
-
return (
|
|
99
|
-
<Field data-invalid={isInvalid}>
|
|
100
|
-
<FieldLabel htmlFor={id}>{label}</FieldLabel>
|
|
101
|
-
{description && <FieldDescription id={descriptionId}>{description}</FieldDescription>}
|
|
102
|
-
<Select value={field.state.value ?? ""} onValueChange={(value) => field.handleChange(value)}>
|
|
103
|
-
<SelectTrigger
|
|
104
|
-
id={id}
|
|
105
|
-
aria-invalid={isInvalid}
|
|
106
|
-
aria-describedby={cn(description && descriptionId, isInvalid && errorId)}
|
|
107
|
-
>
|
|
108
|
-
<SelectValue placeholder={placeholder} />
|
|
109
|
-
</SelectTrigger>
|
|
110
|
-
<SelectContent>
|
|
111
|
-
{options.map((option) => {
|
|
112
|
-
if (!option || !option.value) return null;
|
|
113
|
-
return (
|
|
114
|
-
<SelectItem key={option.value} value={option.value}>
|
|
115
|
-
{option.label || option.value}
|
|
116
|
-
</SelectItem>
|
|
117
|
-
);
|
|
118
|
-
})}
|
|
119
|
-
</SelectContent>
|
|
120
|
-
</Select>
|
|
121
|
-
{isInvalid && uniqueErrors.length > 0 && <FieldError errors={uniqueErrors} />}
|
|
122
|
-
</Field>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
interface FilterRangeFieldProps extends Omit<
|
|
127
|
-
React.ComponentProps<typeof Input>,
|
|
128
|
-
"name" | "value" | "onBlur" | "onChange" | "aria-invalid"
|
|
129
|
-
> {
|
|
130
|
-
label?: string;
|
|
131
|
-
description?: React.ReactNode;
|
|
132
|
-
placeholder?: string;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function FilterRangeFieldBase({
|
|
136
|
-
label,
|
|
137
|
-
id: providedId,
|
|
138
|
-
description,
|
|
139
|
-
placeholder,
|
|
140
|
-
type = "text",
|
|
141
|
-
...props
|
|
142
|
-
}: FilterRangeFieldProps) {
|
|
143
|
-
const field = useFieldContext<string>();
|
|
144
|
-
const generatedId = useId();
|
|
145
|
-
const id = providedId ?? generatedId;
|
|
146
|
-
const descriptionId = `${id}-description`;
|
|
147
|
-
const errorId = `${id}-error`;
|
|
148
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
149
|
-
|
|
150
|
-
const uniqueErrors = getUniqueErrors(field.state.meta.errors);
|
|
151
|
-
|
|
152
|
-
return (
|
|
153
|
-
<div>
|
|
154
|
-
{label && <FieldLabel htmlFor={id}>{label}</FieldLabel>}
|
|
155
|
-
{description && <FieldDescription id={descriptionId}>{description}</FieldDescription>}
|
|
156
|
-
<Input
|
|
157
|
-
id={id}
|
|
158
|
-
name={field.name as string}
|
|
159
|
-
type={type}
|
|
160
|
-
value={field.state.value ?? ""}
|
|
161
|
-
onBlur={field.handleBlur}
|
|
162
|
-
onChange={(e: React.ChangeEvent<HTMLInputElement>) => field.handleChange(e.target.value)}
|
|
163
|
-
placeholder={placeholder}
|
|
164
|
-
aria-invalid={isInvalid}
|
|
165
|
-
aria-describedby={cn(description && descriptionId, isInvalid && errorId)}
|
|
166
|
-
{...props}
|
|
167
|
-
/>
|
|
168
|
-
{isInvalid && uniqueErrors.length > 0 && <FieldError errors={uniqueErrors} />}
|
|
169
|
-
</div>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
interface FilterRangeMinFieldProps extends Omit<
|
|
174
|
-
React.ComponentProps<typeof Input>,
|
|
175
|
-
"name" | "value" | "onBlur" | "onChange" | "aria-invalid"
|
|
176
|
-
> {
|
|
177
|
-
label?: string;
|
|
178
|
-
description?: React.ReactNode;
|
|
179
|
-
placeholder?: string;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
interface FilterRangeMaxFieldProps extends Omit<
|
|
183
|
-
React.ComponentProps<typeof Input>,
|
|
184
|
-
"name" | "value" | "onBlur" | "onChange" | "aria-invalid"
|
|
185
|
-
> {
|
|
186
|
-
label?: string;
|
|
187
|
-
description?: React.ReactNode;
|
|
188
|
-
placeholder?: string;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function FilterRangeMinField({ placeholder = "Min", ...props }: FilterRangeMinFieldProps) {
|
|
192
|
-
return <FilterRangeFieldBase placeholder={placeholder} {...props} />;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function FilterRangeMaxField({ placeholder = "Max", ...props }: FilterRangeMaxFieldProps) {
|
|
196
|
-
return <FilterRangeFieldBase placeholder={placeholder} {...props} />;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export const { useAppForm } = createFormHook({
|
|
200
|
-
fieldContext,
|
|
201
|
-
formContext,
|
|
202
|
-
fieldComponents: {
|
|
203
|
-
FilterTextField,
|
|
204
|
-
FilterSelectField,
|
|
205
|
-
FilterRangeMinField,
|
|
206
|
-
FilterRangeMaxField,
|
|
207
|
-
},
|
|
208
|
-
formComponents: {},
|
|
209
|
-
});
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useObjectInfoBatch
|
|
3
|
-
*
|
|
4
|
-
* Fetches object metadata (label, labelPlural, fields, etc.) for the given object API names.
|
|
5
|
-
* Uses the shared cache in objectInfoService so List, Home, and Detail views reuse one request.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useState, useEffect, useRef } from "react";
|
|
9
|
-
import { objectInfoService } from "../api/objectInfoService";
|
|
10
|
-
import type { ObjectInfoResult } from "../types/objectInfo/objectInfo";
|
|
11
|
-
|
|
12
|
-
export interface UseObjectInfoBatchResult {
|
|
13
|
-
/** Object metadata in the same order as the requested objectApiNames. */
|
|
14
|
-
objectInfos: ObjectInfoResult[];
|
|
15
|
-
loading: boolean;
|
|
16
|
-
error: string | null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Fetches batch object info for the given object API names. Results are cached;
|
|
21
|
-
* multiple callers (List, Home, Detail) share the same request.
|
|
22
|
-
*
|
|
23
|
-
* @param objectApiNames - Array of object API names (e.g. OBJECT_API_NAMES)
|
|
24
|
-
* @returns objectInfos (same order as input), loading, error
|
|
25
|
-
*/
|
|
26
|
-
export function useObjectInfoBatch(objectApiNames: string[]): UseObjectInfoBatchResult {
|
|
27
|
-
const [state, setState] = useState<UseObjectInfoBatchResult>({
|
|
28
|
-
objectInfos: [],
|
|
29
|
-
loading: objectApiNames.length > 0,
|
|
30
|
-
error: null,
|
|
31
|
-
});
|
|
32
|
-
const isCancelled = useRef(false);
|
|
33
|
-
// Derive a stable primitive from the array so the effect dependency doesn't
|
|
34
|
-
// change on every render. A new array reference (even with identical contents)
|
|
35
|
-
// would otherwise trigger the effect on every render, causing an infinite loop.
|
|
36
|
-
const namesKey = objectApiNames.filter(Boolean).join(",");
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
isCancelled.current = false;
|
|
40
|
-
// Re-derive the array inside the effect from the stable key rather than
|
|
41
|
-
// closing over objectApiNames directly, which would require it in the dep
|
|
42
|
-
// array and reintroduce the infinite loop.
|
|
43
|
-
const names = namesKey ? namesKey.split(",") : [];
|
|
44
|
-
if (names.length === 0) {
|
|
45
|
-
queueMicrotask(() => setState({ objectInfos: [], loading: false, error: null }));
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
queueMicrotask(() => setState((s) => ({ ...s, loading: true, error: null })));
|
|
49
|
-
objectInfoService
|
|
50
|
-
.getObjectInfoBatch(namesKey)
|
|
51
|
-
.then((res) => {
|
|
52
|
-
if (isCancelled.current) return;
|
|
53
|
-
const objectInfos = names
|
|
54
|
-
.map((apiName) => res.results?.find((r) => r.result?.ApiName === apiName)?.result)
|
|
55
|
-
.filter((r) => r != null) as ObjectInfoResult[];
|
|
56
|
-
setState({ objectInfos, loading: false, error: null });
|
|
57
|
-
})
|
|
58
|
-
.catch((err) => {
|
|
59
|
-
if (isCancelled.current) return;
|
|
60
|
-
setState({
|
|
61
|
-
objectInfos: [],
|
|
62
|
-
loading: false,
|
|
63
|
-
error: err instanceof Error ? err.message : (err as string),
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
return () => {
|
|
67
|
-
isCancelled.current = true;
|
|
68
|
-
};
|
|
69
|
-
}, [namesKey]);
|
|
70
|
-
|
|
71
|
-
return state;
|
|
72
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Object Search Data Hooks
|
|
3
|
-
*
|
|
4
|
-
* - useObjectListMetadata: single source for list-view metadata (filters → columns + picklists). Use in list pages to avoid duplicate state and API calls.
|
|
5
|
-
* - useObjectColumns / useObjectFilters: thin wrappers over useObjectListMetadata for backward compatibility.
|
|
6
|
-
* - getSharedFilters: module-level deduplication for getObjectListFilters across hook instances.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { useState, useEffect } from "react";
|
|
10
|
-
import { objectInfoService } from "../api/objectInfoService";
|
|
11
|
-
import type { Column } from "../types/search/searchResults";
|
|
12
|
-
import type { Filter } from "../types/filters/filters";
|
|
13
|
-
import type { PicklistValue } from "../types/filters/picklist";
|
|
14
|
-
|
|
15
|
-
// --- Shared filters cache (deduplicates getObjectListFilters across useObjectColumns + useObjectFilters) ---
|
|
16
|
-
const sharedFiltersCache = new Map<string, Filter[]>();
|
|
17
|
-
const sharedFiltersInFlight = new Map<string, Promise<Filter[]>>();
|
|
18
|
-
|
|
19
|
-
function getSharedFilters(objectApiName: string): Promise<Filter[]> {
|
|
20
|
-
const cached = sharedFiltersCache.get(objectApiName);
|
|
21
|
-
if (cached) return Promise.resolve(cached);
|
|
22
|
-
const inFlight = sharedFiltersInFlight.get(objectApiName);
|
|
23
|
-
if (inFlight) return inFlight;
|
|
24
|
-
const promise = objectInfoService
|
|
25
|
-
.getObjectListFilters(objectApiName)
|
|
26
|
-
.then((filters) => {
|
|
27
|
-
sharedFiltersCache.set(objectApiName, filters);
|
|
28
|
-
sharedFiltersInFlight.delete(objectApiName);
|
|
29
|
-
return filters;
|
|
30
|
-
})
|
|
31
|
-
.catch((err) => {
|
|
32
|
-
sharedFiltersInFlight.delete(objectApiName);
|
|
33
|
-
throw err;
|
|
34
|
-
});
|
|
35
|
-
sharedFiltersInFlight.set(objectApiName, promise);
|
|
36
|
-
return promise;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// --- Shared Types ---
|
|
40
|
-
export interface FiltersData {
|
|
41
|
-
filters: Filter[];
|
|
42
|
-
picklistValues: Record<string, PicklistValue[]>;
|
|
43
|
-
loading: boolean;
|
|
44
|
-
error: string | null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Derives column definitions from filter definitions for list/result UI.
|
|
49
|
-
*/
|
|
50
|
-
function filtersToColumns(filters: Filter[]): Column[] {
|
|
51
|
-
return filters.map((f) => ({
|
|
52
|
-
fieldApiName: f.targetFieldPath,
|
|
53
|
-
label: f.label,
|
|
54
|
-
searchable: true,
|
|
55
|
-
sortable: true,
|
|
56
|
-
}));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface ObjectListMetadata {
|
|
60
|
-
columns: Column[];
|
|
61
|
-
filters: Filter[];
|
|
62
|
-
picklistValues: Record<string, PicklistValue[]>;
|
|
63
|
-
loading: boolean;
|
|
64
|
-
error: string | null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Single hook for list-view metadata: filters (shared API), derived columns, and picklist values.
|
|
69
|
-
* Use this in list/search pages to avoid duplicate useObjectColumns + useObjectFilters and duplicate state.
|
|
70
|
-
*/
|
|
71
|
-
export function useObjectListMetadata(objectApiName: string | null): ObjectListMetadata {
|
|
72
|
-
const [state, setState] = useState<{
|
|
73
|
-
columns: Column[];
|
|
74
|
-
filters: Filter[];
|
|
75
|
-
picklistValues: Record<string, PicklistValue[]>;
|
|
76
|
-
loading: boolean;
|
|
77
|
-
error: string | null;
|
|
78
|
-
}>({
|
|
79
|
-
columns: [],
|
|
80
|
-
filters: [],
|
|
81
|
-
picklistValues: {},
|
|
82
|
-
loading: true,
|
|
83
|
-
error: null,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
if (!objectApiName) {
|
|
88
|
-
queueMicrotask(() => setState((s) => ({ ...s, loading: false, error: "Invalid object" })));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
let isCancelled = false;
|
|
93
|
-
|
|
94
|
-
const run = async () => {
|
|
95
|
-
queueMicrotask(() => setState((s) => ({ ...s, loading: true, error: null })));
|
|
96
|
-
try {
|
|
97
|
-
const filters = await getSharedFilters(objectApiName!);
|
|
98
|
-
if (isCancelled) return;
|
|
99
|
-
|
|
100
|
-
const selectFilters = filters.filter((f) => f.affordance?.toLowerCase() === "select");
|
|
101
|
-
const picklistPromises = selectFilters.map((f) =>
|
|
102
|
-
objectInfoService
|
|
103
|
-
.getPicklistValues(objectApiName!, f.targetFieldPath)
|
|
104
|
-
.then((values) => ({ fieldPath: f.targetFieldPath, values }))
|
|
105
|
-
.catch(() => ({ fieldPath: f.targetFieldPath, values: [] as PicklistValue[] })),
|
|
106
|
-
);
|
|
107
|
-
const picklistResults = await Promise.all(picklistPromises);
|
|
108
|
-
if (isCancelled) return;
|
|
109
|
-
|
|
110
|
-
const picklistValues: Record<string, PicklistValue[]> = {};
|
|
111
|
-
picklistResults.forEach(({ fieldPath, values }) => {
|
|
112
|
-
picklistValues[fieldPath] = values;
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
setState({
|
|
116
|
-
columns: filtersToColumns(filters),
|
|
117
|
-
filters,
|
|
118
|
-
picklistValues,
|
|
119
|
-
loading: false,
|
|
120
|
-
error: null,
|
|
121
|
-
});
|
|
122
|
-
} catch {
|
|
123
|
-
if (isCancelled) return;
|
|
124
|
-
setState((s) => ({
|
|
125
|
-
...s,
|
|
126
|
-
columns: [],
|
|
127
|
-
filters: [],
|
|
128
|
-
picklistValues: {},
|
|
129
|
-
loading: false,
|
|
130
|
-
error: "Failed to load list metadata",
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
run();
|
|
136
|
-
return () => {
|
|
137
|
-
isCancelled = true;
|
|
138
|
-
};
|
|
139
|
-
}, [objectApiName]);
|
|
140
|
-
|
|
141
|
-
return state;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Hook: useObjectColumns
|
|
146
|
-
* Thin wrapper over useObjectListMetadata for backward compatibility.
|
|
147
|
-
*/
|
|
148
|
-
export function useObjectColumns(objectApiName: string | null) {
|
|
149
|
-
const { columns, loading, error } = useObjectListMetadata(objectApiName);
|
|
150
|
-
return {
|
|
151
|
-
columns: objectApiName ? columns : [],
|
|
152
|
-
columnsLoading: loading,
|
|
153
|
-
columnsError: error,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Hook: useObjectFilters
|
|
159
|
-
* Thin wrapper over useObjectListMetadata for backward compatibility.
|
|
160
|
-
*/
|
|
161
|
-
export function useObjectFilters(objectApiName: string | null) {
|
|
162
|
-
const { filters, picklistValues, loading, error } = useObjectListMetadata(objectApiName);
|
|
163
|
-
const filtersData: Record<string, FiltersData> = objectApiName
|
|
164
|
-
? {
|
|
165
|
-
[objectApiName]: {
|
|
166
|
-
filters,
|
|
167
|
-
picklistValues,
|
|
168
|
-
loading,
|
|
169
|
-
error,
|
|
170
|
-
},
|
|
171
|
-
}
|
|
172
|
-
: {};
|
|
173
|
-
return { filtersData };
|
|
174
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from "react";
|
|
2
|
-
import { objectDetailService } from "../api/objectDetailService";
|
|
3
|
-
import type { LayoutResponse } from "../types/recordDetail/recordDetail";
|
|
4
|
-
import type { ObjectInfoResult } from "../types/objectInfo/objectInfo";
|
|
5
|
-
import type { GraphQLRecordNode } from "../api/recordListGraphQLService";
|
|
6
|
-
|
|
7
|
-
export interface UseRecordDetailLayoutReturn {
|
|
8
|
-
layout: LayoutResponse | null;
|
|
9
|
-
record: GraphQLRecordNode | null;
|
|
10
|
-
objectMetadata: ObjectInfoResult | null;
|
|
11
|
-
loading: boolean;
|
|
12
|
-
error: string | null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface UseRecordDetailLayoutParams {
|
|
16
|
-
objectApiName: string | null;
|
|
17
|
-
recordId: string | null;
|
|
18
|
-
recordTypeId?: string | null;
|
|
19
|
-
initialData?: {
|
|
20
|
-
layout: LayoutResponse;
|
|
21
|
-
record: GraphQLRecordNode;
|
|
22
|
-
objectMetadata: ObjectInfoResult;
|
|
23
|
-
} | null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const MAX_CACHE_SIZE = 50;
|
|
27
|
-
const CACHE_TTL_MS = 5 * 60 * 1000;
|
|
28
|
-
|
|
29
|
-
type CacheEntry = {
|
|
30
|
-
layout: LayoutResponse;
|
|
31
|
-
record: GraphQLRecordNode;
|
|
32
|
-
objectMetadata: ObjectInfoResult;
|
|
33
|
-
cachedAt: number;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export function useRecordDetailLayout({
|
|
37
|
-
objectApiName,
|
|
38
|
-
recordId,
|
|
39
|
-
recordTypeId = null,
|
|
40
|
-
initialData = null,
|
|
41
|
-
}: UseRecordDetailLayoutParams): UseRecordDetailLayoutReturn {
|
|
42
|
-
const [layout, setLayout] = useState<LayoutResponse | null>(initialData?.layout ?? null);
|
|
43
|
-
const [record, setRecord] = useState<GraphQLRecordNode | null>(initialData?.record ?? null);
|
|
44
|
-
const [objectMetadata, setObjectMetadata] = useState<ObjectInfoResult | null>(
|
|
45
|
-
initialData?.objectMetadata ?? null,
|
|
46
|
-
);
|
|
47
|
-
const [loading, setLoading] = useState(!initialData);
|
|
48
|
-
const [error, setError] = useState<string | null>(null);
|
|
49
|
-
|
|
50
|
-
const cacheKey =
|
|
51
|
-
objectApiName && recordId ? `${objectApiName}:${recordId}:${recordTypeId ?? "default"}` : null;
|
|
52
|
-
const cacheRef = useRef<Map<string, CacheEntry>>(new Map());
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
if (!objectApiName || !recordId) {
|
|
56
|
-
setError("Invalid object or record ID");
|
|
57
|
-
setLoading(false);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
initialData?.layout != null &&
|
|
63
|
-
initialData?.record != null &&
|
|
64
|
-
initialData?.objectMetadata != null
|
|
65
|
-
) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const cached = cacheRef.current.get(cacheKey!);
|
|
70
|
-
const now = Date.now();
|
|
71
|
-
if (cached && now - cached.cachedAt < CACHE_TTL_MS) {
|
|
72
|
-
setLayout(cached.layout);
|
|
73
|
-
setRecord(cached.record);
|
|
74
|
-
setObjectMetadata(cached.objectMetadata);
|
|
75
|
-
setLoading(false);
|
|
76
|
-
setError(null);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let isCancelled = false;
|
|
81
|
-
|
|
82
|
-
const fetchDetail = async () => {
|
|
83
|
-
setLoading(true);
|
|
84
|
-
setError(null);
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
const {
|
|
88
|
-
layout: layoutData,
|
|
89
|
-
record: recordData,
|
|
90
|
-
objectMetadata: objectMetadataData,
|
|
91
|
-
} = await objectDetailService.getRecordDetail(
|
|
92
|
-
objectApiName,
|
|
93
|
-
recordId,
|
|
94
|
-
recordTypeId ?? undefined,
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
if (isCancelled) return;
|
|
98
|
-
|
|
99
|
-
const cache = cacheRef.current;
|
|
100
|
-
if (cache.size >= MAX_CACHE_SIZE) {
|
|
101
|
-
const firstKey = cache.keys().next().value;
|
|
102
|
-
if (firstKey != null) cache.delete(firstKey);
|
|
103
|
-
}
|
|
104
|
-
cache.set(cacheKey!, {
|
|
105
|
-
layout: layoutData,
|
|
106
|
-
record: recordData,
|
|
107
|
-
objectMetadata: objectMetadataData,
|
|
108
|
-
cachedAt: Date.now(),
|
|
109
|
-
});
|
|
110
|
-
setLayout(layoutData);
|
|
111
|
-
setRecord(recordData);
|
|
112
|
-
setObjectMetadata(objectMetadataData);
|
|
113
|
-
} catch {
|
|
114
|
-
if (isCancelled) return;
|
|
115
|
-
setError("Failed to load record details");
|
|
116
|
-
} finally {
|
|
117
|
-
if (!isCancelled) {
|
|
118
|
-
setLoading(false);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
fetchDetail();
|
|
124
|
-
|
|
125
|
-
return () => {
|
|
126
|
-
isCancelled = true;
|
|
127
|
-
};
|
|
128
|
-
}, [objectApiName, recordId, recordTypeId, cacheKey, initialData]);
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
layout,
|
|
132
|
-
record,
|
|
133
|
-
objectMetadata,
|
|
134
|
-
loading,
|
|
135
|
-
error,
|
|
136
|
-
};
|
|
137
|
-
}
|