@meshmakers/octo-ui 3.4.1480 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -0
- package/entity-forms/README.md +462 -0
- package/fesm2022/meshmakers-octo-ui-branding-settings.mjs +2 -2
- package/fesm2022/meshmakers-octo-ui-branding-settings.mjs.map +1 -1
- package/fesm2022/meshmakers-octo-ui-entity-forms.mjs +7944 -0
- package/fesm2022/meshmakers-octo-ui-entity-forms.mjs.map +1 -0
- package/fesm2022/meshmakers-octo-ui-tree-navigation-settings.mjs +2 -2
- package/fesm2022/meshmakers-octo-ui-tree-navigation-settings.mjs.map +1 -1
- package/fesm2022/meshmakers-octo-ui.mjs +985 -402
- package/fesm2022/meshmakers-octo-ui.mjs.map +1 -1
- package/lib/runtime-browser/styles/_button.scss +123 -0
- package/lib/runtime-browser/styles/_field-input.scss +16 -0
- package/lib/runtime-browser/styles/_flat-button.scss +14 -0
- package/lib/runtime-browser/styles/_index.scss +1 -1
- package/lib/runtime-browser/styles/_styles.scss +781 -1407
- package/lib/runtime-browser/styles/_theme.scss +248 -288
- package/lib/runtime-browser/styles/_variables.scss +26 -41
- package/package.json +5 -1
- package/types/meshmakers-octo-ui-entity-forms.d.ts +2648 -0
- package/types/meshmakers-octo-ui.d.ts +197 -4
- package/lib/runtime-browser/styles/_lcars-button.scss +0 -57
- package/lib/runtime-browser/styles/_lcars-flat-btn.scss +0 -11
- package/lib/runtime-browser/styles/_lcars-input.scss +0 -13
|
@@ -0,0 +1,2648 @@
|
|
|
1
|
+
import * as Types from '@meshmakers/octo-services';
|
|
2
|
+
import { SecretState, SecretStatusLabels } from '@meshmakers/octo-services';
|
|
3
|
+
import * as _angular_core from '@angular/core';
|
|
4
|
+
import { EnvironmentProviders, InjectionToken, TemplateRef, Signal } from '@angular/core';
|
|
5
|
+
import * as _progress_kendo_svg_icons from '@progress/kendo-svg-icons';
|
|
6
|
+
import { SVGIcon } from '@progress/kendo-svg-icons';
|
|
7
|
+
import { FormGroup, FormControl, ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
|
8
|
+
import { Observable } from 'rxjs';
|
|
9
|
+
import { EntitySelectDataSource, EntitySelectResult, CommandItem } from '@meshmakers/shared-services';
|
|
10
|
+
import { EntitySelectDialogDataSource, ColumnDefinition, DialogFetchOptions, DialogFetchResult, FetchDataOptions, FetchResultTyped, TableColumn, RowClassFn, HasUnsavedChanges, UnsavedChangesMessages, DangerConfirmationOptions, ConfirmationService } from '@meshmakers/shared-ui';
|
|
11
|
+
import * as Apollo from 'apollo-angular';
|
|
12
|
+
import { OctoGraphQlDataSource } from '@meshmakers/octo-ui';
|
|
13
|
+
import { Routes } from '@angular/router';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Contract types of the `@meshmakers/octo-ui/entity-forms` entry point (AB#5522).
|
|
17
|
+
*
|
|
18
|
+
* The `*Def` interfaces mirror the `System.UI/EntityForm` runtime entities as parsed from the
|
|
19
|
+
* generic runtime API. The `Resolved*` interfaces are the output of `resolveEntityForm()`: a
|
|
20
|
+
* form definition matched against the CK metadata of one concrete type, ready to render.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** Editor kinds a resolved field can use. */
|
|
24
|
+
type EntityFormEditor = 'text' | 'multiline' | 'password' | 'number' | 'toggle' | 'enum' | 'datetime' | 'url' | 'email' | 'json' | 'yaml' | 'cron' | 'chips' | 'reference' | 'records' | 'unsupported';
|
|
25
|
+
/** Read-only behaviour of a field. `afterCreate` means editable on create, read-only on edit. */
|
|
26
|
+
type ReadOnlyMode = 'never' | 'always' | 'afterCreate';
|
|
27
|
+
/** Mode a form is rendered in. */
|
|
28
|
+
type EntityFormMode = 'create' | 'edit' | 'view';
|
|
29
|
+
/** CK metadata of one attribute of a type or record. */
|
|
30
|
+
interface CkAttributeInfo {
|
|
31
|
+
/** camelCase, canonical attribute name as returned by the CK API. */
|
|
32
|
+
attributeName: string;
|
|
33
|
+
/** AttributeValueType (STRING, INT, INTEGER_64, RECORD_ARRAY, ...). */
|
|
34
|
+
valueType: string;
|
|
35
|
+
isOptional: boolean;
|
|
36
|
+
description?: string | null;
|
|
37
|
+
defaultValues: unknown[];
|
|
38
|
+
enumOptions?: {
|
|
39
|
+
key: number;
|
|
40
|
+
name: string;
|
|
41
|
+
}[];
|
|
42
|
+
/** Versioned record full name (usable with `records(ckId:)`). */
|
|
43
|
+
ckRecordId?: string | null;
|
|
44
|
+
/** True when the CK attribute metaData carries `secret = true`. */
|
|
45
|
+
secret: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The CK metaData `secret` marker as a tri-state (AB#5542): `true`, `false` (explicit opt-out of
|
|
48
|
+
* the credential-name rule) or `undefined` (no marker).
|
|
49
|
+
*/
|
|
50
|
+
metaSecret?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** One association role a type takes part in. */
|
|
53
|
+
interface CkAssociationRoleInfo {
|
|
54
|
+
rtRoleId: string;
|
|
55
|
+
navigationPropertyName: string;
|
|
56
|
+
direction: 'out' | 'in';
|
|
57
|
+
multiplicity: 'ONE' | 'ZERO_OR_ONE' | 'N';
|
|
58
|
+
otherRtCkTypeId: string;
|
|
59
|
+
}
|
|
60
|
+
/** CK metadata of one type. */
|
|
61
|
+
interface CkTypeInfo {
|
|
62
|
+
rtCkTypeId: string;
|
|
63
|
+
ckTypeIdFullName: string;
|
|
64
|
+
isAbstract: boolean;
|
|
65
|
+
/** Ancestor rtCkTypeIds, nearest first, ending with System/Entity; excludes the type itself. */
|
|
66
|
+
ancestors: string[];
|
|
67
|
+
/** Attributes in model order as returned (inherited ones included). */
|
|
68
|
+
attributes: CkAttributeInfo[];
|
|
69
|
+
associations: CkAssociationRoleInfo[];
|
|
70
|
+
}
|
|
71
|
+
/** CK metadata of one record. */
|
|
72
|
+
interface CkRecordInfo {
|
|
73
|
+
ckRecordId: string;
|
|
74
|
+
attributes: CkAttributeInfo[];
|
|
75
|
+
}
|
|
76
|
+
interface EntityFormSectionDef {
|
|
77
|
+
key: string;
|
|
78
|
+
title?: string | null;
|
|
79
|
+
description?: string | null;
|
|
80
|
+
order?: number | null;
|
|
81
|
+
collapsed?: boolean | null;
|
|
82
|
+
columns?: number | null;
|
|
83
|
+
}
|
|
84
|
+
interface EntityFormFieldDef {
|
|
85
|
+
attributePath: string;
|
|
86
|
+
sectionKey?: string | null;
|
|
87
|
+
order?: number | null;
|
|
88
|
+
label?: string | null;
|
|
89
|
+
help?: string | null;
|
|
90
|
+
placeholder?: string | null;
|
|
91
|
+
editor?: string | null;
|
|
92
|
+
readOnly?: string | null;
|
|
93
|
+
required?: boolean | null;
|
|
94
|
+
width?: string | null;
|
|
95
|
+
default?: string | null;
|
|
96
|
+
min?: number | null;
|
|
97
|
+
max?: number | null;
|
|
98
|
+
pattern?: string | null;
|
|
99
|
+
secret?: boolean | null;
|
|
100
|
+
visibleWhen?: string | null;
|
|
101
|
+
referenceCkTypeId?: string | null;
|
|
102
|
+
associationRoleId?: string | null;
|
|
103
|
+
recordColumns?: string[] | null;
|
|
104
|
+
hidden?: boolean | null;
|
|
105
|
+
/**
|
|
106
|
+
* `EntityFormField.ReferenceDisplayAttributes` (System.UI 2.8.0; host fallback forms may set it
|
|
107
|
+
* too): non-secret attributes of the reference target shown next to its name in the picker, e.g.
|
|
108
|
+
* `['repositoryUrl', 'channel']`. Read with an explicit `attributeNames` list of exactly these
|
|
109
|
+
* names (AB#5547).
|
|
110
|
+
*/
|
|
111
|
+
referenceDisplayAttributes?: string[] | null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* One entry of the default list order (AB#5623). Not part of the `System.UI/EntityForm` CK type:
|
|
115
|
+
* set it in host fallback forms (`provideEntityFormFallbacks`) or pass `defaultSort` to the list.
|
|
116
|
+
*/
|
|
117
|
+
interface EntityFormSortDef {
|
|
118
|
+
/** Attribute path (any casing) or system property (`rtChangedDateTime`, `rtWellKnownName`, ...). */
|
|
119
|
+
attributePath: string;
|
|
120
|
+
/** Default `'asc'`. */
|
|
121
|
+
direction?: 'asc' | 'desc' | null;
|
|
122
|
+
}
|
|
123
|
+
interface EntityFormColumnDef {
|
|
124
|
+
attributePath: string;
|
|
125
|
+
label?: string | null;
|
|
126
|
+
width?: number | null;
|
|
127
|
+
display?: string | null;
|
|
128
|
+
}
|
|
129
|
+
/** A parsed `System.UI/EntityForm` entity. */
|
|
130
|
+
interface EntityFormDefinition {
|
|
131
|
+
rtId: string;
|
|
132
|
+
rtWellKnownName?: string | null;
|
|
133
|
+
/** True when `rtBlueprintSource` is empty or null (the form was authored in the tenant). */
|
|
134
|
+
isTenantForm: boolean;
|
|
135
|
+
targetCkTypeId: string;
|
|
136
|
+
includeDerivedTypes: boolean;
|
|
137
|
+
priority: number;
|
|
138
|
+
name?: string | null;
|
|
139
|
+
description?: string | null;
|
|
140
|
+
category?: string | null;
|
|
141
|
+
icon?: string | null;
|
|
142
|
+
canCreate?: boolean | null;
|
|
143
|
+
canEdit?: boolean | null;
|
|
144
|
+
canDelete?: boolean | null;
|
|
145
|
+
canDuplicate?: boolean | null;
|
|
146
|
+
canExport?: boolean | null;
|
|
147
|
+
singleton?: boolean | null;
|
|
148
|
+
singletonWellKnownName?: string | null;
|
|
149
|
+
customComponent?: string | null;
|
|
150
|
+
generateRemainingFields?: boolean | null;
|
|
151
|
+
generatedSectionTitle?: string | null;
|
|
152
|
+
sections: EntityFormSectionDef[];
|
|
153
|
+
fields: EntityFormFieldDef[];
|
|
154
|
+
listColumns: EntityFormColumnDef[];
|
|
155
|
+
/**
|
|
156
|
+
* Initial order of the list (AB#5623; host fallback forms only, the CK type has no such
|
|
157
|
+
* attribute). The user can still sort by any column; without a user sort this order applies.
|
|
158
|
+
*/
|
|
159
|
+
listDefaultSort?: EntityFormSortDef[] | null;
|
|
160
|
+
}
|
|
161
|
+
/** A parsed `VisibleWhen` expression: `Path=value` or `Path=*` (any value). */
|
|
162
|
+
interface VisibleWhenRule {
|
|
163
|
+
/** Form control key of the source field (canonical). */
|
|
164
|
+
path: string;
|
|
165
|
+
value: string | '*';
|
|
166
|
+
}
|
|
167
|
+
interface ResolvedField {
|
|
168
|
+
/** Form control name: attributeName | 'rtWellKnownName' | 'assoc:<rtRoleId with . → _>' (`associationFieldKey`). */
|
|
169
|
+
key: string;
|
|
170
|
+
kind: 'attribute' | 'system' | 'association';
|
|
171
|
+
attributeName?: string;
|
|
172
|
+
valueType?: string;
|
|
173
|
+
label: string;
|
|
174
|
+
help?: string;
|
|
175
|
+
placeholder?: string;
|
|
176
|
+
editor: EntityFormEditor;
|
|
177
|
+
required: boolean;
|
|
178
|
+
readOnly: ReadOnlyMode;
|
|
179
|
+
width: 'full' | 'half';
|
|
180
|
+
order: number;
|
|
181
|
+
/** Already parsed to the form value shape. Applied in create mode only. */
|
|
182
|
+
defaultValue?: unknown;
|
|
183
|
+
min?: number;
|
|
184
|
+
max?: number;
|
|
185
|
+
pattern?: string;
|
|
186
|
+
secret: boolean;
|
|
187
|
+
visibleWhen?: VisibleWhenRule;
|
|
188
|
+
enumOptions?: {
|
|
189
|
+
key: number;
|
|
190
|
+
name: string;
|
|
191
|
+
}[];
|
|
192
|
+
record?: {
|
|
193
|
+
ckRecordId: string;
|
|
194
|
+
single: boolean;
|
|
195
|
+
columns: {
|
|
196
|
+
path: string;
|
|
197
|
+
label: string;
|
|
198
|
+
}[];
|
|
199
|
+
};
|
|
200
|
+
/** `role` absent means the attribute itself holds the target rtId. */
|
|
201
|
+
reference?: {
|
|
202
|
+
targetCkTypeId: string;
|
|
203
|
+
role?: CkAssociationRoleInfo;
|
|
204
|
+
multiple: boolean;
|
|
205
|
+
displayAttributes?: string[];
|
|
206
|
+
/**
|
|
207
|
+
* CK metadata of the display attributes on the target type (set by `EntityFormService.resolve`),
|
|
208
|
+
* used to format their values (enum names, yes/no, dates). Missing when the target type could not
|
|
209
|
+
* be read; the raw values are shown then.
|
|
210
|
+
*/
|
|
211
|
+
displayAttributeInfo?: CkAttributeInfo[];
|
|
212
|
+
};
|
|
213
|
+
generated: boolean;
|
|
214
|
+
}
|
|
215
|
+
interface ResolvedSection {
|
|
216
|
+
key: string;
|
|
217
|
+
title: string | null;
|
|
218
|
+
description?: string;
|
|
219
|
+
columns: 1 | 2;
|
|
220
|
+
collapsed: boolean;
|
|
221
|
+
generated: boolean;
|
|
222
|
+
fields: ResolvedField[];
|
|
223
|
+
}
|
|
224
|
+
interface ResolvedListColumn {
|
|
225
|
+
field: string;
|
|
226
|
+
label: string;
|
|
227
|
+
width?: number;
|
|
228
|
+
/**
|
|
229
|
+
* Cell rendering. `icon` (AB#5623) shows a BOOLEAN column as a check / x icon with an accessible
|
|
230
|
+
* name (other value types render as `text`).
|
|
231
|
+
*/
|
|
232
|
+
display: 'text' | 'chip' | 'date' | 'mono' | 'icon';
|
|
233
|
+
kind: 'attribute' | 'system';
|
|
234
|
+
/**
|
|
235
|
+
* CK value type of an attribute column (ENUM, BOOLEAN, DATE_TIME, ...). The list formats the
|
|
236
|
+
* cells by it like the reference display does: enum key → name, boolean → yes/no (AB#5547).
|
|
237
|
+
*/
|
|
238
|
+
valueType?: string;
|
|
239
|
+
/** Options of an ENUM column (the API returns the key, e.g. `0`). */
|
|
240
|
+
enumOptions?: {
|
|
241
|
+
key: number;
|
|
242
|
+
name: string;
|
|
243
|
+
}[];
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Sort order of `mm-entity-list` (AB#5623). Same shape as a Kendo `SortDescriptor`; `field` is the
|
|
247
|
+
* list row field = GraphQL attribute path (camelCase attribute name or system property).
|
|
248
|
+
*/
|
|
249
|
+
interface EntityListSortDescriptor {
|
|
250
|
+
field: string;
|
|
251
|
+
dir: 'asc' | 'desc';
|
|
252
|
+
}
|
|
253
|
+
interface ResolvedEntityForm {
|
|
254
|
+
source: 'tenant' | 'seeded' | 'builtIn';
|
|
255
|
+
formRtId?: string;
|
|
256
|
+
formWellKnownName?: string;
|
|
257
|
+
rtCkTypeId: string;
|
|
258
|
+
formTargetCkTypeId: string;
|
|
259
|
+
isAbstract: boolean;
|
|
260
|
+
includeDerivedTypes: boolean;
|
|
261
|
+
title: string;
|
|
262
|
+
description?: string;
|
|
263
|
+
category?: string;
|
|
264
|
+
icon?: string;
|
|
265
|
+
customComponent?: string;
|
|
266
|
+
capabilities: {
|
|
267
|
+
canCreate: boolean;
|
|
268
|
+
canEdit: boolean;
|
|
269
|
+
canDelete: boolean;
|
|
270
|
+
canDuplicate: boolean;
|
|
271
|
+
canExport: boolean;
|
|
272
|
+
createRequiresSubtype: boolean;
|
|
273
|
+
};
|
|
274
|
+
singleton?: {
|
|
275
|
+
wellKnownName?: string;
|
|
276
|
+
};
|
|
277
|
+
sections: ResolvedSection[];
|
|
278
|
+
listColumns: ResolvedListColumn[];
|
|
279
|
+
/**
|
|
280
|
+
* Initial list order from the form definition (`listDefaultSort`, canonicalised; secret
|
|
281
|
+
* attributes dropped). Absent = server order (today's behaviour).
|
|
282
|
+
*/
|
|
283
|
+
listDefaultSort?: EntityListSortDescriptor[];
|
|
284
|
+
/**
|
|
285
|
+
* Attribute names to read (non-secret fields plus record sub-attribute names, plus the SECRET
|
|
286
|
+
* fields of {@link secretStateFields}, whose value the server never returns).
|
|
287
|
+
*/
|
|
288
|
+
readAttributeNames: string[];
|
|
289
|
+
/** attributeNames of all secret fields (never prefilled, never listed). */
|
|
290
|
+
secretFields: string[];
|
|
291
|
+
/**
|
|
292
|
+
* The secret fields of value type SECRET (AB#5528): their state is read with the values
|
|
293
|
+
* (`secretIsSet`, later `secretKeyMissing` / `secretSetAt`) and they can be cleared explicitly
|
|
294
|
+
* (`clearSecretAttributes`). The other secret fields (credential-name / metadata fallback) are
|
|
295
|
+
* probed for presence with a field filter and cannot be cleared.
|
|
296
|
+
*/
|
|
297
|
+
secretStateFields?: string[];
|
|
298
|
+
warnings: string[];
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* State of one secret field (AB#5528): the shared octo-services {@link SecretState}
|
|
302
|
+
* (`keyMissing` implies `isSet: false`). Kept as an alias for existing imports.
|
|
303
|
+
*/
|
|
304
|
+
type EntityFormSecretFieldState = SecretState;
|
|
305
|
+
interface EntityFormValueState {
|
|
306
|
+
values: Record<string, unknown>;
|
|
307
|
+
/** Per secret attributeName: set, or stored but unreadable (counts as present for "required"). */
|
|
308
|
+
secretPresence: Record<string, boolean>;
|
|
309
|
+
/** Per SECRET attributeName: the full state (badge "Set · set at …" / "Key missing — re-enter"). */
|
|
310
|
+
secretStates?: Record<string, EntityFormSecretFieldState>;
|
|
311
|
+
associations: Record<string, {
|
|
312
|
+
rtId: string;
|
|
313
|
+
ckTypeId: string;
|
|
314
|
+
displayName: string;
|
|
315
|
+
}[]>;
|
|
316
|
+
rtWellKnownName?: string | null;
|
|
317
|
+
}
|
|
318
|
+
interface EntityFormChangeSet {
|
|
319
|
+
rtWellKnownName?: string;
|
|
320
|
+
attributes: {
|
|
321
|
+
attributeName: string;
|
|
322
|
+
value: unknown;
|
|
323
|
+
}[];
|
|
324
|
+
/** camelCase names of optional SECRET attributes to clear on save (edit mode only, Q8). */
|
|
325
|
+
clearSecretAttributes?: string[];
|
|
326
|
+
associations: {
|
|
327
|
+
roleName: string;
|
|
328
|
+
targets: {
|
|
329
|
+
modOption: 'CREATE' | 'DELETE';
|
|
330
|
+
target: {
|
|
331
|
+
ckTypeId: string;
|
|
332
|
+
rtId: string;
|
|
333
|
+
};
|
|
334
|
+
}[];
|
|
335
|
+
}[];
|
|
336
|
+
isEmpty: boolean;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* UI strings of the entity form components (`mm-entity-form`, `mm-entity-list`,
|
|
341
|
+
* `mm-entity-page` and their field editors).
|
|
342
|
+
*
|
|
343
|
+
* Hosts pass a `Partial<EntityFormsMessages>` through the `messages` input; missing keys fall
|
|
344
|
+
* back to {@link DEFAULT_ENTITY_FORMS_MESSAGES}. Strings containing `{name}` placeholders are
|
|
345
|
+
* filled with {@link formatEntityFormsMessage}.
|
|
346
|
+
*/
|
|
347
|
+
interface EntityFormsMessages {
|
|
348
|
+
save: string;
|
|
349
|
+
cancel: string;
|
|
350
|
+
delete: string;
|
|
351
|
+
new: string;
|
|
352
|
+
edit: string;
|
|
353
|
+
duplicate: string;
|
|
354
|
+
export: string;
|
|
355
|
+
close: string;
|
|
356
|
+
apply: string;
|
|
357
|
+
refresh: string;
|
|
358
|
+
back: string;
|
|
359
|
+
add: string;
|
|
360
|
+
remove: string;
|
|
361
|
+
moveUp: string;
|
|
362
|
+
moveDown: string;
|
|
363
|
+
select: string;
|
|
364
|
+
clear: string;
|
|
365
|
+
/** Placeholder of a secret field whose value is set on the server. */
|
|
366
|
+
secretSetPlaceholder: string;
|
|
367
|
+
/** Placeholder of a secret field without a value on the server. */
|
|
368
|
+
secretNotSetPlaceholder: string;
|
|
369
|
+
/** Badge next to a secret field label. */
|
|
370
|
+
secretBadge: string;
|
|
371
|
+
/** Help text explaining write-only secrets. */
|
|
372
|
+
secretHelp: string;
|
|
373
|
+
/** Badge of a set secret without a timestamp (legacy value). */
|
|
374
|
+
secretStatusSet: string;
|
|
375
|
+
/** Badge of a set secret; `{setAt}` = formatted timestamp. */
|
|
376
|
+
secretStatusSetAt: string;
|
|
377
|
+
/** Badge of a secret without a value. */
|
|
378
|
+
secretStatusNotSet: string;
|
|
379
|
+
/** Badge of a stored secret whose key is not in this environment's key ring (re-entry needed). */
|
|
380
|
+
secretStatusKeyMissing: string;
|
|
381
|
+
/** Badge of a required SECRET without a value (same wording as the secrets inventory). */
|
|
382
|
+
secretStatusNeedsReEntry: string;
|
|
383
|
+
/** Badge of a secret whose clear is staged for the next save. */
|
|
384
|
+
secretStatusClearStaged: string;
|
|
385
|
+
/** Button: stage clearing an optional secret. */
|
|
386
|
+
secretClear: string;
|
|
387
|
+
/** Button: undo a staged clear. */
|
|
388
|
+
secretUndoClear: string;
|
|
389
|
+
/** Note shown while a clear is staged. */
|
|
390
|
+
secretClearStagedNote: string;
|
|
391
|
+
/** Button: reveal the typed (unsaved) value. */
|
|
392
|
+
secretShow: string;
|
|
393
|
+
/** Button: mask the typed value again. */
|
|
394
|
+
secretHide: string;
|
|
395
|
+
/** Hint when secrets cannot be written (no key ring configured, Q17). */
|
|
396
|
+
secretWritesDisabled: string;
|
|
397
|
+
/**
|
|
398
|
+
* Why Create is blocked: a required secret cannot be entered without a key ring (Q17).
|
|
399
|
+
* `{fields}` = the field labels.
|
|
400
|
+
*/
|
|
401
|
+
secretRequiredWritesDisabled: string;
|
|
402
|
+
/** Status line of a masked multiline secret (PEM); `{lines}` = number of typed lines. */
|
|
403
|
+
secretMultilineMasked: string;
|
|
404
|
+
/** Placeholder of a SECRET record member whose stored value is kept when left empty. */
|
|
405
|
+
secretRecordMemberKeep: string;
|
|
406
|
+
/** Grid cell of a SECRET record member with a typed, unsaved value (never the value itself). */
|
|
407
|
+
secretRecordMemberNewValue: string;
|
|
408
|
+
/** Default title of the section holding fields that the form does not list. */
|
|
409
|
+
furtherAttributes: string;
|
|
410
|
+
/** @deprecated Deletes use the danger confirmation keys below (AB#5579); no longer shown. */
|
|
411
|
+
confirmDeleteTitle: string;
|
|
412
|
+
/** `{name}` = display name of the entity. @deprecated No longer shown (AB#5579). */
|
|
413
|
+
confirmDeleteMessage: string;
|
|
414
|
+
/** `{count}` = number of entities. @deprecated No longer shown (AB#5579). */
|
|
415
|
+
confirmDeleteManyMessage: string;
|
|
416
|
+
/**
|
|
417
|
+
* Danger confirmation (AB#5579): title naming the entity, `{name}` = display name.
|
|
418
|
+
* Optional for hosts that pass a complete message set; missing = English default.
|
|
419
|
+
*/
|
|
420
|
+
confirmDeleteNamedTitle?: string;
|
|
421
|
+
/** Danger confirmation title of a multi-delete; `{count}` = number of entities. */
|
|
422
|
+
confirmDeleteManyTitle?: string;
|
|
423
|
+
/** Target shown in a multi-delete confirmation; `{count}` = number of entities. */
|
|
424
|
+
confirmDeleteManyTarget?: string;
|
|
425
|
+
/** What a single delete loses. */
|
|
426
|
+
confirmDeleteConsequence?: string;
|
|
427
|
+
/** What a multi-delete loses; `{count}` = number of entities. */
|
|
428
|
+
confirmDeleteManyConsequence?: string;
|
|
429
|
+
/** Confirming button of a single delete (verb + object). */
|
|
430
|
+
confirmDeleteConfirmText?: string;
|
|
431
|
+
/** Confirming button of a multi-delete (verb + object). */
|
|
432
|
+
confirmDeleteManyConfirmText?: string;
|
|
433
|
+
/** Row name in the accessible names of the records editor's row buttons; `{index}` = 1-based row. */
|
|
434
|
+
recordRowLabel?: string;
|
|
435
|
+
unsavedChangesTitle: string;
|
|
436
|
+
unsavedChangesMessage: string;
|
|
437
|
+
discardChanges: string;
|
|
438
|
+
keepEditing: string;
|
|
439
|
+
saveSuccess: string;
|
|
440
|
+
saveError: string;
|
|
441
|
+
createSuccess: string;
|
|
442
|
+
deleteSuccess: string;
|
|
443
|
+
deleteError: string;
|
|
444
|
+
loadError: string;
|
|
445
|
+
noChanges: string;
|
|
446
|
+
/**
|
|
447
|
+
* Warning when a host `beforeSave` hook vetoed the save without a message of its own (AB#5623).
|
|
448
|
+
* Optional so that complete message objects of older hosts keep compiling.
|
|
449
|
+
*/
|
|
450
|
+
saveVetoed?: string;
|
|
451
|
+
/**
|
|
452
|
+
* List cell and form field hint of a non-secret value that holds a host-listed placeholder
|
|
453
|
+
* (`ENTITY_FORM_UNSET_PLACEHOLDER_VALUES`, AB#5623). Optional for older complete message objects.
|
|
454
|
+
*/
|
|
455
|
+
notConfigured?: string;
|
|
456
|
+
emptyList: string;
|
|
457
|
+
emptyRecords: string;
|
|
458
|
+
emptyReferences: string;
|
|
459
|
+
entityNotFound: string;
|
|
460
|
+
formNotFound: string;
|
|
461
|
+
noFieldsToShow: string;
|
|
462
|
+
loading: string;
|
|
463
|
+
validationRequired: string;
|
|
464
|
+
/** `{min}` = minimum value. */
|
|
465
|
+
validationMin: string;
|
|
466
|
+
/** `{max}` = maximum value. */
|
|
467
|
+
validationMax: string;
|
|
468
|
+
/** `{pattern}` = regular expression. */
|
|
469
|
+
validationPattern: string;
|
|
470
|
+
validationEmail: string;
|
|
471
|
+
validationUrl: string;
|
|
472
|
+
validationJson: string;
|
|
473
|
+
validationNumber: string;
|
|
474
|
+
/** `{max}` = maximum number of selected entities. */
|
|
475
|
+
validationMaxItems: string;
|
|
476
|
+
formInvalid: string;
|
|
477
|
+
unsupportedEditor: string;
|
|
478
|
+
chipsPlaceholder: string;
|
|
479
|
+
referencePlaceholder: string;
|
|
480
|
+
enumPlaceholder: string;
|
|
481
|
+
toggleOn: string;
|
|
482
|
+
toggleOff: string;
|
|
483
|
+
/** Warning on a record field that cannot be saved safely (sub-attribute name collides with a secret). */
|
|
484
|
+
recordReadOnlyWarning: string;
|
|
485
|
+
nestedRecordReadOnly: string;
|
|
486
|
+
recordRowDialogTitleAdd: string;
|
|
487
|
+
recordRowDialogTitleEdit: string;
|
|
488
|
+
columnWellKnownName: string;
|
|
489
|
+
columnName: string;
|
|
490
|
+
columnChanged: string;
|
|
491
|
+
columnCreated: string;
|
|
492
|
+
columnType: string;
|
|
493
|
+
columnActions: string;
|
|
494
|
+
copyId: string;
|
|
495
|
+
copyRtId: string;
|
|
496
|
+
copyCkTypeId: string;
|
|
497
|
+
copyRtCkTypeId: string;
|
|
498
|
+
copyRtEntityId: string;
|
|
499
|
+
/** @deprecated No longer shown (AB#5623): both copy actions use {@link copiedId}. */
|
|
500
|
+
copied: string;
|
|
501
|
+
/** Tooltip of the Copy ID button in the form header (AB#5623). */
|
|
502
|
+
copyIdTooltip: string;
|
|
503
|
+
/** Notification after copying one ID (list menu and form header); `{label}` = RtId, CkTypeId, ... (AB#5623). */
|
|
504
|
+
copiedId: string;
|
|
505
|
+
/** Notification when the clipboard is not available (AB#5623). */
|
|
506
|
+
copyFailed: string;
|
|
507
|
+
searchPlaceholder: string;
|
|
508
|
+
/** Header of the optional Type column of the list. */
|
|
509
|
+
typeColumn: string;
|
|
510
|
+
selectSubtypeTitle: string;
|
|
511
|
+
createTitle: string;
|
|
512
|
+
/** `{name}` = display name of the entity. */
|
|
513
|
+
editTitle: string;
|
|
514
|
+
viewTitle: string;
|
|
515
|
+
readOnlyNotice: string;
|
|
516
|
+
singletonCreateHint: string;
|
|
517
|
+
}
|
|
518
|
+
/** English defaults; hosts may override any key via the `messages` input. */
|
|
519
|
+
declare const DEFAULT_ENTITY_FORMS_MESSAGES: EntityFormsMessages;
|
|
520
|
+
/** Replaces `{key}` placeholders in a message with the given values. */
|
|
521
|
+
declare function formatEntityFormsMessage(message: string, values: Record<string, string | number>): string;
|
|
522
|
+
/** Merges host overrides over the English defaults. */
|
|
523
|
+
declare function mergeEntityFormsMessages(overrides?: Partial<EntityFormsMessages> | null): EntityFormsMessages;
|
|
524
|
+
/** The secret status labels of a message set, for octo-services `formatSecretStatus`. */
|
|
525
|
+
declare function secretStatusLabelsOf(messages: EntityFormsMessages): SecretStatusLabels;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Loads entity forms and CK metadata and resolves the form for a type (plan §2.3).
|
|
529
|
+
*
|
|
530
|
+
* - Forms are read only after the type probe confirms `System.UI/EntityForm` exists (System.UI >=
|
|
531
|
+
* 2.7.0); otherwise, and when the forms query fails, every type resolves to the built-in form.
|
|
532
|
+
* - Results are cached per tenant (`TENANT_ID_PROVIDER`, empty string when not provided) in a
|
|
533
|
+
* `Map<string, Promise<…>>`; a failed entry is evicted so the next call retries.
|
|
534
|
+
* - Host fallback forms (`ENTITY_FORM_FALLBACK_FORMS`, `registerFallbackForms`) are appended where
|
|
535
|
+
* the normal resolution would end at `form-default` — also when the forms cannot be loaded
|
|
536
|
+
* (AB#5524).
|
|
537
|
+
* - Resolver warnings are logged with `console.warn`.
|
|
538
|
+
*/
|
|
539
|
+
declare class EntityFormService {
|
|
540
|
+
private readonly probeGql;
|
|
541
|
+
private readonly formsGql;
|
|
542
|
+
private readonly ckTypeGql;
|
|
543
|
+
private readonly ckRecordGql;
|
|
544
|
+
private readonly tenantIdProvider;
|
|
545
|
+
private readonly fallbackForms;
|
|
546
|
+
private readonly cache;
|
|
547
|
+
private readonly registeredFallbacks;
|
|
548
|
+
/**
|
|
549
|
+
* Adds host fallback forms at runtime (see `provideEntityFormFallbacks`). Registering the same
|
|
550
|
+
* array again is a no-op; a new one drops the cached forms and resolutions.
|
|
551
|
+
*/
|
|
552
|
+
registerFallbackForms(forms: readonly EntityFormDefinition[]): void;
|
|
553
|
+
/** Drops every cached form, type, record and resolution (all tenants). */
|
|
554
|
+
invalidate(): void;
|
|
555
|
+
/**
|
|
556
|
+
* All parsed `System.UI/EntityForm` definitions of the current tenant (`[]` when not installed),
|
|
557
|
+
* plus the host fallback forms for target types without a loaded form.
|
|
558
|
+
*/
|
|
559
|
+
getForms(): Promise<EntityFormDefinition[]>;
|
|
560
|
+
private loadForms;
|
|
561
|
+
/** CK metadata of a type, or `null` when the type does not exist. */
|
|
562
|
+
getCkType(rtCkTypeId: string): Promise<CkTypeInfo | null>;
|
|
563
|
+
/** CK metadata of a record (versioned ckRecordId, e.g. `System.UI-2.7.0/EntityFormSection-1`). */
|
|
564
|
+
getCkRecord(ckRecordId: string): Promise<CkRecordInfo | null>;
|
|
565
|
+
/**
|
|
566
|
+
* Loads every record reachable from the given attributes (recursively), keyed by ckRecordId.
|
|
567
|
+
* Records that cannot be loaded are left out.
|
|
568
|
+
*/
|
|
569
|
+
getRecordsFor(type: CkTypeInfo): Promise<Record<string, CkRecordInfo>>;
|
|
570
|
+
/**
|
|
571
|
+
* Resolves the form for a type. Rejects when the CK type does not exist; falls back to the
|
|
572
|
+
* built-in form when no form applies or the forms cannot be loaded.
|
|
573
|
+
*/
|
|
574
|
+
resolve(rtCkTypeId: string): Promise<ResolvedEntityForm>;
|
|
575
|
+
/**
|
|
576
|
+
* Adds the target type's CK metadata of the display attributes to every reference field that
|
|
577
|
+
* has `displayAttributes` (AB#5547: the channel enum showed its key `0` instead of "Release").
|
|
578
|
+
* A display attribute marked secret on the target is dropped (it must never be read).
|
|
579
|
+
*/
|
|
580
|
+
private attachDisplayAttributeInfo;
|
|
581
|
+
/**
|
|
582
|
+
* Resolves by form key: the form's `rtWellKnownName` (`form-sftp-configuration`) or the kebab
|
|
583
|
+
* type key (`sftp-configuration`, matched against `form-<key>` and then against the kebab-cased
|
|
584
|
+
* name of each form's target type). The type's form is then resolved normally, so a tenant form
|
|
585
|
+
* for the same type still wins. Returns `null` when no form matches the key.
|
|
586
|
+
*/
|
|
587
|
+
resolveByFormKey(formKey: string): Promise<ResolvedEntityForm | null>;
|
|
588
|
+
private tenantId;
|
|
589
|
+
private cached;
|
|
590
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormService, never>;
|
|
591
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EntityFormService>;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Registers host fallback forms in the root `EntityFormService` when the providing (lazy) route's
|
|
595
|
+
* environment injector is created — one service, one cache, and the entry point stays out of the
|
|
596
|
+
* initial bundle (AB#5524). Put it into the `providers` of every lazy route that renders entity
|
|
597
|
+
* forms; registering the same array several times is harmless.
|
|
598
|
+
*/
|
|
599
|
+
declare function provideEntityFormFallbacks(forms: readonly EntityFormDefinition[]): EnvironmentProviders;
|
|
600
|
+
|
|
601
|
+
/** How to find the entity to load. `ckTypeId` defaults to the form's type (derived types match). */
|
|
602
|
+
type EntityFormLoadKey = {
|
|
603
|
+
rtId: string;
|
|
604
|
+
ckTypeId?: string;
|
|
605
|
+
} | {
|
|
606
|
+
wellKnownName: string;
|
|
607
|
+
ckTypeId?: string;
|
|
608
|
+
};
|
|
609
|
+
/** Result of {@link EntityFormDataService.load}. */
|
|
610
|
+
interface EntityFormLoadResult {
|
|
611
|
+
rtId: string;
|
|
612
|
+
ckTypeId: string;
|
|
613
|
+
rtDisplayName?: string | null;
|
|
614
|
+
state: EntityFormValueState;
|
|
615
|
+
}
|
|
616
|
+
/** One selected reference / association target as held by a reference control. */
|
|
617
|
+
interface EntityFormTargetRef {
|
|
618
|
+
rtId: string;
|
|
619
|
+
ckTypeId: string;
|
|
620
|
+
displayName: string;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Reads and writes entity values for the entity form (plan §2.3, rules D5/D6).
|
|
624
|
+
*
|
|
625
|
+
* SECURITY: values are read with an explicit `attributeNames` list (`model.readAttributeNames`
|
|
626
|
+
* minus every secret, never omitted — omission returns every attribute). SECRET attributes
|
|
627
|
+
* (AB#5528, `model.secretStateFields`) are listed too: the server returns `value: null` and
|
|
628
|
+
* `secretIsSet`. Fallback secrets (credential name / metadata on non-SECRET attributes) are only
|
|
629
|
+
* probed for presence (`IS_NOT_NULL` + `totalCount`). Mutations never select attributes; an
|
|
630
|
+
* explicit clear goes through `clearSecretAttributes`.
|
|
631
|
+
*/
|
|
632
|
+
declare class EntityFormDataService {
|
|
633
|
+
private readonly valuesGql;
|
|
634
|
+
private readonly presenceGql;
|
|
635
|
+
private readonly targetsGql;
|
|
636
|
+
private readonly definitionsGql;
|
|
637
|
+
private readonly referenceOptionsGql;
|
|
638
|
+
private readonly createGql;
|
|
639
|
+
private readonly updateGql;
|
|
640
|
+
private readonly deleteGql;
|
|
641
|
+
private readonly listGql;
|
|
642
|
+
private readonly countGql;
|
|
643
|
+
private readonly formService;
|
|
644
|
+
private readonly secretPlaceholders;
|
|
645
|
+
/**
|
|
646
|
+
* The attribute names to read for a model: `readAttributeNames` with every secret removed except
|
|
647
|
+
* the SECRET fields (`secretStateFields`, read for their state only). Always an array (an omitted
|
|
648
|
+
* list would return secrets).
|
|
649
|
+
*/
|
|
650
|
+
static readAttributeNamesFor(model: ResolvedEntityForm): string[];
|
|
651
|
+
/**
|
|
652
|
+
* Number of entities of a type (e.g. for a settings overview). Without `includeDerivedTypes`
|
|
653
|
+
* only entities of exactly that type are counted (`runtimeEntities(ckId)` includes derived
|
|
654
|
+
* types by default). Selects only `totalCount` — no items, so no attributes are resolved
|
|
655
|
+
* (with `attributes(attributeNames: [])` per item the count failed with CK_CACHE whenever one
|
|
656
|
+
* item's type could not be resolved, AB#5523). Errors reject the promise without a toast.
|
|
657
|
+
*/
|
|
658
|
+
count(ckTypeId: string, includeDerivedTypes?: boolean): Promise<number>;
|
|
659
|
+
/** Loads values, secret presence and associations of one entity in parallel; `null` if not found. */
|
|
660
|
+
load(model: ResolvedEntityForm, key: EntityFormLoadKey): Promise<EntityFormLoadResult | null>;
|
|
661
|
+
/** Creates an entity; returns its rtId. */
|
|
662
|
+
create(model: ResolvedEntityForm, ckTypeId: string, changeSet: EntityFormChangeSet): Promise<string>;
|
|
663
|
+
/**
|
|
664
|
+
* Updates an entity with exactly the change set (partial update: attributes that are not sent
|
|
665
|
+
* keep their value — verified live, including the presence of secrets). `rtWellKnownName` is
|
|
666
|
+
* never changed on update. Staged secret clears are sent as `clearSecretAttributes` (Q8).
|
|
667
|
+
*/
|
|
668
|
+
update(rtId: string, ckTypeId: string, changeSet: EntityFormChangeSet): Promise<void>;
|
|
669
|
+
/** Deletes entities (default strategy ARCHIVE). */
|
|
670
|
+
delete(entities: {
|
|
671
|
+
rtId: string;
|
|
672
|
+
ckTypeId: string;
|
|
673
|
+
}[], strategy?: 'ARCHIVE' | 'ERASE'): Promise<boolean>;
|
|
674
|
+
private associationInputs;
|
|
675
|
+
private loadRecords;
|
|
676
|
+
/**
|
|
677
|
+
* "Set / not set" per secret: not null AND — for STRING secrets — not the empty string (an empty
|
|
678
|
+
* string is "no secret", AB#5524; same rule as the Studio's service account page) and none of the
|
|
679
|
+
* host's placeholder values (`ENTITY_FORM_SECRET_PLACEHOLDER_VALUES`, AB#5623). SECRET-typed
|
|
680
|
+
* attributes are not probed here: their state comes from the server.
|
|
681
|
+
*/
|
|
682
|
+
private loadSecretPresence;
|
|
683
|
+
private loadAssociations;
|
|
684
|
+
private loadAssociationTargets;
|
|
685
|
+
/** Display names for ids, grouped by type; selects only the `name` attribute (secret-safe). */
|
|
686
|
+
private lookupDisplayNames;
|
|
687
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormDataService, never>;
|
|
688
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EntityFormDataService>;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* What a label belongs to (AB#5623):
|
|
693
|
+
* - `formTitle` / `formDescription` — the form's name and description (`key` = the form key, else
|
|
694
|
+
* the runtime CK type id);
|
|
695
|
+
* - `section` / `sectionDescription` — a section title / description (`key` = section key);
|
|
696
|
+
* - `field` / `help` / `placeholder` — a field's label, help text and placeholder
|
|
697
|
+
* (`key` = the field key: camelCase attribute name, `rtWellKnownName` or `assoc:<role>`);
|
|
698
|
+
* - `listColumn` — a list column title (`key` = the column field);
|
|
699
|
+
* - `recordColumn` — a column of a record grid (`key` = the record sub-attribute path,
|
|
700
|
+
* `attributeName` = the record attribute);
|
|
701
|
+
* - `enumOption` — the display text of an enum value (`key` = the enum value name, `enumKey` = its
|
|
702
|
+
* numeric key, `attributeName` = the ENUM attribute).
|
|
703
|
+
*/
|
|
704
|
+
type EntityFormLabelKind = 'formTitle' | 'formDescription' | 'section' | 'sectionDescription' | 'field' | 'help' | 'placeholder' | 'listColumn' | 'recordColumn' | 'enumOption';
|
|
705
|
+
/** One label lookup of {@link EntityFormLabelResolver}. */
|
|
706
|
+
interface EntityFormLabelRequest {
|
|
707
|
+
kind: EntityFormLabelKind;
|
|
708
|
+
/**
|
|
709
|
+
* Runtime CK type the label belongs to (`Basic.Accounting/BankAccount`). For enum options of a
|
|
710
|
+
* reference display attribute this is the reference target type.
|
|
711
|
+
*/
|
|
712
|
+
rtCkTypeId: string;
|
|
713
|
+
/** Well-known name (else rtId) of the form definition, when the form came from one. */
|
|
714
|
+
formKey?: string;
|
|
715
|
+
/** See {@link EntityFormLabelKind}. */
|
|
716
|
+
key: string;
|
|
717
|
+
/** The attribute an `enumOption` / `recordColumn` belongs to (camelCase). */
|
|
718
|
+
attributeName?: string;
|
|
719
|
+
/** Numeric key of an `enumOption`. */
|
|
720
|
+
enumKey?: number;
|
|
721
|
+
/** The text shown without a resolver (form definition text, else derived from the CK model). */
|
|
722
|
+
defaultText: string;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Host hook that translates the texts of an entity form (AB#5623): field labels, help texts,
|
|
726
|
+
* placeholders, section titles, form title, list column titles, record columns and enum option
|
|
727
|
+
* texts. Return `null`, `undefined` or `''` to keep {@link EntityFormLabelRequest.defaultText}.
|
|
728
|
+
*
|
|
729
|
+
* The resolver is called inside Angular `computed`s: when it reads a signal (e.g. the current
|
|
730
|
+
* language), the forms re-render on a change of that signal. A resolver that reads no signal is
|
|
731
|
+
* evaluated once per model; pass a new function to the `labelResolver` input to refresh it.
|
|
732
|
+
* A language change never rebuilds the form controls, so unsaved edits are kept.
|
|
733
|
+
*
|
|
734
|
+
* Fixed UI texts (buttons, notifications, validation messages) are translated with the `messages`
|
|
735
|
+
* input ({@link EntityFormsMessages}), not with this hook.
|
|
736
|
+
*/
|
|
737
|
+
type EntityFormLabelResolver = (request: EntityFormLabelRequest) => string | null | undefined;
|
|
738
|
+
/**
|
|
739
|
+
* App-wide {@link EntityFormLabelResolver} for `mm-entity-form`, `mm-entity-list` and
|
|
740
|
+
* `mm-entity-page`. Their `labelResolver` input wins over this token. Not provided = the texts of
|
|
741
|
+
* the form definition / CK model are shown unchanged (today's behaviour).
|
|
742
|
+
*/
|
|
743
|
+
declare const ENTITY_FORM_LABEL_RESOLVER: InjectionToken<EntityFormLabelResolver>;
|
|
744
|
+
/**
|
|
745
|
+
* Resolves one label; falls back to the default text when there is no resolver, no translation,
|
|
746
|
+
* or the resolver throws (logged once per resolver with `console.warn`).
|
|
747
|
+
*/
|
|
748
|
+
declare function resolveEntityFormLabel(resolver: EntityFormLabelResolver | null | undefined, request: EntityFormLabelRequest): string;
|
|
749
|
+
/** The list columns of a model with translated titles and enum texts (unchanged without a resolver). */
|
|
750
|
+
declare function localizeEntityListColumns(model: ResolvedEntityForm, resolver: EntityFormLabelResolver | null | undefined): ResolvedListColumn[];
|
|
751
|
+
/** Translated form title (unchanged without a resolver). */
|
|
752
|
+
declare function localizeEntityFormTitle(model: ResolvedEntityForm, resolver: EntityFormLabelResolver | null | undefined): string;
|
|
753
|
+
/**
|
|
754
|
+
* A copy of a resolved form with every display text passed through the resolver (AB#5623). Keys,
|
|
755
|
+
* attribute names and enum keys are unchanged, so form controls, change sets and queries are not
|
|
756
|
+
* affected. Returns the model itself when there is no resolver.
|
|
757
|
+
*/
|
|
758
|
+
declare function localizeEntityForm(model: ResolvedEntityForm, resolver: EntityFormLabelResolver | null | undefined): ResolvedEntityForm;
|
|
759
|
+
|
|
760
|
+
/** What a {@link EntityFormBeforeSaveHook} learns about the save besides the change set. */
|
|
761
|
+
interface EntityFormBeforeSaveContext {
|
|
762
|
+
/** `create` or `edit` (a view form never saves). */
|
|
763
|
+
mode: Exclude<EntityFormMode, 'view'>;
|
|
764
|
+
/** Runtime CK type id of the entity that is saved (the concrete type in create mode). */
|
|
765
|
+
ckTypeId: string;
|
|
766
|
+
/** rtId of the entity in edit mode; absent in create mode. */
|
|
767
|
+
rtId?: string;
|
|
768
|
+
/** The resolved form (fields, sections, secret field names) - metadata only, no values. */
|
|
769
|
+
form: ResolvedEntityForm;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Result of a {@link EntityFormBeforeSaveHook}:
|
|
773
|
+
* - a change set → saved instead of the original one (`isEmpty` is recomputed);
|
|
774
|
+
* - `undefined` / `void` / `true` → the change set handed to the hook is saved, including any
|
|
775
|
+
* in-place changes the hook made to it;
|
|
776
|
+
* - `null` / `false` → the save is vetoed silently (the hook told the user itself, or nothing
|
|
777
|
+
* needs saying). To veto with a message, throw an {@link EntityFormSaveVeto}.
|
|
778
|
+
*/
|
|
779
|
+
type EntityFormBeforeSaveResult = EntityFormChangeSet | boolean | null | undefined | void;
|
|
780
|
+
/**
|
|
781
|
+
* Host hook run right before an entity form is saved (AB#5623), after validation — e.g. to
|
|
782
|
+
* normalise values (trim texts, format IBAN / BIC / phone numbers, lower-case an e-mail) or to
|
|
783
|
+
* derive attributes (`NormalizedEmail` from `Email`). It may be synchronous or return a
|
|
784
|
+
* `Promise` / `Observable` (the first emitted value counts).
|
|
785
|
+
*
|
|
786
|
+
* - Attribute names in `changeSet.attributes` are the camelCase CK attribute names
|
|
787
|
+
* (`email`, `normalizedEmail`); values are wire values (strings, numbers, enum keys, …).
|
|
788
|
+
* - Edit mode: the change set holds only changed attributes (D6). A hook that derives an
|
|
789
|
+
* attribute from another one therefore acts only when the source is in the change set; it may
|
|
790
|
+
* add attributes that are not in the form.
|
|
791
|
+
* - **Secrets:** the hook sees nothing beyond the change set. A SECRET attribute appears there
|
|
792
|
+
* only as the write value the user just typed into this form (or in `clearSecretAttributes`
|
|
793
|
+
* when a clear is staged) — never a stored value, which the form never reads. Do not log the
|
|
794
|
+
* change set.
|
|
795
|
+
* - Throw an {@link EntityFormSaveVeto} to stop the save with a message for the user; any other
|
|
796
|
+
* error also stops the save and is reported like a failed save.
|
|
797
|
+
*
|
|
798
|
+
* Provide it as the `beforeSave` input of `mm-entity-form` / `mm-entity-page`, as the
|
|
799
|
+
* `beforeSave` option of `entityFormRoutes` (route data key `entityFormBeforeSave`), or via
|
|
800
|
+
* {@link ENTITY_FORM_BEFORE_SAVE} on a route / root injector. Precedence: input > route data >
|
|
801
|
+
* token.
|
|
802
|
+
*/
|
|
803
|
+
type EntityFormBeforeSaveHook = (changeSet: EntityFormChangeSet, context: EntityFormBeforeSaveContext) => EntityFormBeforeSaveResult | Promise<EntityFormBeforeSaveResult> | Observable<EntityFormBeforeSaveResult>;
|
|
804
|
+
/** Injection token of a {@link EntityFormBeforeSaveHook} (lowest precedence, see there). */
|
|
805
|
+
declare const ENTITY_FORM_BEFORE_SAVE: InjectionToken<EntityFormBeforeSaveHook>;
|
|
806
|
+
/**
|
|
807
|
+
* Thrown by a {@link EntityFormBeforeSaveHook} to stop a save on purpose. `userMessage` (already
|
|
808
|
+
* translated by the host) is shown as a warning; without it the generic `saveVetoed` message is
|
|
809
|
+
* shown.
|
|
810
|
+
*/
|
|
811
|
+
declare class EntityFormSaveVeto extends Error {
|
|
812
|
+
readonly userMessage?: string | undefined;
|
|
813
|
+
constructor(userMessage?: string | undefined);
|
|
814
|
+
}
|
|
815
|
+
/** Outcome of {@link runEntityFormBeforeSave}. */
|
|
816
|
+
type EntityFormBeforeSaveOutcome = {
|
|
817
|
+
kind: 'save';
|
|
818
|
+
changeSet: EntityFormChangeSet;
|
|
819
|
+
} | {
|
|
820
|
+
kind: 'veto';
|
|
821
|
+
message?: string;
|
|
822
|
+
} | {
|
|
823
|
+
kind: 'error';
|
|
824
|
+
error: unknown;
|
|
825
|
+
};
|
|
826
|
+
/** True for a thrown {@link EntityFormSaveVeto} (also across bundle copies, by name). */
|
|
827
|
+
declare function isEntityFormSaveVeto(error: unknown): error is EntityFormSaveVeto;
|
|
828
|
+
/**
|
|
829
|
+
* Runs the host hook on a copy of the change set (the caller's object is never touched) and
|
|
830
|
+
* normalises its result. Absent hook = save unchanged.
|
|
831
|
+
*/
|
|
832
|
+
declare function runEntityFormBeforeSave(hook: EntityFormBeforeSaveHook | null | undefined, changeSet: EntityFormChangeSet, context: EntityFormBeforeSaveContext): Promise<EntityFormBeforeSaveOutcome>;
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Values a host puts into a form (AB#5623), keyed by field key: the camelCase attribute name (any
|
|
836
|
+
* casing is accepted), `rtWellKnownName`, or the association field key (`assoc:<role>`).
|
|
837
|
+
*
|
|
838
|
+
* Values use the form value shape (as in {@link EntityFormValueState.values}): strings, numbers,
|
|
839
|
+
* booleans, `Date` for DATE_TIME, arrays for chips and records, and for references either a bare
|
|
840
|
+
* rtId or `{ rtId, ckTypeId, displayName }[]`. Secret fields are never prefilled.
|
|
841
|
+
*/
|
|
842
|
+
type EntityFormPrefillValues = Readonly<Record<string, unknown>>;
|
|
843
|
+
/** Options of {@link entityFormPrefillState}. */
|
|
844
|
+
interface EntityFormPrefillOptions {
|
|
845
|
+
/** Well-known name of the entity to create (carried even when the form has no such field). */
|
|
846
|
+
rtWellKnownName?: string | null;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Builds the `state` of `<mm-entity-form mode="create">` from host values (AB#5623): a prefilled
|
|
850
|
+
* value wins over the field's default, everything else starts empty. Equivalent to the form's
|
|
851
|
+
* `initialValues` input; use it when the host already passes a `state`.
|
|
852
|
+
*/
|
|
853
|
+
declare function entityFormPrefillState(values: EntityFormPrefillValues | null | undefined, options?: EntityFormPrefillOptions): EntityFormValueState;
|
|
854
|
+
/**
|
|
855
|
+
* Merges host values over a create-mode state (host values win). Returns the state unchanged when
|
|
856
|
+
* there are no values. Canonicalise the keys first ({@link canonicaliseEntityFormPrefill}).
|
|
857
|
+
*/
|
|
858
|
+
declare function mergeEntityFormPrefill(state: EntityFormValueState | null | undefined, values: EntityFormPrefillValues | null | undefined): EntityFormValueState | null;
|
|
859
|
+
/**
|
|
860
|
+
* Host values re-keyed to the form's field keys (AB#5623). Unknown keys are kept as they are
|
|
861
|
+
* (`rtWellKnownName` is always kept); secret fields are dropped (never prefilled); a bare rtId for
|
|
862
|
+
* a reference field becomes the reference editor's `{ rtId, ckTypeId, displayName }[]` value.
|
|
863
|
+
*/
|
|
864
|
+
declare function canonicaliseEntityFormPrefill(model: ResolvedEntityForm, values: EntityFormPrefillValues | null | undefined): Record<string, unknown>;
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Secret state shown next to a secret field (AB#5542 / AB#5544 item 4): set on the server, not set
|
|
868
|
+
* (`needsReEntry` for a required SECRET — same wording as the secrets inventory),
|
|
869
|
+
* stored but unreadable (`keyMissing`, re-entry needed), clear staged for the next save, or `null`
|
|
870
|
+
* (not a secret, or create mode — then the plain "Secret" badge is shown).
|
|
871
|
+
*/
|
|
872
|
+
type EntityFormSecretState = 'set' | 'notSet' | 'needsReEntry' | 'keyMissing' | 'clearStaged' | null;
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Renders a {@link ResolvedEntityForm} as a reactive form: sections (1 or 2 columns,
|
|
876
|
+
* collapsible), one field shell per field and the editor chosen by the resolver.
|
|
877
|
+
*
|
|
878
|
+
* Rules applied here (see the plan, §2.4):
|
|
879
|
+
* - A field hidden by `VisibleWhen` has its control disabled, so it neither validates nor appears
|
|
880
|
+
* in the change set. `Path=*` on a secret source counts the server-side presence as a value.
|
|
881
|
+
* - Secrets are never prefilled; the badge says whether a value is set (also for read-only users).
|
|
882
|
+
* Empty = unchanged. An optional SECRET can be cleared: the clear is staged and sent on Save as
|
|
883
|
+
* `clearSecretAttributes` (mutually exclusive with a new value). Without a key ring
|
|
884
|
+
* (`ENTITY_FORM_SECRET_KEY_RING_CONFIGURED` = false) secret inputs are disabled with a hint; the
|
|
885
|
+
* signal may change at any time (status loaded asynchronously) and the controls follow it. In
|
|
886
|
+
* create mode a required secret that cannot be entered blocks the form: `isValid()` is false and
|
|
887
|
+
* `saveBlockedReason()` names the fields, so hosts disable Create with that reason (Q17: no late
|
|
888
|
+
* `SecretEncryptionNotConfigured` / "required secret missing" error on save).
|
|
889
|
+
* - `afterCreate` fields are read-only outside create mode; `readOnly`, `view` mode or
|
|
890
|
+
* `capabilities.canEdit === false` (edit mode) make every field read-only.
|
|
891
|
+
* - The change set holds only dirty controls (D6), built by `buildChangeSet`.
|
|
892
|
+
* - Texts (labels, help, sections, enum options, record columns) go through the label resolver
|
|
893
|
+
* (`labelResolver` input or `ENTITY_FORM_LABEL_RESOLVER`, AB#5623); a language change re-renders
|
|
894
|
+
* the texts without rebuilding the controls.
|
|
895
|
+
* - Host prefill (AB#5623): `initialValues` in create mode, `patchValues()` at any time.
|
|
896
|
+
* - Before-save hook (AB#5623): `beforeSave` input / `ENTITY_FORM_BEFORE_SAVE`, applied by
|
|
897
|
+
* {@link getChangeSetForSave}; secrets reach it only as values typed into this form.
|
|
898
|
+
* - Unset placeholders (AB#5623, `ENTITY_FORM_UNSET_PLACEHOLDER_VALUES`): a non-secret field whose
|
|
899
|
+
* stored / default / prefilled value is a listed placeholder starts empty with the
|
|
900
|
+
* `notConfigured` hint; untouched it is not part of the change set, so the placeholder is never
|
|
901
|
+
* written back. Secrets are never affected.
|
|
902
|
+
*/
|
|
903
|
+
declare class EntityFormComponent {
|
|
904
|
+
private readonly destroyRef;
|
|
905
|
+
private readonly keyRingConfigured;
|
|
906
|
+
private readonly injectedLabelResolver;
|
|
907
|
+
private readonly injectedBeforeSave;
|
|
908
|
+
private readonly unsetPlaceholders;
|
|
909
|
+
readonly model: _angular_core.InputSignal<ResolvedEntityForm>;
|
|
910
|
+
readonly mode: _angular_core.InputSignal<EntityFormMode>;
|
|
911
|
+
readonly state: _angular_core.InputSignal<EntityFormValueState | null | undefined>;
|
|
912
|
+
readonly readOnly: _angular_core.InputSignal<boolean>;
|
|
913
|
+
readonly messages: _angular_core.InputSignal<Partial<EntityFormsMessages>>;
|
|
914
|
+
/** Record metadata keyed by versioned ckRecordId; improves type conversion of record sub-values. */
|
|
915
|
+
readonly records: _angular_core.InputSignal<Record<string, CkRecordInfo>>;
|
|
916
|
+
/**
|
|
917
|
+
* Translates field labels, help texts, section titles, enum option texts and record columns
|
|
918
|
+
* (AB#5623). Wins over `ENTITY_FORM_LABEL_RESOLVER`; absent = the definition / CK texts.
|
|
919
|
+
*/
|
|
920
|
+
readonly labelResolver: _angular_core.InputSignal<EntityFormLabelResolver | null | undefined>;
|
|
921
|
+
/**
|
|
922
|
+
* Host prefill of a create form (AB#5623), keyed by field key / attribute name (any casing).
|
|
923
|
+
* Wins over the field defaults and over `state.values`; secrets are never prefilled. The values
|
|
924
|
+
* are the starting point of the form (not "dirty"); a create sends every non-empty value anyway.
|
|
925
|
+
* Ignored in edit / view mode — use {@link patchValues} there.
|
|
926
|
+
*/
|
|
927
|
+
readonly initialValues: _angular_core.InputSignal<Readonly<Record<string, unknown>> | null | undefined>;
|
|
928
|
+
/**
|
|
929
|
+
* Hook run by {@link getChangeSetForSave} (AB#5623): may modify the change set or veto the save.
|
|
930
|
+
* Wins over `ENTITY_FORM_BEFORE_SAVE`. `mm-entity-page` runs its own (input > route data >
|
|
931
|
+
* token), so set it there when the page saves. See `EntityFormBeforeSaveHook`.
|
|
932
|
+
*/
|
|
933
|
+
readonly beforeSave: _angular_core.InputSignal<EntityFormBeforeSaveHook | null | undefined>;
|
|
934
|
+
readonly changeSetChange: _angular_core.OutputEmitterRef<EntityFormChangeSet>;
|
|
935
|
+
readonly validChange: _angular_core.OutputEmitterRef<boolean>;
|
|
936
|
+
readonly dirtyChange: _angular_core.OutputEmitterRef<boolean>;
|
|
937
|
+
protected readonly chevronDownIcon: _progress_kendo_svg_icons.SVGIcon;
|
|
938
|
+
protected readonly chevronRightIcon: _progress_kendo_svg_icons.SVGIcon;
|
|
939
|
+
/** Stable empty list for reference fields without display attributes. */
|
|
940
|
+
protected readonly noDisplayAttributes: readonly string[];
|
|
941
|
+
protected readonly noDisplayAttributeInfo: readonly CkAttributeInfo[];
|
|
942
|
+
protected readonly resolvedMessages: _angular_core.Signal<EntityFormsMessages>;
|
|
943
|
+
/** The effective label resolver (input, else the injected one, else none). */
|
|
944
|
+
private readonly effectiveLabelResolver;
|
|
945
|
+
/**
|
|
946
|
+
* The model as rendered: every text passed through the label resolver (AB#5623). Keys are
|
|
947
|
+
* unchanged, so the controls built from {@link model} match it.
|
|
948
|
+
*/
|
|
949
|
+
protected readonly view: _angular_core.Signal<ResolvedEntityForm>;
|
|
950
|
+
protected readonly form: _angular_core.WritableSignal<FormGroup<Record<string, FormControl<unknown>>>>;
|
|
951
|
+
/** Bumped on every form event so OnPush children re-evaluate errors. */
|
|
952
|
+
protected readonly revision: _angular_core.WritableSignal<number>;
|
|
953
|
+
/** Raw values (disabled controls included) for VisibleWhen evaluation. */
|
|
954
|
+
private readonly rawValues;
|
|
955
|
+
private readonly collapsed;
|
|
956
|
+
/** Keys of the fields whose stored value was an unset placeholder (AB#5623); they start empty. */
|
|
957
|
+
protected readonly unsetPlaceholderFields: _angular_core.WritableSignal<ReadonlySet<string>>;
|
|
958
|
+
/** attributeNames of secrets whose clear is staged for the next save (Q8). */
|
|
959
|
+
private readonly clearedSecrets;
|
|
960
|
+
/** Value snapshot taken when the form was built (D6 baseline). */
|
|
961
|
+
private baselineValues;
|
|
962
|
+
/** The state the form was built from (input `state` plus host prefill). */
|
|
963
|
+
private builtState;
|
|
964
|
+
private formSub?;
|
|
965
|
+
private lastValid?;
|
|
966
|
+
private lastDirty?;
|
|
967
|
+
protected readonly secretPresence: _angular_core.Signal<Record<string, boolean>>;
|
|
968
|
+
protected readonly formReadOnly: _angular_core.Signal<boolean>;
|
|
969
|
+
/** No key ring in this environment (Q17): secret inputs are disabled with a hint. */
|
|
970
|
+
protected readonly secretWritesDisabled: _angular_core.Signal<boolean>;
|
|
971
|
+
/** The `secretWritesDisabled` value the controls were last enabled / disabled for. */
|
|
972
|
+
private appliedSecretWritesDisabled?;
|
|
973
|
+
/** Visibility per field key, from VisibleWhen and the current raw values. */
|
|
974
|
+
protected readonly visibility: _angular_core.Signal<Record<string, boolean>>;
|
|
975
|
+
/**
|
|
976
|
+
* Why the form cannot be saved although every enabled control is valid, or `null`: in create
|
|
977
|
+
* mode without a key ring (Q17), a visible, writable, required secret cannot be entered — the
|
|
978
|
+
* server would reject the create (required secret missing). Hosts disable Create and show this.
|
|
979
|
+
* In edit mode a missing required secret does not block saving other fields (the server only
|
|
980
|
+
* enforces required secrets on create).
|
|
981
|
+
*/
|
|
982
|
+
readonly saveBlockedReason: _angular_core.Signal<string | null>;
|
|
983
|
+
/** Default item of optional enum dropdowns. */
|
|
984
|
+
protected readonly enumDefaultItem: _angular_core.Signal<{
|
|
985
|
+
key: null;
|
|
986
|
+
name: string;
|
|
987
|
+
}>;
|
|
988
|
+
constructor();
|
|
989
|
+
/** Change set of the current values (only dirty controls on edit). */
|
|
990
|
+
getChangeSet(): EntityFormChangeSet;
|
|
991
|
+
/**
|
|
992
|
+
* The change set to save, after the before-save hook (`beforeSave` input, else
|
|
993
|
+
* `ENTITY_FORM_BEFORE_SAVE`; AB#5623) — for hosts that render `mm-entity-form` and save
|
|
994
|
+
* themselves. The form never shows notifications: on `veto` / `error` the host tells the user
|
|
995
|
+
* (e.g. `outcome.message ?? messages.saveVetoed`). View mode, and an edit form without changes,
|
|
996
|
+
* skip the hook. `context.rtId` names the edited entity; `context.ckTypeId` defaults to the
|
|
997
|
+
* form's runtime CK type.
|
|
998
|
+
*/
|
|
999
|
+
getChangeSetForSave(context?: {
|
|
1000
|
+
rtId?: string;
|
|
1001
|
+
ckTypeId?: string;
|
|
1002
|
+
}): Promise<EntityFormBeforeSaveOutcome>;
|
|
1003
|
+
/** True when any editable, visible control differs from the value it was built with. */
|
|
1004
|
+
isDirty(): boolean;
|
|
1005
|
+
/** True when every enabled control is valid and nothing blocks saving ({@link saveBlockedReason}). */
|
|
1006
|
+
isValid(): boolean;
|
|
1007
|
+
/** Marks every control as touched so validation errors become visible. */
|
|
1008
|
+
markAllAsTouched(): void;
|
|
1009
|
+
/** Rebuilds the form from the current inputs, discarding user edits. */
|
|
1010
|
+
reset(): void;
|
|
1011
|
+
/**
|
|
1012
|
+
* Sets form values from the host (AB#5623), e.g. a "Prefill from user" action. Keys are field
|
|
1013
|
+
* keys or attribute names (any casing). The values always count as user edits: the form gets
|
|
1014
|
+
* dirty (compared with the values it was built from), the unsaved-changes guard applies and the
|
|
1015
|
+
* change set sends them. To start a create form with values that are NOT edits, use the
|
|
1016
|
+
* `initialValues` input instead. Secret fields, read-only fields and unknown keys are skipped.
|
|
1017
|
+
* Returns the field keys that were set.
|
|
1018
|
+
*/
|
|
1019
|
+
patchValues(values: EntityFormPrefillValues): string[];
|
|
1020
|
+
protected control(key: string): FormControl<unknown>;
|
|
1021
|
+
protected isFieldVisible(field: ResolvedField): boolean;
|
|
1022
|
+
protected visibleFieldCount(section: ResolvedSection): number;
|
|
1023
|
+
protected isCollapsed(section: ResolvedSection): boolean;
|
|
1024
|
+
protected toggleSection(section: ResolvedSection): void;
|
|
1025
|
+
protected isReadOnly(field: ResolvedField): boolean;
|
|
1026
|
+
protected isRequired(field: ResolvedField): boolean;
|
|
1027
|
+
protected secretState(field: ResolvedField): EntityFormSecretState;
|
|
1028
|
+
protected secretSetAt(field: ResolvedField): Date | null;
|
|
1029
|
+
/**
|
|
1030
|
+
* "Clear" is offered for an optional SECRET (only SECRET attributes accept
|
|
1031
|
+
* `clearSecretAttributes`) that holds a value (set or key missing), in edit mode, when the field
|
|
1032
|
+
* is writable. Required secrets cannot be cleared (Q8).
|
|
1033
|
+
*/
|
|
1034
|
+
protected canClearSecret(field: ResolvedField): boolean;
|
|
1035
|
+
protected isSecretClearStaged(field: ResolvedField): boolean;
|
|
1036
|
+
/** Stages or undoes clearing a secret; a staged clear empties and disables the input. */
|
|
1037
|
+
protected setSecretClearStaged(field: ResolvedField, staged: boolean): void;
|
|
1038
|
+
protected placeholder(field: ResolvedField): string;
|
|
1039
|
+
/** Q17 applies to SECRET-typed fields only (the encryption key ring is not needed for fallback secrets). */
|
|
1040
|
+
protected isSecretWriteBlocked(field: ResolvedField): boolean;
|
|
1041
|
+
protected isIntegerField(field: ResolvedField): boolean;
|
|
1042
|
+
protected isIntArray(field: ResolvedField): boolean;
|
|
1043
|
+
protected displayUnsupported(field: ResolvedField): string;
|
|
1044
|
+
/** `state` with the host prefill merged in (create mode only). */
|
|
1045
|
+
private withPrefill;
|
|
1046
|
+
private rebuild;
|
|
1047
|
+
/**
|
|
1048
|
+
* Empties the fields that hold an unset placeholder (AB#5623) before the baseline is taken, so an
|
|
1049
|
+
* untouched field is "no change" and the placeholder is never written back.
|
|
1050
|
+
*/
|
|
1051
|
+
private clearUnsetPlaceholders;
|
|
1052
|
+
/** Attribute-held references store a bare rtId; the reference editor works with an array. */
|
|
1053
|
+
private normaliseAttributeReferences;
|
|
1054
|
+
private onFormEvent;
|
|
1055
|
+
/**
|
|
1056
|
+
* Enables/disables controls by visibility. A hidden field is always disabled; a visible field
|
|
1057
|
+
* is enabled unless it is read-only.
|
|
1058
|
+
*/
|
|
1059
|
+
private applyVisibility;
|
|
1060
|
+
/** Values of enabled controls only (hidden and read-only fields are absent). */
|
|
1061
|
+
private enabledValues;
|
|
1062
|
+
private emitState;
|
|
1063
|
+
private bump;
|
|
1064
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormComponent, never>;
|
|
1065
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityFormComponent, "mm-entity-form", never, { "model": { "alias": "model"; "required": true; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "state": { "alias": "state"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "messages": { "alias": "messages"; "required": false; "isSignal": true; }; "records": { "alias": "records"; "required": false; "isSignal": true; }; "labelResolver": { "alias": "labelResolver"; "required": false; "isSignal": true; }; "initialValues": { "alias": "initialValues"; "required": false; "isSignal": true; }; "beforeSave": { "alias": "beforeSave"; "required": false; "isSignal": true; }; }, { "changeSetChange": "changeSetChange"; "validChange": "validChange"; "dirtyChange": "dirtyChange"; }, never, never, true, never>;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
type EntityFormGetReferenceOptionsQueryVariablesDto = Types.Exact<{
|
|
1069
|
+
ckTypeId: Types.Scalars['String']['input'];
|
|
1070
|
+
first?: Types.InputMaybe<Types.Scalars['Int']['input']>;
|
|
1071
|
+
after?: Types.InputMaybe<Types.Scalars['String']['input']>;
|
|
1072
|
+
searchFilter?: Types.InputMaybe<Types.SearchFilterDto>;
|
|
1073
|
+
fieldFilters?: Types.InputMaybe<Array<Types.InputMaybe<Types.FieldFilterDto>> | Types.InputMaybe<Types.FieldFilterDto>>;
|
|
1074
|
+
sort?: Types.InputMaybe<Array<Types.InputMaybe<Types.SortDto>> | Types.InputMaybe<Types.SortDto>>;
|
|
1075
|
+
}>;
|
|
1076
|
+
type EntityFormGetReferenceOptionsQueryDto = {
|
|
1077
|
+
__typename?: 'OctoQuery';
|
|
1078
|
+
runtime?: {
|
|
1079
|
+
__typename?: 'RuntimeModelQuery';
|
|
1080
|
+
runtimeEntities?: {
|
|
1081
|
+
__typename?: 'RtEntityGenericDtoConnection';
|
|
1082
|
+
totalCount?: number | null;
|
|
1083
|
+
pageInfo: {
|
|
1084
|
+
__typename?: 'PageInfo';
|
|
1085
|
+
endCursor?: string | null;
|
|
1086
|
+
hasNextPage: boolean;
|
|
1087
|
+
};
|
|
1088
|
+
items?: Array<{
|
|
1089
|
+
__typename?: 'RtEntity';
|
|
1090
|
+
rtId: any;
|
|
1091
|
+
ckTypeId: any;
|
|
1092
|
+
rtWellKnownName?: string | null;
|
|
1093
|
+
rtDisplayName: string;
|
|
1094
|
+
rtDisplayDescription?: string | null;
|
|
1095
|
+
attributes?: {
|
|
1096
|
+
__typename?: 'RtEntityAttributeDtoConnection';
|
|
1097
|
+
items?: Array<{
|
|
1098
|
+
__typename?: 'RtEntityAttribute';
|
|
1099
|
+
attributeName?: string | null;
|
|
1100
|
+
value?: any | null;
|
|
1101
|
+
} | null> | null;
|
|
1102
|
+
} | null;
|
|
1103
|
+
} | null> | null;
|
|
1104
|
+
} | null;
|
|
1105
|
+
} | null;
|
|
1106
|
+
};
|
|
1107
|
+
declare class EntityFormGetReferenceOptionsDtoGQL extends Apollo.Query<EntityFormGetReferenceOptionsQueryDto, EntityFormGetReferenceOptionsQueryVariablesDto> {
|
|
1108
|
+
document: Apollo.TypedDocumentNode<unknown, unknown>;
|
|
1109
|
+
constructor(apollo: Apollo.Apollo);
|
|
1110
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormGetReferenceOptionsDtoGQL, never>;
|
|
1111
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EntityFormGetReferenceOptionsDtoGQL>;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
type EntityFormGetReferenceOptionsWithAttributesQueryVariablesDto = Types.Exact<{
|
|
1115
|
+
ckTypeId: Types.Scalars['String']['input'];
|
|
1116
|
+
first?: Types.InputMaybe<Types.Scalars['Int']['input']>;
|
|
1117
|
+
after?: Types.InputMaybe<Types.Scalars['String']['input']>;
|
|
1118
|
+
searchFilter?: Types.InputMaybe<Types.SearchFilterDto>;
|
|
1119
|
+
fieldFilters?: Types.InputMaybe<Array<Types.InputMaybe<Types.FieldFilterDto>> | Types.InputMaybe<Types.FieldFilterDto>>;
|
|
1120
|
+
sort?: Types.InputMaybe<Array<Types.InputMaybe<Types.SortDto>> | Types.InputMaybe<Types.SortDto>>;
|
|
1121
|
+
attributeNames: Array<Types.InputMaybe<Types.Scalars['String']['input']>> | Types.InputMaybe<Types.Scalars['String']['input']>;
|
|
1122
|
+
}>;
|
|
1123
|
+
type EntityFormGetReferenceOptionsWithAttributesQueryDto = {
|
|
1124
|
+
__typename?: 'OctoQuery';
|
|
1125
|
+
runtime?: {
|
|
1126
|
+
__typename?: 'RuntimeModelQuery';
|
|
1127
|
+
runtimeEntities?: {
|
|
1128
|
+
__typename?: 'RtEntityGenericDtoConnection';
|
|
1129
|
+
totalCount?: number | null;
|
|
1130
|
+
pageInfo: {
|
|
1131
|
+
__typename?: 'PageInfo';
|
|
1132
|
+
endCursor?: string | null;
|
|
1133
|
+
hasNextPage: boolean;
|
|
1134
|
+
};
|
|
1135
|
+
items?: Array<{
|
|
1136
|
+
__typename?: 'RtEntity';
|
|
1137
|
+
rtId: any;
|
|
1138
|
+
ckTypeId: any;
|
|
1139
|
+
rtWellKnownName?: string | null;
|
|
1140
|
+
rtDisplayName: string;
|
|
1141
|
+
rtDisplayDescription?: string | null;
|
|
1142
|
+
attributes?: {
|
|
1143
|
+
__typename?: 'RtEntityAttributeDtoConnection';
|
|
1144
|
+
items?: Array<{
|
|
1145
|
+
__typename?: 'RtEntityAttribute';
|
|
1146
|
+
attributeName?: string | null;
|
|
1147
|
+
value?: any | null;
|
|
1148
|
+
} | null> | null;
|
|
1149
|
+
} | null;
|
|
1150
|
+
} | null> | null;
|
|
1151
|
+
} | null;
|
|
1152
|
+
} | null;
|
|
1153
|
+
};
|
|
1154
|
+
declare class EntityFormGetReferenceOptionsWithAttributesDtoGQL extends Apollo.Query<EntityFormGetReferenceOptionsWithAttributesQueryDto, EntityFormGetReferenceOptionsWithAttributesQueryVariablesDto> {
|
|
1155
|
+
document: Apollo.TypedDocumentNode<unknown, unknown>;
|
|
1156
|
+
constructor(apollo: Apollo.Apollo);
|
|
1157
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormGetReferenceOptionsWithAttributesDtoGQL, never>;
|
|
1158
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EntityFormGetReferenceOptionsWithAttributesDtoGQL>;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* How the display attributes of a reference target (`referenceDisplayAttributes`, AB#5547) are
|
|
1163
|
+
* turned into text: by the CK value type of each attribute. Without metadata for an attribute the
|
|
1164
|
+
* raw value is shown (booleans still as yes/no).
|
|
1165
|
+
*/
|
|
1166
|
+
interface ReferenceDisplayFormat {
|
|
1167
|
+
/** CK metadata of the target type's display attributes (matched case-insensitively by name). */
|
|
1168
|
+
attributes?: readonly CkAttributeInfo[];
|
|
1169
|
+
/** Label of `true` (default "Yes"). */
|
|
1170
|
+
yes?: string;
|
|
1171
|
+
/** Label of `false` (default "No"). */
|
|
1172
|
+
no?: string;
|
|
1173
|
+
/** Locale of dates; the browser locale when omitted. */
|
|
1174
|
+
locale?: string;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/** One candidate target of a reference field. Carries system properties only, never attributes. */
|
|
1178
|
+
interface EntityReferenceItem {
|
|
1179
|
+
rtId: string;
|
|
1180
|
+
ckTypeId: string;
|
|
1181
|
+
rtWellKnownName?: string;
|
|
1182
|
+
rtDisplayName?: string;
|
|
1183
|
+
rtDisplayDescription?: string;
|
|
1184
|
+
/** Label shown in the picker and stored as `displayName` in the field value. */
|
|
1185
|
+
displayName: string;
|
|
1186
|
+
}
|
|
1187
|
+
/** Column labels of the reference picker dialog. */
|
|
1188
|
+
interface EntityReferenceColumnLabels {
|
|
1189
|
+
name: string;
|
|
1190
|
+
wellKnownName: string;
|
|
1191
|
+
type: string;
|
|
1192
|
+
rtId: string;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Secret-safe data source of `mm-entity-form-reference-field`, used both for the typeahead
|
|
1196
|
+
* (`EntitySelectDataSource`) and for the grid dialog (`EntitySelectDialogDataSource`) of shared-ui
|
|
1197
|
+
* `mm-entity-select-input`.
|
|
1198
|
+
*
|
|
1199
|
+
* It queries `entityFormGetReferenceOptions`, a document that selects **no `attributes` field at
|
|
1200
|
+
* all**: only `rtId`, `ckTypeId`, `rtWellKnownName`, `rtDisplayName` and `rtDisplayDescription`.
|
|
1201
|
+
* The target type's secrets therefore never reach the browser, unlike the octo-services
|
|
1202
|
+
* `RuntimeEntitySelectDataSource` (its `getEntitiesByCkType` selects every attribute).
|
|
1203
|
+
*
|
|
1204
|
+
* Derived types of `targetCkTypeId` are included (`runtimeEntities(ckId)` is polymorphic), which is
|
|
1205
|
+
* what a reference to a base type expects. Search matches `rtWellKnownName` and `rtDisplayName`.
|
|
1206
|
+
*/
|
|
1207
|
+
declare class EntityReferenceDataSource implements EntitySelectDataSource<EntityReferenceItem>, EntitySelectDialogDataSource<EntityReferenceItem> {
|
|
1208
|
+
private readonly gql;
|
|
1209
|
+
readonly targetCkTypeId: string;
|
|
1210
|
+
readonly displayAttributes: readonly string[];
|
|
1211
|
+
private readonly attributesGql?;
|
|
1212
|
+
private readonly format;
|
|
1213
|
+
private readonly columnLabels;
|
|
1214
|
+
/**
|
|
1215
|
+
* @param displayAttributes Non-secret target attributes shown next to the name (field
|
|
1216
|
+
* `referenceDisplayAttributes`). Non-empty → the options are read with
|
|
1217
|
+
* `entityFormGetReferenceOptionsWithAttributes` and exactly these `attributeNames` (plus the
|
|
1218
|
+
* non-secret `name`, which the plain document reads for the label as well).
|
|
1219
|
+
* @param format CK metadata and labels used to format the display attribute values.
|
|
1220
|
+
*/
|
|
1221
|
+
constructor(gql: EntityFormGetReferenceOptionsDtoGQL, targetCkTypeId: string, columnLabels?: Partial<EntityReferenceColumnLabels>, displayAttributes?: readonly string[], attributesGql?: EntityFormGetReferenceOptionsWithAttributesDtoGQL | undefined, format?: ReferenceDisplayFormat);
|
|
1222
|
+
/** Variables of one page; exposed for tests (it is the complete request apart from the document). */
|
|
1223
|
+
buildVariables(searchTerm: string | null, first: number, skip?: number): EntityFormGetReferenceOptionsQueryVariablesDto;
|
|
1224
|
+
onFilter(filter: string, take?: number): Promise<EntitySelectResult<EntityReferenceItem>>;
|
|
1225
|
+
getColumns(): ColumnDefinition[];
|
|
1226
|
+
fetchData(options: DialogFetchOptions): Observable<DialogFetchResult<EntityReferenceItem>>;
|
|
1227
|
+
onDisplayEntity(entity: EntityReferenceItem): string;
|
|
1228
|
+
getIdEntity(entity: EntityReferenceItem): string;
|
|
1229
|
+
/**
|
|
1230
|
+
* The targets with the given rtIds, labelled like the picker rows (display attributes included).
|
|
1231
|
+
* Used for the label of the current value; ids that cannot be read are missing from the map.
|
|
1232
|
+
*/
|
|
1233
|
+
lookup(rtIds: readonly string[]): Promise<Map<string, EntityReferenceItem>>;
|
|
1234
|
+
private fetchPage;
|
|
1235
|
+
private request;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/** One selected reference target. The field value is always an array of these. */
|
|
1239
|
+
interface EntityFormReferenceValue$1 {
|
|
1240
|
+
rtId: string;
|
|
1241
|
+
ckTypeId: string;
|
|
1242
|
+
displayName: string;
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* Reference editor of `mm-entity-form` (association roles and rtId-holding STRING attributes).
|
|
1246
|
+
*
|
|
1247
|
+
* - **Value:** `EntityFormReferenceValue[]` (`{ rtId, ckTypeId, displayName }`), an array even for
|
|
1248
|
+
* single selection; `[]` when nothing is selected.
|
|
1249
|
+
* - **Limit:** with `multiple = false` a new pick replaces the current one, so the value never
|
|
1250
|
+
* grows beyond one entry; a written value with more entries is reported by the validator as
|
|
1251
|
+
* `{ maxItems: { max: 1, actual } }`. With `multiple = true` picks are appended, de-duplicated by
|
|
1252
|
+
* `rtId`.
|
|
1253
|
+
* - **Picker:** shared-ui `mm-entity-select-input` (typeahead plus grid dialog) over the
|
|
1254
|
+
* secret-safe {@link EntityReferenceDataSource}, which selects only the non-secret `name` attribute of the targets.
|
|
1255
|
+
* - **Display attributes:** with `displayAttributes` the picker rows and the current value read
|
|
1256
|
+
* `name · value1 · value2`, each value formatted by its CK value type (`displayAttributeInfo`):
|
|
1257
|
+
* enum names, yes/no, dates. The current value's label is looked up once per rtId; it only
|
|
1258
|
+
* changes what is shown, never the field value.
|
|
1259
|
+
*/
|
|
1260
|
+
declare class EntityFormReferenceFieldComponent implements ControlValueAccessor, Validator {
|
|
1261
|
+
private readonly gql;
|
|
1262
|
+
private readonly attributesGql;
|
|
1263
|
+
readonly targetCkTypeId: _angular_core.InputSignal<string>;
|
|
1264
|
+
readonly multiple: _angular_core.InputSignal<boolean>;
|
|
1265
|
+
/** Non-secret target attributes shown next to the name (AB#5547). */
|
|
1266
|
+
readonly displayAttributes: _angular_core.InputSignal<readonly string[]>;
|
|
1267
|
+
/** CK metadata of the display attributes on the target type; formats their values (AB#5547). */
|
|
1268
|
+
readonly displayAttributeInfo: _angular_core.InputSignal<readonly CkAttributeInfo[]>;
|
|
1269
|
+
readonly placeholder: _angular_core.InputSignal<string | null | undefined>;
|
|
1270
|
+
readonly readOnly: _angular_core.InputSignal<boolean>;
|
|
1271
|
+
readonly messages: _angular_core.InputSignal<Partial<EntityFormsMessages>>;
|
|
1272
|
+
protected readonly msg: _angular_core.Signal<EntityFormsMessages>;
|
|
1273
|
+
protected readonly value: _angular_core.WritableSignal<EntityFormReferenceValue$1[]>;
|
|
1274
|
+
private readonly disabledByForm;
|
|
1275
|
+
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
1276
|
+
/** Labels with display attributes, by rtId (from picks and from lookups of the current value). */
|
|
1277
|
+
private readonly labels;
|
|
1278
|
+
private readonly requested;
|
|
1279
|
+
/** One data source per target type. */
|
|
1280
|
+
readonly dataSource: _angular_core.Signal<EntityReferenceDataSource | null>;
|
|
1281
|
+
constructor();
|
|
1282
|
+
/** Label shown for a selected target: with display attributes when known, else its display name. */
|
|
1283
|
+
labelOf(item: EntityFormReferenceValue$1): string;
|
|
1284
|
+
private readonly selectInput;
|
|
1285
|
+
private onChange;
|
|
1286
|
+
private onTouched;
|
|
1287
|
+
private onValidatorChange;
|
|
1288
|
+
/** Current value (a copy). */
|
|
1289
|
+
getValue(): EntityFormReferenceValue$1[];
|
|
1290
|
+
writeValue(value: EntityFormReferenceValue$1[] | null | undefined): void;
|
|
1291
|
+
registerOnChange(fn: (value: EntityFormReferenceValue$1[]) => void): void;
|
|
1292
|
+
registerOnTouched(fn: () => void): void;
|
|
1293
|
+
registerOnValidatorChange(fn: () => void): void;
|
|
1294
|
+
setDisabledState(isDisabled: boolean): void;
|
|
1295
|
+
validate(_control: AbstractControl): ValidationErrors | null;
|
|
1296
|
+
/** Applies picked entities: replaces in single mode (first pick wins), appends unique in multi mode. */
|
|
1297
|
+
onPicked(items: (EntityReferenceItem | EntityFormReferenceValue$1)[] | null | undefined): void;
|
|
1298
|
+
/** Removes one selected target. */
|
|
1299
|
+
remove(rtId: string): void;
|
|
1300
|
+
private lookupLabels;
|
|
1301
|
+
private commit;
|
|
1302
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormReferenceFieldComponent, never>;
|
|
1303
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityFormReferenceFieldComponent, "mm-entity-form-reference-field", never, { "targetCkTypeId": { "alias": "targetCkTypeId"; "required": true; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "displayAttributes": { "alias": "displayAttributes"; "required": false; "isSignal": true; }; "displayAttributeInfo": { "alias": "displayAttributeInfo"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "messages": { "alias": "messages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
/** Grid column of the records editor. */
|
|
1307
|
+
interface EntityFormRecordColumn {
|
|
1308
|
+
path: string;
|
|
1309
|
+
label: string;
|
|
1310
|
+
}
|
|
1311
|
+
/** Grid row: the stored dict plus its position (rows have no identity of their own). */
|
|
1312
|
+
interface GridRow {
|
|
1313
|
+
index: number;
|
|
1314
|
+
row: Record<string, unknown>;
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Records editor of `mm-entity-form` for RECORD and RECORD_ARRAY attributes.
|
|
1318
|
+
*
|
|
1319
|
+
* - **Value:** `Record<string, unknown>[]`, one flat camelCase dict per record
|
|
1320
|
+
* (`{ key: 'a', order: 1 }`, the write shape of the value mapper). A single RECORD uses an array
|
|
1321
|
+
* of at most one entry (`single = true`); `[]` means "no record".
|
|
1322
|
+
* - **Grid:** add / edit / move up / move down / remove. Edit and add open
|
|
1323
|
+
* `EntityFormRecordRowDialogComponent`, whose fields come from `EntityFormService.getCkRecord()`.
|
|
1324
|
+
* - **Limits:** `single` disables "add" once one row exists. Nested RECORD / RECORD_ARRAY sub-fields
|
|
1325
|
+
* are read-only in the row dialog and their values are passed through unchanged.
|
|
1326
|
+
*/
|
|
1327
|
+
declare class EntityFormRecordsFieldComponent implements ControlValueAccessor {
|
|
1328
|
+
private readonly entityFormService;
|
|
1329
|
+
private readonly dialogService;
|
|
1330
|
+
private readonly locale;
|
|
1331
|
+
readonly ckRecordId: _angular_core.InputSignal<string>;
|
|
1332
|
+
readonly columns: _angular_core.InputSignal<EntityFormRecordColumn[] | null | undefined>;
|
|
1333
|
+
readonly single: _angular_core.InputSignal<boolean>;
|
|
1334
|
+
readonly readOnly: _angular_core.InputSignal<boolean>;
|
|
1335
|
+
readonly messages: _angular_core.InputSignal<Partial<EntityFormsMessages>>;
|
|
1336
|
+
/** No key ring (Q17): SECRET members cannot get a new value in the row editor (badge + hint only). */
|
|
1337
|
+
readonly secretWritesDisabled: _angular_core.InputSignal<boolean>;
|
|
1338
|
+
protected readonly icons: {
|
|
1339
|
+
plus: _progress_kendo_svg_icons.SVGIcon;
|
|
1340
|
+
edit: _progress_kendo_svg_icons.SVGIcon;
|
|
1341
|
+
up: _progress_kendo_svg_icons.SVGIcon;
|
|
1342
|
+
down: _progress_kendo_svg_icons.SVGIcon;
|
|
1343
|
+
remove: _progress_kendo_svg_icons.SVGIcon;
|
|
1344
|
+
view: _progress_kendo_svg_icons.SVGIcon;
|
|
1345
|
+
};
|
|
1346
|
+
/** Row name in the accessible names of the row buttons ("Remove row 2", AB#5579). */
|
|
1347
|
+
protected rowLabel(index: number): string;
|
|
1348
|
+
protected readonly msg: _angular_core.Signal<EntityFormsMessages>;
|
|
1349
|
+
protected readonly rows: _angular_core.WritableSignal<Record<string, unknown>[]>;
|
|
1350
|
+
private readonly disabledByForm;
|
|
1351
|
+
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
1352
|
+
/** CK metadata of the record, loaded per `ckRecordId`; `null` until loaded or when unknown. */
|
|
1353
|
+
readonly record: _angular_core.WritableSignal<CkRecordInfo | null>;
|
|
1354
|
+
protected readonly gridRows: _angular_core.Signal<GridRow[]>;
|
|
1355
|
+
readonly canAdd: _angular_core.Signal<boolean>;
|
|
1356
|
+
/** Configured columns, or the first record attributes when the form lists none. */
|
|
1357
|
+
readonly effectiveColumns: _angular_core.Signal<EntityFormRecordColumn[]>;
|
|
1358
|
+
private readonly enumOptionsByAttribute;
|
|
1359
|
+
/** Lower-cased names of SECRET members: their cells show the badge text, never a value. */
|
|
1360
|
+
private readonly secretAttributes;
|
|
1361
|
+
private onChange;
|
|
1362
|
+
private onTouched;
|
|
1363
|
+
private recordRequest;
|
|
1364
|
+
constructor();
|
|
1365
|
+
/** Current value (a shallow copy). */
|
|
1366
|
+
getValue(): Record<string, unknown>[];
|
|
1367
|
+
writeValue(value: Record<string, unknown>[] | Record<string, unknown> | null | undefined): void;
|
|
1368
|
+
registerOnChange(fn: (value: Record<string, unknown>[]) => void): void;
|
|
1369
|
+
registerOnTouched(fn: () => void): void;
|
|
1370
|
+
setDisabledState(isDisabled: boolean): void;
|
|
1371
|
+
protected cellText(row: Record<string, unknown>, path: string): string;
|
|
1372
|
+
/** Opens the row dialog for a new row and appends the result. No-op when the limit is reached. */
|
|
1373
|
+
addRow(): Promise<void>;
|
|
1374
|
+
/** Opens the row dialog for an existing row; in read-only mode the dialog only displays it. */
|
|
1375
|
+
editRow(index: number): Promise<void>;
|
|
1376
|
+
removeRow(index: number): void;
|
|
1377
|
+
moveUp(index: number): void;
|
|
1378
|
+
moveDown(index: number): void;
|
|
1379
|
+
/**
|
|
1380
|
+
* Opens `EntityFormRecordRowDialogComponent` and resolves with the edited row, or `undefined` when
|
|
1381
|
+
* cancelled. Protected seam so specs can stub the dialog.
|
|
1382
|
+
*/
|
|
1383
|
+
protected openRowDialog(row: Record<string, unknown> | null): Promise<Record<string, unknown> | undefined>;
|
|
1384
|
+
private swap;
|
|
1385
|
+
private commit;
|
|
1386
|
+
private loadRecord;
|
|
1387
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormRecordsFieldComponent, never>;
|
|
1388
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityFormRecordsFieldComponent, "mm-entity-form-records-field", never, { "ckRecordId": { "alias": "ckRecordId"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "single": { "alias": "single"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "messages": { "alias": "messages"; "required": false; "isSignal": true; }; "secretWritesDisabled": { "alias": "secretWritesDisabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* Editor of a write-only secret field (AB#5542, AB#5544 item 4, decisions 2026-10-06 Q8/Q10/Q15/Q17).
|
|
1393
|
+
*
|
|
1394
|
+
* - The stored value is never shown or prefilled; the status badge lives in the field shell.
|
|
1395
|
+
* - "Show" reveals only the value the user typed in this session (never a stored value); it is
|
|
1396
|
+
* disabled while the input is empty and resets when the input is emptied.
|
|
1397
|
+
* - "Clear" stages removing an optional secret; the parent sends it on Save as
|
|
1398
|
+
* `clearSecretAttributes`. Clear and a new value are mutually exclusive: Clear is disabled while a
|
|
1399
|
+
* value is typed, and the input is replaced by a note with "Undo" while a clear is staged.
|
|
1400
|
+
* - `multiline` renders a monospace text area (PEM keys, `EntityFormField.Editor: multiline`). It is
|
|
1401
|
+
* masked by rendering the text transparent (caret, selection and placeholder stay visible) and a
|
|
1402
|
+
* status line says how many lines were entered. This works in every browser — unlike
|
|
1403
|
+
* `-webkit-text-security`, which Firefox does not reliably support and which cannot keep line
|
|
1404
|
+
* breaks visible; an `<input type="password">` would drop the PEM line breaks.
|
|
1405
|
+
* - The placeholder is also the input's tooltip, so it stays readable when a narrow panel (Data
|
|
1406
|
+
* Explorer peek) truncates it.
|
|
1407
|
+
* - Read-only users get no editor at all (the badge is enough); without a key ring the input is
|
|
1408
|
+
* disabled and a hint explains why (`writesDisabled`, the parent disables the control).
|
|
1409
|
+
*/
|
|
1410
|
+
declare class EntityFormSecretEditorComponent {
|
|
1411
|
+
readonly control: _angular_core.InputSignal<FormControl<unknown>>;
|
|
1412
|
+
readonly messages: _angular_core.InputSignal<EntityFormsMessages>;
|
|
1413
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
1414
|
+
readonly multiline: _angular_core.InputSignal<boolean>;
|
|
1415
|
+
readonly readOnly: _angular_core.InputSignal<boolean>;
|
|
1416
|
+
/** Offer "Clear": optional SECRET with a stored value, edit mode, write access. */
|
|
1417
|
+
readonly canClear: _angular_core.InputSignal<boolean>;
|
|
1418
|
+
readonly clearStaged: _angular_core.InputSignal<boolean>;
|
|
1419
|
+
/** No key ring (Q17): the input is disabled by the parent; this shows the hint. */
|
|
1420
|
+
readonly writesDisabled: _angular_core.InputSignal<boolean>;
|
|
1421
|
+
/** Change counter of the parent form, read so `hasTypedValue` follows the control value. */
|
|
1422
|
+
readonly revision: _angular_core.InputSignal<number>;
|
|
1423
|
+
readonly clearStagedChange: _angular_core.OutputEmitterRef<boolean>;
|
|
1424
|
+
/** The user asked to reveal the typed value. */
|
|
1425
|
+
protected readonly shown: _angular_core.WritableSignal<boolean>;
|
|
1426
|
+
protected readonly hasTypedValue: _angular_core.Signal<boolean>;
|
|
1427
|
+
/** Only a typed value can be revealed; emptying the input masks it again. */
|
|
1428
|
+
protected readonly revealed: _angular_core.Signal<boolean>;
|
|
1429
|
+
/** Status line of a masked multiline value: the number of lines, never the content. */
|
|
1430
|
+
protected readonly maskedStatus: _angular_core.Signal<string>;
|
|
1431
|
+
constructor();
|
|
1432
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityFormSecretEditorComponent, never>;
|
|
1433
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityFormSecretEditorComponent, "mm-entity-form-secret-editor", never, { "control": { "alias": "control"; "required": true; "isSignal": true; }; "messages": { "alias": "messages"; "required": true; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "multiline": { "alias": "multiline"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "canClear": { "alias": "canClear"; "required": false; "isSignal": true; }; "clearStaged": { "alias": "clearStaged"; "required": false; "isSignal": true; }; "writesDisabled": { "alias": "writesDisabled"; "required": false; "isSignal": true; }; "revision": { "alias": "revision"; "required": false; "isSignal": true; }; }, { "clearStagedChange": "clearStagedChange"; }, never, never, true, never>;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
type EntityFormGetListQueryDto = {
|
|
1437
|
+
__typename?: 'OctoQuery';
|
|
1438
|
+
runtime?: {
|
|
1439
|
+
__typename?: 'RuntimeModelQuery';
|
|
1440
|
+
runtimeEntities?: {
|
|
1441
|
+
__typename?: 'RtEntityGenericDtoConnection';
|
|
1442
|
+
totalCount?: number | null;
|
|
1443
|
+
pageInfo: {
|
|
1444
|
+
__typename?: 'PageInfo';
|
|
1445
|
+
endCursor?: string | null;
|
|
1446
|
+
hasNextPage: boolean;
|
|
1447
|
+
};
|
|
1448
|
+
items?: Array<{
|
|
1449
|
+
__typename?: 'RtEntity';
|
|
1450
|
+
rtId: any;
|
|
1451
|
+
ckTypeId: any;
|
|
1452
|
+
rtWellKnownName?: string | null;
|
|
1453
|
+
rtDisplayName: string;
|
|
1454
|
+
rtCreationDateTime?: any | null;
|
|
1455
|
+
rtChangedDateTime?: any | null;
|
|
1456
|
+
attributes?: {
|
|
1457
|
+
__typename?: 'RtEntityAttributeDtoConnection';
|
|
1458
|
+
items?: Array<{
|
|
1459
|
+
__typename?: 'RtEntityAttribute';
|
|
1460
|
+
attributeName?: string | null;
|
|
1461
|
+
value?: any | null;
|
|
1462
|
+
} | null> | null;
|
|
1463
|
+
} | null;
|
|
1464
|
+
} | null> | null;
|
|
1465
|
+
} | null;
|
|
1466
|
+
} | null;
|
|
1467
|
+
};
|
|
1468
|
+
|
|
1469
|
+
/**
|
|
1470
|
+
* One row of `<mm-entity-list>`. System properties keep their GraphQL names and every list
|
|
1471
|
+
* attribute is flattened onto the row under its camelCase CK attribute name, so a Kendo column
|
|
1472
|
+
* `field` equals the GraphQL `attributePath` and server-side sort / filter work unchanged.
|
|
1473
|
+
*/
|
|
1474
|
+
interface EntityListRow {
|
|
1475
|
+
rtId: string;
|
|
1476
|
+
ckTypeId: string;
|
|
1477
|
+
rtWellKnownName: string | null;
|
|
1478
|
+
rtDisplayName: string | null;
|
|
1479
|
+
rtCreationDateTime: string | null;
|
|
1480
|
+
rtChangedDateTime: string | null;
|
|
1481
|
+
[attributeName: string]: unknown;
|
|
1482
|
+
}
|
|
1483
|
+
type ListItem = NonNullable<NonNullable<NonNullable<NonNullable<EntityFormGetListQueryDto['runtime']>['runtimeEntities']>['items']>[number]>;
|
|
1484
|
+
/**
|
|
1485
|
+
* Attribute names the list may read for a resolved form: the `attribute` list columns, minus
|
|
1486
|
+
* anything flagged secret. The resolver already drops secret columns; the second filter is a
|
|
1487
|
+
* defensive guard so a resolver regression can never put a secret into the list query.
|
|
1488
|
+
*/
|
|
1489
|
+
declare function entityListAttributeNames(model: ResolvedEntityForm): string[];
|
|
1490
|
+
/** Whether the list shows derived types too (`includeDerivedTypes` or an abstract target type). */
|
|
1491
|
+
declare function entityListIncludesDerivedTypes(model: ResolvedEntityForm): boolean;
|
|
1492
|
+
/** Flattens a GraphQL list item into an {@link EntityListRow}. */
|
|
1493
|
+
declare function toEntityListRow(item: ListItem, fallbackCkTypeId: string): EntityListRow;
|
|
1494
|
+
/**
|
|
1495
|
+
* Secret-safe `mm-list-view` data source of `<mm-entity-list>`.
|
|
1496
|
+
*
|
|
1497
|
+
* - Uses the package's own `entityFormGetList` document, whose `$attributeNames` is
|
|
1498
|
+
* `[String]!` — it always sends the explicit list of non-secret list-column attributes
|
|
1499
|
+
* (an omitted variable would make the server return every attribute, secrets included).
|
|
1500
|
+
* - Restricts the query to the exact type with a `ckTypeId EQUALS` field filter unless the
|
|
1501
|
+
* form includes derived types or the type is abstract (`runtimeEntities(ckId)` returns
|
|
1502
|
+
* derived types by default).
|
|
1503
|
+
*/
|
|
1504
|
+
declare class EntityListDataSourceDirective extends OctoGraphQlDataSource<EntityListRow> {
|
|
1505
|
+
private readonly listGQL;
|
|
1506
|
+
private model;
|
|
1507
|
+
private defaultSort;
|
|
1508
|
+
constructor();
|
|
1509
|
+
/**
|
|
1510
|
+
* Sets the order used while the user has not sorted by a column (AB#5623). Refetches when the
|
|
1511
|
+
* order changed and a model is set.
|
|
1512
|
+
*/
|
|
1513
|
+
setDefaultSort(sort: readonly EntityListSortDescriptor[] | null | undefined): void;
|
|
1514
|
+
/** The user's column sort, else the default sort, else `null` (server order). */
|
|
1515
|
+
private effectiveSort;
|
|
1516
|
+
/**
|
|
1517
|
+
* Sets the resolved form and refetches from the first page. `defaultSort` (optional) replaces
|
|
1518
|
+
* the order used while the user has not sorted by a column (see {@link setDefaultSort}).
|
|
1519
|
+
*/
|
|
1520
|
+
setModel(model: ResolvedEntityForm | null, defaultSort?: readonly EntityListSortDescriptor[] | null): void;
|
|
1521
|
+
/** The variables of the next list query (exposed for tests). */
|
|
1522
|
+
buildVariables(options: FetchDataOptions): Record<string, unknown> | null;
|
|
1523
|
+
fetchData(options: FetchDataOptions): Observable<FetchResultTyped<EntityListRow> | null>;
|
|
1524
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityListDataSourceDirective, never>;
|
|
1525
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EntityListDataSourceDirective, "[mmEntityListDataSource]", ["mmEntityListDataSource"], {}, {}, never, never, true, never>;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
/**
|
|
1529
|
+
* Seeded placeholder values of NON-secret configuration attributes (AB#5623), e.g.
|
|
1530
|
+
* `TODO_SET_AZURE_TENANT_ID`, that must read as "not configured" instead of as a real value.
|
|
1531
|
+
*
|
|
1532
|
+
* - A list `readonly string[]` applies to every attribute.
|
|
1533
|
+
* - An object lists values `global`ly and/or per attribute (`attributes`, keyed by attribute name
|
|
1534
|
+
* in any casing: `azureTenantId`, `AzureTenantId`).
|
|
1535
|
+
*
|
|
1536
|
+
* Matching is exact and case-sensitive, on string values only.
|
|
1537
|
+
*/
|
|
1538
|
+
type EntityFormUnsetPlaceholderValues = readonly string[] | {
|
|
1539
|
+
readonly global?: readonly string[];
|
|
1540
|
+
readonly attributes?: Readonly<Record<string, readonly string[]>>;
|
|
1541
|
+
};
|
|
1542
|
+
/**
|
|
1543
|
+
* Placeholder values of non-secret attributes that count as "not configured" (AB#5623). Analogous
|
|
1544
|
+
* to `ENTITY_FORM_SECRET_PLACEHOLDER_VALUES`, but for plain configuration values:
|
|
1545
|
+
*
|
|
1546
|
+
* - **List** (`mm-entity-list`): a cell holding a placeholder shows the `notConfigured` message.
|
|
1547
|
+
* - **Form** (`mm-entity-form`): the field starts empty with the `notConfigured` message as
|
|
1548
|
+
* placeholder hint; the value counts as unset (a required field is invalid, `VisibleWhen` sees no
|
|
1549
|
+
* value).
|
|
1550
|
+
* - **Save**: the form never writes a placeholder back. An untouched placeholder field is not part
|
|
1551
|
+
* of the change set (the stored placeholder stays and keeps reading "not configured"); a typed
|
|
1552
|
+
* value replaces it; emptying the field again is "no change". A host that wants to remove the
|
|
1553
|
+
* placeholder from the store has to write `null` itself (e.g. in `beforeSave`).
|
|
1554
|
+
*
|
|
1555
|
+
* Never applies to secrets (SECRET decision, AB#5528: secret placeholders are dropped; a secret's
|
|
1556
|
+
* state comes from `secretIsSet`): fields with `secret` (value type `SECRET`, CK `secret` metadata,
|
|
1557
|
+
* the credential-name rule or a form decision) and attributes listed in `secretFields` are skipped,
|
|
1558
|
+
* even when listed here.
|
|
1559
|
+
*
|
|
1560
|
+
* Optional; not provided = no placeholders (unchanged behaviour). The library ships no values.
|
|
1561
|
+
*/
|
|
1562
|
+
declare const ENTITY_FORM_UNSET_PLACEHOLDER_VALUES: InjectionToken<EntityFormUnsetPlaceholderValues>;
|
|
1563
|
+
/** Normalised lookup of {@link EntityFormUnsetPlaceholderValues}. */
|
|
1564
|
+
interface EntityFormUnsetPlaceholderLookup {
|
|
1565
|
+
readonly global: ReadonlySet<string>;
|
|
1566
|
+
/** Keyed by lower-case attribute name. */
|
|
1567
|
+
readonly attributes: ReadonlyMap<string, ReadonlySet<string>>;
|
|
1568
|
+
}
|
|
1569
|
+
/** Builds the lookup of a placeholder configuration (`null` / `undefined` = none). */
|
|
1570
|
+
declare function entityFormUnsetPlaceholderLookup(config: EntityFormUnsetPlaceholderValues | null | undefined): EntityFormUnsetPlaceholderLookup;
|
|
1571
|
+
/** What is known about the attribute a value belongs to. */
|
|
1572
|
+
interface EntityFormUnsetPlaceholderTarget {
|
|
1573
|
+
attributeName: string;
|
|
1574
|
+
valueType?: string | null;
|
|
1575
|
+
/** The field / column is treated as a secret (any reason). */
|
|
1576
|
+
secret?: boolean;
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Whether `value` is a configured placeholder of the attribute. Always `false` for secrets
|
|
1580
|
+
* (`secret` flag or value type `SECRET`) and for non-string values.
|
|
1581
|
+
*/
|
|
1582
|
+
declare function isEntityFormUnsetPlaceholder(lookup: EntityFormUnsetPlaceholderLookup, target: EntityFormUnsetPlaceholderTarget, value: unknown): boolean;
|
|
1583
|
+
/**
|
|
1584
|
+
* Keys of the fields whose value in `values` (form values or `state.values`, keyed by field key)
|
|
1585
|
+
* is an unset placeholder. Only non-secret attribute fields are considered.
|
|
1586
|
+
*/
|
|
1587
|
+
declare function entityFormUnsetPlaceholderFields(model: ResolvedEntityForm, values: Readonly<Record<string, unknown>> | null | undefined, lookup: EntityFormUnsetPlaceholderLookup): string[];
|
|
1588
|
+
|
|
1589
|
+
/** Payload of {@link EntityListComponent.createRequested}: the concrete type to create. */
|
|
1590
|
+
interface EntityListCreateRequest {
|
|
1591
|
+
ckTypeId: string;
|
|
1592
|
+
}
|
|
1593
|
+
/** Payload of {@link EntityListComponent.openRequested}. */
|
|
1594
|
+
interface EntityListOpenRequest {
|
|
1595
|
+
rtId: string;
|
|
1596
|
+
ckTypeId: string;
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* CSS classes of one list row (AB#5623), e.g. `{ 'row-disabled': row['enabled'] === false }`.
|
|
1600
|
+
* Same shapes as Angular's `[ngClass]`; `null` / `undefined` = no class. The classes are set on the
|
|
1601
|
+
* row's `<tr>` of the Kendo grid, so style them with global (or `::ng-deep`) CSS of the host.
|
|
1602
|
+
*/
|
|
1603
|
+
type EntityListRowClass = (row: EntityListRow) => string | string[] | Record<string, boolean> | null | undefined;
|
|
1604
|
+
/**
|
|
1605
|
+
* App-wide default of {@link EntityListComponent.rowClass} (AB#5623). The input (and
|
|
1606
|
+
* `mm-entity-page`'s `listRowClass` / route data `entityListRowClass`) wins.
|
|
1607
|
+
*/
|
|
1608
|
+
declare const ENTITY_LIST_ROW_CLASS: InjectionToken<EntityListRowClass>;
|
|
1609
|
+
/**
|
|
1610
|
+
* Maps an {@link EntityListRowClass} onto `mm-list-view`'s `rowClass`. A throwing callback is
|
|
1611
|
+
* logged and yields no class, so a host bug never breaks the list.
|
|
1612
|
+
*/
|
|
1613
|
+
declare function toListViewRowClass(rowClass: EntityListRowClass | null | undefined): RowClassFn | undefined;
|
|
1614
|
+
/** Labels of boolean list cells (default "Yes" / "No"). */
|
|
1615
|
+
interface EntityListCellLabels {
|
|
1616
|
+
yes?: string;
|
|
1617
|
+
no?: string;
|
|
1618
|
+
/** Text of a cell holding an unset placeholder (AB#5623). Default "Not configured". */
|
|
1619
|
+
notConfigured?: string;
|
|
1620
|
+
}
|
|
1621
|
+
/**
|
|
1622
|
+
* How BOOLEAN list columns without an explicit `display` render (AB#5623): `'text'` (Yes / No,
|
|
1623
|
+
* default) or `'icon'` (check / x icon named "<column>: Yes|No", filterable as boolean).
|
|
1624
|
+
*/
|
|
1625
|
+
type EntityListBooleanDisplay = 'text' | 'icon';
|
|
1626
|
+
/** Options of {@link toEntityListColumn}. */
|
|
1627
|
+
interface EntityListColumnOptions {
|
|
1628
|
+
/** See {@link EntityListBooleanDisplay}. Default `'text'`. */
|
|
1629
|
+
booleanDisplay?: EntityListBooleanDisplay;
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Maps a resolved list column onto an `mm-list-view` column definition. Cells are formatted by the
|
|
1633
|
+
* CK value type like the reference display of the form (AB#5547): ENUM → the enum value's name
|
|
1634
|
+
* (the API returns the key), BOOLEAN → yes/no, dates → localized date and time.
|
|
1635
|
+
*/
|
|
1636
|
+
declare function toEntityListColumn(column: ResolvedListColumn, labels?: EntityListCellLabels, unsetPlaceholders?: EntityFormUnsetPlaceholderLookup, options?: EntityListColumnOptions): TableColumn;
|
|
1637
|
+
/**
|
|
1638
|
+
* `<mm-entity-list>` — the list view of a resolved entity form.
|
|
1639
|
+
*
|
|
1640
|
+
* Columns come from the form's `ListColumns` (secret columns are never listed or queried).
|
|
1641
|
+
* Row click and the "Edit"/"View" action emit {@link openRequested}; "New" emits
|
|
1642
|
+
* {@link createRequested} — for an abstract type only after the user picked a concrete
|
|
1643
|
+
* subtype. The context menu carries the Copy ID submenu (RtId / CkTypeId / RtCkTypeId /
|
|
1644
|
+
* RtEntityId) and, when `canDelete && canWrite`, Delete with a confirmation.
|
|
1645
|
+
*
|
|
1646
|
+
* Host extensions (AB#5623): `toolbarActions` (after New), `rowActions` (icon buttons in the
|
|
1647
|
+
* actions column after Edit/View), `rowMenuActions` (context menu between Copy ID and Delete) —
|
|
1648
|
+
* plain `CommandItem`s as in `mm-list-view`; `onClick` receives the row (`EntityListRow`) as
|
|
1649
|
+
* `e.data`. `rowClass` sets CSS classes per row (e.g. disabled rows). `defaultSort` (or the form's `listDefaultSort`) orders the list while the user has not
|
|
1650
|
+
* sorted by a column; `labelResolver` translates column titles and enum texts.
|
|
1651
|
+
*
|
|
1652
|
+
* The component does not navigate; `<mm-entity-page>` (or the host) reacts to the outputs.
|
|
1653
|
+
*/
|
|
1654
|
+
declare class EntityListComponent {
|
|
1655
|
+
private readonly confirmationService;
|
|
1656
|
+
private readonly dangerConfirmation;
|
|
1657
|
+
private readonly actionConfirmation;
|
|
1658
|
+
private readonly notificationService;
|
|
1659
|
+
private readonly dataService;
|
|
1660
|
+
private readonly ckTypeSelectorDialog;
|
|
1661
|
+
/** Resolves `EntityFormService` lazily: only the Type column needs the form titles. */
|
|
1662
|
+
private readonly injector;
|
|
1663
|
+
private readonly injectedLabelResolver;
|
|
1664
|
+
private readonly injectedRowClass;
|
|
1665
|
+
private readonly unsetPlaceholders;
|
|
1666
|
+
/** Form titles per CK type (lower-case id) for the Type column (AB#5524). */
|
|
1667
|
+
private readonly typeTitles;
|
|
1668
|
+
private typeTitlesRequested;
|
|
1669
|
+
/** The resolved form (`EntityFormService.resolve` / `resolveByFormKey`). */
|
|
1670
|
+
readonly model: _angular_core.InputSignal<ResolvedEntityForm>;
|
|
1671
|
+
/** Whether the current user may write (mapped from roles by the host). Default `true`. */
|
|
1672
|
+
readonly canWrite: _angular_core.InputSignal<boolean>;
|
|
1673
|
+
/** Partial message overrides; missing keys use the English defaults. */
|
|
1674
|
+
readonly messages: _angular_core.InputSignal<Partial<EntityFormsMessages>>;
|
|
1675
|
+
/** `mm-list-view` state persistence key; defaults to the route path. */
|
|
1676
|
+
readonly listStateKey: _angular_core.InputSignal<string | undefined>;
|
|
1677
|
+
/**
|
|
1678
|
+
* Appends a "Type" column with the display name of each row's CK type (lists over a base type):
|
|
1679
|
+
* the title of the type's entity form, else the humanized type name (AB#5524).
|
|
1680
|
+
*/
|
|
1681
|
+
readonly showTypeColumn: _angular_core.InputSignal<boolean>;
|
|
1682
|
+
/**
|
|
1683
|
+
* Order while the user has not sorted by a column (AB#5623). Wins over the form's
|
|
1684
|
+
* `listDefaultSort`; `[]` = server order. A sort the user picked (also a remembered one from
|
|
1685
|
+
* `listStateKey`) always wins. The column header shows no sort marker for the default order.
|
|
1686
|
+
*/
|
|
1687
|
+
readonly defaultSort: _angular_core.InputSignal<readonly EntityListSortDescriptor[] | null | undefined>;
|
|
1688
|
+
/** Translates column titles and enum texts (AB#5623); wins over `ENTITY_FORM_LABEL_RESOLVER`. */
|
|
1689
|
+
readonly labelResolver: _angular_core.InputSignal<EntityFormLabelResolver | null | undefined>;
|
|
1690
|
+
/** Host toolbar actions, shown after "New" (AB#5623). */
|
|
1691
|
+
readonly toolbarActions: _angular_core.InputSignal<readonly CommandItem[]>;
|
|
1692
|
+
/**
|
|
1693
|
+
* Host row actions (AB#5623): icon buttons in the actions column after Edit / View. Set
|
|
1694
|
+
* `svgIcon` and `text` (tooltip / aria-label); `onClick` gets the row as `e.data`.
|
|
1695
|
+
*/
|
|
1696
|
+
readonly rowActions: _angular_core.InputSignal<readonly CommandItem[]>;
|
|
1697
|
+
/** Host row menu entries (AB#5623): context menu, between Copy ID and Delete. */
|
|
1698
|
+
readonly rowMenuActions: _angular_core.InputSignal<readonly CommandItem[]>;
|
|
1699
|
+
/**
|
|
1700
|
+
* CSS classes per row (AB#5623), e.g. to style disabled rows. Wins over `ENTITY_LIST_ROW_CLASS`;
|
|
1701
|
+
* absent = no row classes (unchanged). See {@link EntityListRowClass}.
|
|
1702
|
+
*/
|
|
1703
|
+
readonly rowClass: _angular_core.InputSignal<EntityListRowClass | null | undefined>;
|
|
1704
|
+
/**
|
|
1705
|
+
* How BOOLEAN columns without an explicit display render (AB#5623): `'text'` (Yes / No, default)
|
|
1706
|
+
* or `'icon'` (check / x with an accessible name, boolean filter). A column's own
|
|
1707
|
+
* `display: icon` always renders as icon.
|
|
1708
|
+
*/
|
|
1709
|
+
readonly booleanDisplay: _angular_core.InputSignal<EntityListBooleanDisplay>;
|
|
1710
|
+
/**
|
|
1711
|
+
* Row field used as the row's human label (AB#5623): row action names ("Actions for <label>"),
|
|
1712
|
+
* the delete confirmation target. A dotted path reads a nested value. Absent = today's
|
|
1713
|
+
* behaviour (`name`, then `rtWellKnownName`, display name, `rtId`).
|
|
1714
|
+
*/
|
|
1715
|
+
readonly rowLabelField: _angular_core.InputSignal<string | null | undefined>;
|
|
1716
|
+
/** "New" was confirmed; carries the concrete type (after the subtype picker for abstract types). */
|
|
1717
|
+
readonly createRequested: _angular_core.OutputEmitterRef<EntityListCreateRequest>;
|
|
1718
|
+
/** A row was opened. */
|
|
1719
|
+
readonly openRequested: _angular_core.OutputEmitterRef<EntityListOpenRequest>;
|
|
1720
|
+
/** Entities were deleted. */
|
|
1721
|
+
readonly deleted: _angular_core.OutputEmitterRef<EntityListOpenRequest[]>;
|
|
1722
|
+
private readonly dataSource;
|
|
1723
|
+
protected readonly msgs: _angular_core.Signal<EntityFormsMessages>;
|
|
1724
|
+
protected readonly listViewMessages: _angular_core.Signal<{
|
|
1725
|
+
searchPlaceholder: string;
|
|
1726
|
+
noRecords: string;
|
|
1727
|
+
booleanYes: string;
|
|
1728
|
+
booleanNo: string;
|
|
1729
|
+
}>;
|
|
1730
|
+
protected readonly columns: _angular_core.Signal<TableColumn[]>;
|
|
1731
|
+
protected readonly canCreate: _angular_core.Signal<boolean>;
|
|
1732
|
+
protected readonly canDelete: _angular_core.Signal<boolean>;
|
|
1733
|
+
protected readonly editable: _angular_core.Signal<boolean>;
|
|
1734
|
+
/** Copy ID submenu (Studio convention, see the refinery-studio CLAUDE.md). */
|
|
1735
|
+
readonly copyIdMenuItem: _angular_core.Signal<CommandItem>;
|
|
1736
|
+
/**
|
|
1737
|
+
* Context menu: Copy ID, the host's `rowMenuActions`, then (only with `canDelete && canWrite`)
|
|
1738
|
+
* separator + Delete.
|
|
1739
|
+
*/
|
|
1740
|
+
readonly contextMenuItems: _angular_core.Signal<CommandItem[]>;
|
|
1741
|
+
/** Row action column: Edit (or View when read-only), then the host's `rowActions`. */
|
|
1742
|
+
readonly actionItems: _angular_core.Signal<CommandItem[]>;
|
|
1743
|
+
/** The `mm-list-view` row class callback (input, else the token, else none). */
|
|
1744
|
+
protected readonly listViewRowClass: _angular_core.Signal<RowClassFn | undefined>;
|
|
1745
|
+
/** Width of the actions column: Edit/View + the row menu, plus one icon button per host row action. */
|
|
1746
|
+
protected readonly actionsColumnWidth: _angular_core.Signal<number>;
|
|
1747
|
+
/** Toolbar: New (only with `canCreate && canWrite`), then the host's `toolbarActions`. */
|
|
1748
|
+
readonly toolbarItems: _angular_core.Signal<CommandItem[]>;
|
|
1749
|
+
/** The order used while the user has not sorted: the input, else the form's `listDefaultSort`. */
|
|
1750
|
+
protected readonly effectiveDefaultSort: _angular_core.Signal<readonly EntityListSortDescriptor[]>;
|
|
1751
|
+
constructor();
|
|
1752
|
+
/** Loads the form titles of the Type column once; without them the type names are humanized. */
|
|
1753
|
+
private loadTypeTitles;
|
|
1754
|
+
/** Reloads the list. */
|
|
1755
|
+
refresh(): void;
|
|
1756
|
+
/**
|
|
1757
|
+
* Starts "New". For an abstract type (`createRequiresSubtype`) the concrete-subtype picker
|
|
1758
|
+
* opens first; cancelling it emits nothing.
|
|
1759
|
+
*/
|
|
1760
|
+
requestCreate(): Promise<void>;
|
|
1761
|
+
protected onRowClicked(rows: unknown[]): void;
|
|
1762
|
+
private open;
|
|
1763
|
+
private onDelete;
|
|
1764
|
+
private copy;
|
|
1765
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityListComponent, never>;
|
|
1766
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityListComponent, "mm-entity-list", never, { "model": { "alias": "model"; "required": true; "isSignal": true; }; "canWrite": { "alias": "canWrite"; "required": false; "isSignal": true; }; "messages": { "alias": "messages"; "required": false; "isSignal": true; }; "listStateKey": { "alias": "listStateKey"; "required": false; "isSignal": true; }; "showTypeColumn": { "alias": "showTypeColumn"; "required": false; "isSignal": true; }; "defaultSort": { "alias": "defaultSort"; "required": false; "isSignal": true; }; "labelResolver": { "alias": "labelResolver"; "required": false; "isSignal": true; }; "toolbarActions": { "alias": "toolbarActions"; "required": false; "isSignal": true; }; "rowActions": { "alias": "rowActions"; "required": false; "isSignal": true; }; "rowMenuActions": { "alias": "rowMenuActions"; "required": false; "isSignal": true; }; "rowClass": { "alias": "rowClass"; "required": false; "isSignal": true; }; "booleanDisplay": { "alias": "booleanDisplay"; "required": false; "isSignal": true; }; "rowLabelField": { "alias": "rowLabelField"; "required": false; "isSignal": true; }; }, { "createRequested": "createRequested"; "openRequested": "openRequested"; "deleted": "deleted"; }, never, never, true, never>;
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* `System.Communication/SftpConfiguration` → `SFTP configuration`.
|
|
1770
|
+
* @deprecated Use `humanizeCkTypeName` (or `ckTypeDisplayName` with form titles).
|
|
1771
|
+
*/
|
|
1772
|
+
declare function shortTypeName(ckTypeId: string): string;
|
|
1773
|
+
|
|
1774
|
+
/** Template context of {@link EntityPageActionsDirective} (AB#5623). */
|
|
1775
|
+
interface EntityPageActionsContext {
|
|
1776
|
+
/** The context object itself (`let-ctx`). */
|
|
1777
|
+
$implicit: EntityPageActionsContext;
|
|
1778
|
+
/** Which part of the page is shown. */
|
|
1779
|
+
view: 'list' | 'form';
|
|
1780
|
+
/** Form mode (`null` on the list). */
|
|
1781
|
+
mode: EntityFormMode | null;
|
|
1782
|
+
/** rtId of the open entity (`null` on the list and in create mode). */
|
|
1783
|
+
rtId: string | null;
|
|
1784
|
+
/** Runtime CK type of the open entity, else of the list. */
|
|
1785
|
+
ckTypeId: string | null;
|
|
1786
|
+
/** The resolved form of the open entity, else of the list. */
|
|
1787
|
+
model: ResolvedEntityForm | null;
|
|
1788
|
+
/** True while a save is running. */
|
|
1789
|
+
saving: boolean;
|
|
1790
|
+
/**
|
|
1791
|
+
* The page (typed loosely to avoid a circular import): call `saveChanges()`, `patchFormValues()`
|
|
1792
|
+
* or `refreshList()` on it, e.g. `(ctx.page as EntityPageComponent).patchFormValues({...})`.
|
|
1793
|
+
*/
|
|
1794
|
+
page: unknown;
|
|
1795
|
+
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Host page actions of `<mm-entity-page>` (AB#5623): the template is rendered next to the page's
|
|
1798
|
+
* own buttons — in the list header, and in the form's action bar (header or bottom bar, see
|
|
1799
|
+
* `actionBarPosition`) before Cancel / Delete / Save.
|
|
1800
|
+
*
|
|
1801
|
+
* ```html
|
|
1802
|
+
* <mm-entity-page formKey="form-company-profile">
|
|
1803
|
+
* <ng-template mmEntityPageActions let-ctx>
|
|
1804
|
+
* @if (ctx.view === 'form') {
|
|
1805
|
+
* <button kendoButton fillMode="flat" (click)="export(ctx.rtId)">Export</button>
|
|
1806
|
+
* }
|
|
1807
|
+
* </ng-template>
|
|
1808
|
+
* </mm-entity-page>
|
|
1809
|
+
* ```
|
|
1810
|
+
*/
|
|
1811
|
+
declare class EntityPageActionsDirective {
|
|
1812
|
+
readonly templateRef: TemplateRef<EntityPageActionsContext>;
|
|
1813
|
+
static ngTemplateContextGuard(_dir: EntityPageActionsDirective, _ctx: unknown): _ctx is EntityPageActionsContext;
|
|
1814
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityPageActionsDirective, never>;
|
|
1815
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EntityPageActionsDirective, "ng-template[mmEntityPageActions]", never, {}, {}, never, never, true, never>;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
/** Value of the `rtId` input / route parameter that opens the create form. */
|
|
1819
|
+
declare const ENTITY_PAGE_NEW = "new";
|
|
1820
|
+
/**
|
|
1821
|
+
* Query parameter carrying the concrete runtime CK type of the entity to create or open
|
|
1822
|
+
* (`new?type=…` after the subtype picker of an abstract type, `:rtId?type=…` for an entity of
|
|
1823
|
+
* a derived type). Named `type`, not `ckTypeId`, so that `withComponentInputBinding` never
|
|
1824
|
+
* binds it onto the page's `ckTypeId` input (the form's target type).
|
|
1825
|
+
*/
|
|
1826
|
+
declare const ENTITY_PAGE_TYPE_QUERY_PARAM = "type";
|
|
1827
|
+
/** Event of {@link EntityPageComponent.navigate}. */
|
|
1828
|
+
interface EntityPageNavigateEvent {
|
|
1829
|
+
kind: 'list' | 'create' | 'edit';
|
|
1830
|
+
rtId?: string;
|
|
1831
|
+
ckTypeId?: string;
|
|
1832
|
+
}
|
|
1833
|
+
/** Event of {@link EntityPageComponent.saved}: an entity was created or updated. */
|
|
1834
|
+
interface EntityPageSavedEvent {
|
|
1835
|
+
kind: 'create' | 'update';
|
|
1836
|
+
rtId: string;
|
|
1837
|
+
ckTypeId: string;
|
|
1838
|
+
}
|
|
1839
|
+
/** Event of {@link EntityPageComponent.deleted}. */
|
|
1840
|
+
interface EntityPageDeletedEvent {
|
|
1841
|
+
rtId: string;
|
|
1842
|
+
ckTypeId: string;
|
|
1843
|
+
}
|
|
1844
|
+
/** Which part of the page is shown. */
|
|
1845
|
+
type EntityPageView = 'loading' | 'list' | 'form' | 'error';
|
|
1846
|
+
/** Where the form's Save / Cancel / Delete buttons sit (AB#5623). */
|
|
1847
|
+
type EntityPageActionBarPosition = 'top' | 'bottom';
|
|
1848
|
+
/**
|
|
1849
|
+
* How create / edit of a list row opens (AB#5623): `'page'` (navigate to the `new` / `:rtId`
|
|
1850
|
+
* route, default) or `'dialog'` (a dialog over the list; the URL does not change).
|
|
1851
|
+
*/
|
|
1852
|
+
type EntityPageEditMode = 'page' | 'dialog';
|
|
1853
|
+
/**
|
|
1854
|
+
* Prefill of the create form (AB#5623): the values, or a function of the concrete type to create
|
|
1855
|
+
* (called once per create form; may return `null`).
|
|
1856
|
+
*/
|
|
1857
|
+
type EntityPageInitialValues = EntityFormPrefillValues | ((context: {
|
|
1858
|
+
ckTypeId: string;
|
|
1859
|
+
}) => EntityFormPrefillValues | null | undefined);
|
|
1860
|
+
/**
|
|
1861
|
+
* `<mm-entity-page>` — route component that combines `<mm-entity-list>` and `<mm-entity-form>`
|
|
1862
|
+
* for one form (by `formKey`) or CK type (by `ckTypeId`).
|
|
1863
|
+
*
|
|
1864
|
+
* - No `rtId` → list (or, for a singleton form, the singleton entity directly).
|
|
1865
|
+
* - `rtId === 'new'` → create form (`?type=` carries the concrete subtype of an abstract type).
|
|
1866
|
+
* - any other `rtId` → edit form (or view form without write permission).
|
|
1867
|
+
*
|
|
1868
|
+
* Inputs can be bound by `withComponentInputBinding()` from route params / data; without it the
|
|
1869
|
+
* page falls back to `ActivatedRoute` (params, data of this route and its parents, query params).
|
|
1870
|
+
* Navigation is relative (`..`, `new`, `:rtId`), so it works under any mount point; set
|
|
1871
|
+
* `routerNavigation` to `false` and handle {@link navigate} to drive it yourself.
|
|
1872
|
+
*
|
|
1873
|
+
* Host extensions (AB#5623, all optional, defaults = unchanged behaviour): `actionBarPosition`
|
|
1874
|
+
* (Save / Cancel at the bottom), page actions via `<ng-template mmEntityPageActions>`, list
|
|
1875
|
+
* `listToolbarActions` / `listRowActions` / `listRowMenuActions`, `defaultSort`, `labelResolver`
|
|
1876
|
+
* (translated labels and enum texts), `initialValues` (create prefill),
|
|
1877
|
+
* {@link patchFormValues} (prefill from a host action), `beforeSave` (normalise / veto the
|
|
1878
|
+
* change set before it is saved), `listRowClass` (CSS classes per row) and `editMode: 'dialog'`
|
|
1879
|
+
* (create / edit in a dialog over the list).
|
|
1880
|
+
*
|
|
1881
|
+
* Dialog mode (`editMode: 'dialog'`, AB#5623): "New", row click and Edit / View open the form in
|
|
1882
|
+
* a Kendo dialog over the list instead of navigating. The same form, hooks and texts apply
|
|
1883
|
+
* (`beforeSave`, `initialValues`, `labelResolver`, secrets, page actions with `view: 'form'`);
|
|
1884
|
+
* actions sit in the dialog's bottom bar (page actions, Cancel, Delete, Save — Cancel left of the
|
|
1885
|
+
* primary Save). Cancel, the close button and Escape ask before discarding unsaved changes; a
|
|
1886
|
+
* route change while the dialog has changes goes through the unsaved-changes guard. After a save
|
|
1887
|
+
* or delete the dialog closes and the list reloads; focus returns to the element that opened the
|
|
1888
|
+
* dialog. No `navigate` events are emitted for dialog transitions. The `new` / `:rtId` routes keep
|
|
1889
|
+
* working as pages (deep links); singleton forms always use the page.
|
|
1890
|
+
*/
|
|
1891
|
+
declare class EntityPageComponent implements HasUnsavedChanges {
|
|
1892
|
+
private readonly route;
|
|
1893
|
+
private readonly router;
|
|
1894
|
+
private readonly formService;
|
|
1895
|
+
private readonly dataService;
|
|
1896
|
+
private readonly listGQL;
|
|
1897
|
+
private readonly notificationService;
|
|
1898
|
+
private readonly confirmationService;
|
|
1899
|
+
private readonly actionConfirmation;
|
|
1900
|
+
private readonly dangerConfirmation;
|
|
1901
|
+
private readonly breadCrumbService;
|
|
1902
|
+
private readonly injectedLabelResolver;
|
|
1903
|
+
private readonly injectedBeforeSave;
|
|
1904
|
+
/** Form key (`form-sftp-configuration` or `sftp-configuration`). Wins over `ckTypeId`. */
|
|
1905
|
+
readonly formKey: _angular_core.InputSignal<string | undefined>;
|
|
1906
|
+
/** Runtime CK type id of the form's target type (used when no `formKey` is given). */
|
|
1907
|
+
readonly ckTypeId: _angular_core.InputSignal<string | undefined>;
|
|
1908
|
+
/** Entity to edit; `'new'` opens the create form; absent shows the list. */
|
|
1909
|
+
readonly rtId: _angular_core.InputSignal<string | undefined>;
|
|
1910
|
+
/** Whether the user may write. Falls back to route data `canWrite`, then `true`. */
|
|
1911
|
+
readonly canWrite: _angular_core.InputSignal<boolean | undefined>;
|
|
1912
|
+
/** Partial message overrides; falls back to route data `messages`, then English. */
|
|
1913
|
+
readonly messages: _angular_core.InputSignal<Partial<EntityFormsMessages> | undefined>;
|
|
1914
|
+
/** Perform the default relative Router navigation (in addition to emitting {@link navigate}). */
|
|
1915
|
+
readonly routerNavigation: _angular_core.InputSignal<boolean>;
|
|
1916
|
+
/**
|
|
1917
|
+
* Where Save / Cancel / Delete sit on the form (AB#5623): `'top'` (header, default) or
|
|
1918
|
+
* `'bottom'` (a bar below the form, right-aligned). Falls back to route data
|
|
1919
|
+
* `entityPageActionBarPosition`.
|
|
1920
|
+
*/
|
|
1921
|
+
readonly actionBarPosition: _angular_core.InputSignal<EntityPageActionBarPosition | undefined>;
|
|
1922
|
+
/** Translates labels, titles and enum texts (AB#5623); wins over `ENTITY_FORM_LABEL_RESOLVER`. */
|
|
1923
|
+
readonly labelResolver: _angular_core.InputSignal<EntityFormLabelResolver | null | undefined>;
|
|
1924
|
+
/** List order while the user has not sorted (AB#5623). Falls back to route data `entityListDefaultSort`, then the form's `listDefaultSort`. */
|
|
1925
|
+
readonly defaultSort: _angular_core.InputSignal<readonly EntityListSortDescriptor[] | null | undefined>;
|
|
1926
|
+
/** Prefill of the create form (AB#5623). Falls back to route data `entityFormInitialValues`. */
|
|
1927
|
+
readonly initialValues: _angular_core.InputSignal<EntityPageInitialValues | null | undefined>;
|
|
1928
|
+
/**
|
|
1929
|
+
* Hook run before every save (AB#5623): may modify the change set or veto the save. Wins over
|
|
1930
|
+
* route data `entityFormBeforeSave` and `ENTITY_FORM_BEFORE_SAVE`. See {@link EntityFormBeforeSaveHook}.
|
|
1931
|
+
*/
|
|
1932
|
+
readonly beforeSave: _angular_core.InputSignal<EntityFormBeforeSaveHook | null | undefined>;
|
|
1933
|
+
/** Host toolbar actions of the list, after "New" (AB#5623). */
|
|
1934
|
+
readonly listToolbarActions: _angular_core.InputSignal<readonly CommandItem[]>;
|
|
1935
|
+
/** Host row actions of the list (icon buttons after Edit / View, AB#5623). */
|
|
1936
|
+
readonly listRowActions: _angular_core.InputSignal<readonly CommandItem[]>;
|
|
1937
|
+
/** Host row menu entries of the list (context menu, AB#5623). */
|
|
1938
|
+
readonly listRowMenuActions: _angular_core.InputSignal<readonly CommandItem[]>;
|
|
1939
|
+
/**
|
|
1940
|
+
* How create / edit opens (AB#5623): `'page'` (default) or `'dialog'` (over the list). Falls back
|
|
1941
|
+
* to route data `entityPageEditMode`. Ignored for singleton forms.
|
|
1942
|
+
*/
|
|
1943
|
+
readonly editMode: _angular_core.InputSignal<EntityPageEditMode | undefined>;
|
|
1944
|
+
/**
|
|
1945
|
+
* CSS classes per list row (AB#5623), passed to `mm-entity-list`'s `rowClass`. Falls back to
|
|
1946
|
+
* route data `entityListRowClass`, then `ENTITY_LIST_ROW_CLASS`.
|
|
1947
|
+
*/
|
|
1948
|
+
readonly listRowClass: _angular_core.InputSignal<EntityListRowClass | null | undefined>;
|
|
1949
|
+
/**
|
|
1950
|
+
* How the list renders BOOLEAN columns (AB#5623), passed to `mm-entity-list`'s `booleanDisplay`:
|
|
1951
|
+
* `'text'` (default) or `'icon'`. Falls back to route data `entityListBooleanDisplay`.
|
|
1952
|
+
*/
|
|
1953
|
+
readonly listBooleanDisplay: _angular_core.InputSignal<EntityListBooleanDisplay | undefined>;
|
|
1954
|
+
/**
|
|
1955
|
+
* Field naming a row / entity for people (AB#5623): passed to `mm-entity-list`'s
|
|
1956
|
+
* `rowLabelField` (row action names, delete confirmation) and used for the dialog / page title
|
|
1957
|
+
* ("Edit <label>") and the delete confirmation of the open entity. Falls back to route data
|
|
1958
|
+
* `entityListRowLabelField`; absent = today's behaviour (`name`, well-known name, display name, rtId).
|
|
1959
|
+
*/
|
|
1960
|
+
readonly listRowLabelField: _angular_core.InputSignal<string | undefined>;
|
|
1961
|
+
/** Emitted for every list / create / edit transition. */
|
|
1962
|
+
readonly navigate: _angular_core.OutputEmitterRef<EntityPageNavigateEvent>;
|
|
1963
|
+
/** Emitted after a successful create or update (not for "no changes"). Hosts refresh their lists on it. */
|
|
1964
|
+
readonly saved: _angular_core.OutputEmitterRef<EntityPageSavedEvent>;
|
|
1965
|
+
/** Emitted after the open entity was deleted from the form (before the navigation to the list). */
|
|
1966
|
+
readonly deleted: _angular_core.OutputEmitterRef<EntityPageDeletedEvent>;
|
|
1967
|
+
private readonly form;
|
|
1968
|
+
/** Why Save / Create is disabled (e.g. a required secret without key ring, Q17), or `null`. */
|
|
1969
|
+
protected readonly saveBlockedReason: _angular_core.Signal<string | null>;
|
|
1970
|
+
private readonly list;
|
|
1971
|
+
private readonly listElement;
|
|
1972
|
+
/** Host page actions (`<ng-template mmEntityPageActions>`, AB#5623). */
|
|
1973
|
+
protected readonly pageActions: _angular_core.Signal<EntityPageActionsDirective | undefined>;
|
|
1974
|
+
private readonly paramMap;
|
|
1975
|
+
private readonly queryParamMap;
|
|
1976
|
+
private readonly routeData;
|
|
1977
|
+
protected readonly view: _angular_core.WritableSignal<EntityPageView>;
|
|
1978
|
+
protected readonly errorMessage: _angular_core.WritableSignal<string | null>;
|
|
1979
|
+
/** The form resolved for the page's type (list + breadcrumb title). */
|
|
1980
|
+
protected readonly baseModel: _angular_core.WritableSignal<ResolvedEntityForm | null>;
|
|
1981
|
+
/** The form resolved for the entity's concrete type (create / edit). */
|
|
1982
|
+
protected readonly formModel: _angular_core.WritableSignal<ResolvedEntityForm | null>;
|
|
1983
|
+
protected readonly mode: _angular_core.WritableSignal<EntityFormMode>;
|
|
1984
|
+
protected readonly state: _angular_core.WritableSignal<EntityFormValueState | undefined>;
|
|
1985
|
+
protected readonly entityRtId: _angular_core.WritableSignal<string | null>;
|
|
1986
|
+
protected readonly entityCkTypeId: _angular_core.WritableSignal<string | null>;
|
|
1987
|
+
protected readonly entityName: _angular_core.WritableSignal<string | null>;
|
|
1988
|
+
protected readonly saving: _angular_core.WritableSignal<boolean>;
|
|
1989
|
+
/** Record metadata of the form's type (type conversion of record sub-values in the form). */
|
|
1990
|
+
protected readonly records: _angular_core.WritableSignal<Record<string, CkRecordInfo>>;
|
|
1991
|
+
/** Well-known name forced onto a singleton that is created on first save. */
|
|
1992
|
+
protected readonly singletonWellKnownName: _angular_core.WritableSignal<string | null>;
|
|
1993
|
+
/** The create / edit dialog over the list is shown (`editMode: 'dialog'`, AB#5623). */
|
|
1994
|
+
protected readonly dialogOpen: _angular_core.WritableSignal<boolean>;
|
|
1995
|
+
protected readonly saveIcon: _progress_kendo_svg_icons.SVGIcon;
|
|
1996
|
+
protected readonly backIcon: _progress_kendo_svg_icons.SVGIcon;
|
|
1997
|
+
protected readonly deleteIcon: _progress_kendo_svg_icons.SVGIcon;
|
|
1998
|
+
protected readonly msgs: _angular_core.Signal<EntityFormsMessages>;
|
|
1999
|
+
protected readonly effectiveCanWrite: _angular_core.Signal<boolean>;
|
|
2000
|
+
protected readonly effectiveLabelResolver: _angular_core.Signal<EntityFormLabelResolver | null>;
|
|
2001
|
+
/** The effective before-save hook: input, else route data `entityFormBeforeSave`, else the token. */
|
|
2002
|
+
private effectiveBeforeSave;
|
|
2003
|
+
/** `'dialog'` only for non-singleton forms with `editMode` (input, else route data) `'dialog'`. */
|
|
2004
|
+
protected readonly effectiveEditMode: _angular_core.Signal<EntityPageEditMode>;
|
|
2005
|
+
protected readonly effectiveActionBarPosition: _angular_core.Signal<EntityPageActionBarPosition>;
|
|
2006
|
+
/** `undefined` = no page-level default (the list falls back to the form's `listDefaultSort`). */
|
|
2007
|
+
protected readonly effectiveDefaultSort: _angular_core.Signal<readonly EntityListSortDescriptor[] | undefined>;
|
|
2008
|
+
/** The list's row class callback: input, else route data `entityListRowClass` (else the list's token). */
|
|
2009
|
+
protected readonly effectiveListRowClass: _angular_core.Signal<EntityListRowClass | undefined>;
|
|
2010
|
+
/** Row label field: input, else route data `entityListRowLabelField`, else none (default naming). */
|
|
2011
|
+
protected readonly effectiveRowLabelField: _angular_core.Signal<string | undefined>;
|
|
2012
|
+
/** Boolean columns of the list: input, else route data `entityListBooleanDisplay`, else text. */
|
|
2013
|
+
protected readonly effectiveListBooleanDisplay: _angular_core.Signal<EntityListBooleanDisplay>;
|
|
2014
|
+
/** The prefill of the current create form (AB#5623), computed when the form opens. */
|
|
2015
|
+
protected readonly createInitialValues: _angular_core.WritableSignal<Readonly<Record<string, unknown>> | null>;
|
|
2016
|
+
/** Base model with translated title / description (list header). */
|
|
2017
|
+
protected readonly localizedBase: _angular_core.Signal<ResolvedEntityForm | null>;
|
|
2018
|
+
/**
|
|
2019
|
+
* Breadcrumb labels (`{{entityFormTitle}}` / `{{entityName}}`), derived from the page state so
|
|
2020
|
+
* they follow a language change of the label resolver or the messages (AB#5623). `null` while
|
|
2021
|
+
* nothing is resolved.
|
|
2022
|
+
*/
|
|
2023
|
+
protected readonly breadcrumbLabels: _angular_core.Signal<Record<string, string> | null>;
|
|
2024
|
+
/** Context of the host page actions template. */
|
|
2025
|
+
protected readonly actionsContext: _angular_core.Signal<EntityPageActionsContext>;
|
|
2026
|
+
/** Context of the host page actions in the create / edit dialog (always the form view). */
|
|
2027
|
+
protected readonly dialogActionsContext: _angular_core.Signal<EntityPageActionsContext>;
|
|
2028
|
+
private buildActionsContext;
|
|
2029
|
+
protected readonly isSingleton: _angular_core.Signal<boolean>;
|
|
2030
|
+
/** Host heading override (`entityListTitle` route data), else the resolved form title. */
|
|
2031
|
+
protected readonly listTitle: _angular_core.Signal<string>;
|
|
2032
|
+
/** `entityListTypeColumn` route data: show the row's CK type in the list. */
|
|
2033
|
+
protected readonly showTypeColumn: _angular_core.Signal<boolean>;
|
|
2034
|
+
protected readonly readOnly: _angular_core.Signal<boolean>;
|
|
2035
|
+
protected readonly canDeleteEntity: _angular_core.Signal<boolean>;
|
|
2036
|
+
protected readonly title: _angular_core.Signal<string>;
|
|
2037
|
+
/** The effective navigation context (inputs win over the route). */
|
|
2038
|
+
private readonly context;
|
|
2039
|
+
private loadToken;
|
|
2040
|
+
private suppressGuard;
|
|
2041
|
+
/** Where the next loaded form is shown: the page, or the dialog over the list. */
|
|
2042
|
+
private formTarget;
|
|
2043
|
+
/** Element focused when the dialog opened; focused again when it closes. */
|
|
2044
|
+
private dialogTrigger;
|
|
2045
|
+
constructor();
|
|
2046
|
+
hasUnsavedChanges(): boolean;
|
|
2047
|
+
unsavedChangesMessages(): UnsavedChangesMessages;
|
|
2048
|
+
/**
|
|
2049
|
+
* Validates and saves the form. Creates the entity in create mode (then switches to its edit
|
|
2050
|
+
* route), updates only the changed attributes in edit mode. Resolves `false` when the form is
|
|
2051
|
+
* invalid or the server rejected the change.
|
|
2052
|
+
*/
|
|
2053
|
+
saveChanges(): Promise<boolean>;
|
|
2054
|
+
protected onSave(): Promise<void>;
|
|
2055
|
+
protected onBack(): Promise<void>;
|
|
2056
|
+
protected onCreateRequested(event: EntityListCreateRequest): Promise<void>;
|
|
2057
|
+
protected onOpenRequested(event: EntityListOpenRequest): Promise<void>;
|
|
2058
|
+
/** Cancel, the dialog's close button and Escape: asks before discarding unsaved changes. */
|
|
2059
|
+
protected onDialogCancel(): Promise<void>;
|
|
2060
|
+
protected onDelete(): Promise<void>;
|
|
2061
|
+
private load;
|
|
2062
|
+
private openCreate;
|
|
2063
|
+
private openSingleton;
|
|
2064
|
+
private startCreate;
|
|
2065
|
+
/**
|
|
2066
|
+
* Loads an entity into the form. When the entity turns out to be of a different (derived)
|
|
2067
|
+
* type than the model, the form for that type is resolved and the values are read again with
|
|
2068
|
+
* its attribute list. Resolves `false` when the entity does not exist.
|
|
2069
|
+
*/
|
|
2070
|
+
private openEntity;
|
|
2071
|
+
private applyLoaded;
|
|
2072
|
+
private recordsFor;
|
|
2073
|
+
private modelForType;
|
|
2074
|
+
/** rtId of the first entity of the type (singleton forms without a well-known name). */
|
|
2075
|
+
private firstEntityRtId;
|
|
2076
|
+
private resetEntity;
|
|
2077
|
+
private fail;
|
|
2078
|
+
/** Shows the loaded form: on the page, or in the dialog over the list. */
|
|
2079
|
+
private showForm;
|
|
2080
|
+
/** Loads the create / edit form into the dialog over the list. */
|
|
2081
|
+
private openDialog;
|
|
2082
|
+
/**
|
|
2083
|
+
* Closes the dialog without asking, optionally reloads the list, and gives the focus back to
|
|
2084
|
+
* the element that opened the dialog (or the list when that element is gone).
|
|
2085
|
+
*/
|
|
2086
|
+
private closeDialog;
|
|
2087
|
+
private go;
|
|
2088
|
+
/** Reads a route data key from this route or the nearest ancestor that defines it. */
|
|
2089
|
+
private inheritedData;
|
|
2090
|
+
/** Reloads the list (when the list is shown). */
|
|
2091
|
+
refreshList(): void;
|
|
2092
|
+
/**
|
|
2093
|
+
* Sets values of the open form from the host (AB#5623), e.g. a "Prefill from user" page action.
|
|
2094
|
+
* See `EntityFormComponent.patchValues`: the values always count as user edits (the form gets
|
|
2095
|
+
* dirty, the unsaved-changes guard applies and Save sends them); secret and read-only fields are
|
|
2096
|
+
* skipped. Returns the field keys that were set (`[]` when no writable form is shown).
|
|
2097
|
+
*/
|
|
2098
|
+
patchFormValues(values: EntityFormPrefillValues): string[];
|
|
2099
|
+
/** Translated title of a model (AB#5623). */
|
|
2100
|
+
private formTitle;
|
|
2101
|
+
/** The host prefill for a create form of the given type. */
|
|
2102
|
+
private initialValuesFor;
|
|
2103
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityPageComponent, never>;
|
|
2104
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityPageComponent, "mm-entity-page", never, { "formKey": { "alias": "formKey"; "required": false; "isSignal": true; }; "ckTypeId": { "alias": "ckTypeId"; "required": false; "isSignal": true; }; "rtId": { "alias": "rtId"; "required": false; "isSignal": true; }; "canWrite": { "alias": "canWrite"; "required": false; "isSignal": true; }; "messages": { "alias": "messages"; "required": false; "isSignal": true; }; "routerNavigation": { "alias": "routerNavigation"; "required": false; "isSignal": true; }; "actionBarPosition": { "alias": "actionBarPosition"; "required": false; "isSignal": true; }; "labelResolver": { "alias": "labelResolver"; "required": false; "isSignal": true; }; "defaultSort": { "alias": "defaultSort"; "required": false; "isSignal": true; }; "initialValues": { "alias": "initialValues"; "required": false; "isSignal": true; }; "beforeSave": { "alias": "beforeSave"; "required": false; "isSignal": true; }; "listToolbarActions": { "alias": "listToolbarActions"; "required": false; "isSignal": true; }; "listRowActions": { "alias": "listRowActions"; "required": false; "isSignal": true; }; "listRowMenuActions": { "alias": "listRowMenuActions"; "required": false; "isSignal": true; }; "editMode": { "alias": "editMode"; "required": false; "isSignal": true; }; "listRowClass": { "alias": "listRowClass"; "required": false; "isSignal": true; }; "listBooleanDisplay": { "alias": "listBooleanDisplay"; "required": false; "isSignal": true; }; "listRowLabelField": { "alias": "listRowLabelField"; "required": false; "isSignal": true; }; }, { "navigate": "navigate"; "saved": "saved"; "deleted": "deleted"; }, ["pageActions"], never, true, never>;
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
/**
|
|
2108
|
+
* Options of {@link entityFormRoutes}.
|
|
2109
|
+
*
|
|
2110
|
+
* Route parameter contract (stable, relied upon by the Refinery Studio, AB#5523):
|
|
2111
|
+
*
|
|
2112
|
+
* | Path | Page state |
|
|
2113
|
+
* |-----------|---------------------------------------------------------------------|
|
|
2114
|
+
* | `''` | list (a singleton form opens its entity directly) |
|
|
2115
|
+
* | `new` | create form; `?type=<rtCkTypeId>` = concrete type (abstract forms) |
|
|
2116
|
+
* | `:rtId` | edit form (view form without write permission); optional `?type=` |
|
|
2117
|
+
*
|
|
2118
|
+
* Route `data` carries `formKey` / `ckTypeId` / `canWrite` / `messages` (bound to the page
|
|
2119
|
+
* inputs by `withComponentInputBinding()`, read from `ActivatedRoute` otherwise), the `new`
|
|
2120
|
+
* route additionally `rtId: 'new'`, and the `breadcrumb` items with the `{{entityFormTitle}}` /
|
|
2121
|
+
* `{{entityName}}` labels the page fills via `BreadCrumbService.updateBreadcrumbLabels`.
|
|
2122
|
+
*/
|
|
2123
|
+
interface EntityFormRoutesOptions {
|
|
2124
|
+
/** Form key (`form-sftp-configuration` or `sftp-configuration`). Wins over `ckTypeId`. */
|
|
2125
|
+
formKey?: string;
|
|
2126
|
+
/** Runtime CK type id of the target type, used when no `formKey` is given. */
|
|
2127
|
+
ckTypeId?: string;
|
|
2128
|
+
/**
|
|
2129
|
+
* Write permission for every user who can reach the routes. Hosts with role-dependent
|
|
2130
|
+
* permissions bind `canWrite` on their own wrapper or pass it as route data of a parent.
|
|
2131
|
+
*/
|
|
2132
|
+
canWrite?: boolean;
|
|
2133
|
+
/** Message overrides passed to the page. */
|
|
2134
|
+
messages?: Partial<EntityFormsMessages>;
|
|
2135
|
+
/**
|
|
2136
|
+
* Breadcrumb URL of the list (relative to the host's breadcrumb root, e.g.
|
|
2137
|
+
* `communication/sftp`). Without it no breadcrumb items are added.
|
|
2138
|
+
*/
|
|
2139
|
+
breadcrumbUrl?: string;
|
|
2140
|
+
/** Label of the list breadcrumb. Default `{{entityFormTitle}}` (the resolved form title). */
|
|
2141
|
+
breadcrumbLabel?: string;
|
|
2142
|
+
/**
|
|
2143
|
+
* Heading of the list (and of the singleton form) instead of the resolved form's title — e.g.
|
|
2144
|
+
* "All configurations" for a generic list over a base type whose `form-default` title would be
|
|
2145
|
+
* the type name. Route data key `entityListTitle`.
|
|
2146
|
+
*/
|
|
2147
|
+
title?: string;
|
|
2148
|
+
/**
|
|
2149
|
+
* Adds a "Type" column (short CK type name of each row) to the list — for lists over a base type
|
|
2150
|
+
* with derived types. Route data key `entityListTypeColumn`.
|
|
2151
|
+
*/
|
|
2152
|
+
showTypeColumn?: boolean;
|
|
2153
|
+
/**
|
|
2154
|
+
* Order of the list while the user has not sorted by a column (AB#5623). Wins over the form's
|
|
2155
|
+
* `listDefaultSort`. Route data key `entityListDefaultSort`.
|
|
2156
|
+
*/
|
|
2157
|
+
defaultSort?: EntityListSortDescriptor[];
|
|
2158
|
+
/**
|
|
2159
|
+
* Where the form's Save / Cancel / Delete buttons sit (AB#5623): `'top'` (header, default) or
|
|
2160
|
+
* `'bottom'` (bar below the form). Route data key `entityPageActionBarPosition`.
|
|
2161
|
+
*/
|
|
2162
|
+
actionBarPosition?: 'top' | 'bottom';
|
|
2163
|
+
/** Prefill of the create form (AB#5623). Route data key `entityFormInitialValues`. */
|
|
2164
|
+
initialValues?: EntityFormPrefillValues;
|
|
2165
|
+
/**
|
|
2166
|
+
* Hook run before every save (AB#5623): normalise / derive values or veto the save. Route data
|
|
2167
|
+
* key `entityFormBeforeSave`. See `EntityFormBeforeSaveHook`.
|
|
2168
|
+
*/
|
|
2169
|
+
beforeSave?: EntityFormBeforeSaveHook;
|
|
2170
|
+
/**
|
|
2171
|
+
* CSS classes per list row (AB#5623), e.g. to style disabled rows. Route data key
|
|
2172
|
+
* `entityListRowClass`. See `EntityListRowClass`.
|
|
2173
|
+
*/
|
|
2174
|
+
rowClass?: EntityListRowClass;
|
|
2175
|
+
/**
|
|
2176
|
+
* `'dialog'` opens create / edit of a list row in a dialog over the list instead of navigating
|
|
2177
|
+
* to `new` / `:rtId` (AB#5623; those routes still work as pages). Default `'page'`. Route data
|
|
2178
|
+
* key `entityPageEditMode`.
|
|
2179
|
+
*/
|
|
2180
|
+
editMode?: 'page' | 'dialog';
|
|
2181
|
+
/**
|
|
2182
|
+
* `'icon'` renders the list's BOOLEAN columns as check / x icons (AB#5623). Default `'text'`.
|
|
2183
|
+
* Route data key `entityListBooleanDisplay`.
|
|
2184
|
+
*/
|
|
2185
|
+
booleanDisplay?: 'text' | 'icon';
|
|
2186
|
+
/**
|
|
2187
|
+
* Field naming a row / entity for people (AB#5623): row action names, dialog / page title and
|
|
2188
|
+
* delete confirmations. Route data key `entityListRowLabelField`.
|
|
2189
|
+
*/
|
|
2190
|
+
rowLabelField?: string;
|
|
2191
|
+
/** Label of the create breadcrumb. Default `New`. */
|
|
2192
|
+
newBreadcrumbLabel?: string;
|
|
2193
|
+
/** Label of the edit breadcrumb. Default `{{entityName}}`. */
|
|
2194
|
+
entityBreadcrumbLabel?: string;
|
|
2195
|
+
/** Icon of the list breadcrumb. */
|
|
2196
|
+
svgIcon?: SVGIcon;
|
|
2197
|
+
/** Additional route data merged into all three routes (e.g. `roles`). */
|
|
2198
|
+
data?: Record<string, unknown>;
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* Builds the three child routes of an entity form page: `''` (list), `new` (create) and
|
|
2202
|
+
* `:rtId` (edit), each rendering `EntityPageComponent` lazily and guarded by
|
|
2203
|
+
* `UnsavedChangesGuard`. Mount them under any path:
|
|
2204
|
+
*
|
|
2205
|
+
* ```ts
|
|
2206
|
+
* { path: 'sftp', children: entityFormRoutes({ formKey: 'sftp-configuration', breadcrumbUrl: 'communication/sftp' }) }
|
|
2207
|
+
* ```
|
|
2208
|
+
*/
|
|
2209
|
+
declare function entityFormRoutes(opts?: EntityFormRoutesOptions): Routes;
|
|
2210
|
+
|
|
2211
|
+
/** Minimal shape of an `RtEntity` row as returned by `entityFormGetEntityForms`. */
|
|
2212
|
+
interface RawRtEntityRow {
|
|
2213
|
+
rtId: string;
|
|
2214
|
+
rtWellKnownName?: string | null;
|
|
2215
|
+
ckTypeId?: string | null;
|
|
2216
|
+
attributes?: {
|
|
2217
|
+
items?: ({
|
|
2218
|
+
attributeName?: string | null;
|
|
2219
|
+
value?: unknown;
|
|
2220
|
+
} | null)[] | null;
|
|
2221
|
+
} | null;
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Parses one `System.UI/EntityForm` row of the generic runtime API into an
|
|
2225
|
+
* {@link EntityFormDefinition}. Returns `null` when the row has no `TargetCkTypeId`.
|
|
2226
|
+
* Absent optionals stay `undefined`; explicit `null` values from the server are kept as `null`.
|
|
2227
|
+
*/
|
|
2228
|
+
declare function parseEntityForm(row: RawRtEntityRow): EntityFormDefinition | null;
|
|
2229
|
+
/** Parses every row; rows without a target type are dropped. */
|
|
2230
|
+
declare function parseEntityForms(rows: readonly (RawRtEntityRow | null | undefined)[] | null | undefined): EntityFormDefinition[];
|
|
2231
|
+
|
|
2232
|
+
/** Section key of the implicit section used when a form declares no sections. */
|
|
2233
|
+
declare const DEFAULT_SECTION_KEY = "__default";
|
|
2234
|
+
/** Section key of the section holding generated (unmentioned) attributes. */
|
|
2235
|
+
declare const GENERATED_SECTION_KEY = "__generated";
|
|
2236
|
+
/** Default title of the generated section. */
|
|
2237
|
+
declare const DEFAULT_GENERATED_SECTION_TITLE = "Further attributes";
|
|
2238
|
+
type EntityFormSource = 'tenant' | 'seeded';
|
|
2239
|
+
interface ResolveEntityFormOptions {
|
|
2240
|
+
/** Record metadata keyed by versioned ckRecordId (CkAttributeInfo.ckRecordId). */
|
|
2241
|
+
records?: Record<string, CkRecordInfo>;
|
|
2242
|
+
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Picks the form for a type. Exact-target forms win; otherwise the nearest ancestor that has
|
|
2245
|
+
* forms with `includeDerivedTypes` supplies the candidates. Candidates are ordered tenant before
|
|
2246
|
+
* seeded, then priority descending, then rtWellKnownName/rtId ascending. Forms are never merged.
|
|
2247
|
+
*/
|
|
2248
|
+
declare function pickEntityForm(type: CkTypeInfo, forms: readonly EntityFormDefinition[]): {
|
|
2249
|
+
form: EntityFormDefinition;
|
|
2250
|
+
source: EntityFormSource;
|
|
2251
|
+
} | null;
|
|
2252
|
+
/** Editor chosen when the form says `auto`, nothing, or something unknown. */
|
|
2253
|
+
declare function autoEditorFor(valueType: string | null | undefined): EntityFormEditor;
|
|
2254
|
+
/** True when an explicit editor can edit the given value type. */
|
|
2255
|
+
declare function isEditorCompatible(editor: EntityFormEditor, valueType: string | null | undefined): boolean;
|
|
2256
|
+
/**
|
|
2257
|
+
* Form control key of an association field: `assoc:<rtRoleId>` with `.` replaced by `_` —
|
|
2258
|
+
* Angular FormGroup keys must not contain `.` ("FormGroup keys cannot include '.'" for role ids
|
|
2259
|
+
* such as `System.Communication/Manages`, visual check 2026-10-06). The key is only an id; the
|
|
2260
|
+
* role itself travels on `ResolvedField.association`.
|
|
2261
|
+
*/
|
|
2262
|
+
declare function associationFieldKey(rtRoleId: string): string;
|
|
2263
|
+
/**
|
|
2264
|
+
* The default list order of a form (AB#5623): `listDefaultSort` canonicalised against the type.
|
|
2265
|
+
* Unknown paths, secrets and record attributes are dropped (with a warning); `rtId` sorts by id.
|
|
2266
|
+
*/
|
|
2267
|
+
declare function resolveListDefaultSort(form: EntityFormDefinition, type: CkTypeInfo, secretNames: ReadonlySet<string>, warnings?: string[]): EntityListSortDescriptor[];
|
|
2268
|
+
/**
|
|
2269
|
+
* Resolves the form for a type: picks it ({@link pickEntityForm}), falls back to
|
|
2270
|
+
* {@link BUILT_IN_DEFAULT_FORM} (`source: 'builtIn'`, with a warning), and matches every field
|
|
2271
|
+
* against the CK metadata. See plan §2.2 for the normative rules; they are implemented here
|
|
2272
|
+
* in the order they are listed there.
|
|
2273
|
+
*/
|
|
2274
|
+
declare function resolveEntityForm(type: CkTypeInfo, forms: readonly EntityFormDefinition[], opts?: ResolveEntityFormOptions): ResolvedEntityForm;
|
|
2275
|
+
|
|
2276
|
+
/**
|
|
2277
|
+
* URL key of a form (`sftp-configuration`), accepted by `EntityFormService.resolveByFormKey`:
|
|
2278
|
+
* the well-known name without the `form-` prefix, otherwise the kebab-cased target type name.
|
|
2279
|
+
* The well-known name wins because the kebab form of some type names differs from the seeded
|
|
2280
|
+
* name (`EMailSenderConfiguration` → `e-mail-sender-configuration`, seeded as
|
|
2281
|
+
* `form-email-sender-configuration`).
|
|
2282
|
+
*/
|
|
2283
|
+
declare function entityFormKey(form: Pick<EntityFormDefinition, 'rtWellKnownName' | 'targetCkTypeId'>): string;
|
|
2284
|
+
/** One entry of {@link entityFormCatalog}: the effective form of one target type. */
|
|
2285
|
+
interface EntityFormCatalogEntry {
|
|
2286
|
+
/** URL key (see {@link entityFormKey}); stable per target type. */
|
|
2287
|
+
key: string;
|
|
2288
|
+
/** Settings category key (`connections`, `ai`, …), lower case. */
|
|
2289
|
+
category: string;
|
|
2290
|
+
title: string;
|
|
2291
|
+
description?: string;
|
|
2292
|
+
icon?: string;
|
|
2293
|
+
targetCkTypeId: string;
|
|
2294
|
+
includeDerivedTypes: boolean;
|
|
2295
|
+
singleton: boolean;
|
|
2296
|
+
/** The form that wins for the target type (tenant form before seeded, then priority). */
|
|
2297
|
+
form: EntityFormDefinition;
|
|
2298
|
+
}
|
|
2299
|
+
/**
|
|
2300
|
+
* The forms that belong in a settings overview (concept §5.6): one entry per target type whose
|
|
2301
|
+
* effective form has a `Category`. The effective form is picked like the resolver does for an
|
|
2302
|
+
* exact type match (tenant form first, then higher priority, then well-known name), so a tenant
|
|
2303
|
+
* override replaces the delivered entry — and can also move it to another category or remove it
|
|
2304
|
+
* from the overview by leaving `Category` empty. The key prefers a delivered `form-*` name of
|
|
2305
|
+
* the type, so URLs stay stable when a tenant form is added. Sorted by title.
|
|
2306
|
+
*/
|
|
2307
|
+
declare function entityFormCatalog(forms: readonly EntityFormDefinition[]): EntityFormCatalogEntry[];
|
|
2308
|
+
/**
|
|
2309
|
+
* Display names of CK types from the forms (AB#5524): per target type (lower-case key) the
|
|
2310
|
+
* `Name` of its effective form (tenant form first, then priority), for every form with a name —
|
|
2311
|
+
* also forms without `Category`. CK types carry no display name of their own.
|
|
2312
|
+
*/
|
|
2313
|
+
declare function entityFormTypeTitles(forms: readonly EntityFormDefinition[]): Map<string, string>;
|
|
2314
|
+
/**
|
|
2315
|
+
* Display name of a CK type: the form title of {@link entityFormTypeTitles} when there is one,
|
|
2316
|
+
* else {@link humanizeCkTypeName} (`FinApiConfiguration` → `finAPI configuration`).
|
|
2317
|
+
*/
|
|
2318
|
+
declare function ckTypeDisplayName(ckTypeId: string, titles?: ReadonlyMap<string, string>): string;
|
|
2319
|
+
|
|
2320
|
+
/**
|
|
2321
|
+
* Human-readable names of CK types (AB#5524): `System.Communication/EMailReceiverConfiguration-1`
|
|
2322
|
+
* → `E-mail receiver configuration`, `…/FinApiConfiguration` → `finAPI configuration`.
|
|
2323
|
+
*
|
|
2324
|
+
* CK types carry no display name, so a name is derived from the type name: PascalCase is split
|
|
2325
|
+
* into words in sentence case, and known acronyms / brand names keep their spelling.
|
|
2326
|
+
*/
|
|
2327
|
+
/** `System.Communication/SftpConfiguration-1` → `SftpConfiguration` (no model, no version). */
|
|
2328
|
+
declare function ckTypeShortName(ckTypeId: string): string;
|
|
2329
|
+
/**
|
|
2330
|
+
* Human-readable name of a CK type id or type name, in sentence case with known acronyms and
|
|
2331
|
+
* brand names (`SAP`, `SFTP`, `AI`, `EDA`, `E-mail`, `finAPI`, `weclapp`, …). Returns the input
|
|
2332
|
+
* when it holds no name.
|
|
2333
|
+
*/
|
|
2334
|
+
declare function humanizeCkTypeName(ckTypeIdOrName: string): string;
|
|
2335
|
+
|
|
2336
|
+
/**
|
|
2337
|
+
* Built-in copy of the seeded `form-default` (platform-services
|
|
2338
|
+
* `SystemUiCkModel/Blueprints/System.UI.EntityForms/seed-data/entities.yaml`, rtId
|
|
2339
|
+
* 670300000000000000000001), transcribed field by field.
|
|
2340
|
+
*
|
|
2341
|
+
* Used when a tenant has no applicable form at all: System.UI < 2.7.0 (no EntityForm type), the
|
|
2342
|
+
* forms query failed, or `form-default` was deleted. Keep it in step with the seed; a spec asserts
|
|
2343
|
+
* that it resolves exactly like the parsed seed entity.
|
|
2344
|
+
*/
|
|
2345
|
+
declare const BUILT_IN_DEFAULT_FORM: EntityFormDefinition;
|
|
2346
|
+
|
|
2347
|
+
/**
|
|
2348
|
+
* Host-provided built-in forms (AB#5524). Each one stands in for a delivered form of its target
|
|
2349
|
+
* type **only where the normal resolution would end at the chain end** (`form-default` on
|
|
2350
|
+
* `System/Entity`, or no form at all) — e.g. before a new version of the seeding blueprint has
|
|
2351
|
+
* been rolled out. A tenant or seeded form for the exact type, or for an ancestor with
|
|
2352
|
+
* `IncludeDerivedTypes`, always wins over a fallback. Same idea as the built-in `form-default`
|
|
2353
|
+
* safety net (concept §5.3 step 4), but per type and owned by the host.
|
|
2354
|
+
*
|
|
2355
|
+
* Provide them at root with this token, or — to keep the entry point out of the initial bundle —
|
|
2356
|
+
* with `provideEntityFormFallbacks(forms)` on lazy routes (registers them in the root
|
|
2357
|
+
* `EntityFormService`, one cache).
|
|
2358
|
+
*
|
|
2359
|
+
* Use the delivered form's `rtWellKnownName` (`form-sap-configuration`) so URL keys stay the same
|
|
2360
|
+
* when the seeded form arrives, set `isTenantForm: false` and leave `rtId` empty. As soon as any
|
|
2361
|
+
* form (tenant or seeded) targets the type, the fallback is ignored — a tenant can therefore hide
|
|
2362
|
+
* a fallback entry from a settings overview by creating a form without `Category`.
|
|
2363
|
+
*/
|
|
2364
|
+
declare const ENTITY_FORM_FALLBACK_FORMS: InjectionToken<readonly EntityFormDefinition[]>;
|
|
2365
|
+
/**
|
|
2366
|
+
* The loaded forms plus every fallback whose target type no loaded form targets (exact type,
|
|
2367
|
+
* case-insensitive). Later fallbacks for an already covered type are dropped as well.
|
|
2368
|
+
*/
|
|
2369
|
+
declare function withFallbackForms(loaded: readonly EntityFormDefinition[], fallbacks: readonly EntityFormDefinition[] | null | undefined): EntityFormDefinition[];
|
|
2370
|
+
/** The end of the resolution chain: a form on `System/Entity` (the seeded or built-in `form-default`). */
|
|
2371
|
+
declare function isChainEndForm(form: Pick<EntityFormDefinition, 'targetCkTypeId'>): boolean;
|
|
2372
|
+
/**
|
|
2373
|
+
* The fallbacks that apply on top of the loaded forms: per target type (first fallback wins),
|
|
2374
|
+
* only when the type exists (`typeOf` returns its CK metadata) and `pickEntityForm(type, loaded)`
|
|
2375
|
+
* finds nothing or only the chain end. Fallbacks for a type without metadata are dropped, so a
|
|
2376
|
+
* tenant without that model gets no Settings entry for it.
|
|
2377
|
+
*/
|
|
2378
|
+
declare function selectFallbackForms(loaded: readonly EntityFormDefinition[], fallbacks: readonly EntityFormDefinition[] | null | undefined, typeOf: (rtCkTypeId: string) => CkTypeInfo | null | undefined): EntityFormDefinition[];
|
|
2379
|
+
|
|
2380
|
+
/** A destructive action the entity form components are about to run (AB#5524). */
|
|
2381
|
+
interface EntityFormActionRequest {
|
|
2382
|
+
action: 'delete';
|
|
2383
|
+
/** Runtime CK type id of the (first) affected entity. */
|
|
2384
|
+
ckTypeId: string;
|
|
2385
|
+
/** Number of affected entities. */
|
|
2386
|
+
count: number;
|
|
2387
|
+
/** Short English description, e.g. `delete 2 entities`. */
|
|
2388
|
+
description: string;
|
|
2389
|
+
}
|
|
2390
|
+
/**
|
|
2391
|
+
* Optional host hook asked **before** the component's own danger confirmation of a destructive
|
|
2392
|
+
* action — e.g. the Refinery Studio's production-mode check (`TenantModeService
|
|
2393
|
+
* .confirmProductionAction`), which the former configuration list ran before deleting. Resolve
|
|
2394
|
+
* `false` to cancel. Provide it on the route (or root) injector of the pages that render
|
|
2395
|
+
* `mm-entity-list` / `mm-entity-page`.
|
|
2396
|
+
*/
|
|
2397
|
+
type EntityFormActionConfirmation = (request: EntityFormActionRequest) => Promise<boolean>;
|
|
2398
|
+
declare const ENTITY_FORM_ACTION_CONFIRMATION: InjectionToken<EntityFormActionConfirmation>;
|
|
2399
|
+
/** Runs the host hook (absent = allowed); a throwing hook cancels the action. */
|
|
2400
|
+
declare function confirmEntityFormAction(hook: EntityFormActionConfirmation | null | undefined, request: EntityFormActionRequest): Promise<boolean>;
|
|
2401
|
+
/**
|
|
2402
|
+
* Optional host replacement of the components' own danger confirmation (AB#5579). By default
|
|
2403
|
+
* `mm-entity-list` / `mm-entity-page` ask `ConfirmationService.showDangerConfirm(options)`; a host
|
|
2404
|
+
* that adds environment knowledge (e.g. the Refinery Studio's `DangerConfirmService`: production =
|
|
2405
|
+
* type the name) provides this token instead and then usually needs no
|
|
2406
|
+
* {@link ENTITY_FORM_ACTION_CONFIRMATION} for deletes. Resolve `false` to cancel.
|
|
2407
|
+
*/
|
|
2408
|
+
type EntityFormDangerConfirmation = (options: DangerConfirmationOptions, request: EntityFormActionRequest) => Promise<boolean>;
|
|
2409
|
+
declare const ENTITY_FORM_DANGER_CONFIRMATION: InjectionToken<EntityFormDangerConfirmation>;
|
|
2410
|
+
/**
|
|
2411
|
+
* The danger confirmation of an entity delete (AB#5579): the title names the entity (or the
|
|
2412
|
+
* count), `confirmText` = verb + object, texts from {@link EntityFormsMessages}.
|
|
2413
|
+
*/
|
|
2414
|
+
declare function entityDeleteConfirmation(messages: EntityFormsMessages, names: readonly string[]): DangerConfirmationOptions;
|
|
2415
|
+
/** Asks the host replacement (when provided) or `ConfirmationService.showDangerConfirm`; errors cancel. */
|
|
2416
|
+
declare function confirmEntityFormDanger(hook: EntityFormDangerConfirmation | null | undefined, confirmation: ConfirmationService, options: DangerConfirmationOptions, request: EntityFormActionRequest): Promise<boolean>;
|
|
2417
|
+
|
|
2418
|
+
/**
|
|
2419
|
+
* Whether secrets can be written in this environment (decision Q17, AB#5544): `false` when the
|
|
2420
|
+
* environment has no key ring (`SecretEnvironmentStatusDto.keyRingConfigured`, bot services
|
|
2421
|
+
* `GET {tenantId}/v1/secrets/status`). Then every secret input of `mm-entity-form` is disabled with
|
|
2422
|
+
* a hint instead of failing late on save (`SecretEncryptionNotConfigured`).
|
|
2423
|
+
*
|
|
2424
|
+
* Optional: without a provider (or while the signal is `null` / `undefined`) secrets are writable.
|
|
2425
|
+
* The host provides it from its status client, e.g.
|
|
2426
|
+
* `{ provide: ENTITY_FORM_SECRET_KEY_RING_CONFIGURED, useFactory: () => statusService.keyRingConfigured }`.
|
|
2427
|
+
*/
|
|
2428
|
+
declare const ENTITY_FORM_SECRET_KEY_RING_CONFIGURED: InjectionToken<Signal<boolean | null | undefined>>;
|
|
2429
|
+
/**
|
|
2430
|
+
* Values that count as "not set" for LEGACY secret fields (AB#5623): plain `STRING` attributes
|
|
2431
|
+
* treated as secrets by form decision, CK metadata or the credential-name rule. Their presence is
|
|
2432
|
+
* probed with field filters (`IS_NOT_NULL` and `NOT_EQUALS ''`); each value listed here adds a
|
|
2433
|
+
* `NOT_EQUALS <value>` filter, so a seeded placeholder (exact, case-sensitive match) reads
|
|
2434
|
+
* "Not set" instead of "Set".
|
|
2435
|
+
*
|
|
2436
|
+
* Optional; not provided = only `null` and `''` count as not set (unchanged behaviour). The
|
|
2437
|
+
* library ships no placeholder values of its own — the host lists the ones its seed data uses.
|
|
2438
|
+
* It has no effect on attributes of value type `SECRET` (AB#5528): their state comes from the
|
|
2439
|
+
* server (`secretIsSet`), which is the reliable way — migrate secrets to `SECRET` where possible.
|
|
2440
|
+
*/
|
|
2441
|
+
declare const ENTITY_FORM_SECRET_PLACEHOLDER_VALUES: InjectionToken<readonly string[]>;
|
|
2442
|
+
|
|
2443
|
+
/**
|
|
2444
|
+
* Entity system properties that a form may reference by AttributePath. They are not CK
|
|
2445
|
+
* attributes: `rtWellKnownName` is written through `RtEntityInput.rtWellKnownName`, the two
|
|
2446
|
+
* timestamps are engine-stamped and always read-only.
|
|
2447
|
+
*/
|
|
2448
|
+
declare const SYSTEM_PROPERTIES: readonly string[];
|
|
2449
|
+
/** Result of matching a form AttributePath against the CK metadata of a type. */
|
|
2450
|
+
type CanonicalPath = {
|
|
2451
|
+
kind: 'attribute';
|
|
2452
|
+
name: string;
|
|
2453
|
+
attribute: CkAttributeInfo;
|
|
2454
|
+
} | {
|
|
2455
|
+
kind: 'system';
|
|
2456
|
+
name: string;
|
|
2457
|
+
} | {
|
|
2458
|
+
kind: 'rtId';
|
|
2459
|
+
} | {
|
|
2460
|
+
kind: 'dotted';
|
|
2461
|
+
path: string;
|
|
2462
|
+
} | {
|
|
2463
|
+
kind: 'unknown';
|
|
2464
|
+
path: string;
|
|
2465
|
+
};
|
|
2466
|
+
/**
|
|
2467
|
+
* Canonicalises a form AttributePath (forms use PascalCase, the CK API camelCase):
|
|
2468
|
+
* system properties and attributes match case-insensitively, `rtId` is reported separately
|
|
2469
|
+
* (never a field), dotted paths are reported as deferred, everything else is unknown.
|
|
2470
|
+
*/
|
|
2471
|
+
declare function canonicalisePath(path: string | null | undefined, attributes: readonly CkAttributeInfo[]): CanonicalPath;
|
|
2472
|
+
/** Converts `SftpConfiguration` / `System.Communication/SftpConfiguration` to `sftp-configuration`. */
|
|
2473
|
+
declare function toKebabTypeKey(rtCkTypeId: string): string;
|
|
2474
|
+
|
|
2475
|
+
/**
|
|
2476
|
+
* Parses a `VisibleWhen` expression (`Path=value` or `Path=*`). The expression is split at the
|
|
2477
|
+
* FIRST `=`, so values may contain `=`. The path is canonicalised against the type's attributes
|
|
2478
|
+
* (system properties allowed); returns `null` for an empty, malformed or unresolvable expression.
|
|
2479
|
+
*/
|
|
2480
|
+
declare function parseVisibleWhen(expression: string | null | undefined, attributes: readonly CkAttributeInfo[]): VisibleWhenRule | null;
|
|
2481
|
+
/**
|
|
2482
|
+
* Evaluates a rule against the current form values.
|
|
2483
|
+
*
|
|
2484
|
+
* - `*`: visible when the source has a value, or (for a secret source) when the server reports the
|
|
2485
|
+
* secret as set (`secretPresence[path] === true`).
|
|
2486
|
+
* - Booleans compare against `true`/`false` (case-insensitive).
|
|
2487
|
+
* - Enums compare against the key or the name (case-insensitive) using `enumOptions`.
|
|
2488
|
+
* - Everything else compares the string form (case-sensitive).
|
|
2489
|
+
*/
|
|
2490
|
+
declare function isVisible(rule: VisibleWhenRule | undefined | null, values: Record<string, unknown>, secretPresence?: Record<string, boolean>, enumOptions?: {
|
|
2491
|
+
key: number;
|
|
2492
|
+
name: string;
|
|
2493
|
+
}[]): boolean;
|
|
2494
|
+
|
|
2495
|
+
/** Record infos keyed by versioned `ckRecordId` (as found in `CkAttributeInfo.ckRecordId`). */
|
|
2496
|
+
type RecordInfoMap = Record<string, CkRecordInfo>;
|
|
2497
|
+
/** Attribute metadata the mapper needs (a subset of {@link CkAttributeInfo}). */
|
|
2498
|
+
type MapperAttribute = Pick<CkAttributeInfo, 'attributeName' | 'valueType' | 'isOptional'> & Partial<Pick<CkAttributeInfo, 'enumOptions' | 'ckRecordId'>>;
|
|
2499
|
+
/**
|
|
2500
|
+
* Converts a raw API value to the form value shape of the given attribute.
|
|
2501
|
+
* Records/record arrays become arrays of flat dicts; unsupported types pass through unchanged.
|
|
2502
|
+
*/
|
|
2503
|
+
declare function toFormValue(raw: unknown, attribute: MapperAttribute, records?: RecordInfoMap): unknown;
|
|
2504
|
+
/**
|
|
2505
|
+
* Maps form values to `RtEntityAttributeInput[]` for the given attributes (in the given order).
|
|
2506
|
+
* Values whose key is absent from `values` are skipped.
|
|
2507
|
+
*/
|
|
2508
|
+
declare function toAttributeInputs(values: Record<string, unknown>, attributes: readonly MapperAttribute[], records?: RecordInfoMap): {
|
|
2509
|
+
attributeName: string;
|
|
2510
|
+
value: unknown;
|
|
2511
|
+
}[];
|
|
2512
|
+
/**
|
|
2513
|
+
* Parses a form `Default` string (or a CK `defaultValues[0]`) into the form value shape:
|
|
2514
|
+
* Int via parseInt, Double via parseFloat, Boolean via 'true'/'false', ENUM by name or key,
|
|
2515
|
+
* DateTime as ISO -> Date, arrays as a JSON array or a comma list. Returns `undefined` when the
|
|
2516
|
+
* input is empty or cannot be parsed.
|
|
2517
|
+
*/
|
|
2518
|
+
declare function parseDefault(raw: unknown, attribute: MapperAttribute): unknown;
|
|
2519
|
+
|
|
2520
|
+
/** One selected reference target as held by a reference control. */
|
|
2521
|
+
interface EntityFormReferenceValue {
|
|
2522
|
+
rtId: string;
|
|
2523
|
+
ckTypeId: string;
|
|
2524
|
+
displayName?: string;
|
|
2525
|
+
}
|
|
2526
|
+
interface BuildChangeSetOptions {
|
|
2527
|
+
/** Record metadata keyed by versioned ckRecordId, for type conversion of record sub-values. */
|
|
2528
|
+
records?: Record<string, CkRecordInfo>;
|
|
2529
|
+
/**
|
|
2530
|
+
* attributeNames of secrets whose clear the user staged (Q8, edit mode). Sent as
|
|
2531
|
+
* `clearSecretAttributes` unless a new value was typed for the same field (mutually exclusive —
|
|
2532
|
+
* the typed value wins, the server would reject both).
|
|
2533
|
+
*/
|
|
2534
|
+
clearedSecrets?: ReadonlySet<string>;
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* The association `roleName` written in `RtEntityAssociationInput`: the navigation property name
|
|
2538
|
+
* with a lower-case first letter (the backend matches it case-insensitively; verified live, and
|
|
2539
|
+
* the role id `System/Related` is NOT accepted as roleName — it is silently ignored).
|
|
2540
|
+
*/
|
|
2541
|
+
declare function associationRoleName(navigationPropertyName: string): string;
|
|
2542
|
+
/**
|
|
2543
|
+
* Builds the change set of a form (D6: only dirty controls on edit).
|
|
2544
|
+
*
|
|
2545
|
+
* - `current` is the form's enabled value: a key that is absent (disabled control, e.g. hidden by
|
|
2546
|
+
* VisibleWhen) is never sent.
|
|
2547
|
+
* - Create mode sends every non-empty editable value (defaults included) plus `rtWellKnownName`.
|
|
2548
|
+
* - Edit mode sends only attributes whose value differs from `initial`; read-only, `afterCreate`
|
|
2549
|
+
* and unsupported fields and `rtWellKnownName` are never sent.
|
|
2550
|
+
* - Secrets: an empty secret is left out (= unchanged); a typed secret is always sent. A staged
|
|
2551
|
+
* clear (edit mode, `options.clearedSecrets`) goes to `clearSecretAttributes` instead.
|
|
2552
|
+
* - Associations: diff of the selected targets by rtId; a single-valued replace produces DELETE old
|
|
2553
|
+
* plus CREATE new.
|
|
2554
|
+
* - View mode produces an empty change set.
|
|
2555
|
+
*/
|
|
2556
|
+
declare function buildChangeSet(initial: Record<string, unknown>, current: Record<string, unknown>, model: ResolvedEntityForm, mode: EntityFormMode, _secretPresence?: Record<string, boolean>, options?: BuildChangeSetOptions): EntityFormChangeSet;
|
|
2557
|
+
|
|
2558
|
+
/** Shape of one attribute row of `entityFormGetCkType` / `entityFormGetCkRecord`. */
|
|
2559
|
+
interface RawCkAttribute {
|
|
2560
|
+
attributeName: string;
|
|
2561
|
+
attributeValueType: string;
|
|
2562
|
+
isOptional: boolean;
|
|
2563
|
+
ckAttributeId?: {
|
|
2564
|
+
fullName: string;
|
|
2565
|
+
} | null;
|
|
2566
|
+
attribute?: {
|
|
2567
|
+
description?: string | null;
|
|
2568
|
+
defaultValues?: (unknown | null)[] | null;
|
|
2569
|
+
metaData?: ({
|
|
2570
|
+
key: string;
|
|
2571
|
+
value?: string | null;
|
|
2572
|
+
} | null)[] | null;
|
|
2573
|
+
ckEnum?: {
|
|
2574
|
+
values: ({
|
|
2575
|
+
key?: number | null;
|
|
2576
|
+
name?: string | null;
|
|
2577
|
+
} | null)[];
|
|
2578
|
+
} | null;
|
|
2579
|
+
ckRecord?: {
|
|
2580
|
+
ckRecordId: {
|
|
2581
|
+
fullName: string;
|
|
2582
|
+
};
|
|
2583
|
+
} | null;
|
|
2584
|
+
} | null;
|
|
2585
|
+
}
|
|
2586
|
+
interface RawBaseType {
|
|
2587
|
+
rtCkTypeId: string;
|
|
2588
|
+
isAbstract?: boolean;
|
|
2589
|
+
baseType?: RawBaseType | null;
|
|
2590
|
+
}
|
|
2591
|
+
interface RawRole {
|
|
2592
|
+
rtRoleId: string;
|
|
2593
|
+
navigationPropertyName: string;
|
|
2594
|
+
multiplicity: string;
|
|
2595
|
+
rtTargetCkTypeId: string;
|
|
2596
|
+
rtOriginCkTypeId: string;
|
|
2597
|
+
}
|
|
2598
|
+
/** Shape of one type of `entityFormGetCkType`. */
|
|
2599
|
+
interface RawCkType {
|
|
2600
|
+
rtCkTypeId: string;
|
|
2601
|
+
isAbstract: boolean;
|
|
2602
|
+
description?: string | null;
|
|
2603
|
+
ckTypeId: {
|
|
2604
|
+
fullName: string;
|
|
2605
|
+
};
|
|
2606
|
+
baseType?: RawBaseType | null;
|
|
2607
|
+
attributes?: {
|
|
2608
|
+
items?: (RawCkAttribute | null)[] | null;
|
|
2609
|
+
} | null;
|
|
2610
|
+
associations?: {
|
|
2611
|
+
in?: {
|
|
2612
|
+
all?: (RawRole | null)[] | null;
|
|
2613
|
+
} | null;
|
|
2614
|
+
out?: {
|
|
2615
|
+
all?: (RawRole | null)[] | null;
|
|
2616
|
+
} | null;
|
|
2617
|
+
} | null;
|
|
2618
|
+
}
|
|
2619
|
+
/** Shape of one record of `entityFormGetCkRecord`. */
|
|
2620
|
+
interface RawCkRecord {
|
|
2621
|
+
ckRecordId: {
|
|
2622
|
+
fullName: string;
|
|
2623
|
+
};
|
|
2624
|
+
isAbstract?: boolean;
|
|
2625
|
+
attributes?: {
|
|
2626
|
+
items?: (RawCkAttribute | null)[] | null;
|
|
2627
|
+
} | null;
|
|
2628
|
+
}
|
|
2629
|
+
/**
|
|
2630
|
+
* The CK attribute metaData `secret` marker: `true`, `false` (explicit opt-out of the
|
|
2631
|
+
* credential-name rule) or `undefined` when there is no (valid) marker.
|
|
2632
|
+
*/
|
|
2633
|
+
declare function secretMetaDataMarker(metaData: readonly ({
|
|
2634
|
+
key: string;
|
|
2635
|
+
value?: string | null;
|
|
2636
|
+
} | null)[] | null | undefined): boolean | undefined;
|
|
2637
|
+
/** True when the CK attribute metaData marks the attribute as secret (`secret = true`). */
|
|
2638
|
+
declare function isSecretMetaData(metaData: readonly ({
|
|
2639
|
+
key: string;
|
|
2640
|
+
value?: string | null;
|
|
2641
|
+
} | null)[] | null | undefined): boolean;
|
|
2642
|
+
/** Maps a raw `entityFormGetCkType` item to {@link CkTypeInfo}. */
|
|
2643
|
+
declare function toCkTypeInfo(raw: RawCkType): CkTypeInfo;
|
|
2644
|
+
/** Maps a raw `entityFormGetCkRecord` item to {@link CkRecordInfo}. */
|
|
2645
|
+
declare function toCkRecordInfo(raw: RawCkRecord): CkRecordInfo;
|
|
2646
|
+
|
|
2647
|
+
export { BUILT_IN_DEFAULT_FORM, DEFAULT_ENTITY_FORMS_MESSAGES, DEFAULT_GENERATED_SECTION_TITLE, DEFAULT_SECTION_KEY, ENTITY_FORM_ACTION_CONFIRMATION, ENTITY_FORM_BEFORE_SAVE, ENTITY_FORM_DANGER_CONFIRMATION, ENTITY_FORM_FALLBACK_FORMS, ENTITY_FORM_LABEL_RESOLVER, ENTITY_FORM_SECRET_KEY_RING_CONFIGURED, ENTITY_FORM_SECRET_PLACEHOLDER_VALUES, ENTITY_FORM_UNSET_PLACEHOLDER_VALUES, ENTITY_LIST_ROW_CLASS, ENTITY_PAGE_NEW, ENTITY_PAGE_TYPE_QUERY_PARAM, EntityFormComponent, EntityFormDataService, EntityFormRecordsFieldComponent, EntityFormReferenceFieldComponent, EntityFormSaveVeto, EntityFormSecretEditorComponent, EntityFormService, EntityListComponent, EntityListDataSourceDirective, EntityPageActionsDirective, EntityPageComponent, GENERATED_SECTION_KEY, SYSTEM_PROPERTIES, associationFieldKey, associationRoleName, autoEditorFor, buildChangeSet, canonicaliseEntityFormPrefill, canonicalisePath, ckTypeDisplayName, ckTypeShortName, confirmEntityFormAction, confirmEntityFormDanger, entityDeleteConfirmation, entityFormCatalog, entityFormKey, entityFormPrefillState, entityFormRoutes, entityFormTypeTitles, entityFormUnsetPlaceholderFields, entityFormUnsetPlaceholderLookup, entityListAttributeNames, entityListIncludesDerivedTypes, formatEntityFormsMessage, humanizeCkTypeName, isChainEndForm, isEditorCompatible, isEntityFormSaveVeto, isEntityFormUnsetPlaceholder, isSecretMetaData, isVisible, localizeEntityForm, localizeEntityFormTitle, localizeEntityListColumns, mergeEntityFormPrefill, mergeEntityFormsMessages, parseDefault, parseEntityForm, parseEntityForms, parseVisibleWhen, pickEntityForm, provideEntityFormFallbacks, resolveEntityForm, resolveEntityFormLabel, resolveListDefaultSort, runEntityFormBeforeSave, secretMetaDataMarker, secretStatusLabelsOf, selectFallbackForms, shortTypeName, toAttributeInputs, toCkRecordInfo, toCkTypeInfo, toEntityListColumn, toEntityListRow, toFormValue, toKebabTypeKey, toListViewRowClass, withFallbackForms };
|
|
2648
|
+
export type { BuildChangeSetOptions, CanonicalPath, CkAssociationRoleInfo, CkAttributeInfo, CkRecordInfo, CkTypeInfo, EntityFormActionConfirmation, EntityFormActionRequest, EntityFormBeforeSaveContext, EntityFormBeforeSaveHook, EntityFormBeforeSaveOutcome, EntityFormBeforeSaveResult, EntityFormCatalogEntry, EntityFormChangeSet, EntityFormColumnDef, EntityFormDangerConfirmation, EntityFormDefinition, EntityFormEditor, EntityFormFieldDef, EntityFormLabelKind, EntityFormLabelRequest, EntityFormLabelResolver, EntityFormLoadKey, EntityFormLoadResult, EntityFormMode, EntityFormPrefillOptions, EntityFormPrefillValues, EntityFormRecordColumn, EntityFormReferenceValue, EntityFormRoutesOptions, EntityFormSecretFieldState, EntityFormSectionDef, EntityFormSortDef, EntityFormSource, EntityFormTargetRef, EntityFormUnsetPlaceholderLookup, EntityFormUnsetPlaceholderTarget, EntityFormUnsetPlaceholderValues, EntityFormValueState, EntityFormsMessages, EntityListBooleanDisplay, EntityListCellLabels, EntityListColumnOptions, EntityListCreateRequest, EntityListOpenRequest, EntityListRow, EntityListRowClass, EntityListSortDescriptor, EntityPageActionBarPosition, EntityPageActionsContext, EntityPageDeletedEvent, EntityPageEditMode, EntityPageInitialValues, EntityPageNavigateEvent, EntityPageSavedEvent, EntityPageView, RawRtEntityRow, ReadOnlyMode, ResolveEntityFormOptions, ResolvedEntityForm, ResolvedField, ResolvedListColumn, ResolvedSection, VisibleWhenRule };
|