@aglyn/plugins-crm 1.0.0-beta.199 → 1.0.0-beta.201
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/package.json +13 -13
- package/src/lib/components/activity-list.d.ts +36 -5
- package/src/lib/components/activity-list.js +159 -137
- package/src/lib/components/activity-list.js.map +1 -1
- package/src/lib/components/activity-timeline.d.ts +84 -0
- package/src/lib/components/activity-timeline.js +224 -0
- package/src/lib/components/activity-timeline.js.map +1 -0
- package/src/lib/components/companies-section.d.ts +6 -6
- package/src/lib/components/companies-section.js +54 -84
- package/src/lib/components/companies-section.js.map +1 -1
- package/src/lib/components/company-edit-drawer.js +17 -4
- package/src/lib/components/company-edit-drawer.js.map +1 -1
- package/src/lib/components/company-picker.js +6 -2
- package/src/lib/components/company-picker.js.map +1 -1
- package/src/lib/components/company-properties-card.js +53 -36
- package/src/lib/components/company-properties-card.js.map +1 -1
- package/src/lib/components/contact-associations-card.d.ts +3 -2
- package/src/lib/components/contact-associations-card.js +12 -12
- package/src/lib/components/contact-associations-card.js.map +1 -1
- package/src/lib/components/contact-detail-page.d.ts +4 -3
- package/src/lib/components/contact-detail-page.js +18 -12
- package/src/lib/components/contact-detail-page.js.map +1 -1
- package/src/lib/components/contact-list-columns.d.ts +3 -5
- package/src/lib/components/contact-list-columns.js +6 -8
- package/src/lib/components/contact-list-columns.js.map +1 -1
- package/src/lib/components/contact-properties-card.d.ts +21 -4
- package/src/lib/components/contact-properties-card.js +129 -29
- package/src/lib/components/contact-properties-card.js.map +1 -1
- package/src/lib/components/contact-timeline-card.d.ts +12 -6
- package/src/lib/components/contact-timeline-card.js +132 -174
- package/src/lib/components/contact-timeline-card.js.map +1 -1
- package/src/lib/components/contacts-bulk-bar.js +10 -1
- package/src/lib/components/contacts-bulk-bar.js.map +1 -1
- package/src/lib/components/contacts-section.js +282 -331
- package/src/lib/components/contacts-section.js.map +1 -1
- package/src/lib/components/crm-email-state-chip.js +4 -1
- package/src/lib/components/crm-email-state-chip.js.map +1 -1
- package/src/lib/components/crm-next-activity-column.d.ts +4 -2
- package/src/lib/components/crm-next-activity-column.js +6 -3
- package/src/lib/components/crm-next-activity-column.js.map +1 -1
- package/src/lib/components/deal-edit-drawer.js +8 -4
- package/src/lib/components/deal-edit-drawer.js.map +1 -1
- package/src/lib/components/deal-products-card.js +15 -13
- package/src/lib/components/deal-products-card.js.map +1 -1
- package/src/lib/components/deal-properties-card.js +7 -0
- package/src/lib/components/deal-properties-card.js.map +1 -1
- package/src/lib/components/deal-stage-card.js +31 -29
- package/src/lib/components/deal-stage-card.js.map +1 -1
- package/src/lib/components/deals-section.d.ts +2 -2
- package/src/lib/components/deals-section.js +67 -97
- package/src/lib/components/deals-section.js.map +1 -1
- package/src/lib/components/fields-section.d.ts +4 -0
- package/src/lib/components/fields-section.js +368 -154
- package/src/lib/components/fields-section.js.map +1 -1
- package/src/lib/components/form-contact-fields-card.js +24 -20
- package/src/lib/components/form-contact-fields-card.js.map +1 -1
- package/src/lib/components/lead-campaigns-card.d.ts +1 -1
- package/src/lib/components/lead-campaigns-card.js +43 -38
- package/src/lib/components/lead-campaigns-card.js.map +1 -1
- package/src/lib/components/lead-properties-card.d.ts +14 -6
- package/src/lib/components/lead-properties-card.js +323 -311
- package/src/lib/components/lead-properties-card.js.map +1 -1
- package/src/lib/components/lead-surfaces-note.js +13 -2
- package/src/lib/components/lead-surfaces-note.js.map +1 -1
- package/src/lib/components/leads-bulk-bar.js +16 -3
- package/src/lib/components/leads-bulk-bar.js.map +1 -1
- package/src/lib/components/leads-section.d.ts +2 -1
- package/src/lib/components/leads-section.js +110 -148
- package/src/lib/components/leads-section.js.map +1 -1
- package/src/lib/components/linked-deals-card.js +12 -10
- package/src/lib/components/linked-deals-card.js.map +1 -1
- package/src/lib/components/recent-activity-feed.d.ts +12 -8
- package/src/lib/components/recent-activity-feed.js +54 -29
- package/src/lib/components/recent-activity-feed.js.map +1 -1
- package/src/lib/components/record-activity-card.d.ts +4 -2
- package/src/lib/components/record-activity-card.js +29 -11
- package/src/lib/components/record-activity-card.js.map +1 -1
- package/src/lib/components/reports/activity-card.js +18 -12
- package/src/lib/components/reports/activity-card.js.map +1 -1
- package/src/lib/components/reports/lead-funnel-card.js +47 -37
- package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
- package/src/lib/components/reports/pipeline-card.js +22 -16
- package/src/lib/components/reports/pipeline-card.js.map +1 -1
- package/src/lib/components/reports/report-export.d.ts +4 -11
- package/src/lib/components/reports/report-export.js +16 -33
- package/src/lib/components/reports/report-export.js.map +1 -1
- package/src/lib/components/reports/source-conversion-card.js +18 -12
- package/src/lib/components/reports/source-conversion-card.js.map +1 -1
- package/src/lib/components/reports/tasks-card.js +35 -25
- package/src/lib/components/reports/tasks-card.js.map +1 -1
- package/src/lib/components/tasks-section.js +151 -144
- package/src/lib/components/tasks-section.js.map +1 -1
- package/src/lib/constants/company-filters.d.ts +13 -0
- package/src/lib/constants/company-filters.js +47 -17
- package/src/lib/constants/company-filters.js.map +1 -1
- package/src/lib/constants/contact-filters.d.ts +61 -10
- package/src/lib/constants/contact-filters.js +373 -141
- package/src/lib/constants/contact-filters.js.map +1 -1
- package/src/lib/constants/deal-filters.d.ts +44 -0
- package/src/lib/constants/deal-filters.js +78 -0
- package/src/lib/constants/deal-filters.js.map +1 -0
- package/src/lib/constants/field-list-query.d.ts +23 -0
- package/src/lib/constants/field-list-query.js +80 -0
- package/src/lib/constants/field-list-query.js.map +1 -0
- package/src/lib/hooks/use-crm-list-query.d.ts +68 -0
- package/src/lib/hooks/use-crm-list-query.js +182 -0
- package/src/lib/hooks/use-crm-list-query.js.map +1 -0
- package/src/lib/hooks/use-crm-tasks.d.ts +23 -6
- package/src/lib/hooks/use-crm-tasks.js +44 -42
- package/src/lib/hooks/use-crm-tasks.js.map +1 -1
- package/src/lib/hooks/use-deals.d.ts +2 -34
- package/src/lib/hooks/use-deals.js +3 -62
- package/src/lib/hooks/use-deals.js.map +1 -1
- package/src/lib/model/crm-list-query.d.ts +91 -0
- package/src/lib/model/crm-list-query.js +182 -0
- package/src/lib/model/crm-list-query.js.map +1 -0
- package/src/lib/model/lead-filters.d.ts +50 -44
- package/src/lib/model/lead-filters.js +194 -88
- package/src/lib/model/lead-filters.js.map +1 -1
- package/src/lib/model/list-fields-api.d.ts +26 -0
- package/src/lib/model/list-fields-api.js +47 -0
- package/src/lib/model/list-fields-api.js.map +1 -0
- package/src/lib/model/list-fields.d.ts +47 -0
- package/src/lib/model/list-fields.js +39 -0
- package/src/lib/model/list-fields.js.map +1 -0
- package/src/lib/model/task-views.d.ts +15 -10
- package/src/lib/model/task-views.js +68 -9
- package/src/lib/model/task-views.js.map +1 -1
- package/src/lib/server/capture-contact.js +7 -5
- package/src/lib/server/capture-contact.js.map +1 -1
- package/src/lib/server/companies-import.js +3 -3
- package/src/lib/server/companies-import.js.map +1 -1
- package/src/lib/server/company-delete.js +3 -1
- package/src/lib/server/company-delete.js.map +1 -1
- package/src/lib/server/consent-group-participant.js +4 -0
- package/src/lib/server/consent-group-participant.js.map +1 -1
- package/src/lib/server/contact-update.js +14 -8
- package/src/lib/server/contact-update.js.map +1 -1
- package/src/lib/server/contacts-import.js +4 -2
- package/src/lib/server/contacts-import.js.map +1 -1
- package/src/lib/server/deals-import.js +4 -2
- package/src/lib/server/deals-import.js.map +1 -1
- package/src/lib/server/erase-person.js +2 -1
- package/src/lib/server/erase-person.js.map +1 -1
- package/src/lib/server/lead-create.js +4 -1
- package/src/lib/server/lead-create.js.map +1 -1
- package/src/lib/server/lead-source-values.js +9 -5
- package/src/lib/server/lead-source-values.js.map +1 -1
- package/src/lib/server/leads-import.js +4 -1
- package/src/lib/server/leads-import.js.map +1 -1
- package/src/lib/server/list-fields-routes.d.ts +29 -0
- package/src/lib/server/list-fields-routes.js +85 -0
- package/src/lib/server/list-fields-routes.js.map +1 -0
- package/src/lib/server/record-email-state.js +5 -2
- package/src/lib/server/record-email-state.js.map +1 -1
- package/src/lib/server/record-timeline.js +3 -2
- package/src/lib/server/record-timeline.js.map +1 -1
- package/src/lib/server/task-routes.js +6 -3
- package/src/lib/server/task-routes.js.map +1 -1
- package/src/lib/server/tasks-import.js +5 -2
- package/src/lib/server/tasks-import.js.map +1 -1
- package/src/lib/server.js +10 -1
- package/src/lib/server.js.map +1 -1
- package/src/lib/components/contact-custom-fields-card.d.ts +0 -39
- package/src/lib/components/contact-custom-fields-card.js +0 -204
- package/src/lib/components/contact-custom-fields-card.js.map +0 -1
- package/src/lib/hooks/use-org-leads.d.ts +0 -50
- package/src/lib/hooks/use-org-leads.js +0 -104
- package/src/lib/hooks/use-org-leads.js.map +0 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { CRM_SCOPED_SEARCH_TOKENS_FIELD, CRM_SEARCH_TOKENS_FIELD, crmListFields } from "@aglyn/aglyn";
|
|
18
|
+
import { scopedSearch } from "@aglyn/aglyn/app-utils/name-search";
|
|
19
|
+
import { listQueryRefusals } from "@aglyn/shared-ui-jsx/components/list-query-notices.component";
|
|
20
|
+
/*
|
|
21
|
+
* THE CRM LISTS ON THEIR QUERIES (AGL-3321).
|
|
22
|
+
*
|
|
23
|
+
* Every CRM list — Leads, Contacts, Companies, Deals, Tasks — declares its
|
|
24
|
+
* filterable fields, its one order and its search as a
|
|
25
|
+
* `ListQueryDeclaration`, and `planListQuery` puts every clause and the
|
|
26
|
+
* search word on ONE Firestore query paged by `useListQuery`. What a query
|
|
27
|
+
* cannot hold is refused by name (`ListQueryNotices`), never matched over
|
|
28
|
+
* the rows a page happened to load.
|
|
29
|
+
*
|
|
30
|
+
* This module is what the five share: the search every CRM record carries
|
|
31
|
+
* (`searchTokens`, and `scopedSearchTokens` under a site — see
|
|
32
|
+
* `crmListFields` in `@aglyn/aglyn`), the scope clause as the plan's base,
|
|
33
|
+
* a stored clause translated to the one its query asks, and the refusals
|
|
34
|
+
* read back through the clause the reader set.
|
|
35
|
+
*/ /** Every CRM list's quick search: the tokens every writer stamps. */ export const CRM_LIST_SEARCH = {
|
|
36
|
+
tokensPath: CRM_SEARCH_TOKENS_FIELD,
|
|
37
|
+
scoped: scopedSearch(CRM_SCOPED_SEARCH_TOKENS_FIELD)
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The scope clause as the plan's base: `visibleTo array-contains-any` over
|
|
41
|
+
* the reader's tokens under a site, nothing at the organization level
|
|
42
|
+
* (`null` tokens), where an org-wide member's listeners carry none.
|
|
43
|
+
*/ export function crmListBase(visibleTo) {
|
|
44
|
+
return visibleTo ? [
|
|
45
|
+
{
|
|
46
|
+
path: 'visibleTo',
|
|
47
|
+
op: 'array-contains-any',
|
|
48
|
+
value: [
|
|
49
|
+
...visibleTo
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
] : [];
|
|
53
|
+
}
|
|
54
|
+
/** The base's shape, for `listQueryIndexes`: the scope clause is an array clause. */ export const CRM_LIST_BASE_INDEX = [
|
|
55
|
+
{
|
|
56
|
+
path: 'visibleTo',
|
|
57
|
+
array: true
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
/**
|
|
61
|
+
* The declaration a reader may run.
|
|
62
|
+
*
|
|
63
|
+
* Under a site the search folds into the scope clause (`search.scoped`),
|
|
64
|
+
* and a query without `visibleTo` is one the rules can prove only for an
|
|
65
|
+
* ORG-WIDE member — `canReadScoped()` short-circuits on it, and for anybody
|
|
66
|
+
* else inspects `visibleTo`, which the folded query no longer constrains.
|
|
67
|
+
* A member whose reach is some sites keeps the scope clause, and the plan
|
|
68
|
+
* refuses their search by name rather than sending a query the rules deny.
|
|
69
|
+
*/ export function crmListDeclarationFor(declaration, foldsScope) {
|
|
70
|
+
var _declaration_search;
|
|
71
|
+
if (foldsScope || !((_declaration_search = declaration.search) == null ? void 0 : _declaration_search.scoped)) return declaration;
|
|
72
|
+
return _extends({}, declaration, {
|
|
73
|
+
search: {
|
|
74
|
+
tokensPath: declaration.search.tokensPath
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** Every stored clause through `ask`, keeping where each came from. */ export function crmAskClauses(stored, ask) {
|
|
79
|
+
const clauses = [];
|
|
80
|
+
const origins = [];
|
|
81
|
+
const refused = [];
|
|
82
|
+
for (const clause of stored){
|
|
83
|
+
const asked = ask(clause);
|
|
84
|
+
if ('refused' in asked) {
|
|
85
|
+
refused.push({
|
|
86
|
+
clause,
|
|
87
|
+
reason: asked.refused
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
clauses.push(asked);
|
|
91
|
+
origins.push(clause);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
clauses,
|
|
96
|
+
origins,
|
|
97
|
+
refused
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const sameClause = (a, b)=>a.field === b.field && a.op === b.op && a.value === b.value;
|
|
101
|
+
/**
|
|
102
|
+
* The plan's refusals and the translation's, each named by the clause the
|
|
103
|
+
* reader SET, as `ListQueryNotices` takes them — through the platform's one
|
|
104
|
+
* wording (`listQueryRefusals`), so a notice and its chip read alike.
|
|
105
|
+
*/ export function crmQueryRefusals(plan, asked, context) {
|
|
106
|
+
const planned = plan.refused.map((entry)=>{
|
|
107
|
+
if (entry.clause === 'search') return entry;
|
|
108
|
+
const clause = entry.clause;
|
|
109
|
+
const at = asked.clauses.findIndex((candidate)=>sameClause(candidate, clause));
|
|
110
|
+
return {
|
|
111
|
+
clause: at >= 0 ? asked.origins[at] : clause,
|
|
112
|
+
reason: entry.reason
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
return listQueryRefusals([
|
|
116
|
+
...asked.refused,
|
|
117
|
+
...planned
|
|
118
|
+
], context);
|
|
119
|
+
}
|
|
120
|
+
/** The comma-separated values of an `isAnyOf`, or the one value of anything else. */ export function crmClauseValues(clause) {
|
|
121
|
+
const raw = clause.op === 'isAnyOf' ? clause.value.split(',') : [
|
|
122
|
+
clause.value
|
|
123
|
+
];
|
|
124
|
+
return [
|
|
125
|
+
...new Set(raw.map((value)=>value.trim()).filter(Boolean))
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
/** One value as `equals`, several as `isAnyOf` — the shape the plan takes a list in. */ export function crmAnyOf(field, values) {
|
|
129
|
+
const unique = [
|
|
130
|
+
...new Set(values)
|
|
131
|
+
];
|
|
132
|
+
if (!unique.length) return {
|
|
133
|
+
refused: 'no value yet'
|
|
134
|
+
};
|
|
135
|
+
return unique.length === 1 ? {
|
|
136
|
+
field,
|
|
137
|
+
op: 'equals',
|
|
138
|
+
value: unique[0]
|
|
139
|
+
} : {
|
|
140
|
+
field,
|
|
141
|
+
op: 'isAnyOf',
|
|
142
|
+
value: unique.join(',')
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** A `select` field: equality and "any of" over stored values, nothing else. */ export function crmSelectField(column, path = column) {
|
|
146
|
+
return {
|
|
147
|
+
column,
|
|
148
|
+
kind: 'exact',
|
|
149
|
+
path,
|
|
150
|
+
operators: [
|
|
151
|
+
'equals',
|
|
152
|
+
'isAnyOf'
|
|
153
|
+
]
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The list fields a CLIENT edit writes beside its patch (AGL-3321): the
|
|
158
|
+
* record as the listener holds it with the patch laid over — a `null` or a
|
|
159
|
+
* sentinel in the patch reads as the field removed — through
|
|
160
|
+
* `crmListFields`, narrowed to `fields`. A client never writes a field the
|
|
161
|
+
* rules keep for the server (a lead's `emailStatus`), which is why the
|
|
162
|
+
* caller names the ones it may.
|
|
163
|
+
*/ export function crmClientListFields(collection, record, patch, fields) {
|
|
164
|
+
const merged = _extends({}, record);
|
|
165
|
+
for (const [key, value] of Object.entries(patch)){
|
|
166
|
+
// A dotted path is a map entry (`custom.tier`), never a searched field.
|
|
167
|
+
if (key.includes('.')) continue;
|
|
168
|
+
merged[key] = value === null || isSentinel(value) ? undefined : value;
|
|
169
|
+
}
|
|
170
|
+
const computed = crmListFields(collection, merged);
|
|
171
|
+
return Object.fromEntries(fields.filter((field)=>field in computed).map((field)=>[
|
|
172
|
+
field,
|
|
173
|
+
computed[field]
|
|
174
|
+
]));
|
|
175
|
+
}
|
|
176
|
+
/** A web-SDK `FieldValue` — `deleteField()`, the one a client edit of these fields sends. */ const isSentinel = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date) && typeof value.isEqual === 'function';
|
|
177
|
+
/** The search fields every CRM record carries — what a client edit of searched text rewrites. */ export const CRM_CLIENT_SEARCH_FIELDS = [
|
|
178
|
+
'searchTokens',
|
|
179
|
+
'scopedSearchTokens'
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=crm-list-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/model/crm-list-query.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CRM_SCOPED_SEARCH_TOKENS_FIELD,\n CRM_SEARCH_TOKENS_FIELD,\n type CrmListCollection,\n crmListFields,\n} from '@aglyn/aglyn'\nimport { scopedSearch } from '@aglyn/aglyn/app-utils/name-search'\nimport type { ListFilterField, ListFilterRequest } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport type { ListFilterOption } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { listQueryRefusals } from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport type {\n ListQueryDeclaration,\n ListQueryFilter,\n ListQueryPlan,\n} from '@aglyn/shared-ui-jsx/const/list-query-plan'\n\n/*\n * THE CRM LISTS ON THEIR QUERIES (AGL-3321).\n *\n * Every CRM list — Leads, Contacts, Companies, Deals, Tasks — declares its\n * filterable fields, its one order and its search as a\n * `ListQueryDeclaration`, and `planListQuery` puts every clause and the\n * search word on ONE Firestore query paged by `useListQuery`. What a query\n * cannot hold is refused by name (`ListQueryNotices`), never matched over\n * the rows a page happened to load.\n *\n * This module is what the five share: the search every CRM record carries\n * (`searchTokens`, and `scopedSearchTokens` under a site — see\n * `crmListFields` in `@aglyn/aglyn`), the scope clause as the plan's base,\n * a stored clause translated to the one its query asks, and the refusals\n * read back through the clause the reader set.\n */\n\n/** Every CRM list's quick search: the tokens every writer stamps. */\nexport const CRM_LIST_SEARCH: NonNullable<ListQueryDeclaration['search']> = {\n tokensPath: CRM_SEARCH_TOKENS_FIELD,\n scoped: scopedSearch(CRM_SCOPED_SEARCH_TOKENS_FIELD),\n}\n\n/**\n * The scope clause as the plan's base: `visibleTo array-contains-any` over\n * the reader's tokens under a site, nothing at the organization level\n * (`null` tokens), where an org-wide member's listeners carry none.\n */\nexport function crmListBase(visibleTo: readonly string[] | null): ListQueryFilter[] {\n return visibleTo ? [{ path: 'visibleTo', op: 'array-contains-any', value: [...visibleTo] }] : []\n}\n\n/** The base's shape, for `listQueryIndexes`: the scope clause is an array clause. */\nexport const CRM_LIST_BASE_INDEX = [{ path: 'visibleTo', array: true }] as const\n\n/**\n * The declaration a reader may run.\n *\n * Under a site the search folds into the scope clause (`search.scoped`),\n * and a query without `visibleTo` is one the rules can prove only for an\n * ORG-WIDE member — `canReadScoped()` short-circuits on it, and for anybody\n * else inspects `visibleTo`, which the folded query no longer constrains.\n * A member whose reach is some sites keeps the scope clause, and the plan\n * refuses their search by name rather than sending a query the rules deny.\n */\nexport function crmListDeclarationFor(\n declaration: ListQueryDeclaration,\n foldsScope: boolean,\n): ListQueryDeclaration {\n if (foldsScope || !declaration.search?.scoped) return declaration\n return { ...declaration, search: { tokensPath: declaration.search.tokensPath } }\n}\n\n/*------------------------------------------\n * WHAT A LIST STORES, AND WHAT IT ASKS.\n *\n * A saved view stores clauses in the grid's grammar — \"Status is Open\",\n * \"Owner is Dana\", \"Lead source is none\" — and some of them name no stored\n * field one query can ask as it is: Open is two statuses, an owner under a\n * site is that holder's facet key, a lead source is compared by its key. A\n * list translates each stored clause into the clause its query asks, plans\n * those, and reads the plan's refusals back through the stored clause, so\n * the notice names what the reader set (\"Status is Open is not applied\")\n * and never the field it was translated to.\n *-----------------------------------------*/\n\n/** How one stored clause is asked: a query clause, or why it cannot be. */\nexport type CrmClauseAsked = ListFilterRequest | { refused: string }\n\nexport interface CrmAskedClauses {\n /** What the plan is asked, in the order the reader set them. */\n clauses: ListFilterRequest[]\n /** The stored clause each asked one stands for, index for index. */\n origins: ListFilterRequest[]\n /** Stored clauses refused before the plan saw them, with why. */\n refused: Array<{ clause: ListFilterRequest; reason: string }>\n}\n\n/** Every stored clause through `ask`, keeping where each came from. */\nexport function crmAskClauses(\n stored: readonly ListFilterRequest[],\n ask: (clause: ListFilterRequest) => CrmClauseAsked,\n): CrmAskedClauses {\n const clauses: ListFilterRequest[] = []\n const origins: ListFilterRequest[] = []\n const refused: CrmAskedClauses['refused'] = []\n for (const clause of stored) {\n const asked = ask(clause)\n if ('refused' in asked) {\n refused.push({ clause, reason: asked.refused })\n } else {\n clauses.push(asked)\n origins.push(clause)\n }\n }\n return { clauses, origins, refused }\n}\n\nconst sameClause = (a: ListFilterRequest, b: ListFilterRequest): boolean =>\n a.field === b.field && a.op === b.op && a.value === b.value\n\n/**\n * The plan's refusals and the translation's, each named by the clause the\n * reader SET, as `ListQueryNotices` takes them — through the platform's one\n * wording (`listQueryRefusals`), so a notice and its chip read alike.\n */\nexport function crmQueryRefusals(\n plan: Pick<ListQueryPlan, 'refused'>,\n asked: CrmAskedClauses,\n context: {\n fields: readonly ListFilterField[]\n headers?: Readonly<Record<string, string>>\n options?: Readonly<Record<string, readonly ListFilterOption[]>>\n },\n): Array<{ label: string; reason: string }> {\n const planned = plan.refused.map((entry) => {\n if (entry.clause === 'search') return entry\n const clause = entry.clause\n const at = asked.clauses.findIndex((candidate) => sameClause(candidate, clause))\n return { clause: at >= 0 ? asked.origins[at] : clause, reason: entry.reason }\n })\n return listQueryRefusals([...asked.refused, ...planned], context)\n}\n\n/** The comma-separated values of an `isAnyOf`, or the one value of anything else. */\nexport function crmClauseValues(clause: Pick<ListFilterRequest, 'op' | 'value'>): string[] {\n const raw = clause.op === 'isAnyOf' ? clause.value.split(',') : [clause.value]\n return [...new Set(raw.map((value) => value.trim()).filter(Boolean))]\n}\n\n/** One value as `equals`, several as `isAnyOf` — the shape the plan takes a list in. */\nexport function crmAnyOf(field: string, values: readonly string[]): CrmClauseAsked {\n const unique = [...new Set(values)]\n if (!unique.length) return { refused: 'no value yet' }\n return unique.length === 1\n ? { field, op: 'equals', value: unique[0] }\n : { field, op: 'isAnyOf', value: unique.join(',') }\n}\n\n/** A `select` field: equality and \"any of\" over stored values, nothing else. */\nexport function crmSelectField(column: string, path: string = column): ListFilterField {\n return { column, kind: 'exact', path, operators: ['equals', 'isAnyOf'] }\n}\n\n/**\n * The list fields a CLIENT edit writes beside its patch (AGL-3321): the\n * record as the listener holds it with the patch laid over — a `null` or a\n * sentinel in the patch reads as the field removed — through\n * `crmListFields`, narrowed to `fields`. A client never writes a field the\n * rules keep for the server (a lead's `emailStatus`), which is why the\n * caller names the ones it may.\n */\nexport function crmClientListFields(\n collection: CrmListCollection,\n record: Readonly<Record<string, unknown>>,\n patch: Readonly<Record<string, unknown>>,\n fields: readonly string[],\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...record }\n for (const [key, value] of Object.entries(patch)) {\n // A dotted path is a map entry (`custom.tier`), never a searched field.\n if (key.includes('.')) continue\n merged[key] = value === null || isSentinel(value) ? undefined : value\n }\n const computed = crmListFields(collection, merged)\n return Object.fromEntries(fields.filter((field) => field in computed).map((field) => [field, computed[field]]))\n}\n\n/** A web-SDK `FieldValue` — `deleteField()`, the one a client edit of these fields sends. */\nconst isSentinel = (value: unknown): boolean =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n typeof (value as { isEqual?: unknown }).isEqual === 'function'\n\n/** The search fields every CRM record carries — what a client edit of searched text rewrites. */\nexport const CRM_CLIENT_SEARCH_FIELDS = ['searchTokens', 'scopedSearchTokens'] as const\n\n"],"names":["CRM_SCOPED_SEARCH_TOKENS_FIELD","CRM_SEARCH_TOKENS_FIELD","crmListFields","scopedSearch","listQueryRefusals","CRM_LIST_SEARCH","tokensPath","scoped","crmListBase","visibleTo","path","op","value","CRM_LIST_BASE_INDEX","array","crmListDeclarationFor","declaration","foldsScope","search","crmAskClauses","stored","ask","clauses","origins","refused","clause","asked","push","reason","sameClause","a","b","field","crmQueryRefusals","plan","context","planned","map","entry","at","findIndex","candidate","crmClauseValues","raw","split","Set","trim","filter","Boolean","crmAnyOf","values","unique","length","join","crmSelectField","column","kind","operators","crmClientListFields","collection","record","patch","fields","merged","key","Object","entries","includes","isSentinel","undefined","computed","fromEntries","Array","isArray","Date","isEqual","CRM_CLIENT_SEARCH_FIELDS"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,8BAA8B,EAC9BC,uBAAuB,EAEvBC,aAAa,QACR,eAAc;AACrB,SAASC,YAAY,QAAQ,qCAAoC;AAGjE,SAASC,iBAAiB,QAAQ,+DAA8D;AAOhG;;;;;;;;;;;;;;;CAeC,GAED,mEAAmE,GACnE,OAAO,MAAMC,kBAA+D;IAC1EC,YAAYL;IACZM,QAAQJ,aAAaH;AACvB,EAAC;AAED;;;;CAIC,GACD,OAAO,SAASQ,YAAYC,SAAmC;IAC7D,OAAOA,YAAY;QAAC;YAAEC,MAAM;YAAaC,IAAI;YAAsBC,OAAO;mBAAIH;aAAU;QAAC;KAAE,GAAG,EAAE;AAClG;AAEA,mFAAmF,GACnF,OAAO,MAAMI,sBAAsB;IAAC;QAAEH,MAAM;QAAaI,OAAO;IAAK;CAAE,CAAS;AAEhF;;;;;;;;;CASC,GACD,OAAO,SAASC,sBACdC,WAAiC,EACjCC,UAAmB;QAEAD;IAAnB,IAAIC,cAAc,GAACD,sBAAAA,YAAYE,MAAM,qBAAlBF,oBAAoBT,MAAM,GAAE,OAAOS;IACtD,OAAO,aAAKA;QAAaE,QAAQ;YAAEZ,YAAYU,YAAYE,MAAM,CAACZ,UAAU;QAAC;;AAC/E;AA2BA,qEAAqE,GACrE,OAAO,SAASa,cACdC,MAAoC,EACpCC,GAAkD;IAElD,MAAMC,UAA+B,EAAE;IACvC,MAAMC,UAA+B,EAAE;IACvC,MAAMC,UAAsC,EAAE;IAC9C,KAAK,MAAMC,UAAUL,OAAQ;QAC3B,MAAMM,QAAQL,IAAII;QAClB,IAAI,aAAaC,OAAO;YACtBF,QAAQG,IAAI,CAAC;gBAAEF;gBAAQG,QAAQF,MAAMF,OAAO;YAAC;QAC/C,OAAO;YACLF,QAAQK,IAAI,CAACD;YACbH,QAAQI,IAAI,CAACF;QACf;IACF;IACA,OAAO;QAAEH;QAASC;QAASC;IAAQ;AACrC;AAEA,MAAMK,aAAa,CAACC,GAAsBC,IACxCD,EAAEE,KAAK,KAAKD,EAAEC,KAAK,IAAIF,EAAEnB,EAAE,KAAKoB,EAAEpB,EAAE,IAAImB,EAAElB,KAAK,KAAKmB,EAAEnB,KAAK;AAE7D;;;;CAIC,GACD,OAAO,SAASqB,iBACdC,IAAoC,EACpCR,KAAsB,EACtBS,OAIC;IAED,MAAMC,UAAUF,KAAKV,OAAO,CAACa,GAAG,CAAC,CAACC;QAChC,IAAIA,MAAMb,MAAM,KAAK,UAAU,OAAOa;QACtC,MAAMb,SAASa,MAAMb,MAAM;QAC3B,MAAMc,KAAKb,MAAMJ,OAAO,CAACkB,SAAS,CAAC,CAACC,YAAcZ,WAAWY,WAAWhB;QACxE,OAAO;YAAEA,QAAQc,MAAM,IAAIb,MAAMH,OAAO,CAACgB,GAAG,GAAGd;YAAQG,QAAQU,MAAMV,MAAM;QAAC;IAC9E;IACA,OAAOxB,kBAAkB;WAAIsB,MAAMF,OAAO;WAAKY;KAAQ,EAAED;AAC3D;AAEA,mFAAmF,GACnF,OAAO,SAASO,gBAAgBjB,MAA+C;IAC7E,MAAMkB,MAAMlB,OAAOd,EAAE,KAAK,YAAYc,OAAOb,KAAK,CAACgC,KAAK,CAAC,OAAO;QAACnB,OAAOb,KAAK;KAAC;IAC9E,OAAO;WAAI,IAAIiC,IAAIF,IAAIN,GAAG,CAAC,CAACzB,QAAUA,MAAMkC,IAAI,IAAIC,MAAM,CAACC;KAAU;AACvE;AAEA,sFAAsF,GACtF,OAAO,SAASC,SAASjB,KAAa,EAAEkB,MAAyB;IAC/D,MAAMC,SAAS;WAAI,IAAIN,IAAIK;KAAQ;IACnC,IAAI,CAACC,OAAOC,MAAM,EAAE,OAAO;QAAE5B,SAAS;IAAe;IACrD,OAAO2B,OAAOC,MAAM,KAAK,IACrB;QAAEpB;QAAOrB,IAAI;QAAUC,OAAOuC,MAAM,CAAC,EAAE;IAAC,IACxC;QAAEnB;QAAOrB,IAAI;QAAWC,OAAOuC,OAAOE,IAAI,CAAC;IAAK;AACtD;AAEA,8EAA8E,GAC9E,OAAO,SAASC,eAAeC,MAAc,EAAE7C,OAAe6C,MAAM;IAClE,OAAO;QAAEA;QAAQC,MAAM;QAAS9C;QAAM+C,WAAW;YAAC;YAAU;SAAU;IAAC;AACzE;AAEA;;;;;;;CAOC,GACD,OAAO,SAASC,oBACdC,UAA6B,EAC7BC,MAAyC,EACzCC,KAAwC,EACxCC,MAAyB;IAEzB,MAAMC,SAAkC,aAAKH;IAC7C,KAAK,MAAM,CAACI,KAAKpD,MAAM,IAAIqD,OAAOC,OAAO,CAACL,OAAQ;QAChD,wEAAwE;QACxE,IAAIG,IAAIG,QAAQ,CAAC,MAAM;QACvBJ,MAAM,CAACC,IAAI,GAAGpD,UAAU,QAAQwD,WAAWxD,SAASyD,YAAYzD;IAClE;IACA,MAAM0D,WAAWpE,cAAcyD,YAAYI;IAC3C,OAAOE,OAAOM,WAAW,CAACT,OAAOf,MAAM,CAAC,CAACf,QAAUA,SAASsC,UAAUjC,GAAG,CAAC,CAACL,QAAU;YAACA;YAAOsC,QAAQ,CAACtC,MAAM;SAAC;AAC/G;AAEA,2FAA2F,GAC3F,MAAMoC,aAAa,CAACxD,QAClB,OAAOA,UAAU,YACjBA,UAAU,QACV,CAAC4D,MAAMC,OAAO,CAAC7D,UACf,CAAEA,CAAAA,iBAAiB8D,IAAG,KACtB,OAAO,AAAC9D,MAAgC+D,OAAO,KAAK;AAEtD,+FAA+F,GAC/F,OAAO,MAAMC,2BAA2B;IAAC;IAAgB;CAAqB,CAAS"}
|
|
@@ -14,22 +14,22 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
import { type EmailStateStatus, type
|
|
17
|
+
import { type EmailStateStatus, type CrmLeadStatus } from '@aglyn/aglyn';
|
|
18
18
|
import type { CrmViewFilterClause } from '@aglyn/aglyn';
|
|
19
|
-
import type { ListFilterField } from '@aglyn/shared-ui-jsx/const/list-filter';
|
|
19
|
+
import type { ListFilterField, ListFilterRequest } from '@aglyn/shared-ui-jsx/const/list-filter';
|
|
20
20
|
import { type ListGridFilterCodec } from '@aglyn/shared-ui-jsx/const/list-grid-filter';
|
|
21
|
+
import type { ListQueryDeclaration, ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan';
|
|
22
|
+
import { type CrmClauseAsked } from './crm-list-query';
|
|
21
23
|
/**
|
|
22
24
|
* What the Leads section's `Show` control offers (AGL-2608): the two
|
|
23
25
|
* aggregate views and each status on its own. `open` is the default — the
|
|
24
|
-
* list opens on the work —
|
|
25
|
-
*
|
|
26
|
-
*
|
|
26
|
+
* list opens on the work — asked of the query as `status in [new, working]`,
|
|
27
|
+
* which every lead answers because every lead writer stores a status, `new`
|
|
28
|
+
* for one nobody has touched (`crmLeadListFields`, AGL-3321).
|
|
27
29
|
*/
|
|
28
30
|
export type LeadFilter = 'open' | 'all' | CrmLeadStatus;
|
|
29
31
|
export declare const LEAD_FILTERS: readonly LeadFilter[];
|
|
30
32
|
export declare const LEAD_FILTER_LABELS: Record<LeadFilter, string>;
|
|
31
|
-
/** Whether a lead belongs in a filter's view. An absent status is `new`. */
|
|
32
|
-
export declare function leadMatchesFilter(lead: Pick<CrmLeadFields, 'status'>, filter: LeadFilter): boolean;
|
|
33
33
|
/**
|
|
34
34
|
* The Leads section's `Email` control (AGL-3245): every lead, the ones a
|
|
35
35
|
* member must not email — any verdict but `ok` — the ones nothing has been
|
|
@@ -40,46 +40,12 @@ export declare function leadMatchesFilter(lead: Pick<CrmLeadFields, 'status'>, f
|
|
|
40
40
|
export type LeadEmailFilter = 'any' | 'problem' | 'none' | EmailStateStatus;
|
|
41
41
|
export declare const LEAD_EMAIL_FILTERS: readonly LeadEmailFilter[];
|
|
42
42
|
export declare const LEAD_EMAIL_FILTER_LABELS: Record<LeadEmailFilter, string>;
|
|
43
|
-
/** Whether a lead belongs in an email filter's view. */
|
|
44
|
-
export declare function leadMatchesEmailFilter(lead: Readonly<Record<string, unknown>>, filter: LeadEmailFilter): boolean;
|
|
45
|
-
/**
|
|
46
|
-
* The Leads section's `Campaign` control (AGL-3254): every lead, or the
|
|
47
|
-
* ones filed under one campaign — read off the lead's own `campaignIds`,
|
|
48
|
-
* the field every campaign member carries. `''` is every lead, which is
|
|
49
|
-
* what the control opens on; the ids are the site's containers', and the
|
|
50
|
-
* section resolves their names for the menu.
|
|
51
|
-
*/
|
|
52
|
-
export declare function leadMatchesCampaignFilter(lead: Readonly<Record<string, unknown>>, campaignId: string): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* The fields the Leads section's search box reads (AGL-3246): who the lead
|
|
55
|
-
* is and where they work — the words a person types to find one — plus the
|
|
56
|
-
* tags, which are how an import names its batch (`sal-15`). `name` and
|
|
57
|
-
* `email` are the capture door's fields rather than the CRM's, so the row is
|
|
58
|
-
* read as a record rather than through `CrmLeadFields`.
|
|
59
|
-
*/
|
|
60
|
-
export declare const LEAD_SEARCH_FIELDS: readonly ["name", "email", "company", "jobTitle", "tags"];
|
|
61
|
-
/**
|
|
62
|
-
* Whether a lead answers a search term.
|
|
63
|
-
*
|
|
64
|
-
* Case-insensitive, and every whitespace-separated word of the term must
|
|
65
|
-
* appear in SOME searched field: `morgan lamphere` and `lamphere sal-15`
|
|
66
|
-
* both find Morgan Lamphere, `morgan smith` does not. A blank term matches
|
|
67
|
-
* every lead, so the box emptied is the list unfiltered.
|
|
68
|
-
*/
|
|
69
|
-
export declare function leadMatchesSearch(lead: Readonly<Record<string, unknown>>, term: string): boolean;
|
|
70
43
|
/**
|
|
71
44
|
* The `Lead source` control's "no lead source" choice (AGL-3298). Held in
|
|
72
45
|
* the saved view as an `isEmpty` clause, never as this string; it is only
|
|
73
46
|
* the select's own value for the choice.
|
|
74
47
|
*/
|
|
75
48
|
export declare const LEAD_SOURCE_FILTER_NONE = "\0none";
|
|
76
|
-
/**
|
|
77
|
-
* The Leads section's `Lead source` control (AGL-3298): every lead (`''`),
|
|
78
|
-
* the ones holding one value — compared the way the picklist compares
|
|
79
|
-
* labels, so a value typed in another case before the list existed is
|
|
80
|
-
* still found — or the ones holding none.
|
|
81
|
-
*/
|
|
82
|
-
export declare function leadMatchesLeadSourceFilter(lead: Readonly<Record<string, unknown>>, filter: string): boolean;
|
|
83
49
|
/** The fields the grid's panel offers on Leads. */
|
|
84
50
|
export declare const LEAD_LIST_FILTER_FIELDS: readonly ListFilterField[];
|
|
85
51
|
/** What each filter field reads as on a chip. */
|
|
@@ -91,7 +57,7 @@ export declare const LEAD_STATUS_FILTER_OPTIONS: {
|
|
|
91
57
|
}[];
|
|
92
58
|
/** The choices for Email: every verdict, plus the two aggregates. */
|
|
93
59
|
export declare const LEAD_EMAIL_FILTER_OPTIONS: {
|
|
94
|
-
value: "none" | "bounced" | "complained" | "ok" | "blocked" | "unsubscribed" | "do_not_contact" | "problem";
|
|
60
|
+
value: "none" | "bounced" | "complained" | "ok" | "undeliverable" | "blocked" | "unsubscribed" | "do_not_contact" | "problem";
|
|
95
61
|
label: string;
|
|
96
62
|
}[];
|
|
97
63
|
/**
|
|
@@ -103,11 +69,51 @@ export declare const LEAD_EMAIL_FILTER_OPTIONS: {
|
|
|
103
69
|
export declare function leadClausesForGrid(stored: readonly CrmViewFilterClause[]): CrmViewFilterClause[];
|
|
104
70
|
/** The inverse of {@link leadClausesForGrid}: what the view stores. */
|
|
105
71
|
export declare function leadClausesToStore(shown: readonly CrmViewFilterClause[]): CrmViewFilterClause[];
|
|
106
|
-
/** Whether a lead answers every clause the grid shows. */
|
|
107
|
-
export declare function leadMatchesClauses(lead: Readonly<Record<string, unknown>> & Pick<CrmLeadFields, 'status'>, clauses: readonly CrmViewFilterClause[]): boolean;
|
|
108
72
|
/** Campaign clauses were stored as `contains`; the panel's select says `is`. */
|
|
109
73
|
export declare const LEAD_CAMPAIGN_CODEC: ListGridFilterCodec;
|
|
110
74
|
/** "No lead source" is an `isEmpty` clause, shown as a choice of the select. */
|
|
111
75
|
export declare const LEAD_SOURCE_CODEC: ListGridFilterCodec;
|
|
112
76
|
/** The Leads fields whose stored clauses translate their own way. */
|
|
113
77
|
export declare const LEAD_FILTER_CODECS: Readonly<Record<string, ListGridFilterCodec>>;
|
|
78
|
+
/** The one order the Leads list takes: newest seen first. */
|
|
79
|
+
export declare const LEAD_LIST_SORTS: readonly ListQuerySort[];
|
|
80
|
+
/** The fields the Leads query asks — each a stored field, as named. */
|
|
81
|
+
export declare const LEAD_QUERY_FIELDS: readonly ListFilterField[];
|
|
82
|
+
export declare const LEAD_LIST_DECLARATION: ListQueryDeclaration;
|
|
83
|
+
/**
|
|
84
|
+
* A collaborator's search (see `prefixSearch` in `useCrmListQuery`): the
|
|
85
|
+
* start of the address, beside the scope clause — the `(visibleTo, email)`
|
|
86
|
+
* composite the Inbox's leads list reads too.
|
|
87
|
+
*/
|
|
88
|
+
export declare const LEAD_PREFIX_SEARCH: {
|
|
89
|
+
field: {
|
|
90
|
+
column: string;
|
|
91
|
+
kind: "text";
|
|
92
|
+
path: string;
|
|
93
|
+
lowerPath: string;
|
|
94
|
+
presence: "always";
|
|
95
|
+
operators: string[];
|
|
96
|
+
};
|
|
97
|
+
notice: string;
|
|
98
|
+
};
|
|
99
|
+
/** Whether an asked clause stands in for the scope clause: a campaign behind the site's scope. */
|
|
100
|
+
export declare const leadClauseImpliesScope: (clause: ListFilterRequest) => boolean;
|
|
101
|
+
/** Who is asking, for the one clause whose shape depends on it: the Campaign. */
|
|
102
|
+
export interface LeadQueryReader {
|
|
103
|
+
/** The site's scope tokens, or `null` at the organization level. */
|
|
104
|
+
scopeTokens: readonly string[] | null;
|
|
105
|
+
/** Whether the reader may run a query without the scope clause (`useCrmFoldsScope`). */
|
|
106
|
+
foldsScope: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* One grid clause as the clause the Leads query asks — see the block above.
|
|
110
|
+
* A value the list does not know is refused by name rather than dropped, so
|
|
111
|
+
* a stored view that names a retired choice says so.
|
|
112
|
+
*/
|
|
113
|
+
export declare function leadQueryClause(clause: CrmViewFilterClause | ListFilterRequest, reader?: LeadQueryReader): CrmClauseAsked;
|
|
114
|
+
/**
|
|
115
|
+
* The query shape the Leads list can send beyond its own declaration, for
|
|
116
|
+
* the index pin (AGL-3321): a collaborator's address prefix beside the
|
|
117
|
+
* equalities they may set.
|
|
118
|
+
*/
|
|
119
|
+
export declare function leadIndexShapes(): ListQueryDeclaration[];
|