@rippling/rippling-sdk 0.2.0-alpha.49 → 0.2.0-alpha.51
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/examples/manifest/existing-manifest-mutations/existing-manifest-mutations.ts +5 -0
- package/lib/manifest/custom-object-page-layout.d.mts +167 -48
- package/lib/manifest/custom-object-page-layout.d.mts.map +1 -1
- package/lib/manifest/custom-object-page-layout.d.ts +167 -48
- package/lib/manifest/custom-object-page-layout.d.ts.map +1 -1
- package/lib/manifest/custom-object-page-layout.js +202 -88
- package/lib/manifest/custom-object-page-layout.js.map +1 -1
- package/lib/manifest/custom-object-page-layout.mjs +202 -88
- package/lib/manifest/custom-object-page-layout.mjs.map +1 -1
- package/lib/manifest/custom-object.d.mts +1 -1
- package/lib/manifest/custom-object.d.ts +1 -1
- package/lib/manifest/custom-object.js +1 -1
- package/lib/manifest/custom-object.mjs +1 -1
- package/lib/manifest/existing-manifest-context.d.mts +1 -0
- package/lib/manifest/existing-manifest-context.d.mts.map +1 -1
- package/lib/manifest/existing-manifest-context.d.ts +1 -0
- package/lib/manifest/existing-manifest-context.d.ts.map +1 -1
- package/lib/manifest/existing-manifest-context.js +7 -6
- package/lib/manifest/existing-manifest-context.js.map +1 -1
- package/lib/manifest/existing-manifest-context.mjs +7 -6
- package/lib/manifest/existing-manifest-context.mjs.map +1 -1
- package/lib/manifest/field.d.mts +3 -3
- package/lib/manifest/field.d.ts +3 -3
- package/lib/manifest/field.js +2 -2
- package/lib/manifest/field.mjs +2 -2
- package/lib/manifest/index.d.mts +1 -1
- package/lib/manifest/index.d.mts.map +1 -1
- package/lib/manifest/index.d.ts +1 -1
- package/lib/manifest/index.d.ts.map +1 -1
- package/lib/manifest/index.js.map +1 -1
- package/lib/manifest/index.mjs.map +1 -1
- package/lib/sdui/components.d.mts +100 -211
- package/lib/sdui/components.d.mts.map +1 -1
- package/lib/sdui/components.d.ts +100 -211
- package/lib/sdui/components.d.ts.map +1 -1
- package/lib/sdui/components.js +96 -182
- package/lib/sdui/components.js.map +1 -1
- package/lib/sdui/components.mjs +93 -178
- package/lib/sdui/components.mjs.map +1 -1
- package/lib/sdui/index.d.mts +12 -52
- package/lib/sdui/index.d.mts.map +1 -1
- package/lib/sdui/index.d.ts +12 -52
- package/lib/sdui/index.d.ts.map +1 -1
- package/lib/sdui/index.js +10 -50
- package/lib/sdui/index.js.map +1 -1
- package/lib/sdui/index.mjs +5 -25
- package/lib/sdui/index.mjs.map +1 -1
- package/lib/sdui/propTypes.d.mts +3156 -3515
- package/lib/sdui/propTypes.d.mts.map +1 -1
- package/lib/sdui/propTypes.d.ts +3156 -3515
- package/lib/sdui/propTypes.d.ts.map +1 -1
- package/lib/sdui/propTypes.js +1 -1
- package/lib/sdui/propTypes.mjs +1 -1
- package/package.json +1 -1
- package/resources/leave-balances.d.mts +10 -0
- package/resources/leave-balances.d.mts.map +1 -1
- package/resources/leave-balances.d.ts +10 -0
- package/resources/leave-balances.d.ts.map +1 -1
- package/src/lib/manifest/custom-object-page-layout.ts +497 -180
- package/src/lib/manifest/custom-object.ts +1 -1
- package/src/lib/manifest/existing-manifest-context.ts +11 -6
- package/src/lib/manifest/field.ts +3 -3
- package/src/lib/manifest/index.ts +27 -0
- package/src/lib/sdui/components.ts +181 -332
- package/src/lib/sdui/index.ts +13 -93
- package/src/lib/sdui/propTypes.ts +3509 -3892
- package/src/resources/leave-balances.ts +12 -0
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -14,32 +14,34 @@ function isFieldRef(value) {
|
|
|
14
14
|
const candidate = value;
|
|
15
15
|
return candidate != null && typeof candidate === 'object' && isField(candidate.field);
|
|
16
16
|
}
|
|
17
|
-
const
|
|
17
|
+
const LAYOUT_SECTION_KEY = Symbol('CustomObjectPageLayout.layoutSectionKey');
|
|
18
18
|
function isCustomObjectFieldSection(value) {
|
|
19
19
|
return value instanceof CustomObjectFieldSection;
|
|
20
20
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
function explicitLayoutSectionKey(section) {
|
|
22
|
+
const record = section;
|
|
23
|
+
const key = section.key ?? record['layout_section_key'] ?? record['layoutSectionKey'];
|
|
24
|
+
return typeof key === 'string' ? key : undefined;
|
|
25
|
+
}
|
|
26
|
+
function attachLayoutSectionKey(section, sectionKey) {
|
|
27
|
+
if (explicitLayoutSectionKey(section) == null)
|
|
28
|
+
section.key = sectionKey;
|
|
29
|
+
Object.defineProperty(section, LAYOUT_SECTION_KEY, {
|
|
30
|
+
value: sectionKey,
|
|
28
31
|
enumerable: false,
|
|
29
32
|
configurable: true,
|
|
30
33
|
});
|
|
31
34
|
return section;
|
|
32
35
|
}
|
|
33
36
|
function layoutSectionKey(section) {
|
|
34
|
-
return (section
|
|
35
|
-
section[
|
|
37
|
+
return (explicitLayoutSectionKey(section) ??
|
|
38
|
+
section[LAYOUT_SECTION_KEY]);
|
|
36
39
|
}
|
|
37
40
|
function layoutSectionMatches(section, sectionKey) {
|
|
38
41
|
return layoutSectionKey(section) === sectionKey;
|
|
39
42
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
return Object.prototype.hasOwnProperty.call(record, 'key') && record['key'] != null;
|
|
43
|
+
function isSerializedFieldsSection(section) {
|
|
44
|
+
return section.type === 'fields_section';
|
|
43
45
|
}
|
|
44
46
|
function assertSameObject(customObject, field, sectionKey) {
|
|
45
47
|
if (field.getCustomObjectApiName() !== customObject.getApiName()) {
|
|
@@ -74,10 +76,29 @@ function toSerializedSectionField(fieldRqlName, options = {}) {
|
|
|
74
76
|
normalized.hidden = options.hidden;
|
|
75
77
|
if (options.editable != null)
|
|
76
78
|
normalized.editable = options.editable;
|
|
79
|
+
if (options.readOnly != null)
|
|
80
|
+
normalized.readOnly = options.readOnly;
|
|
81
|
+
if (options.defaultValue != null)
|
|
82
|
+
normalized.defaultValue = options.defaultValue;
|
|
83
|
+
if (options.height != null)
|
|
84
|
+
normalized.height = options.height;
|
|
85
|
+
if (options.canBeDeleted != null)
|
|
86
|
+
normalized.canBeDeleted = options.canBeDeleted;
|
|
77
87
|
if (options.movementOption != null)
|
|
78
88
|
normalized.movementOption = options.movementOption;
|
|
79
89
|
return normalized;
|
|
80
90
|
}
|
|
91
|
+
function copySectionOptions(target, input) {
|
|
92
|
+
if (input.canBeDeleted != null)
|
|
93
|
+
target.canBeDeleted = input.canBeDeleted;
|
|
94
|
+
if (input.canBeRenamed != null)
|
|
95
|
+
target.canBeRenamed = input.canBeRenamed;
|
|
96
|
+
if (input.movementOption != null)
|
|
97
|
+
target.movementOption = input.movementOption;
|
|
98
|
+
if (input.hideName != null)
|
|
99
|
+
target.hideName = input.hideName;
|
|
100
|
+
return target;
|
|
101
|
+
}
|
|
81
102
|
function normalizeSectionField(customObject, section, sectionKey, entry) {
|
|
82
103
|
if (isField(entry)) {
|
|
83
104
|
assertSameObject(customObject, entry, sectionKey);
|
|
@@ -94,26 +115,28 @@ function normalizeSectionField(customObject, section, sectionKey, entry) {
|
|
|
94
115
|
}
|
|
95
116
|
function normalizeFieldsSection(customObject, input) {
|
|
96
117
|
assertSectionBelongsTo(customObject, input.section);
|
|
97
|
-
const
|
|
98
|
-
if (inputFieldsSectionHasKey(input)) {
|
|
99
|
-
throw new Error('CustomObjectPageLayout fields_section key is not supported. Omit key.');
|
|
100
|
-
}
|
|
118
|
+
const sectionKey = input.key ?? input.section.getSectionId();
|
|
101
119
|
const name = input.name ?? input.section.getName();
|
|
102
|
-
const normalized = {
|
|
120
|
+
const normalized = copySectionOptions({
|
|
103
121
|
name,
|
|
104
122
|
type: 'fields_section',
|
|
105
|
-
fields: input.fields.map((field) => normalizeSectionField(customObject, input.section,
|
|
106
|
-
};
|
|
123
|
+
fields: input.fields.map((field) => normalizeSectionField(customObject, input.section, sectionKey, field)),
|
|
124
|
+
}, input);
|
|
107
125
|
if (input.layout != null)
|
|
108
126
|
normalized.layout = input.layout;
|
|
109
|
-
return
|
|
127
|
+
return attachLayoutSectionKey(normalized, sectionKey);
|
|
128
|
+
}
|
|
129
|
+
function normalizeSection(customObject, section) {
|
|
130
|
+
if (section.type === 'fields_section')
|
|
131
|
+
return normalizeFieldsSection(customObject, section);
|
|
132
|
+
return { ...section };
|
|
110
133
|
}
|
|
111
134
|
function normalizeTab(customObject, tab) {
|
|
112
135
|
if (tab.type === 'custom_tab')
|
|
113
136
|
return tab;
|
|
114
137
|
return {
|
|
115
138
|
...tab,
|
|
116
|
-
sections: tab.sections.map((section) =>
|
|
139
|
+
sections: tab.sections.map((section) => normalizeSection(customObject, section)),
|
|
117
140
|
};
|
|
118
141
|
}
|
|
119
142
|
function normalizeSystemSectionEdit(customObject, tabKey, sectionKey, edit) {
|
|
@@ -128,7 +151,7 @@ function normalizeSystemTabEdit(customObject, tabKey, edit) {
|
|
|
128
151
|
const { newSections: _newSections, systemSectionEdits: _systemSectionEdits, ...rest } = edit;
|
|
129
152
|
const normalized = { ...rest };
|
|
130
153
|
if (edit.newSections != null) {
|
|
131
|
-
normalized.newSections = edit.newSections.map((section) =>
|
|
154
|
+
normalized.newSections = edit.newSections.map((section) => normalizeSection(customObject, section));
|
|
132
155
|
}
|
|
133
156
|
if (edit.systemSectionEdits != null) {
|
|
134
157
|
const systemSectionEdits = {};
|
|
@@ -186,6 +209,18 @@ function normalizeHeaderEdits(headerEdits) {
|
|
|
186
209
|
for (const [index, field] of (headerEdits.newFields ?? []).entries()) {
|
|
187
210
|
assertKnownKeys(field, NEW_HEADER_FIELD_KEYS, `CustomObjectPageLayout headerEdits.newFields[${index}]`, 'Use { rqlName, key } entries, or call addHeaderField(field).');
|
|
188
211
|
}
|
|
212
|
+
if (headerEdits.newTitleField === '') {
|
|
213
|
+
throw new Error('CustomObjectPageLayout headerEdits.newTitleField cannot be empty. Use titleFieldDeleted.');
|
|
214
|
+
}
|
|
215
|
+
if (headerEdits.newDescriptionField === '') {
|
|
216
|
+
throw new Error('CustomObjectPageLayout headerEdits.newDescriptionField cannot be empty. Use descriptionFieldDeleted.');
|
|
217
|
+
}
|
|
218
|
+
if (headerEdits.newTitleField != null && headerEdits.titleFieldDeleted === true) {
|
|
219
|
+
throw new Error('CustomObjectPageLayout headerEdits cannot both set newTitleField and titleFieldDeleted.');
|
|
220
|
+
}
|
|
221
|
+
if (headerEdits.newDescriptionField != null && headerEdits.descriptionFieldDeleted === true) {
|
|
222
|
+
throw new Error('CustomObjectPageLayout headerEdits cannot both set newDescriptionField and descriptionFieldDeleted.');
|
|
223
|
+
}
|
|
189
224
|
if (headerEdits.headerFieldsOrder == null)
|
|
190
225
|
return headerEdits;
|
|
191
226
|
return {
|
|
@@ -248,52 +283,90 @@ function fieldRqlNameOf(entry) {
|
|
|
248
283
|
if (entry == null || typeof entry !== 'object')
|
|
249
284
|
return undefined;
|
|
250
285
|
const record = entry;
|
|
251
|
-
const fieldRqlName = record['fieldRqlName'] ?? record['field_rql_name'];
|
|
286
|
+
const fieldRqlName = record['fieldRqlName'] ?? record['field_rql_name'] ?? record['apiName'] ?? record['api_name'];
|
|
252
287
|
return typeof fieldRqlName === 'string' ? fieldRqlName : undefined;
|
|
253
288
|
}
|
|
254
|
-
function
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
289
|
+
function addFieldSectionLayoutSection(index, fieldSectionId, entry) {
|
|
290
|
+
const entries = index.get(fieldSectionId) ?? [];
|
|
291
|
+
if (!entries.some((existing) => existing.tabKey === entry.tabKey && existing.sectionKey === entry.sectionKey)) {
|
|
292
|
+
entries.push(entry);
|
|
293
|
+
}
|
|
294
|
+
index.set(fieldSectionId, entries);
|
|
260
295
|
}
|
|
261
|
-
function
|
|
262
|
-
|
|
296
|
+
function indexFieldsSectionInput(index, tabKey, section) {
|
|
297
|
+
addFieldSectionLayoutSection(index, section.section.getSectionId(), {
|
|
298
|
+
tabKey,
|
|
299
|
+
sectionKey: section.key ?? section.section.getSectionId(),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
function indexPageLayoutSectionInput(index, tabKey, section) {
|
|
303
|
+
if (section.type === 'fields_section')
|
|
304
|
+
indexFieldsSectionInput(index, tabKey, section);
|
|
305
|
+
}
|
|
306
|
+
function buildFieldSectionLayoutIndexFromProps(tabEdits) {
|
|
307
|
+
const index = new Map();
|
|
308
|
+
if (tabEdits == null)
|
|
309
|
+
return index;
|
|
310
|
+
for (const tab of tabEdits.newTabs ?? []) {
|
|
311
|
+
if (tab.type !== 'tab_with_sections')
|
|
312
|
+
continue;
|
|
313
|
+
for (const section of tab.sections)
|
|
314
|
+
indexPageLayoutSectionInput(index, tab.key, section);
|
|
315
|
+
}
|
|
316
|
+
for (const [tabKey, tabEdit] of Object.entries(tabEdits.systemTabEdits ?? {})) {
|
|
317
|
+
for (const section of tabEdit.newSections ?? []) {
|
|
318
|
+
indexPageLayoutSectionInput(index, tabKey, section);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return index;
|
|
322
|
+
}
|
|
323
|
+
function indexLoadedFieldsSection(index, tabKey, section, resolveFieldSectionId) {
|
|
324
|
+
const sectionKey = layoutSectionKey(section);
|
|
325
|
+
if (sectionKey == null || resolveFieldSectionId == null)
|
|
326
|
+
return;
|
|
263
327
|
for (const field of section.fields ?? []) {
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
266
|
-
sectionIds.add(explicitSectionId);
|
|
328
|
+
const fieldRqlName = fieldRqlNameOf(field);
|
|
329
|
+
if (fieldRqlName == null)
|
|
267
330
|
continue;
|
|
331
|
+
const fieldSectionId = resolveFieldSectionId(fieldRqlName);
|
|
332
|
+
if (fieldSectionId != null) {
|
|
333
|
+
addFieldSectionLayoutSection(index, fieldSectionId, { tabKey, sectionKey });
|
|
268
334
|
}
|
|
269
|
-
|
|
270
|
-
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function buildFieldSectionLayoutIndexFromLoadedTabEdits(tabEdits, resolveFieldSectionId) {
|
|
338
|
+
const index = new Map();
|
|
339
|
+
for (const tab of tabEdits.newTabs ?? []) {
|
|
340
|
+
if (!isTabWithSections(tab))
|
|
271
341
|
continue;
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
342
|
+
for (const section of tab.sections) {
|
|
343
|
+
if (isSerializedFieldsSection(section)) {
|
|
344
|
+
indexLoadedFieldsSection(index, tab.key, section, resolveFieldSectionId);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
275
347
|
}
|
|
276
|
-
|
|
348
|
+
for (const [tabKey, tabEdit] of Object.entries(tabEdits.systemTabEdits ?? {})) {
|
|
349
|
+
for (const section of tabEdit.newSections ?? []) {
|
|
350
|
+
if (isSerializedFieldsSection(section)) {
|
|
351
|
+
indexLoadedFieldsSection(index, tabKey, section, resolveFieldSectionId);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return index;
|
|
277
356
|
}
|
|
278
|
-
function annotateLoadedFieldsSection(section
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
if (explicitSectionId != null && inferredSectionId != null && explicitSectionId !== inferredSectionId) {
|
|
282
|
-
throw new Error(`CustomObjectPageLayout fields_section key "${explicitSectionId}" does not match ` +
|
|
283
|
-
`field section "${inferredSectionId}".`);
|
|
284
|
-
}
|
|
285
|
-
const sectionId = explicitSectionId ?? inferredSectionId;
|
|
286
|
-
return sectionId == null ? section : attachFieldSectionId(section, sectionId);
|
|
357
|
+
function annotateLoadedFieldsSection(section) {
|
|
358
|
+
const sectionKey = layoutSectionKey(section);
|
|
359
|
+
return sectionKey == null ? section : attachLayoutSectionKey(section, sectionKey);
|
|
287
360
|
}
|
|
288
|
-
function annotateLoadedTabEdits(tabEdits
|
|
361
|
+
function annotateLoadedTabEdits(tabEdits) {
|
|
289
362
|
for (const tab of tabEdits.newTabs ?? []) {
|
|
290
363
|
if (!isTabWithSections(tab))
|
|
291
364
|
continue;
|
|
292
|
-
tab.sections = tab.sections.map((section) => annotateLoadedFieldsSection(section
|
|
365
|
+
tab.sections = tab.sections.map((section) => isSerializedFieldsSection(section) ? annotateLoadedFieldsSection(section) : section);
|
|
293
366
|
}
|
|
294
367
|
for (const tabEdit of Object.values(tabEdits.systemTabEdits ?? {})) {
|
|
295
368
|
if (tabEdit.newSections != null) {
|
|
296
|
-
tabEdit.newSections = tabEdit.newSections.map((section) => annotateLoadedFieldsSection(section
|
|
369
|
+
tabEdit.newSections = tabEdit.newSections.map((section) => isSerializedFieldsSection(section) ? annotateLoadedFieldsSection(section) : section);
|
|
297
370
|
}
|
|
298
371
|
}
|
|
299
372
|
return tabEdits;
|
|
@@ -409,6 +482,7 @@ export class CustomObjectPageLayout {
|
|
|
409
482
|
this._customObjectApiName = customObject.getApiName();
|
|
410
483
|
this._name = props.name;
|
|
411
484
|
this._tabEdits = normalizeTabEdits(customObject, props.tabEdits ?? {});
|
|
485
|
+
this._fieldSectionLayoutSections = buildFieldSectionLayoutIndexFromProps(props.tabEdits);
|
|
412
486
|
this._headerEdits = normalizeHeaderEdits(props.headerEdits ?? {});
|
|
413
487
|
this._visibilityConditions = props.visibilityConditions ?? {};
|
|
414
488
|
this._blueprintKey = props.blueprintKey;
|
|
@@ -427,15 +501,17 @@ export class CustomObjectPageLayout {
|
|
|
427
501
|
/** @internal Hydrates a page layout from existing manifest wire JSON. */
|
|
428
502
|
static _fromExistingComponent(customObject, component, resolveFieldSectionId) {
|
|
429
503
|
const layout = Object.create(CustomObjectPageLayout.prototype);
|
|
504
|
+
const tabEdits = annotateLoadedTabEdits(cloneJson(component['tab_edits'] ?? {}));
|
|
430
505
|
Object.assign(layout, {
|
|
431
506
|
_layoutId: requireStringComponentField(component, 'layout_id', CustomObjectPageLayout.componentType),
|
|
432
507
|
_apiName: requireStringComponentField(component, 'api_name', CustomObjectPageLayout.componentType),
|
|
433
508
|
_customObjectApiName: requireStringComponentField(component, 'object_rql_name', CustomObjectPageLayout.componentType),
|
|
434
509
|
_name: requireStringComponentField(component, 'name', CustomObjectPageLayout.componentType),
|
|
435
|
-
_tabEdits:
|
|
510
|
+
_tabEdits: tabEdits,
|
|
436
511
|
_headerEdits: cloneJson(component['header_edits'] ?? {}),
|
|
437
512
|
_visibilityConditions: cloneJson(component['visibility_conditions'] ?? {}),
|
|
438
513
|
_blueprintKey: component['blueprint_key'],
|
|
514
|
+
_fieldSectionLayoutSections: buildFieldSectionLayoutIndexFromLoadedTabEdits(tabEdits, resolveFieldSectionId),
|
|
439
515
|
});
|
|
440
516
|
customObject._register(layout);
|
|
441
517
|
return layout;
|
|
@@ -471,8 +547,8 @@ export class CustomObjectPageLayout {
|
|
|
471
547
|
* Adds multiple fields to an existing layout section.
|
|
472
548
|
*
|
|
473
549
|
* Fields are inserted in the order provided. For custom layout sections,
|
|
474
|
-
* pass `
|
|
475
|
-
*
|
|
550
|
+
* pass `section` to choose the typed field section. Use `sectionKey` only
|
|
551
|
+
* when a field section maps to multiple layout sections.
|
|
476
552
|
*/
|
|
477
553
|
addFields(fields, options) {
|
|
478
554
|
if (fields.length === 0)
|
|
@@ -486,14 +562,19 @@ export class CustomObjectPageLayout {
|
|
|
486
562
|
return this.ensureSystemSectionFieldContainer(options.tabKey, options.sectionKey);
|
|
487
563
|
})()
|
|
488
564
|
: (() => {
|
|
489
|
-
assertOptionAbsent(options, 'sectionKey', 'CustomObjectPageLayout addField sectionKey is only supported with systemSection: true. ' +
|
|
490
|
-
'Pass section: CustomObjectFieldSection for custom layout sections.');
|
|
491
565
|
assertOptionAbsent(options, 'fieldSection', 'CustomObjectPageLayout addField fieldSection is no longer supported. ' +
|
|
492
566
|
'Pass section: CustomObjectFieldSection instead.');
|
|
493
|
-
const section =
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
567
|
+
const section = options.section == null ?
|
|
568
|
+
undefined
|
|
569
|
+
: requireFieldSectionOption(options.section, 'CustomObjectPageLayout addField section');
|
|
570
|
+
if (section != null) {
|
|
571
|
+
this.assertFieldSectionBelongsToLayout(section);
|
|
572
|
+
fieldSectionForMutation = section;
|
|
573
|
+
}
|
|
574
|
+
const sectionKey = options.sectionKey ??
|
|
575
|
+
(section == null ? undefined : this.layoutSectionKeyForFieldSection(options.tabKey, section)) ??
|
|
576
|
+
section?.getSectionId();
|
|
577
|
+
return this.requireOneFieldContainer(options.tabKey, sectionKey, section);
|
|
497
578
|
})();
|
|
498
579
|
const entries = fields.map((field) => this.serializeFieldForMutation(field, container.sectionKey ?? container.label, options, fieldSectionForMutation));
|
|
499
580
|
if (options.allowDuplicate !== true) {
|
|
@@ -527,12 +608,12 @@ export class CustomObjectPageLayout {
|
|
|
527
608
|
sectionKey = options.sectionKey;
|
|
528
609
|
}
|
|
529
610
|
else {
|
|
530
|
-
|
|
531
|
-
'Pass section: CustomObjectFieldSection for custom layout sections.');
|
|
611
|
+
sectionKey = options.sectionKey;
|
|
532
612
|
if (options.section != null) {
|
|
533
613
|
const section = requireFieldSectionOption(options.section, 'CustomObjectPageLayout removeField section');
|
|
534
614
|
this.assertFieldSectionBelongsToLayout(section);
|
|
535
|
-
sectionKey =
|
|
615
|
+
sectionKey ?? (sectionKey = this.layoutSectionKeyForFieldSection(options.tabKey, section));
|
|
616
|
+
sectionKey ?? (sectionKey = section.getSectionId());
|
|
536
617
|
}
|
|
537
618
|
}
|
|
538
619
|
const containers = this.findFieldContainers({
|
|
@@ -590,6 +671,9 @@ export class CustomObjectPageLayout {
|
|
|
590
671
|
const sectionsOrder = this.ensureSystemSectionsOrder(tabEdit);
|
|
591
672
|
insertAt(sections, normalized, options.position);
|
|
592
673
|
insertUniqueAt(sectionsOrder, layoutSectionKey(normalized), options.position);
|
|
674
|
+
if (section.type === 'fields_section') {
|
|
675
|
+
this.rememberFieldSectionLayoutSection(section.section, options.tabKey, layoutSectionKey(normalized));
|
|
676
|
+
}
|
|
593
677
|
return this;
|
|
594
678
|
}
|
|
595
679
|
const tab = this.findNewTabWithSections(options.tabKey);
|
|
@@ -599,6 +683,9 @@ export class CustomObjectPageLayout {
|
|
|
599
683
|
}
|
|
600
684
|
this.assertSectionKeyAvailable(tab.sections, layoutSectionKey(normalized), options.tabKey, options.allowDuplicate);
|
|
601
685
|
insertAt(tab.sections, normalized, options.position);
|
|
686
|
+
if (section.type === 'fields_section') {
|
|
687
|
+
this.rememberFieldSectionLayoutSection(section.section, tab.key, layoutSectionKey(normalized));
|
|
688
|
+
}
|
|
602
689
|
return this;
|
|
603
690
|
}
|
|
604
691
|
removeSection(sectionOrKey, options = {}) {
|
|
@@ -615,9 +702,15 @@ export class CustomObjectPageLayout {
|
|
|
615
702
|
this.removeSectionVisibility(sectionOrKey);
|
|
616
703
|
return this;
|
|
617
704
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
705
|
+
let sectionKey;
|
|
706
|
+
if (typeof sectionOrKey === 'string') {
|
|
707
|
+
sectionKey = sectionOrKey;
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
const section = requireFieldSectionOption(sectionOrKey, 'CustomObjectPageLayout removeSection section');
|
|
711
|
+
this.assertFieldSectionBelongsToLayout(section);
|
|
712
|
+
sectionKey = this.layoutSectionKeyForFieldSection(options.tabKey, section) ?? section.getSectionId();
|
|
713
|
+
}
|
|
621
714
|
const matches = [];
|
|
622
715
|
for (const tab of this._tabEdits.newTabs ?? []) {
|
|
623
716
|
if (!isTabWithSections(tab))
|
|
@@ -625,7 +718,7 @@ export class CustomObjectPageLayout {
|
|
|
625
718
|
if (options.tabKey != null && tab.key !== options.tabKey)
|
|
626
719
|
continue;
|
|
627
720
|
tab.sections.forEach((section, index) => {
|
|
628
|
-
if (layoutSectionMatches(section, sectionKey))
|
|
721
|
+
if (isSerializedFieldsSection(section) && layoutSectionMatches(section, sectionKey))
|
|
629
722
|
matches.push({ sections: tab.sections, section, index, tabKey: tab.key });
|
|
630
723
|
});
|
|
631
724
|
}
|
|
@@ -633,7 +726,7 @@ export class CustomObjectPageLayout {
|
|
|
633
726
|
if (options.tabKey != null && tabKey !== options.tabKey)
|
|
634
727
|
continue;
|
|
635
728
|
(tabEdit.newSections ?? []).forEach((section, index) => {
|
|
636
|
-
if (layoutSectionMatches(section, sectionKey))
|
|
729
|
+
if (isSerializedFieldsSection(section) && layoutSectionMatches(section, sectionKey))
|
|
637
730
|
matches.push({ sections: tabEdit.newSections, section, index, tabEdit, tabKey });
|
|
638
731
|
});
|
|
639
732
|
}
|
|
@@ -671,6 +764,10 @@ export class CustomObjectPageLayout {
|
|
|
671
764
|
const tabsOrder = this.ensureTabsOrder();
|
|
672
765
|
insertAt(newTabs, normalized, options.position);
|
|
673
766
|
insertUniqueAt(tabsOrder, normalized.key, options.position);
|
|
767
|
+
if (tab.type === 'tab_with_sections') {
|
|
768
|
+
for (const section of tab.sections)
|
|
769
|
+
indexPageLayoutSectionInput(this._fieldSectionLayoutSections, tab.key, section);
|
|
770
|
+
}
|
|
674
771
|
return this;
|
|
675
772
|
}
|
|
676
773
|
/**
|
|
@@ -729,13 +826,11 @@ export class CustomObjectPageLayout {
|
|
|
729
826
|
this.removeHeaderOrderFieldIfUnused(removedField);
|
|
730
827
|
return this;
|
|
731
828
|
}
|
|
732
|
-
/** Sets the record title field in `header_edits`. */
|
|
733
829
|
setTitleField(field) {
|
|
734
830
|
const previousTitleField = this._headerEdits.newTitleField;
|
|
735
831
|
const nextTitleField = this.headerFieldApiName(field);
|
|
736
832
|
this._headerEdits.newTitleField = nextTitleField;
|
|
737
|
-
|
|
738
|
-
this._headerEdits.titleFieldDeleted = false;
|
|
833
|
+
this._headerEdits.titleFieldDeleted = false;
|
|
739
834
|
insertUniqueAt(this.ensureHeaderFieldsOrder(), nextTitleField, 'end');
|
|
740
835
|
this.removeHeaderOrderFieldIfUnused(previousTitleField);
|
|
741
836
|
return this;
|
|
@@ -748,13 +843,11 @@ export class CustomObjectPageLayout {
|
|
|
748
843
|
this.removeHeaderOrderFieldIfUnused(previousTitleField);
|
|
749
844
|
return this;
|
|
750
845
|
}
|
|
751
|
-
/** Sets the record description field in `header_edits`. */
|
|
752
846
|
setDescriptionField(field) {
|
|
753
847
|
const previousDescriptionField = this._headerEdits.newDescriptionField;
|
|
754
848
|
const nextDescriptionField = this.headerFieldApiName(field);
|
|
755
849
|
this._headerEdits.newDescriptionField = nextDescriptionField;
|
|
756
|
-
|
|
757
|
-
this._headerEdits.descriptionFieldDeleted = false;
|
|
850
|
+
this._headerEdits.descriptionFieldDeleted = false;
|
|
758
851
|
insertUniqueAt(this.ensureHeaderFieldsOrder(), nextDescriptionField, 'end');
|
|
759
852
|
this.removeHeaderOrderFieldIfUnused(previousDescriptionField);
|
|
760
853
|
return this;
|
|
@@ -830,20 +923,19 @@ export class CustomObjectPageLayout {
|
|
|
830
923
|
'pass a Field instance or { field }.');
|
|
831
924
|
}
|
|
832
925
|
normalizeSectionForMutation(input) {
|
|
926
|
+
if (input.type !== 'fields_section')
|
|
927
|
+
return { ...input };
|
|
833
928
|
this.assertFieldSectionBelongsToLayout(input.section);
|
|
834
|
-
const
|
|
835
|
-
if (inputFieldsSectionHasKey(input)) {
|
|
836
|
-
throw new Error('CustomObjectPageLayout fields_section key is not supported. Omit key.');
|
|
837
|
-
}
|
|
929
|
+
const sectionKey = input.key ?? input.section.getSectionId();
|
|
838
930
|
const name = input.name ?? input.section.getName();
|
|
839
|
-
const normalized = {
|
|
931
|
+
const normalized = copySectionOptions({
|
|
840
932
|
name,
|
|
841
933
|
type: 'fields_section',
|
|
842
|
-
fields: input.fields.map((field) => this.normalizeSectionFieldForMutation(input.section,
|
|
843
|
-
};
|
|
934
|
+
fields: input.fields.map((field) => this.normalizeSectionFieldForMutation(input.section, sectionKey, field)),
|
|
935
|
+
}, input);
|
|
844
936
|
if (input.layout != null)
|
|
845
937
|
normalized.layout = input.layout;
|
|
846
|
-
return
|
|
938
|
+
return attachLayoutSectionKey(normalized, sectionKey);
|
|
847
939
|
}
|
|
848
940
|
normalizeTabForMutation(tab) {
|
|
849
941
|
if (tab.type === 'custom_tab')
|
|
@@ -885,6 +977,26 @@ export class CustomObjectPageLayout {
|
|
|
885
977
|
`"${section.getModelApiName()}", but the layout belongs to "${this._customObjectApiName}".`);
|
|
886
978
|
}
|
|
887
979
|
}
|
|
980
|
+
rememberFieldSectionLayoutSection(section, tabKey, sectionKey) {
|
|
981
|
+
if (sectionKey == null)
|
|
982
|
+
return;
|
|
983
|
+
addFieldSectionLayoutSection(this._fieldSectionLayoutSections, section.getSectionId(), {
|
|
984
|
+
tabKey,
|
|
985
|
+
sectionKey,
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
layoutSectionKeyForFieldSection(tabKey, section) {
|
|
989
|
+
const entries = this._fieldSectionLayoutSections.get(section.getSectionId()) ?? [];
|
|
990
|
+
const matches = tabKey == null ? entries : entries.filter((entry) => entry.tabKey === tabKey);
|
|
991
|
+
const sectionKeys = [...new Set(matches.map((entry) => entry.sectionKey))];
|
|
992
|
+
if (sectionKeys.length === 0)
|
|
993
|
+
return undefined;
|
|
994
|
+
if (sectionKeys.length === 1)
|
|
995
|
+
return sectionKeys[0];
|
|
996
|
+
const scope = tabKey == null ? '' : ` in tab "${tabKey}"`;
|
|
997
|
+
throw new Error(`CustomObjectPageLayout field section "${section.getSectionId()}" maps to multiple layout sections${scope}: ` +
|
|
998
|
+
`${sectionKeys.join(', ')}. Pass sectionKey to choose one.`);
|
|
999
|
+
}
|
|
888
1000
|
requireOneFieldContainer(tabKey, sectionKey, fallbackFieldSection) {
|
|
889
1001
|
const containers = this.findFieldContainers({
|
|
890
1002
|
tabKey,
|
|
@@ -904,8 +1016,8 @@ export class CustomObjectPageLayout {
|
|
|
904
1016
|
`"${fallbackFieldSection.getModelApiName()}", but the layout belongs to "${this._customObjectApiName}".`);
|
|
905
1017
|
}
|
|
906
1018
|
const container = unkeyedContainers[0];
|
|
907
|
-
|
|
908
|
-
container.sectionKey =
|
|
1019
|
+
attachLayoutSectionKey(container.section, sectionKey);
|
|
1020
|
+
container.sectionKey = sectionKey;
|
|
909
1021
|
container.label = `${container.tabKey}.${container.sectionKey}`;
|
|
910
1022
|
return container;
|
|
911
1023
|
}
|
|
@@ -932,6 +1044,8 @@ export class CustomObjectPageLayout {
|
|
|
932
1044
|
if (filter.tabKey != null && tab.key !== filter.tabKey)
|
|
933
1045
|
continue;
|
|
934
1046
|
for (const [index, section] of tab.sections.entries()) {
|
|
1047
|
+
if (!isSerializedFieldsSection(section))
|
|
1048
|
+
continue;
|
|
935
1049
|
const sectionKey = layoutSectionKey(section);
|
|
936
1050
|
if (filter.sectionKey != null && !layoutSectionMatches(section, filter.sectionKey))
|
|
937
1051
|
continue;
|
|
@@ -949,6 +1063,8 @@ export class CustomObjectPageLayout {
|
|
|
949
1063
|
if (filter.tabKey != null && tabKey !== filter.tabKey)
|
|
950
1064
|
continue;
|
|
951
1065
|
for (const [index, section] of (tabEdit.newSections ?? []).entries()) {
|
|
1066
|
+
if (!isSerializedFieldsSection(section))
|
|
1067
|
+
continue;
|
|
952
1068
|
const sectionKey = layoutSectionKey(section);
|
|
953
1069
|
if (filter.sectionKey != null && !layoutSectionMatches(section, filter.sectionKey))
|
|
954
1070
|
continue;
|
|
@@ -1057,8 +1173,6 @@ export class CustomObjectPageLayout {
|
|
|
1057
1173
|
return normalized;
|
|
1058
1174
|
}
|
|
1059
1175
|
headerFieldApiName(field) {
|
|
1060
|
-
if (field == null)
|
|
1061
|
-
return null;
|
|
1062
1176
|
if (typeof field === 'string')
|
|
1063
1177
|
return field;
|
|
1064
1178
|
this.assertFieldBelongsToLayout(field);
|