@salesforce/ui-bundle-template-app-angular-template-b2x 11.35.6 → 11.37.0
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/angularextapp/.graphqlrc.yml +2 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/angular.json +3 -1
- package/dist/force-app/main/default/uiBundles/angularextapp/codegen.yml +95 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/esbuild/graphql-codegen.mjs +13 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/package.json +9 -2
- package/dist/force-app/main/default/uiBundles/angularextapp/scripts/get-graphql-schema.mjs +69 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/src/app/api/account/account-search.service.ts +52 -140
- package/dist/force-app/main/default/uiBundles/angularextapp/src/app/api/graphql-operations-types.ts +29389 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/src/app/features/object-search/api/object-search.service.ts +94 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/src/app/features/object-search/utils/sort-utils.ts +3 -10
- package/dist/force-app/main/default/uiBundles/angularextapp/src/app/pages/account-search/account-search-page.ts +15 -8
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/package.json +1 -1
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.37.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.36.0...v11.37.0) (2026-07-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [11.36.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.35.6...v11.36.0) (2026-07-24)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [11.35.6](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.35.5...v11.35.6) (2026-07-23)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
@@ -43,10 +43,11 @@
|
|
|
43
43
|
"silenceDeprecations": ["import"]
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
|
-
"plugins": [
|
|
46
|
+
"plugins": []
|
|
47
47
|
},
|
|
48
48
|
"configurations": {
|
|
49
49
|
"production": {
|
|
50
|
+
"plugins": ["./esbuild/api-version.mjs"],
|
|
50
51
|
"budgets": [
|
|
51
52
|
{
|
|
52
53
|
"type": "anyComponentStyle",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
}
|
|
65
66
|
},
|
|
66
67
|
"development": {
|
|
68
|
+
"plugins": ["./esbuild/graphql-codegen.mjs"],
|
|
67
69
|
"optimization": false,
|
|
68
70
|
"extractLicenses": false,
|
|
69
71
|
"sourceMap": true
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
schema: '../../../../../schema.graphql'
|
|
2
|
+
documents: 'src/**/*.{graphql,ts}'
|
|
3
|
+
generates:
|
|
4
|
+
src/app/api/graphql-operations-types.ts:
|
|
5
|
+
plugins:
|
|
6
|
+
- 'graphql-codegen-typescript-operation-types'
|
|
7
|
+
- 'typescript-operations'
|
|
8
|
+
config:
|
|
9
|
+
onlyOperationTypes: true
|
|
10
|
+
skipTypename: true
|
|
11
|
+
preResolveTypes: true
|
|
12
|
+
scalars:
|
|
13
|
+
# String-serialized scalars
|
|
14
|
+
JSON:
|
|
15
|
+
input: 'string'
|
|
16
|
+
output: 'string'
|
|
17
|
+
Date:
|
|
18
|
+
input: 'string'
|
|
19
|
+
output: 'string'
|
|
20
|
+
DateTime:
|
|
21
|
+
input: 'string'
|
|
22
|
+
output: 'string'
|
|
23
|
+
Time:
|
|
24
|
+
input: 'string'
|
|
25
|
+
output: 'string'
|
|
26
|
+
Email:
|
|
27
|
+
input: 'string'
|
|
28
|
+
output: 'string'
|
|
29
|
+
Url:
|
|
30
|
+
input: 'string'
|
|
31
|
+
output: 'string'
|
|
32
|
+
PhoneNumber:
|
|
33
|
+
input: 'string'
|
|
34
|
+
output: 'string'
|
|
35
|
+
Picklist:
|
|
36
|
+
input: 'string'
|
|
37
|
+
output: 'string'
|
|
38
|
+
MultiPicklist:
|
|
39
|
+
input: 'string'
|
|
40
|
+
output: 'string'
|
|
41
|
+
TextArea:
|
|
42
|
+
input: 'string'
|
|
43
|
+
output: 'string'
|
|
44
|
+
LongTextArea:
|
|
45
|
+
input: 'string'
|
|
46
|
+
output: 'string'
|
|
47
|
+
RichTextArea:
|
|
48
|
+
input: 'string'
|
|
49
|
+
output: 'string'
|
|
50
|
+
EncryptedString:
|
|
51
|
+
input: 'string'
|
|
52
|
+
output: 'string'
|
|
53
|
+
Base64:
|
|
54
|
+
input: 'string'
|
|
55
|
+
output: 'string'
|
|
56
|
+
IdOrRef:
|
|
57
|
+
input: 'string'
|
|
58
|
+
output: 'string'
|
|
59
|
+
# BigDecimal-serialized scalars (accepts number or string, returns number)
|
|
60
|
+
Currency:
|
|
61
|
+
input: 'number | string'
|
|
62
|
+
output: 'number'
|
|
63
|
+
BigDecimal:
|
|
64
|
+
input: 'number | string'
|
|
65
|
+
output: 'number'
|
|
66
|
+
Double:
|
|
67
|
+
input: 'number | string'
|
|
68
|
+
output: 'number'
|
|
69
|
+
Percent:
|
|
70
|
+
input: 'number | string'
|
|
71
|
+
output: 'number'
|
|
72
|
+
Longitude:
|
|
73
|
+
input: 'number | string'
|
|
74
|
+
output: 'number'
|
|
75
|
+
Latitude:
|
|
76
|
+
input: 'number | string'
|
|
77
|
+
output: 'number'
|
|
78
|
+
# Integer-like scalars
|
|
79
|
+
Long:
|
|
80
|
+
input: 'number'
|
|
81
|
+
output: 'number'
|
|
82
|
+
BigInteger:
|
|
83
|
+
input: 'number'
|
|
84
|
+
output: 'number'
|
|
85
|
+
Short:
|
|
86
|
+
input: 'number'
|
|
87
|
+
output: 'number'
|
|
88
|
+
Byte:
|
|
89
|
+
input: 'number'
|
|
90
|
+
output: 'number'
|
|
91
|
+
Char:
|
|
92
|
+
input: 'number'
|
|
93
|
+
output: 'number'
|
|
94
|
+
overwrite: true
|
|
95
|
+
ignoreNoDocuments: true
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphQL Codegen esbuild plugin — runs codegen on build start.
|
|
3
|
+
*
|
|
4
|
+
* Resolves GraphQL operations into typed TypeScript at build time using the
|
|
5
|
+
* project's `codegen.yml` configuration. Re-runs on every rebuild during
|
|
6
|
+
* `ng serve` so generated types stay in sync with schema/document changes.
|
|
7
|
+
*
|
|
8
|
+
* Referenced from angular.json: architect.build.options.plugins[].
|
|
9
|
+
*/
|
|
10
|
+
import { createGraphQLCodegenPlugin } from '@salesforce/angular-plugin-ui-bundle';
|
|
11
|
+
|
|
12
|
+
const plugin = createGraphQLCodegenPlugin();
|
|
13
|
+
export default plugin;
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"test": "ng test",
|
|
15
15
|
"lint": "ng lint",
|
|
16
16
|
"build:e2e": "ng build && node scripts/rewrite-e2e-assets.mjs",
|
|
17
|
-
"e2e": "playwright test"
|
|
17
|
+
"e2e": "playwright test",
|
|
18
|
+
"graphql:schema": "node scripts/get-graphql-schema.mjs",
|
|
19
|
+
"graphql:codegen": "graphql-codegen"
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
20
22
|
"@angular/animations": "^21.2.0",
|
|
@@ -48,7 +50,12 @@
|
|
|
48
50
|
"tailwindcss": "^4.0.0",
|
|
49
51
|
"typescript": "~5.9.2",
|
|
50
52
|
"typescript-eslint": "^8.0.0",
|
|
51
|
-
"vitest": "^4.1.0"
|
|
53
|
+
"vitest": "^4.1.0",
|
|
54
|
+
"@graphql-codegen/cli": "^6.1.0",
|
|
55
|
+
"@graphql-codegen/typescript-operations": "^5.0.6",
|
|
56
|
+
"graphql": "^16.11.0",
|
|
57
|
+
"graphql-codegen-typescript-operation-types": "^2.0.2",
|
|
58
|
+
"@graphql-eslint/eslint-plugin": "^4.1.0"
|
|
52
59
|
},
|
|
53
60
|
"overrides": {
|
|
54
61
|
"undici": "^7.28.0"
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downloads the full GraphQL schema from a connected Salesforce org via introspection.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npm run graphql:schema
|
|
6
|
+
* node scripts/get-graphql-schema.mjs [output-path]
|
|
7
|
+
*
|
|
8
|
+
* The default output path matches the schema location expected by codegen.yml
|
|
9
|
+
* and .graphqlrc.yml so that codegen and IDE tooling resolve it automatically.
|
|
10
|
+
*/
|
|
11
|
+
import { writeFileSync } from 'node:fs';
|
|
12
|
+
import { resolve } from 'node:path';
|
|
13
|
+
import { getOrgInfo } from '@salesforce/ui-bundle/app';
|
|
14
|
+
import { buildClientSchema, getIntrospectionQuery, printSchema } from 'graphql';
|
|
15
|
+
import { pruneSchema } from '@graphql-tools/utils';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_SCHEMA_PATH = '../../../../../schema.graphql';
|
|
18
|
+
const TARGET_ORG = process.env.SF_TARGET_ORG || undefined;
|
|
19
|
+
|
|
20
|
+
async function executeSalesforceGraphQLQuery(query, variables, operationName) {
|
|
21
|
+
const orgInfo = await getOrgInfo(TARGET_ORG);
|
|
22
|
+
if (!orgInfo) {
|
|
23
|
+
throw new Error('Could not resolve a Salesforce org. Set SF_TARGET_ORG or a default org.');
|
|
24
|
+
}
|
|
25
|
+
const { rawInstanceUrl: instanceUrl, apiVersion, accessToken } = orgInfo;
|
|
26
|
+
|
|
27
|
+
const targetUrl = `${instanceUrl}/services/data/v${apiVersion}/graphql`;
|
|
28
|
+
|
|
29
|
+
console.log(`Executing introspection query against ${targetUrl}`);
|
|
30
|
+
const response = await fetch(targetUrl, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: {
|
|
33
|
+
Authorization: `Bearer ${accessToken}`,
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
'X-Chatter-Entity-Encoding': 'false',
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({ query, variables, operationName }),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const errorText = await response.text();
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Salesforce GraphQL request failed: ${response.status} ${response.statusText} - ${errorText}`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return response.json();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const outputPath = resolve(process.argv[2] || DEFAULT_SCHEMA_PATH);
|
|
52
|
+
|
|
53
|
+
const introspectionResult = await executeSalesforceGraphQLQuery(
|
|
54
|
+
getIntrospectionQuery(),
|
|
55
|
+
{},
|
|
56
|
+
'IntrospectionQuery',
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const schema = buildClientSchema(introspectionResult.data);
|
|
60
|
+
const prunedSchema = pruneSchema(schema);
|
|
61
|
+
const sdl = printSchema(prunedSchema);
|
|
62
|
+
|
|
63
|
+
writeFileSync(outputPath, sdl);
|
|
64
|
+
|
|
65
|
+
console.log(`Schema saved to ${outputPath}`);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('Error:', error.message);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
@@ -16,121 +16,51 @@ import { GET_ACCOUNT_DETAIL } from "./getAccountDetail";
|
|
|
16
16
|
import { DISTINCT_ACCOUNT_INDUSTRIES } from "./distinctAccountIndustries";
|
|
17
17
|
import { DISTINCT_ACCOUNT_TYPES } from "./distinctAccountTypes";
|
|
18
18
|
|
|
19
|
+
import type {
|
|
20
|
+
SearchAccountsQuery,
|
|
21
|
+
SearchAccountsQueryVariables,
|
|
22
|
+
GetAccountDetailQuery,
|
|
23
|
+
DistinctAccountIndustriesQuery,
|
|
24
|
+
DistinctAccountTypesQuery,
|
|
25
|
+
} from "../graphql-operations-types";
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
ObjectSearchService,
|
|
29
|
+
type PicklistOption,
|
|
30
|
+
type ObjectSearchOptions,
|
|
31
|
+
} from "../../features/object-search/api/object-search.service";
|
|
32
|
+
|
|
19
33
|
// ---------------------------------------------------------------------------
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// graphql-operations-types (see the React reference for the equivalent).
|
|
34
|
+
// Derived type aliases — replace the previously hand-written interfaces with
|
|
35
|
+
// types extracted from the generated GraphQL operations
|
|
23
36
|
// ---------------------------------------------------------------------------
|
|
24
37
|
|
|
25
|
-
|
|
26
|
-
export interface UiScalarField<T = unknown> {
|
|
27
|
-
value?: T | null;
|
|
28
|
-
displayValue?: string | null;
|
|
29
|
-
}
|
|
38
|
+
export type AccountSearchResult = NonNullable<SearchAccountsQuery["uiapi"]["query"]["Account"]>;
|
|
30
39
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Name?: UiScalarField<string> | null;
|
|
35
|
-
Industry?: UiScalarField<string> | null;
|
|
36
|
-
Type?: UiScalarField<string> | null;
|
|
37
|
-
Phone?: UiScalarField<string> | null;
|
|
38
|
-
Owner?: { Name?: UiScalarField<string> | null } | null;
|
|
39
|
-
AnnualRevenue?: UiScalarField<number> | null;
|
|
40
|
-
// Detail-only fields (undefined in list responses).
|
|
41
|
-
Fax?: UiScalarField<string> | null;
|
|
42
|
-
Parent?: { Name?: UiScalarField<string> | null } | null;
|
|
43
|
-
Website?: UiScalarField<string> | null;
|
|
44
|
-
NumberOfEmployees?: UiScalarField<number> | null;
|
|
45
|
-
Description?: UiScalarField<string> | null;
|
|
46
|
-
BillingStreet?: UiScalarField<string> | null;
|
|
47
|
-
BillingCity?: UiScalarField<string> | null;
|
|
48
|
-
BillingState?: UiScalarField<string> | null;
|
|
49
|
-
BillingPostalCode?: UiScalarField<string> | null;
|
|
50
|
-
BillingCountry?: UiScalarField<string> | null;
|
|
51
|
-
ShippingStreet?: UiScalarField<string> | null;
|
|
52
|
-
ShippingCity?: UiScalarField<string> | null;
|
|
53
|
-
ShippingState?: UiScalarField<string> | null;
|
|
54
|
-
ShippingPostalCode?: UiScalarField<string> | null;
|
|
55
|
-
ShippingCountry?: UiScalarField<string> | null;
|
|
56
|
-
CreatedBy?: { Name?: UiScalarField<string> | null } | null;
|
|
57
|
-
CreatedDate?: UiScalarField<string> | null;
|
|
58
|
-
LastModifiedBy?: { Name?: UiScalarField<string> | null } | null;
|
|
59
|
-
LastModifiedDate?: UiScalarField<string> | null;
|
|
60
|
-
}
|
|
40
|
+
export type AccountSearchNode = NonNullable<
|
|
41
|
+
NonNullable<NonNullable<AccountSearchResult["edges"]>[number]>["node"]
|
|
42
|
+
>;
|
|
61
43
|
|
|
62
|
-
|
|
63
|
-
export interface AccountPageInfo {
|
|
64
|
-
hasNextPage?: boolean;
|
|
65
|
-
hasPreviousPage?: boolean;
|
|
66
|
-
endCursor?: string | null;
|
|
67
|
-
startCursor?: string | null;
|
|
68
|
-
}
|
|
44
|
+
export type AccountDetailResult = NonNullable<GetAccountDetailQuery["uiapi"]["query"]["Account"]>;
|
|
69
45
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
pageInfo: AccountPageInfo;
|
|
74
|
-
totalCount?: number;
|
|
75
|
-
}
|
|
46
|
+
export type AccountDetailNode = NonNullable<
|
|
47
|
+
NonNullable<NonNullable<AccountDetailResult["edges"]>[number]>["node"]
|
|
48
|
+
>;
|
|
76
49
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
/** Wire shape for the `getAccountDetail` query. */
|
|
83
|
-
interface GetAccountDetailData {
|
|
84
|
-
uiapi: {
|
|
85
|
-
query: {
|
|
86
|
-
Account: { edges: Array<{ node: AccountNode } | null> | null } | null;
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
}
|
|
50
|
+
export type AccountSearchOptions = ObjectSearchOptions<
|
|
51
|
+
SearchAccountsQueryVariables["where"],
|
|
52
|
+
SearchAccountsQueryVariables["orderBy"]
|
|
53
|
+
>;
|
|
90
54
|
|
|
91
|
-
|
|
92
|
-
interface DistinctAccountData {
|
|
93
|
-
uiapi: {
|
|
94
|
-
aggregate: {
|
|
95
|
-
Account: {
|
|
96
|
-
edges: Array<{
|
|
97
|
-
node: {
|
|
98
|
-
aggregate?: Record<
|
|
99
|
-
string,
|
|
100
|
-
{
|
|
101
|
-
value?: string | null;
|
|
102
|
-
displayValue?: string | null;
|
|
103
|
-
label?: string | null;
|
|
104
|
-
} | null
|
|
105
|
-
> | null;
|
|
106
|
-
};
|
|
107
|
-
} | null> | null;
|
|
108
|
-
} | null;
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Picklist option shape shared with filter components. */
|
|
114
|
-
export interface PicklistOption {
|
|
115
|
-
value: string;
|
|
116
|
-
label: string;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Search args mirroring the React `AccountSearchOptions`. */
|
|
120
|
-
export interface AccountSearchArgs {
|
|
121
|
-
where?: unknown;
|
|
122
|
-
orderBy?: unknown;
|
|
123
|
-
first?: number;
|
|
124
|
-
after?: string;
|
|
125
|
-
}
|
|
55
|
+
export type { PicklistOption };
|
|
126
56
|
|
|
127
57
|
/**
|
|
128
58
|
* Angular account-search data service.
|
|
129
59
|
*
|
|
130
|
-
* Wraps
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
60
|
+
* Wraps `ObjectSearchService` for search/aggregate queries and `DataClient`
|
|
61
|
+
* directly for the detail query (which takes an `id` variable rather than
|
|
62
|
+
* search options). Provided in root; the service is stateless (all state lives
|
|
63
|
+
* in `ObjectSearchStateService` per-page).
|
|
134
64
|
*
|
|
135
65
|
* Mirrors the React `accountSearchService` module — the shape of the returned
|
|
136
66
|
* data is identical so the templates can be a straight JSX-to-Angular port.
|
|
@@ -138,26 +68,20 @@ export interface AccountSearchArgs {
|
|
|
138
68
|
@Injectable({ providedIn: "root" })
|
|
139
69
|
export class AccountSearchService {
|
|
140
70
|
private readonly client = inject(DataClient);
|
|
71
|
+
private readonly objectSearch = inject(ObjectSearchService);
|
|
141
72
|
|
|
142
73
|
/** Runs the search query and returns the `Account` connection. */
|
|
143
|
-
async searchAccounts(args:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
after,
|
|
150
|
-
});
|
|
151
|
-
const account = data.uiapi.query.Account;
|
|
152
|
-
if (!account) {
|
|
153
|
-
throw new Error("No Account data returned");
|
|
154
|
-
}
|
|
155
|
-
return account;
|
|
74
|
+
async searchAccounts(args: AccountSearchOptions = {}): Promise<AccountSearchResult> {
|
|
75
|
+
return this.objectSearch.searchObjects<
|
|
76
|
+
AccountSearchResult,
|
|
77
|
+
SearchAccountsQuery,
|
|
78
|
+
SearchAccountsQueryVariables
|
|
79
|
+
>(SEARCH_ACCOUNTS, "Account", args);
|
|
156
80
|
}
|
|
157
81
|
|
|
158
82
|
/** Fetches a single Account by Id; returns `null` if not found. */
|
|
159
|
-
async getAccountDetail(id: string): Promise<
|
|
160
|
-
const data = await this.client.execute<
|
|
83
|
+
async getAccountDetail(id: string): Promise<AccountDetailNode | null> {
|
|
84
|
+
const data = await this.client.execute<GetAccountDetailQuery, { id: string }>(
|
|
161
85
|
GET_ACCOUNT_DETAIL,
|
|
162
86
|
{ id },
|
|
163
87
|
);
|
|
@@ -166,31 +90,19 @@ export class AccountSearchService {
|
|
|
166
90
|
|
|
167
91
|
/** Distinct `Industry` values for the picklist filter. */
|
|
168
92
|
async fetchDistinctIndustries(): Promise<PicklistOption[]> {
|
|
169
|
-
return this.fetchDistinctValues(
|
|
93
|
+
return this.objectSearch.fetchDistinctValues<DistinctAccountIndustriesQuery>(
|
|
94
|
+
DISTINCT_ACCOUNT_INDUSTRIES,
|
|
95
|
+
"Account",
|
|
96
|
+
"Industry",
|
|
97
|
+
);
|
|
170
98
|
}
|
|
171
99
|
|
|
172
100
|
/** Distinct `Type` values for the multipicklist filter. */
|
|
173
101
|
async fetchDistinctTypes(): Promise<PicklistOption[]> {
|
|
174
|
-
return this.fetchDistinctValues(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
* `fetchDistinctValues` in `objectSearchService.ts`: pulls
|
|
180
|
-
* `uiapi.aggregate.Account.edges[].node.aggregate[fieldName]` and derives a
|
|
181
|
-
* `{ value, label }` option, preferring `label` -> `displayValue` -> `value`
|
|
182
|
-
* as the display string.
|
|
183
|
-
*/
|
|
184
|
-
private async fetchDistinctValues(fieldName: string, query: string): Promise<PicklistOption[]> {
|
|
185
|
-
const data = await this.client.execute<DistinctAccountData>(query);
|
|
186
|
-
const edges = data.uiapi.aggregate.Account?.edges ?? [];
|
|
187
|
-
const options: PicklistOption[] = [];
|
|
188
|
-
for (const edge of edges) {
|
|
189
|
-
const field = edge?.node.aggregate?.[fieldName];
|
|
190
|
-
const value = field?.value;
|
|
191
|
-
if (!value) continue;
|
|
192
|
-
options.push({ value, label: field.label ?? field.displayValue ?? value });
|
|
193
|
-
}
|
|
194
|
-
return options;
|
|
102
|
+
return this.objectSearch.fetchDistinctValues<DistinctAccountTypesQuery>(
|
|
103
|
+
DISTINCT_ACCOUNT_TYPES,
|
|
104
|
+
"Account",
|
|
105
|
+
"Type",
|
|
106
|
+
);
|
|
195
107
|
}
|
|
196
108
|
}
|