@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
|
@@ -11,6 +11,23 @@ export interface PageLayoutDeletionIdentifier {
|
|
|
11
11
|
objectRqlName: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export type ObjectRqlName = string;
|
|
15
|
+
export type BlueprintKey = string;
|
|
16
|
+
export type LayoutApiName = string;
|
|
17
|
+
export type TabKey = string;
|
|
18
|
+
export type SectionKey = string;
|
|
19
|
+
export type HeaderFieldKey = string;
|
|
20
|
+
export type FieldRqlName = string;
|
|
21
|
+
export type RelatedObjectRqlName = string;
|
|
22
|
+
export type CanvasCompositionId = string;
|
|
23
|
+
export type HeaderButtonKey = string;
|
|
24
|
+
|
|
25
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
26
|
+
export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
27
|
+
export interface JsonObject {
|
|
28
|
+
[key: string]: JsonValue;
|
|
29
|
+
}
|
|
30
|
+
|
|
14
31
|
// ---------------------------------------------------------------------------
|
|
15
32
|
// header_edits — HeaderEditsDTO
|
|
16
33
|
// ---------------------------------------------------------------------------
|
|
@@ -18,7 +35,7 @@ export interface PageLayoutDeletionIdentifier {
|
|
|
18
35
|
/** Edit to a built-in (system) header field. */
|
|
19
36
|
export interface SystemHeaderFieldEdit {
|
|
20
37
|
/** Replace the system field's RQL field reference. Optional. */
|
|
21
|
-
newRqlField?:
|
|
38
|
+
newRqlField?: FieldRqlName;
|
|
22
39
|
/** Remove this system field from the header. Optional. */
|
|
23
40
|
deleted?: boolean;
|
|
24
41
|
}
|
|
@@ -31,9 +48,9 @@ export interface SystemHeaderFieldEdit {
|
|
|
31
48
|
*/
|
|
32
49
|
export interface NewHeaderField {
|
|
33
50
|
/** RQL field name to display. Required. */
|
|
34
|
-
rqlName:
|
|
51
|
+
rqlName: FieldRqlName;
|
|
35
52
|
/** Stable key for this field. Required. */
|
|
36
|
-
key:
|
|
53
|
+
key: HeaderFieldKey;
|
|
37
54
|
/** Whether the user can remove this field. Optional. */
|
|
38
55
|
canBeDeleted?: boolean;
|
|
39
56
|
/** Whether the user can swap this field for another. Optional. */
|
|
@@ -53,74 +70,200 @@ export interface NewHeaderField {
|
|
|
53
70
|
*/
|
|
54
71
|
export interface HeaderEdits {
|
|
55
72
|
/** Replace the record title field (pass the field's api_name). Optional. */
|
|
56
|
-
newTitleField?:
|
|
73
|
+
newTitleField?: FieldRqlName;
|
|
57
74
|
/** Remove the title field from the header. Optional. */
|
|
58
75
|
titleFieldDeleted?: boolean;
|
|
59
76
|
/** Replace the record description field. Optional. */
|
|
60
|
-
newDescriptionField?:
|
|
77
|
+
newDescriptionField?: FieldRqlName;
|
|
61
78
|
/** Remove the description field from the header. Optional. */
|
|
62
79
|
descriptionFieldDeleted?: boolean;
|
|
63
80
|
/** Edits to built-in system header fields, keyed by system field key. Optional. */
|
|
64
|
-
systemFieldEdits?: Record<
|
|
81
|
+
systemFieldEdits?: Record<HeaderFieldKey, SystemHeaderFieldEdit>;
|
|
65
82
|
/** Additional custom fields to add to the header. Optional. */
|
|
66
83
|
newFields?: NewHeaderField[];
|
|
67
84
|
/** Ordered list of header field RQL names. Custom header keys are accepted and converted. Optional. */
|
|
68
|
-
headerFieldsOrder?:
|
|
85
|
+
headerFieldsOrder?: FieldRqlName[];
|
|
69
86
|
/** Action button keys to show in the header. Optional. */
|
|
70
|
-
buttons?:
|
|
87
|
+
buttons?: HeaderButtonKey[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface SerializedSystemHeaderFieldEdit extends Omit<SystemHeaderFieldEdit, 'newRqlField'> {
|
|
91
|
+
newRqlField?: FieldRqlName | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface SerializedHeaderEdits
|
|
95
|
+
extends Omit<HeaderEdits, 'newTitleField' | 'newDescriptionField' | 'systemFieldEdits'> {
|
|
96
|
+
newTitleField?: FieldRqlName | null;
|
|
97
|
+
newDescriptionField?: FieldRqlName | null;
|
|
98
|
+
systemFieldEdits?: Record<HeaderFieldKey, SerializedSystemHeaderFieldEdit>;
|
|
71
99
|
}
|
|
72
100
|
|
|
73
101
|
// ---------------------------------------------------------------------------
|
|
74
102
|
// tab_edits — TabEditsDTO + section/tab DTOs
|
|
75
103
|
// ---------------------------------------------------------------------------
|
|
76
104
|
|
|
105
|
+
export type SectionFieldsLayout = 'one_column' | 'two_column' | 'three_column' | 'responsive';
|
|
106
|
+
export type TabLayout = 'vertical' | 'horizontal';
|
|
107
|
+
export type SectionMovementOption = 'static' | 'tab' | 'free';
|
|
108
|
+
export type FieldMovementOption = 'tab' | 'free';
|
|
109
|
+
export type CustomObjectCustomSectionComponentKey = 'attachments' | 'comments';
|
|
110
|
+
|
|
111
|
+
/** Default value wrapper used by `SectionField.defaultValue`. */
|
|
112
|
+
export interface SectionFieldDefaultValue {
|
|
113
|
+
value: JsonValue;
|
|
114
|
+
}
|
|
115
|
+
|
|
77
116
|
/** Options for one field entry inside a `fields_section`. */
|
|
78
117
|
export interface SectionFieldOptions {
|
|
79
118
|
/** Hide this field from view. Optional. */
|
|
80
119
|
hidden?: boolean;
|
|
81
120
|
/** Allow inline editing of this field. Optional. */
|
|
82
121
|
editable?: boolean;
|
|
122
|
+
/** Render this field read-only. Optional. */
|
|
123
|
+
readOnly?: boolean;
|
|
124
|
+
/** Default value metadata for the field. Optional. */
|
|
125
|
+
defaultValue?: SectionFieldDefaultValue;
|
|
126
|
+
/** Rich-text field height. Optional. */
|
|
127
|
+
height?: number;
|
|
128
|
+
/** Whether the layout manager can remove this field. Optional. */
|
|
129
|
+
canBeDeleted?: boolean;
|
|
83
130
|
/** Controls how the field can be moved in the UI. Optional. */
|
|
84
|
-
movementOption?:
|
|
131
|
+
movementOption?: FieldMovementOption;
|
|
85
132
|
}
|
|
86
133
|
|
|
87
134
|
/** A typed field entry inside a `fields_section`. */
|
|
88
|
-
export interface
|
|
135
|
+
export interface SectionField extends SectionFieldOptions {
|
|
89
136
|
/** Field to display. Required. */
|
|
90
137
|
field: Field;
|
|
91
138
|
}
|
|
92
139
|
|
|
140
|
+
/** @deprecated Use `SectionField` for object entries or `SectionFieldInput` for field arrays. */
|
|
141
|
+
export type SectionFieldRef = SectionField;
|
|
142
|
+
|
|
93
143
|
/** One field entry inside a `fields_section`. */
|
|
94
|
-
export type
|
|
144
|
+
export type SectionFieldInput = Field | SectionField;
|
|
145
|
+
|
|
146
|
+
/** Common edit controls for sections. */
|
|
147
|
+
export interface PageLayoutSectionOptions {
|
|
148
|
+
/** Whether the layout manager can delete this section. Optional. */
|
|
149
|
+
canBeDeleted?: boolean;
|
|
150
|
+
/** Whether the layout manager can rename this section. Optional. */
|
|
151
|
+
canBeRenamed?: boolean;
|
|
152
|
+
/** Controls how the section can be moved. Optional. */
|
|
153
|
+
movementOption?: SectionMovementOption;
|
|
154
|
+
/** Hide the section title. Optional. */
|
|
155
|
+
hideName?: boolean;
|
|
156
|
+
}
|
|
95
157
|
|
|
96
158
|
/** A standard field-grid section inside a tab. */
|
|
97
|
-
export interface FieldsSection {
|
|
159
|
+
export interface FieldsSection extends PageLayoutSectionOptions {
|
|
98
160
|
type: 'fields_section';
|
|
99
161
|
/** Field section metadata for the fields displayed in this layout section. Required. */
|
|
100
162
|
section: CustomObjectFieldSection;
|
|
101
|
-
/** Stable layout section key.
|
|
102
|
-
key?:
|
|
163
|
+
/** Stable layout section key. Optional. Defaults to `section.getSectionId()`. */
|
|
164
|
+
key?: SectionKey;
|
|
103
165
|
/** Display name of the layout section. Optional. Defaults to the field section name. */
|
|
104
166
|
name?: string;
|
|
105
167
|
/** Fields to display in this section. Required. */
|
|
106
|
-
fields:
|
|
168
|
+
fields: SectionFieldInput[];
|
|
107
169
|
/** Column layout for the fields. Optional. @default `'responsive'` (backend default). */
|
|
108
170
|
layout?: SectionFieldsLayout;
|
|
109
171
|
}
|
|
110
172
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
173
|
+
export interface RelatedObjectSection extends PageLayoutSectionOptions {
|
|
174
|
+
type: 'related_object_section';
|
|
175
|
+
/** Stable layout section key. Required. */
|
|
176
|
+
key: SectionKey;
|
|
177
|
+
/** Display name of the layout section. Required. */
|
|
178
|
+
name: string;
|
|
179
|
+
/** Related object whose records point back to this custom object. Required. */
|
|
180
|
+
relatedObjectRqlName: RelatedObjectRqlName;
|
|
181
|
+
/** Field on the related object that points back to this custom object. Required. */
|
|
182
|
+
relatedFieldRqlName: FieldRqlName;
|
|
183
|
+
/** Field RQL names to display for related records. Required. */
|
|
184
|
+
fields: FieldRqlName[];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface RelatedFieldSection extends PageLayoutSectionOptions {
|
|
188
|
+
type: 'related_field_section';
|
|
189
|
+
/** Stable layout section key. Required. */
|
|
190
|
+
key: SectionKey;
|
|
191
|
+
/** Display name of the layout section. Required. */
|
|
192
|
+
name: string;
|
|
193
|
+
/** Related object reached from this custom object. Required. */
|
|
194
|
+
relatedObjectRqlName: RelatedObjectRqlName;
|
|
195
|
+
/** Field on this custom object that points to the related object. Required. */
|
|
196
|
+
relatedFieldRqlName: FieldRqlName;
|
|
197
|
+
/** Field RQL names to display from the related object. Required. */
|
|
198
|
+
fields: FieldRqlName[];
|
|
199
|
+
/** Column layout for the fields. Optional. @default `'responsive'` (backend default). */
|
|
200
|
+
layout?: SectionFieldsLayout;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface CustomSection extends PageLayoutSectionOptions {
|
|
204
|
+
type: 'custom_section';
|
|
205
|
+
/** Stable layout section key. Required. */
|
|
206
|
+
key: SectionKey;
|
|
207
|
+
/** Display name of the layout section. Required. */
|
|
208
|
+
name: string;
|
|
209
|
+
/** Custom object section component key. Required. */
|
|
210
|
+
componentKey: CustomObjectCustomSectionComponentKey;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface ResizableLayoutPosition {
|
|
214
|
+
identifier: string;
|
|
215
|
+
width: number;
|
|
216
|
+
height: number;
|
|
217
|
+
minWidth?: number;
|
|
218
|
+
minHeight?: number;
|
|
219
|
+
maxWidth?: number;
|
|
220
|
+
maxHeight?: number;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface ReportsSectionItem {
|
|
224
|
+
key: string;
|
|
225
|
+
reportId: string;
|
|
226
|
+
position: ResizableLayoutPosition;
|
|
227
|
+
contextualFieldAttrName?: FieldRqlName;
|
|
228
|
+
visualizationType?: string;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface ReportsSection extends PageLayoutSectionOptions {
|
|
232
|
+
type: 'reports_section';
|
|
233
|
+
/** Stable layout section key. Required. */
|
|
234
|
+
key: SectionKey;
|
|
235
|
+
/** Display name of the layout section. Required. */
|
|
236
|
+
name: string;
|
|
237
|
+
/** Reports to display in this section. Required. */
|
|
238
|
+
reports: ReportsSectionItem[];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface CanvasSection extends PageLayoutSectionOptions {
|
|
242
|
+
type: 'canvas_section';
|
|
243
|
+
/** Stable layout section key. Required. */
|
|
244
|
+
key: SectionKey;
|
|
245
|
+
/** Display name of the layout section. Required. */
|
|
246
|
+
name: string;
|
|
247
|
+
/** Canvas composition to render. Required. */
|
|
248
|
+
canvasCompositionId: CanvasCompositionId;
|
|
249
|
+
/** Composition input name to field or state path mapping. Optional. */
|
|
250
|
+
inputMapping?: Record<string, string>;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** A section inside a page layout tab. */
|
|
254
|
+
export type PageLayoutSection =
|
|
255
|
+
| FieldsSection
|
|
256
|
+
| RelatedObjectSection
|
|
257
|
+
| RelatedFieldSection
|
|
258
|
+
| CustomSection
|
|
259
|
+
| ReportsSection
|
|
260
|
+
| CanvasSection;
|
|
118
261
|
|
|
119
262
|
/** A tab that contains one or more field-grid sections. */
|
|
120
263
|
export interface TabWithSections {
|
|
121
264
|
type: 'tab_with_sections';
|
|
122
265
|
/** Stable key for this tab. Required. */
|
|
123
|
-
key:
|
|
266
|
+
key: TabKey;
|
|
124
267
|
/** Display name of the tab. Required. */
|
|
125
268
|
name: string;
|
|
126
269
|
/** Sections inside this tab. Required. */
|
|
@@ -131,7 +274,7 @@ export interface TabWithSections {
|
|
|
131
274
|
export interface CustomTab {
|
|
132
275
|
type: 'custom_tab';
|
|
133
276
|
/** Stable key for this tab. Required. */
|
|
134
|
-
key:
|
|
277
|
+
key: TabKey;
|
|
135
278
|
/** Display name of the tab. Required. */
|
|
136
279
|
name: string;
|
|
137
280
|
/** Key of the custom component to render. Required. */
|
|
@@ -142,8 +285,6 @@ export interface CustomTab {
|
|
|
142
285
|
export type PageLayoutTab = TabWithSections | CustomTab;
|
|
143
286
|
|
|
144
287
|
/** Column layout for a `fields_section`. */
|
|
145
|
-
export type SectionFieldsLayout = 'one_column' | 'two_column' | 'three_column' | 'responsive';
|
|
146
|
-
|
|
147
288
|
/** Edits to a built-in section inside a system tab. */
|
|
148
289
|
export interface SystemSectionEdit {
|
|
149
290
|
/** Rename this section. Optional. */
|
|
@@ -153,7 +294,7 @@ export interface SystemSectionEdit {
|
|
|
153
294
|
/** Change the column layout. Optional. */
|
|
154
295
|
newLayout?: SectionFieldsLayout;
|
|
155
296
|
/** Add fields to this section. Optional. */
|
|
156
|
-
newFields?:
|
|
297
|
+
newFields?: SectionFieldInput[];
|
|
157
298
|
/** Hide the section name header. Optional. */
|
|
158
299
|
newHideName?: boolean;
|
|
159
300
|
}
|
|
@@ -167,9 +308,9 @@ export interface SystemTabEdit {
|
|
|
167
308
|
/** Add new sections to this tab. Optional. */
|
|
168
309
|
newSections?: PageLayoutSection[];
|
|
169
310
|
/** Edits to built-in sections inside this tab, keyed by section key. Optional. */
|
|
170
|
-
systemSectionEdits?: Record<
|
|
311
|
+
systemSectionEdits?: Record<SectionKey, SystemSectionEdit>;
|
|
171
312
|
/** Reorder sections by key. Optional. */
|
|
172
|
-
sectionsOrder?:
|
|
313
|
+
sectionsOrder?: SectionKey[];
|
|
173
314
|
}
|
|
174
315
|
|
|
175
316
|
/**
|
|
@@ -184,11 +325,11 @@ export interface TabEdits {
|
|
|
184
325
|
/** New tabs to add to this layout. Each must include a `type` discriminator. Optional. */
|
|
185
326
|
newTabs?: PageLayoutTab[];
|
|
186
327
|
/** Edits to existing system tabs, keyed by tab key. Optional. */
|
|
187
|
-
systemTabEdits?: Record<
|
|
328
|
+
systemTabEdits?: Record<TabKey, SystemTabEdit>;
|
|
188
329
|
/** Ordered list of tab `key` values (new + system). Optional. */
|
|
189
|
-
tabsOrder?:
|
|
330
|
+
tabsOrder?: TabKey[];
|
|
190
331
|
/** Tab strip orientation. Optional. */
|
|
191
|
-
newTabLayout?:
|
|
332
|
+
newTabLayout?: TabLayout;
|
|
192
333
|
}
|
|
193
334
|
|
|
194
335
|
// ---------------------------------------------------------------------------
|
|
@@ -205,7 +346,7 @@ export interface VisibilityCondition {
|
|
|
205
346
|
/** RQL formula that controls visibility. Required. */
|
|
206
347
|
rqlFormula: string;
|
|
207
348
|
/** Layered conditions tree (AST). Required. */
|
|
208
|
-
layeredConditionsTree:
|
|
349
|
+
layeredConditionsTree: JsonObject;
|
|
209
350
|
}
|
|
210
351
|
|
|
211
352
|
/**
|
|
@@ -215,9 +356,9 @@ export interface VisibilityCondition {
|
|
|
215
356
|
*/
|
|
216
357
|
export interface VisibilityConditions {
|
|
217
358
|
/** Per-section visibility conditions, keyed by section key. Optional. */
|
|
218
|
-
sections?: Record<
|
|
359
|
+
sections?: Record<SectionKey, VisibilityCondition>;
|
|
219
360
|
/** Per-tab visibility conditions, keyed by tab key. Optional. */
|
|
220
|
-
tabs?: Record<
|
|
361
|
+
tabs?: Record<TabKey, VisibilityCondition>;
|
|
221
362
|
}
|
|
222
363
|
|
|
223
364
|
// ---------------------------------------------------------------------------
|
|
@@ -241,13 +382,13 @@ export interface AddCustomPageLayoutFieldOptions extends AddPageLayoutFieldOptio
|
|
|
241
382
|
* across the layout.
|
|
242
383
|
*/
|
|
243
384
|
tabKey?: string;
|
|
244
|
-
/** Field
|
|
245
|
-
section
|
|
246
|
-
/**
|
|
247
|
-
sectionKey?:
|
|
385
|
+
/** Field-section metadata used to find typed custom layout sections and assign field metadata. */
|
|
386
|
+
section?: CustomObjectFieldSection;
|
|
387
|
+
/** Layout section key. Optional escape hatch for ambiguous custom sections. */
|
|
388
|
+
sectionKey?: SectionKey;
|
|
248
389
|
/** Deprecated. Use `section`. */
|
|
249
390
|
fieldSection?: never;
|
|
250
|
-
/** Custom layout sections are selected by `section`; `sectionKey`
|
|
391
|
+
/** Custom layout sections are selected by `section`; `sectionKey` can disambiguate. */
|
|
251
392
|
systemSection?: false;
|
|
252
393
|
}
|
|
253
394
|
|
|
@@ -291,9 +432,9 @@ export interface RemoveCustomPageLayoutFieldOptions extends RemovePageLayoutFiel
|
|
|
291
432
|
tabKey?: string;
|
|
292
433
|
/** Limit removal to one field section. Optional. */
|
|
293
434
|
section?: CustomObjectFieldSection;
|
|
294
|
-
/**
|
|
295
|
-
sectionKey?:
|
|
296
|
-
/** Custom layout sections are selected by `section`; `sectionKey`
|
|
435
|
+
/** Limit removal to one layout section key. Optional. */
|
|
436
|
+
sectionKey?: SectionKey;
|
|
437
|
+
/** Custom layout sections are selected by `section`; `sectionKey` can disambiguate. */
|
|
297
438
|
systemSection?: false;
|
|
298
439
|
}
|
|
299
440
|
|
|
@@ -339,7 +480,7 @@ export interface RemovePageLayoutSectionOptions {
|
|
|
339
480
|
* more than once throws. Optional. @default true
|
|
340
481
|
*/
|
|
341
482
|
removeAll?: boolean;
|
|
342
|
-
/** Custom layout sections are selected by
|
|
483
|
+
/** Custom layout sections are selected by layout section key or `CustomObjectFieldSection`. */
|
|
343
484
|
systemSection?: false;
|
|
344
485
|
}
|
|
345
486
|
|
|
@@ -451,11 +592,13 @@ export interface CustomObjectPageLayoutLoadFromExistingOptions extends ExistingM
|
|
|
451
592
|
customObjectApiName?: string;
|
|
452
593
|
}
|
|
453
594
|
|
|
595
|
+
type ResolveFieldSectionId = (fieldRqlName: string) => string | undefined;
|
|
596
|
+
|
|
454
597
|
interface SerializedSectionField extends SectionFieldOptions {
|
|
455
598
|
fieldRqlName: string;
|
|
456
599
|
}
|
|
457
600
|
|
|
458
|
-
interface SerializedFieldsSection {
|
|
601
|
+
interface SerializedFieldsSection extends PageLayoutSectionOptions {
|
|
459
602
|
key?: string;
|
|
460
603
|
type: 'fields_section';
|
|
461
604
|
name: string;
|
|
@@ -463,11 +606,19 @@ interface SerializedFieldsSection {
|
|
|
463
606
|
layout?: SectionFieldsLayout;
|
|
464
607
|
}
|
|
465
608
|
|
|
609
|
+
type SerializedPageLayoutSection =
|
|
610
|
+
| SerializedFieldsSection
|
|
611
|
+
| RelatedObjectSection
|
|
612
|
+
| RelatedFieldSection
|
|
613
|
+
| CustomSection
|
|
614
|
+
| ReportsSection
|
|
615
|
+
| CanvasSection;
|
|
616
|
+
|
|
466
617
|
interface SerializedTabWithSections {
|
|
467
618
|
type: 'tab_with_sections';
|
|
468
619
|
key: string;
|
|
469
620
|
name: string;
|
|
470
|
-
sections:
|
|
621
|
+
sections: SerializedPageLayoutSection[];
|
|
471
622
|
}
|
|
472
623
|
|
|
473
624
|
type SerializedPageLayoutTab = SerializedTabWithSections | CustomTab;
|
|
@@ -477,7 +628,7 @@ interface SerializedSystemSectionEdit extends Omit<SystemSectionEdit, 'newFields
|
|
|
477
628
|
}
|
|
478
629
|
|
|
479
630
|
interface SerializedSystemTabEdit extends Omit<SystemTabEdit, 'newSections' | 'systemSectionEdits'> {
|
|
480
|
-
newSections?:
|
|
631
|
+
newSections?: SerializedPageLayoutSection[];
|
|
481
632
|
systemSectionEdits?: Record<string, SerializedSystemSectionEdit>;
|
|
482
633
|
}
|
|
483
634
|
|
|
@@ -502,46 +653,49 @@ function isField(value: unknown): value is Field {
|
|
|
502
653
|
);
|
|
503
654
|
}
|
|
504
655
|
|
|
505
|
-
function isFieldRef(value:
|
|
656
|
+
function isFieldRef(value: SectionFieldInput): value is SectionField {
|
|
506
657
|
const candidate = value as { field?: unknown } | null;
|
|
507
658
|
return candidate != null && typeof candidate === 'object' && isField(candidate.field);
|
|
508
659
|
}
|
|
509
660
|
|
|
510
|
-
const
|
|
661
|
+
const LAYOUT_SECTION_KEY = Symbol('CustomObjectPageLayout.layoutSectionKey');
|
|
511
662
|
|
|
512
663
|
function isCustomObjectFieldSection(value: unknown): value is CustomObjectFieldSection {
|
|
513
664
|
return value instanceof CustomObjectFieldSection;
|
|
514
665
|
}
|
|
515
666
|
|
|
516
|
-
function
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
667
|
+
function explicitLayoutSectionKey(section: { key?: string }): string | undefined {
|
|
668
|
+
const record = section as unknown as Record<string, unknown>;
|
|
669
|
+
const key = section.key ?? record['layout_section_key'] ?? record['layoutSectionKey'];
|
|
670
|
+
return typeof key === 'string' ? key : undefined;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function attachLayoutSectionKey(
|
|
674
|
+
section: SerializedFieldsSection,
|
|
675
|
+
sectionKey: string,
|
|
676
|
+
): SerializedFieldsSection {
|
|
677
|
+
if (explicitLayoutSectionKey(section) == null) section.key = sectionKey;
|
|
678
|
+
Object.defineProperty(section, LAYOUT_SECTION_KEY, {
|
|
679
|
+
value: sectionKey,
|
|
525
680
|
enumerable: false,
|
|
526
681
|
configurable: true,
|
|
527
682
|
});
|
|
528
683
|
return section;
|
|
529
684
|
}
|
|
530
685
|
|
|
531
|
-
function layoutSectionKey(section:
|
|
686
|
+
function layoutSectionKey(section: { key?: string }): string | undefined {
|
|
532
687
|
return (
|
|
533
|
-
section
|
|
534
|
-
(section as unknown as Record<typeof
|
|
688
|
+
explicitLayoutSectionKey(section) ??
|
|
689
|
+
(section as unknown as Record<typeof LAYOUT_SECTION_KEY, string | undefined>)[LAYOUT_SECTION_KEY]
|
|
535
690
|
);
|
|
536
691
|
}
|
|
537
692
|
|
|
538
|
-
function layoutSectionMatches(section:
|
|
693
|
+
function layoutSectionMatches(section: { key?: string }, sectionKey: string): boolean {
|
|
539
694
|
return layoutSectionKey(section) === sectionKey;
|
|
540
695
|
}
|
|
541
696
|
|
|
542
|
-
function
|
|
543
|
-
|
|
544
|
-
return Object.prototype.hasOwnProperty.call(record, 'key') && record['key'] != null;
|
|
697
|
+
function isSerializedFieldsSection(section: SerializedPageLayoutSection): section is SerializedFieldsSection {
|
|
698
|
+
return section.type === 'fields_section';
|
|
545
699
|
}
|
|
546
700
|
|
|
547
701
|
function assertSameObject(customObject: CustomObject, field: Field, sectionKey: string): void {
|
|
@@ -585,15 +739,30 @@ function toSerializedSectionField(
|
|
|
585
739
|
const normalized: SerializedSectionField = { fieldRqlName };
|
|
586
740
|
if (options.hidden != null) normalized.hidden = options.hidden;
|
|
587
741
|
if (options.editable != null) normalized.editable = options.editable;
|
|
742
|
+
if (options.readOnly != null) normalized.readOnly = options.readOnly;
|
|
743
|
+
if (options.defaultValue != null) normalized.defaultValue = options.defaultValue;
|
|
744
|
+
if (options.height != null) normalized.height = options.height;
|
|
745
|
+
if (options.canBeDeleted != null) normalized.canBeDeleted = options.canBeDeleted;
|
|
588
746
|
if (options.movementOption != null) normalized.movementOption = options.movementOption;
|
|
589
747
|
return normalized;
|
|
590
748
|
}
|
|
591
749
|
|
|
750
|
+
function copySectionOptions<T extends PageLayoutSectionOptions>(
|
|
751
|
+
target: T,
|
|
752
|
+
input: PageLayoutSectionOptions,
|
|
753
|
+
): T {
|
|
754
|
+
if (input.canBeDeleted != null) target.canBeDeleted = input.canBeDeleted;
|
|
755
|
+
if (input.canBeRenamed != null) target.canBeRenamed = input.canBeRenamed;
|
|
756
|
+
if (input.movementOption != null) target.movementOption = input.movementOption;
|
|
757
|
+
if (input.hideName != null) target.hideName = input.hideName;
|
|
758
|
+
return target;
|
|
759
|
+
}
|
|
760
|
+
|
|
592
761
|
function normalizeSectionField(
|
|
593
762
|
customObject: CustomObject,
|
|
594
763
|
section: CustomObjectFieldSection | string,
|
|
595
764
|
sectionKey: string,
|
|
596
|
-
entry:
|
|
765
|
+
entry: SectionFieldInput,
|
|
597
766
|
): SerializedSectionField {
|
|
598
767
|
if (isField(entry)) {
|
|
599
768
|
assertSameObject(customObject, entry, sectionKey);
|
|
@@ -613,30 +782,37 @@ function normalizeSectionField(
|
|
|
613
782
|
);
|
|
614
783
|
}
|
|
615
784
|
|
|
616
|
-
function normalizeFieldsSection(
|
|
617
|
-
customObject: CustomObject,
|
|
618
|
-
input: PageLayoutSection,
|
|
619
|
-
): SerializedFieldsSection {
|
|
785
|
+
function normalizeFieldsSection(customObject: CustomObject, input: FieldsSection): SerializedFieldsSection {
|
|
620
786
|
assertSectionBelongsTo(customObject, input.section);
|
|
621
|
-
const
|
|
622
|
-
if (inputFieldsSectionHasKey(input)) {
|
|
623
|
-
throw new Error('CustomObjectPageLayout fields_section key is not supported. Omit key.');
|
|
624
|
-
}
|
|
787
|
+
const sectionKey = input.key ?? input.section.getSectionId();
|
|
625
788
|
const name = input.name ?? input.section.getName();
|
|
626
|
-
const normalized
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
789
|
+
const normalized = copySectionOptions<SerializedFieldsSection>(
|
|
790
|
+
{
|
|
791
|
+
name,
|
|
792
|
+
type: 'fields_section',
|
|
793
|
+
fields: input.fields.map((field) =>
|
|
794
|
+
normalizeSectionField(customObject, input.section, sectionKey, field),
|
|
795
|
+
),
|
|
796
|
+
},
|
|
797
|
+
input,
|
|
798
|
+
);
|
|
631
799
|
if (input.layout != null) normalized.layout = input.layout;
|
|
632
|
-
return
|
|
800
|
+
return attachLayoutSectionKey(normalized, sectionKey);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function normalizeSection(
|
|
804
|
+
customObject: CustomObject,
|
|
805
|
+
section: PageLayoutSection,
|
|
806
|
+
): SerializedPageLayoutSection {
|
|
807
|
+
if (section.type === 'fields_section') return normalizeFieldsSection(customObject, section);
|
|
808
|
+
return { ...section };
|
|
633
809
|
}
|
|
634
810
|
|
|
635
811
|
function normalizeTab(customObject: CustomObject, tab: PageLayoutTab): SerializedPageLayoutTab {
|
|
636
812
|
if (tab.type === 'custom_tab') return tab;
|
|
637
813
|
return {
|
|
638
814
|
...tab,
|
|
639
|
-
sections: tab.sections.map((section) =>
|
|
815
|
+
sections: tab.sections.map((section) => normalizeSection(customObject, section)),
|
|
640
816
|
};
|
|
641
817
|
}
|
|
642
818
|
|
|
@@ -664,7 +840,7 @@ function normalizeSystemTabEdit(
|
|
|
664
840
|
const { newSections: _newSections, systemSectionEdits: _systemSectionEdits, ...rest } = edit;
|
|
665
841
|
const normalized: SerializedSystemTabEdit = { ...rest };
|
|
666
842
|
if (edit.newSections != null) {
|
|
667
|
-
normalized.newSections = edit.newSections.map((section) =>
|
|
843
|
+
normalized.newSections = edit.newSections.map((section) => normalizeSection(customObject, section));
|
|
668
844
|
}
|
|
669
845
|
if (edit.systemSectionEdits != null) {
|
|
670
846
|
const systemSectionEdits: Record<string, SerializedSystemSectionEdit> = {};
|
|
@@ -730,7 +906,7 @@ function assertKnownKeys(
|
|
|
730
906
|
}
|
|
731
907
|
}
|
|
732
908
|
|
|
733
|
-
function normalizeHeaderEdits(headerEdits: HeaderEdits):
|
|
909
|
+
function normalizeHeaderEdits(headerEdits: HeaderEdits): SerializedHeaderEdits {
|
|
734
910
|
assertKnownKeys(
|
|
735
911
|
headerEdits as unknown as Record<string, unknown>,
|
|
736
912
|
HEADER_EDIT_KEYS,
|
|
@@ -756,6 +932,27 @@ function normalizeHeaderEdits(headerEdits: HeaderEdits): HeaderEdits {
|
|
|
756
932
|
);
|
|
757
933
|
}
|
|
758
934
|
|
|
935
|
+
if (headerEdits.newTitleField === '') {
|
|
936
|
+
throw new Error(
|
|
937
|
+
'CustomObjectPageLayout headerEdits.newTitleField cannot be empty. Use titleFieldDeleted.',
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
if (headerEdits.newDescriptionField === '') {
|
|
941
|
+
throw new Error(
|
|
942
|
+
'CustomObjectPageLayout headerEdits.newDescriptionField cannot be empty. Use descriptionFieldDeleted.',
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
if (headerEdits.newTitleField != null && headerEdits.titleFieldDeleted === true) {
|
|
946
|
+
throw new Error(
|
|
947
|
+
'CustomObjectPageLayout headerEdits cannot both set newTitleField and titleFieldDeleted.',
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
if (headerEdits.newDescriptionField != null && headerEdits.descriptionFieldDeleted === true) {
|
|
951
|
+
throw new Error(
|
|
952
|
+
'CustomObjectPageLayout headerEdits cannot both set newDescriptionField and descriptionFieldDeleted.',
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
|
|
759
956
|
if (headerEdits.headerFieldsOrder == null) return headerEdits;
|
|
760
957
|
return {
|
|
761
958
|
...headerEdits,
|
|
@@ -768,13 +965,13 @@ function addUniqueHeaderOrderField(order: string[], field: unknown): void {
|
|
|
768
965
|
if (!order.includes(field)) order.push(field);
|
|
769
966
|
}
|
|
770
967
|
|
|
771
|
-
function normalizeHeaderFieldsOrder(headerEdits:
|
|
968
|
+
function normalizeHeaderFieldsOrder(headerEdits: SerializedHeaderEdits): string[] {
|
|
772
969
|
const customFieldRqlByKey = new Map(
|
|
773
970
|
(headerEdits.newFields ?? []).map((field) => [field.key, field.rqlName]),
|
|
774
971
|
);
|
|
775
972
|
const systemFieldRqlByKey = new Map(
|
|
776
973
|
Object.entries(headerEdits.systemFieldEdits ?? {})
|
|
777
|
-
.filter((entry): entry is [string,
|
|
974
|
+
.filter((entry): entry is [string, SerializedSystemHeaderFieldEdit & { newRqlField: string }] => {
|
|
778
975
|
const [, edit] = entry;
|
|
779
976
|
return typeof edit.newRqlField === 'string' && edit.newRqlField.length > 0;
|
|
780
977
|
})
|
|
@@ -811,6 +1008,11 @@ interface MutableFieldContainer {
|
|
|
811
1008
|
label: string;
|
|
812
1009
|
}
|
|
813
1010
|
|
|
1011
|
+
interface FieldSectionLayoutSection {
|
|
1012
|
+
tabKey: string;
|
|
1013
|
+
sectionKey: string;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
814
1016
|
function isTabWithSections(tab: SerializedPageLayoutTab): tab is SerializedTabWithSections {
|
|
815
1017
|
return tab.type === 'tab_with_sections';
|
|
816
1018
|
}
|
|
@@ -841,66 +1043,126 @@ function fieldRqlNameOf(entry: unknown): string | undefined {
|
|
|
841
1043
|
if (typeof entry === 'string') return entry;
|
|
842
1044
|
if (entry == null || typeof entry !== 'object') return undefined;
|
|
843
1045
|
const record = entry as Record<string, any>;
|
|
844
|
-
const fieldRqlName =
|
|
1046
|
+
const fieldRqlName =
|
|
1047
|
+
record['fieldRqlName'] ?? record['field_rql_name'] ?? record['apiName'] ?? record['api_name'];
|
|
845
1048
|
return typeof fieldRqlName === 'string' ? fieldRqlName : undefined;
|
|
846
1049
|
}
|
|
847
1050
|
|
|
848
|
-
function
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1051
|
+
function addFieldSectionLayoutSection(
|
|
1052
|
+
index: Map<string, FieldSectionLayoutSection[]>,
|
|
1053
|
+
fieldSectionId: string,
|
|
1054
|
+
entry: FieldSectionLayoutSection,
|
|
1055
|
+
): void {
|
|
1056
|
+
const entries = index.get(fieldSectionId) ?? [];
|
|
1057
|
+
if (
|
|
1058
|
+
!entries.some((existing) => existing.tabKey === entry.tabKey && existing.sectionKey === entry.sectionKey)
|
|
1059
|
+
) {
|
|
1060
|
+
entries.push(entry);
|
|
1061
|
+
}
|
|
1062
|
+
index.set(fieldSectionId, entries);
|
|
853
1063
|
}
|
|
854
1064
|
|
|
855
|
-
function
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1065
|
+
function indexFieldsSectionInput(
|
|
1066
|
+
index: Map<string, FieldSectionLayoutSection[]>,
|
|
1067
|
+
tabKey: string,
|
|
1068
|
+
section: FieldsSection,
|
|
1069
|
+
): void {
|
|
1070
|
+
addFieldSectionLayoutSection(index, section.section.getSectionId(), {
|
|
1071
|
+
tabKey,
|
|
1072
|
+
sectionKey: section.key ?? section.section.getSectionId(),
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
function indexPageLayoutSectionInput(
|
|
1077
|
+
index: Map<string, FieldSectionLayoutSection[]>,
|
|
1078
|
+
tabKey: string,
|
|
1079
|
+
section: PageLayoutSection,
|
|
1080
|
+
): void {
|
|
1081
|
+
if (section.type === 'fields_section') indexFieldsSectionInput(index, tabKey, section);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function buildFieldSectionLayoutIndexFromProps(
|
|
1085
|
+
tabEdits: TabEdits | undefined,
|
|
1086
|
+
): Map<string, FieldSectionLayoutSection[]> {
|
|
1087
|
+
const index = new Map<string, FieldSectionLayoutSection[]>();
|
|
1088
|
+
if (tabEdits == null) return index;
|
|
1089
|
+
|
|
1090
|
+
for (const tab of tabEdits.newTabs ?? []) {
|
|
1091
|
+
if (tab.type !== 'tab_with_sections') continue;
|
|
1092
|
+
for (const section of tab.sections) indexPageLayoutSectionInput(index, tab.key, section);
|
|
1093
|
+
}
|
|
866
1094
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1095
|
+
for (const [tabKey, tabEdit] of Object.entries(tabEdits.systemTabEdits ?? {})) {
|
|
1096
|
+
for (const section of tabEdit.newSections ?? []) {
|
|
1097
|
+
indexPageLayoutSectionInput(index, tabKey, section);
|
|
1098
|
+
}
|
|
871
1099
|
}
|
|
872
|
-
|
|
1100
|
+
|
|
1101
|
+
return index;
|
|
873
1102
|
}
|
|
874
1103
|
|
|
875
|
-
function
|
|
1104
|
+
function indexLoadedFieldsSection(
|
|
1105
|
+
index: Map<string, FieldSectionLayoutSection[]>,
|
|
1106
|
+
tabKey: string,
|
|
876
1107
|
section: SerializedFieldsSection,
|
|
877
|
-
resolveFieldSectionId
|
|
878
|
-
):
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
);
|
|
1108
|
+
resolveFieldSectionId: ResolveFieldSectionId | undefined,
|
|
1109
|
+
): void {
|
|
1110
|
+
const sectionKey = layoutSectionKey(section);
|
|
1111
|
+
if (sectionKey == null || resolveFieldSectionId == null) return;
|
|
1112
|
+
|
|
1113
|
+
for (const field of section.fields ?? []) {
|
|
1114
|
+
const fieldRqlName = fieldRqlNameOf(field);
|
|
1115
|
+
if (fieldRqlName == null) continue;
|
|
1116
|
+
const fieldSectionId = resolveFieldSectionId(fieldRqlName);
|
|
1117
|
+
if (fieldSectionId != null) {
|
|
1118
|
+
addFieldSectionLayoutSection(index, fieldSectionId, { tabKey, sectionKey });
|
|
1119
|
+
}
|
|
886
1120
|
}
|
|
887
|
-
const sectionId = explicitSectionId ?? inferredSectionId;
|
|
888
|
-
return sectionId == null ? section : attachFieldSectionId(section, sectionId);
|
|
889
1121
|
}
|
|
890
1122
|
|
|
891
|
-
function
|
|
1123
|
+
function buildFieldSectionLayoutIndexFromLoadedTabEdits(
|
|
892
1124
|
tabEdits: SerializedTabEdits,
|
|
893
|
-
resolveFieldSectionId
|
|
894
|
-
):
|
|
1125
|
+
resolveFieldSectionId: ResolveFieldSectionId | undefined,
|
|
1126
|
+
): Map<string, FieldSectionLayoutSection[]> {
|
|
1127
|
+
const index = new Map<string, FieldSectionLayoutSection[]>();
|
|
1128
|
+
|
|
1129
|
+
for (const tab of tabEdits.newTabs ?? []) {
|
|
1130
|
+
if (!isTabWithSections(tab)) continue;
|
|
1131
|
+
for (const section of tab.sections) {
|
|
1132
|
+
if (isSerializedFieldsSection(section)) {
|
|
1133
|
+
indexLoadedFieldsSection(index, tab.key, section, resolveFieldSectionId);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
for (const [tabKey, tabEdit] of Object.entries(tabEdits.systemTabEdits ?? {})) {
|
|
1139
|
+
for (const section of tabEdit.newSections ?? []) {
|
|
1140
|
+
if (isSerializedFieldsSection(section)) {
|
|
1141
|
+
indexLoadedFieldsSection(index, tabKey, section, resolveFieldSectionId);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
return index;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
function annotateLoadedFieldsSection(section: SerializedFieldsSection): SerializedFieldsSection {
|
|
1150
|
+
const sectionKey = layoutSectionKey(section);
|
|
1151
|
+
return sectionKey == null ? section : attachLayoutSectionKey(section, sectionKey);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
function annotateLoadedTabEdits(tabEdits: SerializedTabEdits): SerializedTabEdits {
|
|
895
1155
|
for (const tab of tabEdits.newTabs ?? []) {
|
|
896
1156
|
if (!isTabWithSections(tab)) continue;
|
|
897
|
-
tab.sections = tab.sections.map((section) =>
|
|
1157
|
+
tab.sections = tab.sections.map((section) =>
|
|
1158
|
+
isSerializedFieldsSection(section) ? annotateLoadedFieldsSection(section) : section,
|
|
1159
|
+
);
|
|
898
1160
|
}
|
|
899
1161
|
|
|
900
1162
|
for (const tabEdit of Object.values(tabEdits.systemTabEdits ?? {})) {
|
|
901
1163
|
if (tabEdit.newSections != null) {
|
|
902
1164
|
tabEdit.newSections = tabEdit.newSections.map((section) =>
|
|
903
|
-
annotateLoadedFieldsSection(section
|
|
1165
|
+
isSerializedFieldsSection(section) ? annotateLoadedFieldsSection(section) : section,
|
|
904
1166
|
);
|
|
905
1167
|
}
|
|
906
1168
|
}
|
|
@@ -1020,9 +1282,10 @@ export class CustomObjectPageLayout {
|
|
|
1020
1282
|
private readonly _customObjectApiName: string;
|
|
1021
1283
|
private readonly _name: string;
|
|
1022
1284
|
private readonly _tabEdits: SerializedTabEdits;
|
|
1023
|
-
private readonly _headerEdits:
|
|
1285
|
+
private readonly _headerEdits: SerializedHeaderEdits;
|
|
1024
1286
|
private readonly _visibilityConditions: VisibilityConditions;
|
|
1025
1287
|
private readonly _blueprintKey: string | undefined;
|
|
1288
|
+
private readonly _fieldSectionLayoutSections: Map<string, FieldSectionLayoutSection[]>;
|
|
1026
1289
|
|
|
1027
1290
|
/**
|
|
1028
1291
|
* @param customObject - The custom object this layout belongs to.
|
|
@@ -1037,6 +1300,7 @@ export class CustomObjectPageLayout {
|
|
|
1037
1300
|
this._customObjectApiName = customObject.getApiName();
|
|
1038
1301
|
this._name = props.name;
|
|
1039
1302
|
this._tabEdits = normalizeTabEdits(customObject, props.tabEdits ?? {});
|
|
1303
|
+
this._fieldSectionLayoutSections = buildFieldSectionLayoutIndexFromProps(props.tabEdits);
|
|
1040
1304
|
this._headerEdits = normalizeHeaderEdits(props.headerEdits ?? {});
|
|
1041
1305
|
this._visibilityConditions = props.visibilityConditions ?? {};
|
|
1042
1306
|
this._blueprintKey = props.blueprintKey;
|
|
@@ -1061,9 +1325,10 @@ export class CustomObjectPageLayout {
|
|
|
1061
1325
|
static _fromExistingComponent(
|
|
1062
1326
|
customObject: CustomObject,
|
|
1063
1327
|
component: Record<string, any>,
|
|
1064
|
-
resolveFieldSectionId?:
|
|
1328
|
+
resolveFieldSectionId?: ResolveFieldSectionId,
|
|
1065
1329
|
): CustomObjectPageLayout {
|
|
1066
1330
|
const layout = Object.create(CustomObjectPageLayout.prototype) as CustomObjectPageLayout;
|
|
1331
|
+
const tabEdits = annotateLoadedTabEdits(cloneJson(component['tab_edits'] ?? {}));
|
|
1067
1332
|
Object.assign(layout as Record<string, any>, {
|
|
1068
1333
|
_layoutId: requireStringComponentField(component, 'layout_id', CustomObjectPageLayout.componentType),
|
|
1069
1334
|
_apiName: requireStringComponentField(component, 'api_name', CustomObjectPageLayout.componentType),
|
|
@@ -1073,10 +1338,14 @@ export class CustomObjectPageLayout {
|
|
|
1073
1338
|
CustomObjectPageLayout.componentType,
|
|
1074
1339
|
),
|
|
1075
1340
|
_name: requireStringComponentField(component, 'name', CustomObjectPageLayout.componentType),
|
|
1076
|
-
_tabEdits:
|
|
1341
|
+
_tabEdits: tabEdits,
|
|
1077
1342
|
_headerEdits: cloneJson(component['header_edits'] ?? {}),
|
|
1078
1343
|
_visibilityConditions: cloneJson(component['visibility_conditions'] ?? {}),
|
|
1079
1344
|
_blueprintKey: component['blueprint_key'],
|
|
1345
|
+
_fieldSectionLayoutSections: buildFieldSectionLayoutIndexFromLoadedTabEdits(
|
|
1346
|
+
tabEdits,
|
|
1347
|
+
resolveFieldSectionId,
|
|
1348
|
+
),
|
|
1080
1349
|
});
|
|
1081
1350
|
customObject._register(layout);
|
|
1082
1351
|
return layout;
|
|
@@ -1117,8 +1386,8 @@ export class CustomObjectPageLayout {
|
|
|
1117
1386
|
* Adds multiple fields to an existing layout section.
|
|
1118
1387
|
*
|
|
1119
1388
|
* Fields are inserted in the order provided. For custom layout sections,
|
|
1120
|
-
* pass `
|
|
1121
|
-
*
|
|
1389
|
+
* pass `section` to choose the typed field section. Use `sectionKey` only
|
|
1390
|
+
* when a field section maps to multiple layout sections.
|
|
1122
1391
|
*/
|
|
1123
1392
|
addFields(fields: Field[], options: AddPageLayoutFieldsOptions): this {
|
|
1124
1393
|
if (fields.length === 0) return this;
|
|
@@ -1141,25 +1410,25 @@ export class CustomObjectPageLayout {
|
|
|
1141
1410
|
return this.ensureSystemSectionFieldContainer(options.tabKey, options.sectionKey);
|
|
1142
1411
|
})()
|
|
1143
1412
|
: (() => {
|
|
1144
|
-
assertOptionAbsent(
|
|
1145
|
-
options,
|
|
1146
|
-
'sectionKey',
|
|
1147
|
-
'CustomObjectPageLayout addField sectionKey is only supported with systemSection: true. ' +
|
|
1148
|
-
'Pass section: CustomObjectFieldSection for custom layout sections.',
|
|
1149
|
-
);
|
|
1150
1413
|
assertOptionAbsent(
|
|
1151
1414
|
options,
|
|
1152
1415
|
'fieldSection',
|
|
1153
1416
|
'CustomObjectPageLayout addField fieldSection is no longer supported. ' +
|
|
1154
1417
|
'Pass section: CustomObjectFieldSection instead.',
|
|
1155
1418
|
);
|
|
1156
|
-
const section =
|
|
1157
|
-
options.section
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1419
|
+
const section =
|
|
1420
|
+
options.section == null ?
|
|
1421
|
+
undefined
|
|
1422
|
+
: requireFieldSectionOption(options.section, 'CustomObjectPageLayout addField section');
|
|
1423
|
+
if (section != null) {
|
|
1424
|
+
this.assertFieldSectionBelongsToLayout(section);
|
|
1425
|
+
fieldSectionForMutation = section;
|
|
1426
|
+
}
|
|
1427
|
+
const sectionKey =
|
|
1428
|
+
options.sectionKey ??
|
|
1429
|
+
(section == null ? undefined : this.layoutSectionKeyForFieldSection(options.tabKey, section)) ??
|
|
1430
|
+
section?.getSectionId();
|
|
1431
|
+
return this.requireOneFieldContainer(options.tabKey, sectionKey, section);
|
|
1163
1432
|
})();
|
|
1164
1433
|
const entries = fields.map((field) =>
|
|
1165
1434
|
this.serializeFieldForMutation(
|
|
@@ -1208,19 +1477,15 @@ export class CustomObjectPageLayout {
|
|
|
1208
1477
|
);
|
|
1209
1478
|
sectionKey = options.sectionKey;
|
|
1210
1479
|
} else {
|
|
1211
|
-
|
|
1212
|
-
options,
|
|
1213
|
-
'sectionKey',
|
|
1214
|
-
'CustomObjectPageLayout removeField sectionKey is only supported with systemSection: true. ' +
|
|
1215
|
-
'Pass section: CustomObjectFieldSection for custom layout sections.',
|
|
1216
|
-
);
|
|
1480
|
+
sectionKey = options.sectionKey;
|
|
1217
1481
|
if (options.section != null) {
|
|
1218
1482
|
const section = requireFieldSectionOption(
|
|
1219
1483
|
options.section,
|
|
1220
1484
|
'CustomObjectPageLayout removeField section',
|
|
1221
1485
|
);
|
|
1222
1486
|
this.assertFieldSectionBelongsToLayout(section);
|
|
1223
|
-
sectionKey
|
|
1487
|
+
sectionKey ??= this.layoutSectionKeyForFieldSection(options.tabKey, section);
|
|
1488
|
+
sectionKey ??= section.getSectionId();
|
|
1224
1489
|
}
|
|
1225
1490
|
}
|
|
1226
1491
|
|
|
@@ -1280,7 +1545,7 @@ export class CustomObjectPageLayout {
|
|
|
1280
1545
|
const normalized = this.normalizeSectionForMutation(section);
|
|
1281
1546
|
if (options.systemTab === true) {
|
|
1282
1547
|
const tabEdit = this.ensureSystemTabEdit(options.tabKey);
|
|
1283
|
-
const sections = ensureArrayProperty<
|
|
1548
|
+
const sections = ensureArrayProperty<SerializedPageLayoutSection>(
|
|
1284
1549
|
tabEdit as Record<string, any>,
|
|
1285
1550
|
'newSections',
|
|
1286
1551
|
`systemTabEdits.${options.tabKey}.newSections`,
|
|
@@ -1294,6 +1559,9 @@ export class CustomObjectPageLayout {
|
|
|
1294
1559
|
const sectionsOrder = this.ensureSystemSectionsOrder(tabEdit);
|
|
1295
1560
|
insertAt(sections, normalized, options.position);
|
|
1296
1561
|
insertUniqueAt(sectionsOrder, layoutSectionKey(normalized), options.position);
|
|
1562
|
+
if (section.type === 'fields_section') {
|
|
1563
|
+
this.rememberFieldSectionLayoutSection(section.section, options.tabKey, layoutSectionKey(normalized));
|
|
1564
|
+
}
|
|
1297
1565
|
return this;
|
|
1298
1566
|
}
|
|
1299
1567
|
|
|
@@ -1311,6 +1579,9 @@ export class CustomObjectPageLayout {
|
|
|
1311
1579
|
options.allowDuplicate,
|
|
1312
1580
|
);
|
|
1313
1581
|
insertAt(tab.sections, normalized, options.position);
|
|
1582
|
+
if (section.type === 'fields_section') {
|
|
1583
|
+
this.rememberFieldSectionLayoutSection(section.section, tab.key, layoutSectionKey(normalized));
|
|
1584
|
+
}
|
|
1314
1585
|
return this;
|
|
1315
1586
|
}
|
|
1316
1587
|
|
|
@@ -1321,6 +1592,7 @@ export class CustomObjectPageLayout {
|
|
|
1321
1592
|
* `systemSectionEdits[sectionKey].deleted`.
|
|
1322
1593
|
*/
|
|
1323
1594
|
removeSection(section: CustomObjectFieldSection, options?: RemovePageLayoutSectionOptions): this;
|
|
1595
|
+
removeSection(sectionKey: string, options?: RemovePageLayoutSectionOptions): this;
|
|
1324
1596
|
removeSection(sectionKey: string, options: RemoveSystemPageLayoutSectionOptions): this;
|
|
1325
1597
|
removeSection(
|
|
1326
1598
|
sectionOrKey: CustomObjectFieldSection | string,
|
|
@@ -1342,11 +1614,16 @@ export class CustomObjectPageLayout {
|
|
|
1342
1614
|
return this;
|
|
1343
1615
|
}
|
|
1344
1616
|
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1617
|
+
let sectionKey: string;
|
|
1618
|
+
if (typeof sectionOrKey === 'string') {
|
|
1619
|
+
sectionKey = sectionOrKey;
|
|
1620
|
+
} else {
|
|
1621
|
+
const section = requireFieldSectionOption(sectionOrKey, 'CustomObjectPageLayout removeSection section');
|
|
1622
|
+
this.assertFieldSectionBelongsToLayout(section);
|
|
1623
|
+
sectionKey = this.layoutSectionKeyForFieldSection(options.tabKey, section) ?? section.getSectionId();
|
|
1624
|
+
}
|
|
1348
1625
|
const matches: Array<{
|
|
1349
|
-
sections:
|
|
1626
|
+
sections: SerializedPageLayoutSection[];
|
|
1350
1627
|
section: SerializedFieldsSection;
|
|
1351
1628
|
index: number;
|
|
1352
1629
|
tabEdit?: SerializedSystemTabEdit;
|
|
@@ -1356,14 +1633,14 @@ export class CustomObjectPageLayout {
|
|
|
1356
1633
|
if (!isTabWithSections(tab)) continue;
|
|
1357
1634
|
if (options.tabKey != null && tab.key !== options.tabKey) continue;
|
|
1358
1635
|
tab.sections.forEach((section, index) => {
|
|
1359
|
-
if (layoutSectionMatches(section, sectionKey))
|
|
1636
|
+
if (isSerializedFieldsSection(section) && layoutSectionMatches(section, sectionKey))
|
|
1360
1637
|
matches.push({ sections: tab.sections, section, index, tabKey: tab.key });
|
|
1361
1638
|
});
|
|
1362
1639
|
}
|
|
1363
1640
|
for (const [tabKey, tabEdit] of Object.entries(this._tabEdits.systemTabEdits ?? {})) {
|
|
1364
1641
|
if (options.tabKey != null && tabKey !== options.tabKey) continue;
|
|
1365
1642
|
(tabEdit.newSections ?? []).forEach((section, index) => {
|
|
1366
|
-
if (layoutSectionMatches(section, sectionKey))
|
|
1643
|
+
if (isSerializedFieldsSection(section) && layoutSectionMatches(section, sectionKey))
|
|
1367
1644
|
matches.push({ sections: tabEdit.newSections!, section, index, tabEdit, tabKey });
|
|
1368
1645
|
});
|
|
1369
1646
|
}
|
|
@@ -1380,7 +1657,7 @@ export class CustomObjectPageLayout {
|
|
|
1380
1657
|
}
|
|
1381
1658
|
|
|
1382
1659
|
const removals = removeAll ? matches : matches.slice(0, 1);
|
|
1383
|
-
const byArray = new Map<
|
|
1660
|
+
const byArray = new Map<SerializedPageLayoutSection[], number[]>();
|
|
1384
1661
|
for (const match of removals) {
|
|
1385
1662
|
const indexes = byArray.get(match.sections) ?? [];
|
|
1386
1663
|
indexes.push(match.index);
|
|
@@ -1404,6 +1681,10 @@ export class CustomObjectPageLayout {
|
|
|
1404
1681
|
const tabsOrder = this.ensureTabsOrder();
|
|
1405
1682
|
insertAt(newTabs, normalized, options.position);
|
|
1406
1683
|
insertUniqueAt(tabsOrder, normalized.key, options.position);
|
|
1684
|
+
if (tab.type === 'tab_with_sections') {
|
|
1685
|
+
for (const section of tab.sections)
|
|
1686
|
+
indexPageLayoutSectionInput(this._fieldSectionLayoutSections, tab.key, section);
|
|
1687
|
+
}
|
|
1407
1688
|
return this;
|
|
1408
1689
|
}
|
|
1409
1690
|
|
|
@@ -1474,11 +1755,13 @@ export class CustomObjectPageLayout {
|
|
|
1474
1755
|
}
|
|
1475
1756
|
|
|
1476
1757
|
/** Sets the record title field in `header_edits`. */
|
|
1477
|
-
setTitleField(field: Field
|
|
1758
|
+
setTitleField(field: Field): this;
|
|
1759
|
+
setTitleField(fieldApiName: FieldRqlName): this;
|
|
1760
|
+
setTitleField(field: Field | FieldRqlName): this {
|
|
1478
1761
|
const previousTitleField = this._headerEdits.newTitleField;
|
|
1479
1762
|
const nextTitleField = this.headerFieldApiName(field);
|
|
1480
1763
|
this._headerEdits.newTitleField = nextTitleField;
|
|
1481
|
-
|
|
1764
|
+
this._headerEdits.titleFieldDeleted = false;
|
|
1482
1765
|
insertUniqueAt(this.ensureHeaderFieldsOrder(), nextTitleField, 'end');
|
|
1483
1766
|
this.removeHeaderOrderFieldIfUnused(previousTitleField);
|
|
1484
1767
|
return this;
|
|
@@ -1494,11 +1777,13 @@ export class CustomObjectPageLayout {
|
|
|
1494
1777
|
}
|
|
1495
1778
|
|
|
1496
1779
|
/** Sets the record description field in `header_edits`. */
|
|
1497
|
-
setDescriptionField(field: Field
|
|
1780
|
+
setDescriptionField(field: Field): this;
|
|
1781
|
+
setDescriptionField(fieldApiName: FieldRqlName): this;
|
|
1782
|
+
setDescriptionField(field: Field | FieldRqlName): this {
|
|
1498
1783
|
const previousDescriptionField = this._headerEdits.newDescriptionField;
|
|
1499
1784
|
const nextDescriptionField = this.headerFieldApiName(field);
|
|
1500
1785
|
this._headerEdits.newDescriptionField = nextDescriptionField;
|
|
1501
|
-
|
|
1786
|
+
this._headerEdits.descriptionFieldDeleted = false;
|
|
1502
1787
|
insertUniqueAt(this.ensureHeaderFieldsOrder(), nextDescriptionField, 'end');
|
|
1503
1788
|
this.removeHeaderOrderFieldIfUnused(previousDescriptionField);
|
|
1504
1789
|
return this;
|
|
@@ -1571,7 +1856,7 @@ export class CustomObjectPageLayout {
|
|
|
1571
1856
|
private normalizeSectionFieldForMutation(
|
|
1572
1857
|
section: CustomObjectFieldSection | string,
|
|
1573
1858
|
sectionKey: string,
|
|
1574
|
-
entry:
|
|
1859
|
+
entry: SectionFieldInput,
|
|
1575
1860
|
): SerializedSectionField {
|
|
1576
1861
|
if (isField(entry)) {
|
|
1577
1862
|
this.assertFieldBelongsToLayout(entry);
|
|
@@ -1591,23 +1876,25 @@ export class CustomObjectPageLayout {
|
|
|
1591
1876
|
);
|
|
1592
1877
|
}
|
|
1593
1878
|
|
|
1594
|
-
private normalizeSectionForMutation(input: PageLayoutSection):
|
|
1879
|
+
private normalizeSectionForMutation(input: PageLayoutSection): SerializedPageLayoutSection {
|
|
1880
|
+
if (input.type !== 'fields_section') return { ...input };
|
|
1881
|
+
|
|
1595
1882
|
this.assertFieldSectionBelongsToLayout(input.section);
|
|
1596
1883
|
|
|
1597
|
-
const
|
|
1598
|
-
if (inputFieldsSectionHasKey(input)) {
|
|
1599
|
-
throw new Error('CustomObjectPageLayout fields_section key is not supported. Omit key.');
|
|
1600
|
-
}
|
|
1884
|
+
const sectionKey = input.key ?? input.section.getSectionId();
|
|
1601
1885
|
const name = input.name ?? input.section.getName();
|
|
1602
|
-
const normalized
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1886
|
+
const normalized = copySectionOptions<SerializedFieldsSection>(
|
|
1887
|
+
{
|
|
1888
|
+
name,
|
|
1889
|
+
type: 'fields_section',
|
|
1890
|
+
fields: input.fields.map((field) =>
|
|
1891
|
+
this.normalizeSectionFieldForMutation(input.section, sectionKey, field),
|
|
1892
|
+
),
|
|
1893
|
+
},
|
|
1894
|
+
input,
|
|
1895
|
+
);
|
|
1609
1896
|
if (input.layout != null) normalized.layout = input.layout;
|
|
1610
|
-
return
|
|
1897
|
+
return attachLayoutSectionKey(normalized, sectionKey);
|
|
1611
1898
|
}
|
|
1612
1899
|
|
|
1613
1900
|
private normalizeTabForMutation(tab: PageLayoutTab): SerializedPageLayoutTab {
|
|
@@ -1670,6 +1957,35 @@ export class CustomObjectPageLayout {
|
|
|
1670
1957
|
}
|
|
1671
1958
|
}
|
|
1672
1959
|
|
|
1960
|
+
private rememberFieldSectionLayoutSection(
|
|
1961
|
+
section: CustomObjectFieldSection,
|
|
1962
|
+
tabKey: string,
|
|
1963
|
+
sectionKey: string | undefined,
|
|
1964
|
+
): void {
|
|
1965
|
+
if (sectionKey == null) return;
|
|
1966
|
+
addFieldSectionLayoutSection(this._fieldSectionLayoutSections, section.getSectionId(), {
|
|
1967
|
+
tabKey,
|
|
1968
|
+
sectionKey,
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
private layoutSectionKeyForFieldSection(
|
|
1973
|
+
tabKey: string | undefined,
|
|
1974
|
+
section: CustomObjectFieldSection,
|
|
1975
|
+
): string | undefined {
|
|
1976
|
+
const entries = this._fieldSectionLayoutSections.get(section.getSectionId()) ?? [];
|
|
1977
|
+
const matches = tabKey == null ? entries : entries.filter((entry) => entry.tabKey === tabKey);
|
|
1978
|
+
const sectionKeys = [...new Set(matches.map((entry) => entry.sectionKey))];
|
|
1979
|
+
if (sectionKeys.length === 0) return undefined;
|
|
1980
|
+
if (sectionKeys.length === 1) return sectionKeys[0];
|
|
1981
|
+
|
|
1982
|
+
const scope = tabKey == null ? '' : ` in tab "${tabKey}"`;
|
|
1983
|
+
throw new Error(
|
|
1984
|
+
`CustomObjectPageLayout field section "${section.getSectionId()}" maps to multiple layout sections${scope}: ` +
|
|
1985
|
+
`${sectionKeys.join(', ')}. Pass sectionKey to choose one.`,
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1673
1989
|
private requireOneFieldContainer(
|
|
1674
1990
|
tabKey: string | undefined,
|
|
1675
1991
|
sectionKey: string | undefined,
|
|
@@ -1699,8 +2015,8 @@ export class CustomObjectPageLayout {
|
|
|
1699
2015
|
const container = unkeyedContainers[0] as MutableFieldContainer & {
|
|
1700
2016
|
section: SerializedFieldsSection;
|
|
1701
2017
|
};
|
|
1702
|
-
|
|
1703
|
-
container.sectionKey =
|
|
2018
|
+
attachLayoutSectionKey(container.section, sectionKey);
|
|
2019
|
+
container.sectionKey = sectionKey;
|
|
1704
2020
|
container.label = `${container.tabKey}.${container.sectionKey}`;
|
|
1705
2021
|
return container;
|
|
1706
2022
|
}
|
|
@@ -1738,6 +2054,7 @@ export class CustomObjectPageLayout {
|
|
|
1738
2054
|
if (!isTabWithSections(tab)) continue;
|
|
1739
2055
|
if (filter.tabKey != null && tab.key !== filter.tabKey) continue;
|
|
1740
2056
|
for (const [index, section] of tab.sections.entries()) {
|
|
2057
|
+
if (!isSerializedFieldsSection(section)) continue;
|
|
1741
2058
|
const sectionKey = layoutSectionKey(section);
|
|
1742
2059
|
if (filter.sectionKey != null && !layoutSectionMatches(section, filter.sectionKey)) continue;
|
|
1743
2060
|
const label = sectionKey == null ? `${tab.key}.sections[${index}]` : `${tab.key}.${sectionKey}`;
|
|
@@ -1758,6 +2075,7 @@ export class CustomObjectPageLayout {
|
|
|
1758
2075
|
for (const [tabKey, tabEdit] of Object.entries(this._tabEdits.systemTabEdits ?? {})) {
|
|
1759
2076
|
if (filter.tabKey != null && tabKey !== filter.tabKey) continue;
|
|
1760
2077
|
for (const [index, section] of (tabEdit.newSections ?? []).entries()) {
|
|
2078
|
+
if (!isSerializedFieldsSection(section)) continue;
|
|
1761
2079
|
const sectionKey = layoutSectionKey(section);
|
|
1762
2080
|
if (filter.sectionKey != null && !layoutSectionMatches(section, filter.sectionKey)) continue;
|
|
1763
2081
|
const label = sectionKey == null ? `${tabKey}.newSections[${index}]` : `${tabKey}.${sectionKey}`;
|
|
@@ -1870,7 +2188,7 @@ export class CustomObjectPageLayout {
|
|
|
1870
2188
|
}
|
|
1871
2189
|
|
|
1872
2190
|
private assertSectionKeyAvailable(
|
|
1873
|
-
sections:
|
|
2191
|
+
sections: SerializedPageLayoutSection[],
|
|
1874
2192
|
sectionKey: string | undefined,
|
|
1875
2193
|
tabKey: string,
|
|
1876
2194
|
allowDuplicate: boolean | undefined,
|
|
@@ -1903,8 +2221,7 @@ export class CustomObjectPageLayout {
|
|
|
1903
2221
|
return normalized;
|
|
1904
2222
|
}
|
|
1905
2223
|
|
|
1906
|
-
private headerFieldApiName(field: Field |
|
|
1907
|
-
if (field == null) return null;
|
|
2224
|
+
private headerFieldApiName(field: Field | FieldRqlName): FieldRqlName {
|
|
1908
2225
|
if (typeof field === 'string') return field;
|
|
1909
2226
|
this.assertFieldBelongsToLayout(field);
|
|
1910
2227
|
return field.getApiName();
|