@salesforce/ui-bundle-template-app-react-sample-b2x 11.68.0 → 11.68.2
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 +16 -0
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/package.json +4 -4
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/api/objectSearchService.ts +2 -8
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/hooks/useObjectSearchParams.ts +1 -19
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/utils/debounce.ts +1 -12
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/utils/filterUtils.ts +8 -123
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/utils/sortUtils.ts +1 -17
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/pages/PropertySearch.tsx +3 -6
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/routes.tsx +0 -10
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/tsconfig.tsbuildinfo +1 -1
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/package.json +4 -1
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/api/accountSearchService.ts +0 -46
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/api/query/distinctAccountIndustries.graphql +0 -19
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/api/query/distinctAccountTypes.graphql +0 -19
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/api/query/getAccountDetail.graphql +0 -121
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/api/query/searchAccounts.graphql +0 -51
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/pages/AccountObjectDetailPage.tsx +0 -355
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/pages/AccountSearch.tsx +0 -304
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/__examples__/pages/Home.tsx +0 -34
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/ActiveFilters.tsx +0 -89
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/FilterContext.tsx +0 -83
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/ObjectBreadcrumb.tsx +0 -66
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/SearchBar.tsx +0 -41
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/SortControl.tsx +0 -143
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/BooleanFilter.tsx +0 -78
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/DateFilter.tsx +0 -128
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/DateRangeFilter.tsx +0 -70
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/FilterFieldWrapper.tsx +0 -43
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/MultiSelectFilter.tsx +0 -105
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/NumericRangeFilter.tsx +0 -171
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/SearchFilter.tsx +0 -52
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/SelectFilter.tsx +0 -97
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/components/filters/TextFilter.tsx +0 -93
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/hooks/useAsyncData.ts +0 -63
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/hooks/useDebouncedCallback.ts +0 -34
- package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/features/object-search/utils/fieldUtils.ts +0 -29
package/dist/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [11.68.2](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.68.1...v11.68.2) (2026-08-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [11.68.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.68.0...v11.68.1) (2026-08-24)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [11.68.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.67.1...v11.68.0) (2026-08-21)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"graphql:schema": "node scripts/get-graphql-schema.mjs"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@salesforce/platform-sdk": "^11.68.
|
|
22
|
-
"@salesforce/ui-bundle": "^11.68.
|
|
21
|
+
"@salesforce/platform-sdk": "^11.68.2",
|
|
22
|
+
"@salesforce/ui-bundle": "^11.68.2",
|
|
23
23
|
"@tailwindcss/vite": "^4.1.17",
|
|
24
24
|
"class-variance-authority": "^0.7.1",
|
|
25
25
|
"clsx": "^2.1.1",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"@graphql-eslint/eslint-plugin": "^4.1.0",
|
|
51
51
|
"@graphql-tools/utils": "^11.0.0",
|
|
52
52
|
"@playwright/test": "^1.49.0",
|
|
53
|
-
"@salesforce/graphiti": "^11.68.
|
|
54
|
-
"@salesforce/vite-plugin-ui-bundle": "^11.68.
|
|
53
|
+
"@salesforce/graphiti": "^11.68.2",
|
|
54
|
+
"@salesforce/vite-plugin-ui-bundle": "^11.68.2",
|
|
55
55
|
"@testing-library/jest-dom": "^6.6.3",
|
|
56
56
|
"@testing-library/react": "^16.1.0",
|
|
57
57
|
"@testing-library/user-event": "^14.5.2",
|
|
@@ -9,10 +9,7 @@ export interface ObjectSearchOptions<TWhere, TOrderBy> {
|
|
|
9
9
|
|
|
10
10
|
export type PicklistOption = { value: string; label: string };
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* Executes a GraphQL search query and extracts the result for the given object name
|
|
14
|
-
* from the standard `uiapi.query.<ObjectName>` response shape.
|
|
15
|
-
*/
|
|
12
|
+
/** Runs a GraphQL search query and extracts the result for the given object name from the `uiapi.query.<ObjectName>` response shape. */
|
|
16
13
|
export async function searchObjects<TResult, TQuery, TVariables>(
|
|
17
14
|
query: string,
|
|
18
15
|
objectName: string,
|
|
@@ -45,10 +42,7 @@ export async function searchObjects<TResult, TQuery, TVariables>(
|
|
|
45
42
|
return queryResult;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
/**
|
|
49
|
-
* Executes a GraphQL aggregate/groupBy query and extracts picklist options
|
|
50
|
-
* from the standard `uiapi.aggregate.<ObjectName>` response shape.
|
|
51
|
-
*/
|
|
45
|
+
/** Runs a GraphQL aggregate/groupBy query and extracts picklist options from the `uiapi.aggregate.<ObjectName>` response shape. */
|
|
52
46
|
export async function fetchDistinctValues<TQuery>(
|
|
53
47
|
query: string,
|
|
54
48
|
objectName: string,
|
|
@@ -36,25 +36,7 @@ export interface UseObjectSearchParamsReturn<TFilter, TOrderBy> {
|
|
|
36
36
|
resetAll: () => void;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
* Manages filter, sort, and cursor-based pagination state for an object search page.
|
|
41
|
-
*
|
|
42
|
-
* ## State model
|
|
43
|
-
* Local React state is the primary driver for instant UI updates.
|
|
44
|
-
* URL search params act as the durable source of truth so that a page
|
|
45
|
-
* refresh or shared link restores the same view. Changes are synced to
|
|
46
|
-
* the URL via a debounced write (300 ms) to avoid excessive history entries.
|
|
47
|
-
*
|
|
48
|
-
* ## Return shape
|
|
49
|
-
* Returns memoized groups so each group's reference is stable unless its
|
|
50
|
-
* contents change — safe to pass directly as props to `React.memo` children.
|
|
51
|
-
*
|
|
52
|
-
* - `filters` — active filter values + set/remove callbacks
|
|
53
|
-
* - `sort` — current sort state + set callback
|
|
54
|
-
* - `query` — derived `where` / `orderBy` objects ready for the API
|
|
55
|
-
* - `pagination` — page size, page index, cursor, and navigation callbacks
|
|
56
|
-
* - `resetAll` — clears all filters, sort, and pagination in one call
|
|
57
|
-
*/
|
|
39
|
+
/** Manages filter, sort, and cursor-based pagination state for an object search page, syncing changes to the URL via a debounced write. */
|
|
58
40
|
export function useObjectSearchParams<TFilter, TOrderBy>(
|
|
59
41
|
filterConfigs: FilterFieldConfig[],
|
|
60
42
|
_sortConfigs?: SortFieldConfig[],
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
/** Default debounce delay for keystroke-driven filter inputs (search, text, numeric). */
|
|
2
2
|
export const FILTER_DEBOUNCE_MS = 300;
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Creates a debounced version of the provided function.
|
|
6
|
-
*
|
|
7
|
-
* Each call to the returned function resets the internal timer. The wrapped
|
|
8
|
-
* function is only invoked once the timer expires without being reset. This
|
|
9
|
-
* makes it ideal for rate-limiting high-frequency events like input changes.
|
|
10
|
-
*
|
|
11
|
-
* @typeParam T - The function signature to debounce.
|
|
12
|
-
* @param fn - The function to debounce.
|
|
13
|
-
* @param ms - The debounce delay in milliseconds.
|
|
14
|
-
* @returns A new function with the same signature that delays execution.
|
|
15
|
-
*/
|
|
4
|
+
/** Creates a debounced version of a function; each call resets the timer so only the last call within `ms` fires. */
|
|
16
5
|
export function debounce<T extends (...args: any[]) => void>(
|
|
17
6
|
fn: T,
|
|
18
7
|
ms: number,
|
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* filterUtils.ts
|
|
3
|
-
*
|
|
4
|
-
* Centralizes all filter-related transformations for the object search feature.
|
|
5
|
-
* This module handles two distinct concerns:
|
|
6
|
-
*
|
|
7
|
-
* 1. **URL serialization** — Converting filter/sort state to and from
|
|
8
|
-
* URLSearchParams so that search criteria can be bookmarked, shared, and
|
|
9
|
-
* restored on page load.
|
|
10
|
-
*
|
|
11
|
-
* 2. **GraphQL query building** — Converting the same filter state into the
|
|
12
|
-
* `where` clause shape expected by the GraphQL API.
|
|
13
|
-
*
|
|
14
|
-
* Both concerns operate on the shared {@link ActiveFilterValue} type, which
|
|
15
|
-
* represents a single active filter with a field name, filter type, and one or
|
|
16
|
-
* more values (value, min, max).
|
|
17
|
-
*/
|
|
1
|
+
/** Filter state transformations: URL param serialization and GraphQL where-clause building. */
|
|
18
2
|
|
|
19
3
|
import type { SortState } from "./sortUtils";
|
|
20
4
|
|
|
@@ -55,13 +39,7 @@ export type ActiveFilterValue<TFieldName extends string = string> = {
|
|
|
55
39
|
// URL Serialization
|
|
56
40
|
// ---------------------------------------------------------------------------
|
|
57
41
|
|
|
58
|
-
/**
|
|
59
|
-
* Prefix applied to all filter-related URL search params.
|
|
60
|
-
* This namespaces filter params so they don't collide with other query params
|
|
61
|
-
* (e.g. pagination, feature flags).
|
|
62
|
-
*
|
|
63
|
-
* @example "f.Industry=Technology" or "f.AnnualRevenue.min=1000000"
|
|
64
|
-
*/
|
|
42
|
+
/** Prefix applied to all filter-related URL search param keys. */
|
|
65
43
|
const FILTER_PREFIX = "f.";
|
|
66
44
|
|
|
67
45
|
/** URL param key for the multi-field search term. */
|
|
@@ -77,29 +55,7 @@ const DIR_KEY = "dir";
|
|
|
77
55
|
const PAGE_SIZE_KEY = "ps";
|
|
78
56
|
const PAGE_KEY = "page";
|
|
79
57
|
|
|
80
|
-
/**
|
|
81
|
-
* Serializes filter and sort state into URLSearchParams.
|
|
82
|
-
*
|
|
83
|
-
* Encoding scheme:
|
|
84
|
-
* - Simple values (text, picklist, boolean, multipicklist):
|
|
85
|
-
* `f.<field>=<value>`
|
|
86
|
-
* - Range values (numeric, date, daterange):
|
|
87
|
-
* `f.<field>.min=<min>` and/or `f.<field>.max=<max>`
|
|
88
|
-
* - Sort: `sort=<field>&dir=ASC|DESC`
|
|
89
|
-
*
|
|
90
|
-
* @param filters - The currently active filters to serialize.
|
|
91
|
-
* @param sort - The current sort state, or null if no sort is applied.
|
|
92
|
-
* @returns A URLSearchParams instance representing the full search state.
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* ```ts
|
|
96
|
-
* const params = filtersToSearchParams(
|
|
97
|
-
* [{ field: "Industry", type: "picklist", value: "Technology" }],
|
|
98
|
-
* { field: "Name", direction: "ASC" },
|
|
99
|
-
* );
|
|
100
|
-
* // params.toString() => "f.Industry=Technology&sort=Name&dir=ASC"
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
58
|
+
/** Serializes filter and sort state into URLSearchParams so search criteria can be bookmarked and shared. */
|
|
103
59
|
export function filtersToSearchParams(
|
|
104
60
|
filters: ActiveFilterValue[],
|
|
105
61
|
sort: SortState | null,
|
|
@@ -140,25 +96,7 @@ export function filtersToSearchParams(
|
|
|
140
96
|
return params;
|
|
141
97
|
}
|
|
142
98
|
|
|
143
|
-
/**
|
|
144
|
-
* Deserializes URLSearchParams back into filter and sort state.
|
|
145
|
-
*
|
|
146
|
-
* Requires the full list of filter configs so it knows which URL params to look
|
|
147
|
-
* for and what type each filter is. Params that don't match a known config are
|
|
148
|
-
* silently ignored, making this safe against stale or hand-edited URLs.
|
|
149
|
-
*
|
|
150
|
-
* @param params - The URLSearchParams to parse (typically from the browser URL).
|
|
151
|
-
* @param configs - The filter field configurations defining available filters.
|
|
152
|
-
* @returns An object containing the deserialized `filters` array and `sort` state.
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* ```ts
|
|
156
|
-
* const url = new URLSearchParams("f.Industry=Technology&sort=Name&dir=ASC");
|
|
157
|
-
* const { filters, sort } = searchParamsToFilters(url, filterConfigs);
|
|
158
|
-
* // filters => [{ field: "Industry", type: "picklist", value: "Technology" }]
|
|
159
|
-
* // sort => { field: "Name", direction: "ASC" }
|
|
160
|
-
* ```
|
|
161
|
-
*/
|
|
99
|
+
/** Deserializes URLSearchParams back into filter and sort state, ignoring params that don't match a known config. */
|
|
162
100
|
export function searchParamsToFilters(
|
|
163
101
|
params: URLSearchParams,
|
|
164
102
|
configs: FilterFieldConfig[],
|
|
@@ -222,30 +160,7 @@ export function searchParamsToFilters(
|
|
|
222
160
|
// GraphQL Filter Building
|
|
223
161
|
// ---------------------------------------------------------------------------
|
|
224
162
|
|
|
225
|
-
/**
|
|
226
|
-
* Converts an array of active filter values into a GraphQL `where` clause.
|
|
227
|
-
*
|
|
228
|
-
* Each filter is individually converted to a clause via {@link buildSingleFilter},
|
|
229
|
-
* then multiple clauses are combined with a top-level `and` operator. This ensures
|
|
230
|
-
* all active filters are applied simultaneously (intersection semantics).
|
|
231
|
-
*
|
|
232
|
-
* @typeParam TFilter - The GraphQL filter input type (e.g. `AccountFilterInput`).
|
|
233
|
-
* @param filters - The active filters to convert.
|
|
234
|
-
* @returns A filter object for the GraphQL `where` variable, or `undefined` if
|
|
235
|
-
* no filters are active (which tells the API to return unfiltered results).
|
|
236
|
-
*
|
|
237
|
-
* @example
|
|
238
|
-
* ```ts
|
|
239
|
-
* const where = buildFilter<AccountFilterInput>([
|
|
240
|
-
* { field: "Industry", type: "picklist", value: "Technology" },
|
|
241
|
-
* { field: "AnnualRevenue", type: "numeric", min: "1000000" },
|
|
242
|
-
* ]);
|
|
243
|
-
* // where => { and: [
|
|
244
|
-
* // { Industry: { eq: "Technology" } },
|
|
245
|
-
* // { AnnualRevenue: { gte: 1000000 } },
|
|
246
|
-
* // ]}
|
|
247
|
-
* ```
|
|
248
|
-
*/
|
|
163
|
+
/** Combines active filters into a single GraphQL where clause, ANDing multiple filters together. */
|
|
249
164
|
export function buildFilter<TFilter>(
|
|
250
165
|
filters: ActiveFilterValue[],
|
|
251
166
|
configs: FilterFieldConfig[],
|
|
@@ -263,47 +178,17 @@ export function buildFilter<TFilter>(
|
|
|
263
178
|
return { and: clauses } as TFilter;
|
|
264
179
|
}
|
|
265
180
|
|
|
266
|
-
/**
|
|
267
|
-
* Converts a YYYY-MM-DD date string to a full ISO-8601 datetime at midnight UTC.
|
|
268
|
-
* Used as the inclusive lower bound for date range queries.
|
|
269
|
-
*/
|
|
181
|
+
/** Converts a YYYY-MM-DD date string to an ISO-8601 datetime at midnight UTC (inclusive lower bound). */
|
|
270
182
|
function toStartOfDay(dateStr: string): string {
|
|
271
183
|
return `${dateStr}T00:00:00.000Z`;
|
|
272
184
|
}
|
|
273
185
|
|
|
274
|
-
/**
|
|
275
|
-
* Converts a YYYY-MM-DD date string to a full ISO-8601 datetime at the last
|
|
276
|
-
* millisecond of the day in UTC. Used as the inclusive upper bound for date
|
|
277
|
-
* range queries.
|
|
278
|
-
*/
|
|
186
|
+
/** Converts a YYYY-MM-DD date string to an ISO-8601 datetime at the last millisecond of the day UTC (inclusive upper bound). */
|
|
279
187
|
function toEndOfDay(dateStr: string): string {
|
|
280
188
|
return `${dateStr}T23:59:59.999Z`;
|
|
281
189
|
}
|
|
282
190
|
|
|
283
|
-
/**
|
|
284
|
-
* Converts a single active filter value into a GraphQL filter clause.
|
|
285
|
-
*
|
|
286
|
-
* Supported filter types and their GraphQL mappings:
|
|
287
|
-
*
|
|
288
|
-
* | Type | GraphQL operator(s) | Example output |
|
|
289
|
-
* |-----------------|---------------------|----------------------------------------------------------|
|
|
290
|
-
* | `text` | `like` | `{ Name: { like: "%Acme%" } }` |
|
|
291
|
-
* | `picklist` | `eq` | `{ Industry: { eq: "Technology" } }` |
|
|
292
|
-
* | `multipicklist` | `eq` or `in` | `{ Type: { in: ["A", "B"] } }` |
|
|
293
|
-
* | `numeric` | `gte` / `lte` | `{ Revenue: { gte: 1000, lte: 5000 } }` |
|
|
294
|
-
* | `boolean` | `eq` | `{ IsActive: { eq: true } }` |
|
|
295
|
-
* | `date` | dynamic operator | `{ CreatedDate: { gte: { value: "..." } } }` |
|
|
296
|
-
* | `daterange` | `gte` + `lte` | Combined with `and` if both bounds set |
|
|
297
|
-
* | `search` | `like` + `or` | `{ or: [{ Name: { like: "%x%" } }, { Phone: { like: "%x%" } }] }` |
|
|
298
|
-
*
|
|
299
|
-
* The `search` type uses `config.searchFields` to build an `or` clause that
|
|
300
|
-
* matches the search term across multiple fields simultaneously (union semantics).
|
|
301
|
-
*
|
|
302
|
-
* @param filter - The active filter value to convert.
|
|
303
|
-
* @param config - The corresponding field config. Required for `search` type
|
|
304
|
-
* (provides `searchFields`); optional for all other types.
|
|
305
|
-
* @returns A single filter clause, or `null` if the filter has no meaningful value.
|
|
306
|
-
*/
|
|
191
|
+
/** Converts a single active filter value into a GraphQL filter clause based on its type. */
|
|
307
192
|
function buildSingleFilter<TFilter>(
|
|
308
193
|
filter: ActiveFilterValue,
|
|
309
194
|
config?: FilterFieldConfig,
|
|
@@ -10,23 +10,7 @@ export type SortState<TFieldName extends string = string> = {
|
|
|
10
10
|
direction: "ASC" | "DESC";
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Converts a {@link SortState} into a GraphQL order-by object.
|
|
15
|
-
*
|
|
16
|
-
* @typeParam TOrderBy - The GraphQL order-by input type (e.g. `AccountOrderByInput`).
|
|
17
|
-
* @param sort - The current sort state from the UI, or `null` if no sort is applied.
|
|
18
|
-
* @returns An order-by object for the GraphQL query's `orderBy` variable, or
|
|
19
|
-
* `undefined` if no sort is active (which uses the API's default ordering).
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```ts
|
|
23
|
-
* const orderBy = buildOrderBy<AccountOrderByInput>({
|
|
24
|
-
* field: "Name",
|
|
25
|
-
* direction: "ASC",
|
|
26
|
-
* });
|
|
27
|
-
* // orderBy => { Name: { order: ResultOrder.Asc, nulls: NullOrder.Last } }
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
13
|
+
/** Converts a SortState into a GraphQL order-by object, or undefined if no sort is active. */
|
|
30
14
|
export function buildOrderBy<TOrderBy>(sort: SortState | null): TOrderBy | undefined {
|
|
31
15
|
if (!sort) return undefined;
|
|
32
16
|
return {
|
package/dist/force-app/main/default/uiBundles/propertyrentalapp/src/pages/PropertySearch.tsx
CHANGED
|
@@ -20,10 +20,7 @@ import {
|
|
|
20
20
|
} from "@/features/object-search/hooks/useObjectSearchParams";
|
|
21
21
|
import { useAsyncData } from "@/hooks/useAsyncData";
|
|
22
22
|
import type { FilterFieldConfig } from "@/features/object-search/utils/filterUtils";
|
|
23
|
-
import type {
|
|
24
|
-
SortFieldConfig,
|
|
25
|
-
SortState,
|
|
26
|
-
} from "@/features/object-search/utils/sortUtils";
|
|
23
|
+
import type { SortFieldConfig, SortState } from "@/features/object-search/utils/sortUtils";
|
|
27
24
|
import { usePropertyMapMarkers } from "@/hooks/usePropertyMapMarkers";
|
|
28
25
|
import PaginationControls from "@/features/object-search/components/PaginationControls";
|
|
29
26
|
import PropertyListingCard, {
|
|
@@ -68,7 +65,7 @@ const PAGINATION_CONFIG: PaginationConfig = {
|
|
|
68
65
|
validPageSizes: [10, 20, 50],
|
|
69
66
|
};
|
|
70
67
|
|
|
71
|
-
/* ── Adapter helpers: translate between popover pill UI types and
|
|
68
|
+
/* ── Adapter helpers: translate between popover pill UI types and filter/sort state ── */
|
|
72
69
|
|
|
73
70
|
const SORT_TO_STATE: Record<NonNullable<SortBy>, SortState> = {
|
|
74
71
|
price_asc: { field: "Monthly_Rent__c", direction: "ASC" },
|
|
@@ -100,7 +97,7 @@ function rangeToBedroomBucket(min?: string, max?: string): BedroomFilter {
|
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
export default function PropertySearch() {
|
|
103
|
-
/* ──
|
|
100
|
+
/* ── Search state and pagination ── */
|
|
104
101
|
const { filters, sort, query, pagination } = useObjectSearchParams<
|
|
105
102
|
Property__C_Filter,
|
|
106
103
|
Property__C_OrderBy
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { RouteObject } from 'react-router';
|
|
2
2
|
import Home from '@/pages/Home';
|
|
3
3
|
import NotFound from '@/pages/NotFound';
|
|
4
|
-
import AccountSearch from "./features/object-search/__examples__/pages/AccountSearch";
|
|
5
|
-
import AccountObjectDetail from "./features/object-search/__examples__/pages/AccountObjectDetailPage";
|
|
6
4
|
import AuthAppLayout from "./features/authentication/layouts/AuthAppLayout";
|
|
7
5
|
import Login from "./features/authentication/pages/Login";
|
|
8
6
|
import Register from "./features/authentication/pages/Register";
|
|
@@ -30,14 +28,6 @@ export const routes: RouteObject[] = [
|
|
|
30
28
|
element: <Home />,
|
|
31
29
|
handle: { showInNavigation: true, label: "Home" }
|
|
32
30
|
},
|
|
33
|
-
{
|
|
34
|
-
path: "accounts/:recordId",
|
|
35
|
-
element: <AccountObjectDetail />
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
path: "accounts",
|
|
39
|
-
element: <AccountSearch />
|
|
40
|
-
},
|
|
41
31
|
{
|
|
42
32
|
path: ROUTES.LOGIN.PATH,
|
|
43
33
|
element: <Login />,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/app.tsx","./src/appLayout.tsx","./src/navigationMenu.tsx","./src/router-utils.tsx","./src/routes.tsx","./src/api/graphql-operations-types.ts","./src/api/graphqlClient.ts","./src/api/applications/applicationApi.ts","./src/api/leads/leadApi.ts","./src/api/maintenanceRequests/maintenanceRequestApi.ts","./src/api/properties/propertyDetailGraphQL.ts","./src/api/properties/propertyNodeUtils.ts","./src/api/properties/propertySearchService.ts","./src/api/tenants/tenantApi.ts","./src/components/ErrorBoundary.tsx","./src/components/SkeletonPrimitives.tsx","./src/components/alerts/status-alert.tsx","./src/components/dashboard/WeatherWidget.tsx","./src/components/layout/TopBar.tsx","./src/components/layout/VerticalNav.tsx","./src/components/layouts/card-layout.tsx","./src/components/maintenanceRequests/MaintenanceRequestIcon.tsx","./src/components/maintenanceRequests/MaintenanceRequestList.tsx","./src/components/maintenanceRequests/MaintenanceRequestListItem.tsx","./src/components/maintenanceRequests/MaintenanceSummaryDetailsModal.tsx","./src/components/maintenanceRequests/StatusBadge.tsx","./src/components/properties/PropertyListingCard.tsx","./src/components/properties/PropertyMap.tsx","./src/components/properties/PropertySearchFilters.tsx","./src/components/ui/alert.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/datePicker.tsx","./src/components/ui/dialog.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/field.tsx","./src/components/ui/index.ts","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/sonner.tsx","./src/components/ui/spinner.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/context/TenantAccessContext.tsx","./src/features/authentication/authHelpers.ts","./src/features/authentication/authenticationConfig.ts","./src/features/authentication/api/userProfileApi.ts","./src/features/authentication/components/SocialLogin.tsx","./src/features/authentication/context/AuthContext.tsx","./src/features/authentication/footers/footer-link.tsx","./src/features/authentication/forms/auth-form.tsx","./src/features/authentication/forms/submit-button.tsx","./src/features/authentication/hooks/form.tsx","./src/features/authentication/hooks/useCountdownTimer.ts","./src/features/authentication/hooks/useRetryWithBackoff.ts","./src/features/authentication/layout/centered-page-layout.tsx","./src/features/authentication/layouts/AuthAppLayout.tsx","./src/features/authentication/layouts/TenantRoute.tsx","./src/features/authentication/layouts/privateRouteLayout.tsx","./src/features/authentication/menu/AuthMenu.tsx","./src/features/authentication/pages/ChangePassword.tsx","./src/features/authentication/pages/ForgotPassword.tsx","./src/features/authentication/pages/Login.tsx","./src/features/authentication/pages/Profile.tsx","./src/features/authentication/pages/Register.tsx","./src/features/authentication/pages/ResetPassword.tsx","./src/features/authentication/sessionTimeout/SessionTimeoutValidator.tsx","./src/features/authentication/sessionTimeout/sessionTimeService.ts","./src/features/authentication/sessionTimeout/sessionTimeoutConfig.ts","./src/features/authentication/utils/helpers.ts","./src/features/object-search/
|
|
1
|
+
{"root":["./src/app.tsx","./src/appLayout.tsx","./src/navigationMenu.tsx","./src/router-utils.tsx","./src/routes.tsx","./src/api/graphql-operations-types.ts","./src/api/graphqlClient.ts","./src/api/applications/applicationApi.ts","./src/api/leads/leadApi.ts","./src/api/maintenanceRequests/maintenanceRequestApi.ts","./src/api/properties/propertyDetailGraphQL.ts","./src/api/properties/propertyNodeUtils.ts","./src/api/properties/propertySearchService.ts","./src/api/tenants/tenantApi.ts","./src/components/ErrorBoundary.tsx","./src/components/SkeletonPrimitives.tsx","./src/components/alerts/status-alert.tsx","./src/components/dashboard/WeatherWidget.tsx","./src/components/layout/TopBar.tsx","./src/components/layout/VerticalNav.tsx","./src/components/layouts/card-layout.tsx","./src/components/maintenanceRequests/MaintenanceRequestIcon.tsx","./src/components/maintenanceRequests/MaintenanceRequestList.tsx","./src/components/maintenanceRequests/MaintenanceRequestListItem.tsx","./src/components/maintenanceRequests/MaintenanceSummaryDetailsModal.tsx","./src/components/maintenanceRequests/StatusBadge.tsx","./src/components/properties/PropertyListingCard.tsx","./src/components/properties/PropertyMap.tsx","./src/components/properties/PropertySearchFilters.tsx","./src/components/ui/alert.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/datePicker.tsx","./src/components/ui/dialog.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/field.tsx","./src/components/ui/index.ts","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/sonner.tsx","./src/components/ui/spinner.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/context/TenantAccessContext.tsx","./src/features/authentication/authHelpers.ts","./src/features/authentication/authenticationConfig.ts","./src/features/authentication/api/userProfileApi.ts","./src/features/authentication/components/SocialLogin.tsx","./src/features/authentication/context/AuthContext.tsx","./src/features/authentication/footers/footer-link.tsx","./src/features/authentication/forms/auth-form.tsx","./src/features/authentication/forms/submit-button.tsx","./src/features/authentication/hooks/form.tsx","./src/features/authentication/hooks/useCountdownTimer.ts","./src/features/authentication/hooks/useRetryWithBackoff.ts","./src/features/authentication/layout/centered-page-layout.tsx","./src/features/authentication/layouts/AuthAppLayout.tsx","./src/features/authentication/layouts/TenantRoute.tsx","./src/features/authentication/layouts/privateRouteLayout.tsx","./src/features/authentication/menu/AuthMenu.tsx","./src/features/authentication/pages/ChangePassword.tsx","./src/features/authentication/pages/ForgotPassword.tsx","./src/features/authentication/pages/Login.tsx","./src/features/authentication/pages/Profile.tsx","./src/features/authentication/pages/Register.tsx","./src/features/authentication/pages/ResetPassword.tsx","./src/features/authentication/sessionTimeout/SessionTimeoutValidator.tsx","./src/features/authentication/sessionTimeout/sessionTimeService.ts","./src/features/authentication/sessionTimeout/sessionTimeoutConfig.ts","./src/features/authentication/utils/helpers.ts","./src/features/object-search/api/objectSearchService.ts","./src/features/object-search/components/PaginationControls.tsx","./src/features/object-search/hooks/useObjectSearchParams.ts","./src/features/object-search/utils/debounce.ts","./src/features/object-search/utils/filterUtils.ts","./src/features/object-search/utils/sortUtils.ts","./src/hooks/useAsyncData.ts","./src/hooks/useGeocode.ts","./src/hooks/useMaintenanceRequests.ts","./src/hooks/usePropertyDetail.ts","./src/hooks/usePropertyMapMarkers.ts","./src/hooks/useWeather.ts","./src/lib/utils.ts","./src/pages/Application.tsx","./src/pages/Contact.tsx","./src/pages/Dashboard.tsx","./src/pages/Home.tsx","./src/pages/Maintenance.tsx","./src/pages/NotFound.tsx","./src/pages/PropertyDetails.tsx","./src/pages/PropertySearch.tsx","./src/pages/PropertySearchPlaceholder.tsx","./src/types/leaflet.d.ts","./src/types/searchResults.ts","./src/utils/geocode.ts","./src/utils/propertyListingPaginationUtils.ts","./e2e/app.spec.ts","./vite-env.d.ts","./vitest-env.d.ts","./vitest.setup.ts","../../../../../../../../../sdk/platform-sdk/types/env.d.ts"],"version":"5.9.3"}
|
package/dist/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/ui-bundle-template-base-sfdx-project",
|
|
3
|
-
"version": "11.68.
|
|
3
|
+
"version": "11.68.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@salesforce/ui-bundle-template-base-sfdx-project",
|
|
9
|
-
"version": "11.68.
|
|
9
|
+
"version": "11.68.2",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"fast-xml-parser": "^5.9.3",
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/ui-bundle-template-app-react-sample-b2x",
|
|
3
|
-
"version": "11.68.
|
|
3
|
+
"version": "11.68.2",
|
|
4
4
|
"description": "Salesforce sample property rental React app",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"author": "",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"clean": "rm -rf dist"
|
|
17
17
|
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"lucide-react": "^0.562.0"
|
|
20
|
+
},
|
|
18
21
|
"devDependencies": {
|
|
19
22
|
"@types/react": "^19.2.7",
|
|
20
23
|
"@types/react-dom": "^19.2.3",
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import SEARCH_ACCOUNTS_QUERY from "./query/searchAccounts.graphql?raw";
|
|
2
|
-
import DISTINCT_INDUSTRIES_QUERY from "./query/distinctAccountIndustries.graphql?raw";
|
|
3
|
-
import DISTINCT_TYPES_QUERY from "./query/distinctAccountTypes.graphql?raw";
|
|
4
|
-
import {
|
|
5
|
-
searchObjects,
|
|
6
|
-
fetchDistinctValues,
|
|
7
|
-
type ObjectSearchOptions,
|
|
8
|
-
type PicklistOption,
|
|
9
|
-
} from "../../api/objectSearchService";
|
|
10
|
-
import type {
|
|
11
|
-
SearchAccountsQuery,
|
|
12
|
-
SearchAccountsQueryVariables,
|
|
13
|
-
DistinctAccountIndustriesQuery,
|
|
14
|
-
DistinctAccountTypesQuery,
|
|
15
|
-
} from "../../../../api/graphql-operations-types";
|
|
16
|
-
|
|
17
|
-
export type AccountSearchResult = NonNullable<SearchAccountsQuery["uiapi"]["query"]["Account"]>;
|
|
18
|
-
|
|
19
|
-
export type AccountSearchOptions = ObjectSearchOptions<
|
|
20
|
-
SearchAccountsQueryVariables["where"],
|
|
21
|
-
SearchAccountsQueryVariables["orderBy"]
|
|
22
|
-
>;
|
|
23
|
-
|
|
24
|
-
export type { PicklistOption };
|
|
25
|
-
|
|
26
|
-
export async function searchAccounts(
|
|
27
|
-
options: AccountSearchOptions = {},
|
|
28
|
-
): Promise<AccountSearchResult> {
|
|
29
|
-
return searchObjects<AccountSearchResult, SearchAccountsQuery, SearchAccountsQueryVariables>(
|
|
30
|
-
SEARCH_ACCOUNTS_QUERY,
|
|
31
|
-
"Account",
|
|
32
|
-
options,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function fetchDistinctIndustries(): Promise<PicklistOption[]> {
|
|
37
|
-
return fetchDistinctValues<DistinctAccountIndustriesQuery>(
|
|
38
|
-
DISTINCT_INDUSTRIES_QUERY,
|
|
39
|
-
"Account",
|
|
40
|
-
"Industry",
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function fetchDistinctTypes(): Promise<PicklistOption[]> {
|
|
45
|
-
return fetchDistinctValues<DistinctAccountTypesQuery>(DISTINCT_TYPES_QUERY, "Account", "Type");
|
|
46
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
query DistinctAccountIndustries {
|
|
2
|
-
uiapi {
|
|
3
|
-
aggregate {
|
|
4
|
-
Account(groupBy: { Industry: { group: true } }) {
|
|
5
|
-
edges {
|
|
6
|
-
node {
|
|
7
|
-
aggregate @optional {
|
|
8
|
-
Industry @optional {
|
|
9
|
-
value
|
|
10
|
-
displayValue
|
|
11
|
-
label
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|