@acorex-platform/module-platform-management-client 0.0.38 → 0.0.48

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.
Files changed (87) hide show
  1. package/fesm2022/{acorex-platform-module-platform-management-client-acorex-platform-module-platform-management-client-BGVhn6wv.mjs → acorex-platform-module-platform-management-client-acorex-platform-module-platform-management-client-YuJijjKh.mjs} +465 -101
  2. package/fesm2022/acorex-platform-module-platform-management-client-acorex-platform-module-platform-management-client-YuJijjKh.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-command-definition.mjs +20 -0
  4. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-command-definition.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-entity-access-policy.mjs +20 -0
  6. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-entity-access-policy.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-entity-definition.mjs +1499 -30
  8. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-entity-definition.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-module-definition.mjs +396 -0
  10. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-module-definition.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-plugin-definition.mjs +20 -0
  12. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-plugin-definition.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-query-definition.mjs +49 -1
  14. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-query-definition.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-token.mjs +20 -0
  16. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-token.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-widget.mjs +20 -0
  18. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entities-widget.mjs.map +1 -1
  19. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-acorex-platform-module-platform-management-client-contracts-entity-catalog-BOwC5Ns9.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-acorex-platform-module-platform-management-client-contracts-entity-catalog-HWczTPH2.mjs} +15 -8
  20. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-acorex-platform-module-platform-management-client-contracts-entity-catalog-HWczTPH2.mjs.map +1 -0
  21. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-command-definition.entity-CdvQlwAk.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-command-definition.entity-C3B1_QMs.mjs} +16 -2
  22. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-command-definition.entity-C3B1_QMs.mjs.map +1 -0
  23. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-access-policy.entity-Dye4aSKE.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-access-policy.entity-BPkJloHy.mjs} +16 -2
  24. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-access-policy.entity-BPkJloHy.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-definition.entity-BL1I9pmK.mjs +1621 -0
  26. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-definition.entity-BL1I9pmK.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-module-definition.entity-Cknl0vbc.mjs +299 -0
  28. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-module-definition.entity-Cknl0vbc.mjs.map +1 -0
  29. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-plugin-definition.entity-CwU5hMjI.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-plugin-definition.entity-BxABTl8L.mjs} +16 -2
  30. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-plugin-definition.entity-BxABTl8L.mjs.map +1 -0
  31. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-query-definition.entity-DGK684Q1.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-query-definition.entity-Cv6HVQOU.mjs} +45 -3
  32. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-query-definition.entity-Cv6HVQOU.mjs.map +1 -0
  33. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-token.entity-DI_k6-ha.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-token.entity-BV8iSuoK.mjs} +16 -2
  34. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-token.entity-BV8iSuoK.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-module-platform-management-client-contracts-entity-catalog-widget.entity-C18msniH.mjs → acorex-platform-module-platform-management-client-contracts-entity-catalog-widget.entity-BYH6SIqU.mjs} +16 -2
  36. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-widget.entity-BYH6SIqU.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog.mjs +1 -1
  38. package/fesm2022/acorex-platform-module-platform-management-client-contracts.mjs +1664 -1
  39. package/fesm2022/acorex-platform-module-platform-management-client-contracts.mjs.map +1 -1
  40. package/fesm2022/acorex-platform-module-platform-management-client-create-user-query-contract.util-D_af2BUi.mjs +586 -0
  41. package/fesm2022/acorex-platform-module-platform-management-client-create-user-query-contract.util-D_af2BUi.mjs.map +1 -0
  42. package/fesm2022/{acorex-platform-module-platform-management-client-create-user-query.command-9Ku7C1BC.mjs → acorex-platform-module-platform-management-client-create-user-query.command-Bh49QHkl.mjs} +374 -324
  43. package/fesm2022/acorex-platform-module-platform-management-client-create-user-query.command-Bh49QHkl.mjs.map +1 -0
  44. package/fesm2022/acorex-platform-module-platform-management-client-entity-definition-form-page.component-BgBWob9p.mjs +329 -0
  45. package/fesm2022/acorex-platform-module-platform-management-client-entity-definition-form-page.component-BgBWob9p.mjs.map +1 -0
  46. package/fesm2022/acorex-platform-module-platform-management-client-entity-definition-form-page.provider-hLzgoJu3.mjs +23 -0
  47. package/fesm2022/acorex-platform-module-platform-management-client-entity-definition-form-page.provider-hLzgoJu3.mjs.map +1 -0
  48. package/fesm2022/acorex-platform-module-platform-management-client-list-registered-entities.query-CZM6JQou.mjs +197 -0
  49. package/fesm2022/acorex-platform-module-platform-management-client-list-registered-entities.query-CZM6JQou.mjs.map +1 -0
  50. package/fesm2022/acorex-platform-module-platform-management-client-local-entities.mjs +1 -0
  51. package/fesm2022/acorex-platform-module-platform-management-client-local-entities.mjs.map +1 -1
  52. package/fesm2022/{acorex-platform-module-platform-management-client-menu-list.component-uF5w1c7t.mjs → acorex-platform-module-platform-management-client-menu-list.component-iMEnFPEY.mjs} +2 -2
  53. package/fesm2022/{acorex-platform-module-platform-management-client-menu-list.component-uF5w1c7t.mjs.map → acorex-platform-module-platform-management-client-menu-list.component-iMEnFPEY.mjs.map} +1 -1
  54. package/fesm2022/acorex-platform-module-platform-management-client-query-contract-widget-column.component-COfOzMGh.mjs +45 -0
  55. package/fesm2022/acorex-platform-module-platform-management-client-query-contract-widget-column.component-COfOzMGh.mjs.map +1 -0
  56. package/fesm2022/acorex-platform-module-platform-management-client-query-contract-widget-edit.component-BW2pBOeg.mjs +166 -0
  57. package/fesm2022/acorex-platform-module-platform-management-client-query-contract-widget-edit.component-BW2pBOeg.mjs.map +1 -0
  58. package/fesm2022/acorex-platform-module-platform-management-client-query-contract-widget-view.component-DD9ETjFD.mjs +45 -0
  59. package/fesm2022/acorex-platform-module-platform-management-client-query-contract-widget-view.component-DD9ETjFD.mjs.map +1 -0
  60. package/fesm2022/{acorex-platform-module-platform-management-client-rest-api-generator-widget-column.component-B0g6dweQ.mjs → acorex-platform-module-platform-management-client-rest-api-generator-widget-column.component-DRkE2a7n.mjs} +2 -2
  61. package/fesm2022/{acorex-platform-module-platform-management-client-rest-api-generator-widget-column.component-B0g6dweQ.mjs.map → acorex-platform-module-platform-management-client-rest-api-generator-widget-column.component-DRkE2a7n.mjs.map} +1 -1
  62. package/fesm2022/{acorex-platform-module-platform-management-client-rest-api-generator-widget-edit.component-A0v5MWRU.mjs → acorex-platform-module-platform-management-client-rest-api-generator-widget-edit.component-CXI6fJi3.mjs} +2 -3
  63. package/fesm2022/{acorex-platform-module-platform-management-client-rest-api-generator-widget-edit.component-A0v5MWRU.mjs.map → acorex-platform-module-platform-management-client-rest-api-generator-widget-edit.component-CXI6fJi3.mjs.map} +1 -1
  64. package/fesm2022/{acorex-platform-module-platform-management-client-rest-api-generator-widget-view.component-RR5zcsnI.mjs → acorex-platform-module-platform-management-client-rest-api-generator-widget-view.component-C3iHgoC2.mjs} +2 -2
  65. package/fesm2022/{acorex-platform-module-platform-management-client-rest-api-generator-widget-view.component-RR5zcsnI.mjs.map → acorex-platform-module-platform-management-client-rest-api-generator-widget-view.component-C3iHgoC2.mjs.map} +1 -1
  66. package/fesm2022/acorex-platform-module-platform-management-client-run-user-query.command-BzNa3B48.mjs +144 -0
  67. package/fesm2022/acorex-platform-module-platform-management-client-run-user-query.command-BzNa3B48.mjs.map +1 -0
  68. package/fesm2022/acorex-platform-module-platform-management-client.mjs +1 -1
  69. package/package.json +7 -3
  70. package/types/acorex-platform-module-platform-management-client-contracts-entities-module-definition.d.ts +5 -0
  71. package/types/acorex-platform-module-platform-management-client-contracts.d.ts +225 -5
  72. package/types/acorex-platform-module-platform-management-client.d.ts +35 -3
  73. package/fesm2022/acorex-platform-module-platform-management-client-acorex-platform-module-platform-management-client-BGVhn6wv.mjs.map +0 -1
  74. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-acorex-platform-module-platform-management-client-contracts-entity-catalog-BOwC5Ns9.mjs.map +0 -1
  75. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-command-definition.entity-CdvQlwAk.mjs.map +0 -1
  76. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-access-policy.entity-Dye4aSKE.mjs.map +0 -1
  77. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-definition.entity-CcJ58vfr.mjs +0 -158
  78. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-entity-definition.entity-CcJ58vfr.mjs.map +0 -1
  79. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-plugin-definition.entity-CwU5hMjI.mjs.map +0 -1
  80. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-query-definition.entity-DGK684Q1.mjs.map +0 -1
  81. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-token.entity-DI_k6-ha.mjs.map +0 -1
  82. package/fesm2022/acorex-platform-module-platform-management-client-contracts-entity-catalog-widget.entity-C18msniH.mjs.map +0 -1
  83. package/fesm2022/acorex-platform-module-platform-management-client-create-user-query.command-9Ku7C1BC.mjs.map +0 -1
  84. package/fesm2022/acorex-platform-module-platform-management-client-create-user-query.types-DdygAori.mjs +0 -71
  85. package/fesm2022/acorex-platform-module-platform-management-client-create-user-query.types-DdygAori.mjs.map +0 -1
  86. package/fesm2022/acorex-platform-module-platform-management-client-list-registered-entities.query-DjStd3a8.mjs +0 -136
  87. package/fesm2022/acorex-platform-module-platform-management-client-list-registered-entities.query-DjStd3a8.mjs.map +0 -1
@@ -1,5 +1,6 @@
1
- import { AXPWidgetsCatalog, AXPWidgetsList } from '@acorex-platform/framework-shared/core';
2
- import { entityMasterRecordActions, entityMasterViewAction, createAllQueryView } from '@acorex-platform/framework-shared/entity';
1
+ import { AXPWidgetsList, AXPWidgetsCatalog } from '@acorex-platform/framework-shared/core';
2
+ import { entityMasterCrudActions, entityMasterRecordActions, createAllQueryView, entityMasterCreateAction, entityMasterViewAction } from '@acorex-platform/framework-shared/entity';
3
+ import { ENTITY_CREATE_UI, ENTITY_EDIT_UI, ENTITY_REMOVE_UI } from '@acorex-platform/framework-shared/runtime';
3
4
 
4
5
  const config = {
5
6
  i18n: 'platform-management',
@@ -23,6 +24,12 @@ const RootConfig = {
23
24
  title: `@${config.i18n}:tokens.entities.token.title`,
24
25
  icon: 'fa-light fa-object-exclude',
25
26
  },
27
+ moduleDefinition: {
28
+ name: 'ModuleDefinition',
29
+ title: `@${config.i18n}:module-definitions.entities.module-definition.title`,
30
+ titlePlural: `@${config.i18n}:module-definitions.entities.module-definition.title-plural`,
31
+ icon: 'fa-light fa-layer-group',
32
+ },
26
33
  commandDefinition: {
27
34
  name: 'CommandDefinition',
28
35
  title: `@${config.i18n}:command-definitions.entities.command-definition.title`,
@@ -89,8 +96,1233 @@ const RootConfig = {
89
96
  },
90
97
  };
91
98
 
99
+ //#region ----- Entity definition wizard page keys -----
100
+ /** Schema step: plugins, groups, and properties. */
101
+ const ENTITY_DEFINITION_SCHEMA_PAGE_COMPONENT_KEY = 'entity-definition-schema-page';
102
+ /** Surfaces step: columns, layouts, actions, related entities. */
103
+ const ENTITY_DEFINITION_SURFACES_PAGE_COMPONENT_KEY = 'entity-definition-surfaces-page';
104
+ const ENTITY_DEFINITION_SCHEMA_PROPERTY_NAMES = ['plugins', 'groups', 'properties'];
105
+ const ENTITY_DEFINITION_SURFACES_PROPERTY_NAMES = [
106
+ 'columns',
107
+ 'relatedEntities',
108
+ 'createSections',
109
+ 'createProperties',
110
+ 'listActions',
111
+ 'singleActions',
112
+ 'pages',
113
+ 'rules',
114
+ 'validations',
115
+ 'commandsJson',
116
+ 'queriesJson',
117
+ ];
118
+ const ENTITY_DEFINITION_DESIGNER_FORM_KEYS = [
119
+ 'title',
120
+ 'icon',
121
+ 'module',
122
+ 'parentKey',
123
+ 'searchTags',
124
+ 'formatIndividual',
125
+ 'formatPlural',
126
+ 'formatDisplayName',
127
+ 'formatSearchTitle',
128
+ 'formatSearchDescription',
129
+ 'categoryEntity',
130
+ 'categoryTextField',
131
+ 'categoryValueField',
132
+ 'plugins',
133
+ 'groups',
134
+ 'properties',
135
+ 'columns',
136
+ 'relatedEntities',
137
+ 'createSections',
138
+ 'createProperties',
139
+ 'listActions',
140
+ 'singleActions',
141
+ 'pages',
142
+ 'rules',
143
+ 'validations',
144
+ 'commandsJson',
145
+ 'queriesJson',
146
+ ];
147
+ //#endregion
148
+
149
+ //#region ----- Imports -----
150
+ //#endregion
151
+ //#region ----- Constants -----
152
+ const i18n$1 = RootConfig.config.i18n;
153
+ const field = (name) => `@${i18n$1}:entity-definitions.entities.entity-definition.fields.${name}.title`;
154
+ const PLUGIN_ENTITY = `${RootConfig.module.name}.${RootConfig.entities.pluginDefinition.name}`;
155
+ const ENTITY_DEFINITION_ENTITY = `${RootConfig.module.name}.${RootConfig.entities.entityDefinition.name}`;
156
+ const MODULE_DEFINITION_ENTITY = `${RootConfig.module.name}.${RootConfig.entities.moduleDefinition.name}`;
157
+ const PROPERTIES_DATASOURCE = "{{ context.eval('properties') || [] }}";
158
+ const GROUPS_DATASOURCE = "{{ context.eval('groups') || [] }}";
159
+ //#endregion
160
+ //#region ----- Layout helpers -----
161
+ function gridRow(children) {
162
+ return {
163
+ type: AXPWidgetsList.Layouts.GridLayout,
164
+ mode: 'edit',
165
+ options: {
166
+ grid: {
167
+ default: { columns: 12, gap: '0.75rem' },
168
+ },
169
+ },
170
+ children,
171
+ };
172
+ }
173
+ function gridItem(colSpan, child) {
174
+ return {
175
+ type: AXPWidgetsList.Layouts.GridItemLayout,
176
+ mode: 'edit',
177
+ options: { colSpan },
178
+ children: [child],
179
+ };
180
+ }
181
+ function formField(label, editor) {
182
+ return {
183
+ type: AXPWidgetsList.Layouts.FormField,
184
+ mode: 'edit',
185
+ options: { label, showLabel: true },
186
+ children: [editor],
187
+ };
188
+ }
189
+ function textEditor(path, required = false) {
190
+ return {
191
+ type: AXPWidgetsList.Editors.TextBox,
192
+ mode: 'edit',
193
+ path,
194
+ name: path,
195
+ options: required ? { required: true } : {},
196
+ };
197
+ }
198
+ function largeTextEditor(path, rows = 2) {
199
+ return {
200
+ type: AXPWidgetsList.Editors.LargeTextBox,
201
+ mode: 'edit',
202
+ path,
203
+ name: path,
204
+ options: { rows },
205
+ };
206
+ }
207
+ function toggleEditor(path) {
208
+ return {
209
+ type: AXPWidgetsList.Editors.ToggleSwitch,
210
+ mode: 'edit',
211
+ path,
212
+ name: path,
213
+ };
214
+ }
215
+ function numberEditor(path, defaultValue) {
216
+ return {
217
+ type: AXPWidgetsList.Editors.NumberBox,
218
+ mode: 'edit',
219
+ path,
220
+ name: path,
221
+ options: defaultValue == null ? {} : { defaultValue },
222
+ };
223
+ }
224
+ function iconEditor(path) {
225
+ return {
226
+ type: AXPWidgetsList.Theme.IconChooser,
227
+ mode: 'edit',
228
+ path,
229
+ name: path,
230
+ };
231
+ }
232
+ function codeEditor(path, height = 'h-32') {
233
+ return {
234
+ type: AXPWidgetsList.Advanced.CodeEditor,
235
+ mode: 'edit',
236
+ path,
237
+ name: path,
238
+ options: { language: 'json', height },
239
+ };
240
+ }
241
+ function selectEditor(path, options) {
242
+ return {
243
+ type: AXPWidgetsList.Editors.SelectBox,
244
+ mode: 'edit',
245
+ path,
246
+ name: path,
247
+ options: {
248
+ valueField: options.valueField,
249
+ textField: options.textField,
250
+ dataSource: options.dataSource,
251
+ allowSearch: options.allowSearch ?? true,
252
+ required: options.required ?? false,
253
+ },
254
+ };
255
+ }
256
+ function lookupEditor(path, options) {
257
+ return {
258
+ type: AXPWidgetsList.Editors.LookupBox,
259
+ mode: 'edit',
260
+ path,
261
+ name: path,
262
+ options: {
263
+ entity: options.entity,
264
+ valueField: options.valueField,
265
+ textField: options.textField,
266
+ look: 'select',
267
+ allowSearch: true,
268
+ columns: options.columns,
269
+ },
270
+ };
271
+ }
272
+ //#endregion
273
+ //#region ----- Repeater children -----
274
+ const PLUGIN_REPEATER_CHILDREN = [
275
+ gridRow([
276
+ gridItem(6, formField(field('plugin-name'), lookupEditor('name', {
277
+ entity: PLUGIN_ENTITY,
278
+ valueField: 'name',
279
+ textField: 'catalogTitle',
280
+ columns: ['catalogTitle', 'name'],
281
+ }))),
282
+ gridItem(6, formField(field('plugin-options'), codeEditor('options'))),
283
+ ]),
284
+ ];
285
+ const GROUP_REPEATER_CHILDREN = [
286
+ gridRow([
287
+ gridItem(4, formField(field('group-id'), textEditor('id', true))),
288
+ gridItem(5, formField(field('group-title'), textEditor('title', true))),
289
+ gridItem(3, formField(field('group-icon'), iconEditor('icon'))),
290
+ gridItem(12, formField(field('group-description'), largeTextEditor('description', 2))),
291
+ ]),
292
+ ];
293
+ const PROPERTY_REPEATER_CHILDREN = [
294
+ gridRow([
295
+ gridItem(4, formField('@general:terms.common.name', textEditor('name', true))),
296
+ gridItem(4, formField('@general:terms.common.title', textEditor('title', true))),
297
+ gridItem(4, formField(field('group-id'), selectEditor('groupId', {
298
+ dataSource: GROUPS_DATASOURCE,
299
+ valueField: 'id',
300
+ textField: 'title',
301
+ }))),
302
+ gridItem(12, formField('@general:terms.common.description', largeTextEditor('description', 2))),
303
+ gridItem(12, formField(field('property-interface'), {
304
+ type: AXPWidgetsList.Advanced.WidgetFieldConfigurator,
305
+ mode: 'edit',
306
+ path: 'interface',
307
+ name: 'interface',
308
+ options: {
309
+ fieldName: "{{ context.eval('name') }}",
310
+ fieldTitle: "{{ context.eval('title') }}",
311
+ },
312
+ })),
313
+ gridItem(3, formField(field('property-data-type'), selectEditor('dataType', {
314
+ dataSource: [
315
+ { value: 'string', text: field('data-type-string') },
316
+ { value: 'number', text: field('data-type-number') },
317
+ { value: 'boolean', text: field('data-type-boolean') },
318
+ { value: 'date', text: field('data-type-date') },
319
+ { value: 'uuid', text: field('data-type-uuid') },
320
+ { value: 'object', text: field('data-type-object') },
321
+ { value: 'array', text: field('data-type-array') },
322
+ ],
323
+ valueField: 'value',
324
+ textField: 'text',
325
+ allowSearch: false,
326
+ }))),
327
+ gridItem(3, formField(field('property-required'), toggleEditor('required'))),
328
+ gridItem(3, formField(field('property-nullable'), toggleEditor('nullable'))),
329
+ gridItem(3, formField(field('property-readonly'), toggleEditor('readonly'))),
330
+ gridItem(3, formField(field('property-unique'), toggleEditor('unique'))),
331
+ gridItem(3, formField(field('property-visible'), toggleEditor('visible'))),
332
+ gridItem(9, formField(field('property-default-value'), textEditor('defaultValue'))),
333
+ ]),
334
+ ];
335
+ const COLUMN_REPEATER_CHILDREN = [
336
+ gridRow([
337
+ gridItem(4, formField(field('column-name'), selectEditor('name', {
338
+ dataSource: PROPERTIES_DATASOURCE,
339
+ valueField: 'name',
340
+ textField: 'title',
341
+ required: true,
342
+ }))),
343
+ gridItem(4, formField('@general:terms.common.title', textEditor('title'))),
344
+ gridItem(4, formField(field('column-widget'), selectEditor('widgetType', {
345
+ dataSource: 'PlatformManagement:ListEditorWidgets',
346
+ valueField: 'name',
347
+ textField: 'title',
348
+ }))),
349
+ ]),
350
+ ];
351
+ const RELATED_ENTITY_REPEATER_CHILDREN = [
352
+ gridRow([
353
+ gridItem(6, formField(field('related-entity'), lookupEditor('entity', {
354
+ entity: ENTITY_DEFINITION_ENTITY,
355
+ valueField: 'name',
356
+ textField: 'name',
357
+ columns: ['name'],
358
+ }))),
359
+ gridItem(4, formField('@general:terms.common.title', textEditor('title'))),
360
+ gridItem(2, formField('@general:terms.common.icon', iconEditor('icon'))),
361
+ gridItem(4, formField(field('related-layout-type'), selectEditor('layoutType', {
362
+ dataSource: [
363
+ { value: 'page-list', text: field('layout-type-page-list') },
364
+ { value: 'tab-list', text: field('layout-type-tab-list') },
365
+ { value: 'merge-detail', text: field('layout-type-merge-detail') },
366
+ { value: 'page-detail', text: field('layout-type-page-detail') },
367
+ { value: 'tab-detail', text: field('layout-type-tab-detail') },
368
+ ],
369
+ valueField: 'value',
370
+ textField: 'text',
371
+ allowSearch: false,
372
+ }))),
373
+ gridItem(4, formField(field('related-persistence-strategy'), selectEditor('persistenceStrategy', {
374
+ dataSource: [
375
+ { value: 'referenced', text: field('persistence-referenced') },
376
+ { value: 'embedded', text: field('persistence-embedded') },
377
+ ],
378
+ valueField: 'value',
379
+ textField: 'text',
380
+ allowSearch: false,
381
+ }))),
382
+ gridItem(4, formField(field('related-foreign-key'), textEditor('foreignKeyField'))),
383
+ gridItem(4, formField(field('related-data-path'), textEditor('dataPath'))),
384
+ gridItem(4, formField(field('related-id-field'), textEditor('idField'))),
385
+ gridItem(2, formField(field('appear-on-create'), toggleEditor('appearOnCreate'))),
386
+ gridItem(2, formField(field('appear-on-update'), toggleEditor('appearOnUpdate'))),
387
+ ]),
388
+ ];
389
+ const CREATE_SECTION_REPEATER_CHILDREN = [
390
+ gridRow([
391
+ gridItem(12, formField(field('section-id'), selectEditor('id', {
392
+ dataSource: GROUPS_DATASOURCE,
393
+ valueField: 'id',
394
+ textField: 'title',
395
+ required: true,
396
+ }))),
397
+ ]),
398
+ ];
399
+ const CREATE_PROPERTY_LAYOUT_REPEATER_CHILDREN = [
400
+ gridRow([
401
+ gridItem(8, formField(field('layout-property-name'), selectEditor('name', {
402
+ dataSource: PROPERTIES_DATASOURCE,
403
+ valueField: 'name',
404
+ textField: 'title',
405
+ required: true,
406
+ }))),
407
+ gridItem(4, formField(field('layout-col-span'), numberEditor('colSpan', 6))),
408
+ ]),
409
+ ];
410
+ const ACTION_COMMAND_DATASOURCE = [
411
+ { value: ENTITY_CREATE_UI, text: '@general:actions.create.title' },
412
+ { value: 'Entity:OpenDetails', text: '@general:actions.view.title' },
413
+ { value: ENTITY_EDIT_UI, text: '@general:actions.edit.title' },
414
+ { value: ENTITY_REMOVE_UI, text: '@general:actions.delete.title' },
415
+ ];
416
+ const ACTION_TYPE_DATASOURCE = [
417
+ { value: 'create', text: '@general:actions.create.title' },
418
+ { value: 'view', text: '@general:actions.view.title' },
419
+ { value: 'update', text: '@general:actions.edit.title' },
420
+ { value: 'delete', text: '@general:actions.delete.title' },
421
+ ];
422
+ const ACTION_PRIORITY_DATASOURCE = [
423
+ { value: 'primary', text: field('priority-primary') },
424
+ { value: 'secondary', text: field('priority-secondary') },
425
+ { value: 'none', text: field('priority-none') },
426
+ ];
427
+ const ACTION_SCOPE_DATASOURCE = [
428
+ { value: 'typeLevel', text: field('scope-type-level') },
429
+ { value: 'individual', text: field('scope-individual') },
430
+ { value: 'selected', text: field('scope-selected') },
431
+ ];
432
+ const ACTION_REPEATER_CHILDREN = [
433
+ gridRow([
434
+ gridItem(4, formField('@general:terms.common.title', textEditor('title', true))),
435
+ gridItem(4, formField(field('action-command'), selectEditor('command', {
436
+ dataSource: ACTION_COMMAND_DATASOURCE,
437
+ valueField: 'value',
438
+ textField: 'text',
439
+ required: true,
440
+ }))),
441
+ gridItem(4, formField(field('action-icon'), iconEditor('icon'))),
442
+ gridItem(4, formField(field('action-type'), selectEditor('type', {
443
+ dataSource: ACTION_TYPE_DATASOURCE,
444
+ valueField: 'value',
445
+ textField: 'text',
446
+ allowSearch: false,
447
+ }))),
448
+ gridItem(4, formField(field('action-priority'), selectEditor('priority', {
449
+ dataSource: ACTION_PRIORITY_DATASOURCE,
450
+ valueField: 'value',
451
+ textField: 'text',
452
+ allowSearch: false,
453
+ }))),
454
+ gridItem(4, formField(field('action-scope'), selectEditor('scope', {
455
+ dataSource: ACTION_SCOPE_DATASOURCE,
456
+ valueField: 'value',
457
+ textField: 'text',
458
+ allowSearch: false,
459
+ }))),
460
+ ]),
461
+ ];
462
+ const PAGE_REPEATER_CHILDREN = [
463
+ gridRow([
464
+ gridItem(4, formField(field('page-component-key'), textEditor('componentKey', true))),
465
+ gridItem(4, formField('@general:terms.common.title', textEditor('title'))),
466
+ gridItem(4, formField('@general:terms.common.icon', iconEditor('icon'))),
467
+ gridItem(4, formField(field('page-field'), textEditor('field'))),
468
+ gridItem(4, formField(field('page-order'), numberEditor('order', 1))),
469
+ gridItem(2, formField(field('appear-on-create'), toggleEditor('appearOnCreate'))),
470
+ gridItem(2, formField(field('appear-on-update'), toggleEditor('appearOnUpdate'))),
471
+ ]),
472
+ ];
473
+ //#endregion
474
+
475
+ //#region ----- Imports -----
476
+ //#endregion
477
+ //#region ----- Constants -----
478
+ const i18n = RootConfig.config.i18n;
479
+ const ENTITY_DEFINITION_CREATE_ERROR = {
480
+ nameRequired: `@${i18n}:entity-definitions.messages.name-required`,
481
+ moduleRequired: `@${i18n}:entity-definitions.messages.module-required`,
482
+ nameInvalid: `@${i18n}:entity-definitions.messages.name-invalid`,
483
+ nameDuplicate: `@${i18n}:entity-definitions.messages.name-duplicate`,
484
+ };
485
+ const ENTITY_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9]*$/;
486
+ const DEFAULT_ENTITY_ICON = 'fa-light fa-cube';
487
+ const WIDGET_DATA_TYPE = {
488
+ 'number-editor': 'number',
489
+ 'number-unit-editor': 'number',
490
+ 'toggle-editor': 'boolean',
491
+ 'checkbox-editor': 'boolean',
492
+ 'date-time-editor': 'date',
493
+ 'repeater-layout': 'array',
494
+ 'tag-editor': 'array',
495
+ 'lookup-editor': 'uuid',
496
+ 'contact-editor': 'object',
497
+ attachments: 'array',
498
+ 'widget-field-configurator': 'object',
499
+ };
500
+ //#endregion
501
+ //#region ----- Assemble store row -----
502
+ /**
503
+ * Turns a create/update-form payload into the EntityDefinition store shape
504
+ * `{ name: Module.Entity, content: AXPEntity }`.
505
+ */
506
+ function assembleEntityDefinitionStoreRecord(input, previous) {
507
+ const merged = { ...(previous ?? {}), ...input };
508
+ const previousContent = readContent(previous ?? {}) ?? readContent(merged);
509
+ const moduleName = readTrimmed(merged['module']) || readTrimmed(previousContent?.['module']);
510
+ const rawName = readTrimmed(merged['name']) || readTrimmed(previousContent?.['name']);
511
+ const title = readTrimmed(merged['title']) ||
512
+ readTrimmed(previousContent?.['title']) ||
513
+ rawName;
514
+ const icon = readTrimmed(merged['icon']) ||
515
+ readTrimmed(previousContent?.['icon']) ||
516
+ DEFAULT_ENTITY_ICON;
517
+ if (!rawName) {
518
+ return {
519
+ ok: false,
520
+ message: ENTITY_DEFINITION_CREATE_ERROR.nameRequired,
521
+ code: 'ENTITY_DEFINITION_NAME_REQUIRED',
522
+ };
523
+ }
524
+ if (!moduleName) {
525
+ return {
526
+ ok: false,
527
+ message: ENTITY_DEFINITION_CREATE_ERROR.moduleRequired,
528
+ code: 'ENTITY_DEFINITION_MODULE_REQUIRED',
529
+ };
530
+ }
531
+ const parsed = parseEntityName(rawName, moduleName);
532
+ if (!ENTITY_NAME_PATTERN.test(parsed.entityName)) {
533
+ return {
534
+ ok: false,
535
+ message: ENTITY_DEFINITION_CREATE_ERROR.nameInvalid,
536
+ code: 'ENTITY_DEFINITION_NAME_INVALID',
537
+ };
538
+ }
539
+ const identity = {
540
+ module: parsed.moduleName,
541
+ name: parsed.entityName,
542
+ title: title || parsed.entityName,
543
+ icon,
544
+ };
545
+ const content = overlayDesignerFields(previousContent ?? buildStubEntityContent(identity), merged, identity);
546
+ const record = omitDesignerFormFields(merged);
547
+ record['name'] = parsed.storeName;
548
+ record['content'] = content;
549
+ return { ok: true, record };
550
+ }
551
+ //#endregion
552
+ //#region ----- Overlay designer fields -----
553
+ function overlayDesignerFields(existing, input, identity) {
554
+ const groups = readArray(input['groups']);
555
+ const propertyRows = readArray(input['properties']);
556
+ const pluginRows = input['plugins'] !== undefined ? readArray(input['plugins']) : undefined;
557
+ const columnRows = input['columns'] !== undefined ? readArray(input['columns']) : undefined;
558
+ const relatedRows = input['relatedEntities'] !== undefined ? readArray(input['relatedEntities']) : undefined;
559
+ const createSections = input['createSections'] !== undefined ? readArray(input['createSections']) : undefined;
560
+ const createProperties = input['createProperties'] !== undefined ? readArray(input['createProperties']) : undefined;
561
+ const listActions = input['listActions'] !== undefined ? readArray(input['listActions']) : undefined;
562
+ const singleActions = input['singleActions'] !== undefined ? readArray(input['singleActions']) : undefined;
563
+ const pages = input['pages'] !== undefined ? readArray(input['pages']) : undefined;
564
+ const mappedGroups = groups.length
565
+ ? groups.map(mapGroup)
566
+ : readExistingArray(existing['groups']);
567
+ const mappedProperties = propertyRows.length
568
+ ? propertyRows.map((row) => mapProperty(row, mappedGroups))
569
+ : readExistingArray(existing['properties']);
570
+ const content = {
571
+ ...existing,
572
+ module: identity.module,
573
+ name: identity.name,
574
+ title: identity.title,
575
+ icon: identity.icon,
576
+ };
577
+ const parentKey = readTrimmed(input['parentKey']);
578
+ if (parentKey) {
579
+ content['parentKey'] = parentKey;
580
+ }
581
+ else if (input['parentKey'] !== undefined) {
582
+ delete content['parentKey'];
583
+ }
584
+ const searchTags = input['searchTags'];
585
+ if (searchTags !== undefined) {
586
+ content['searchTags'] = Array.isArray(searchTags)
587
+ ? searchTags.filter((tag) => typeof tag === 'string' && tag.trim())
588
+ : [];
589
+ }
590
+ overlayFormats(content, input, identity.title);
591
+ overlayCategory(content, input);
592
+ if (pluginRows) {
593
+ content['plugins'] = pluginRows.map(mapPlugin).filter((plugin) => plugin.name);
594
+ }
595
+ if (mappedGroups.length) {
596
+ content['groups'] = mappedGroups;
597
+ }
598
+ if (mappedProperties.length) {
599
+ content['properties'] = mappedProperties;
600
+ }
601
+ const resolvedProperties = content['properties'] ?? [];
602
+ if (columnRows) {
603
+ content['columns'] = columnRows.length
604
+ ? columnRows.map((row) => mapColumn(row, resolvedProperties))
605
+ : defaultColumns(resolvedProperties);
606
+ }
607
+ else if (!Array.isArray(existing['columns']) && resolvedProperties.length) {
608
+ content['columns'] = defaultColumns(resolvedProperties);
609
+ }
610
+ if (relatedRows) {
611
+ content['relatedEntities'] = relatedRows.map(mapRelatedEntity).filter((row) => row.entity);
612
+ }
613
+ const schemaChanged = groups.length > 0 || propertyRows.length > 0;
614
+ const layoutExplicit = createSections !== undefined || createProperties !== undefined;
615
+ const actionsExplicit = listActions !== undefined || singleActions !== undefined;
616
+ if (schemaChanged || layoutExplicit || actionsExplicit) {
617
+ overlayInterfaces(content, {
618
+ groups: content['groups'] ?? [],
619
+ properties: resolvedProperties,
620
+ createSections,
621
+ createProperties,
622
+ listActions,
623
+ singleActions,
624
+ schemaChanged,
625
+ layoutExplicit,
626
+ });
627
+ }
628
+ if (pages) {
629
+ content['pages'] = pages.map(mapPage).filter((page) => page['componentKey']);
630
+ }
631
+ overlayJsonKey(content, input, 'rules', 'rules');
632
+ overlayJsonKey(content, input, 'validations', 'validations');
633
+ overlayJsonKey(content, input, 'commandsJson', 'commands');
634
+ overlayJsonKey(content, input, 'queriesJson', 'queries');
635
+ return content;
636
+ }
637
+ function overlayFormats(content, input, fallbackTitle) {
638
+ const current = content['formats'] ?? {};
639
+ const individual = readTrimmed(input['formatIndividual']) || String(current['individual'] ?? fallbackTitle);
640
+ const plural = readTrimmed(input['formatPlural']) || String(current['plural'] ?? fallbackTitle);
641
+ const displayName = readTrimmed(input['formatDisplayName']) ||
642
+ (typeof current['displayName'] === 'string' ? current['displayName'] : undefined);
643
+ const searchTitle = readTrimmed(input['formatSearchTitle']) ||
644
+ String(current['searchResult']?.['title'] ?? '{{ name }}');
645
+ const searchDescription = readTrimmed(input['formatSearchDescription']) ||
646
+ String(current['searchResult']?.['description'] ??
647
+ String(content['module'] ?? ''));
648
+ content['formats'] = {
649
+ ...current,
650
+ individual,
651
+ plural,
652
+ ...(displayName ? { displayName } : {}),
653
+ searchResult: {
654
+ title: searchTitle,
655
+ description: searchDescription,
656
+ },
657
+ };
658
+ }
659
+ function overlayCategory(content, input) {
660
+ const entityName = readTrimmed(input['categoryEntity']);
661
+ if (!entityName) {
662
+ if (input['categoryEntity'] !== undefined) {
663
+ delete content['category'];
664
+ }
665
+ return;
666
+ }
667
+ content['category'] = {
668
+ entity: entityName,
669
+ textField: readTrimmed(input['categoryTextField']) || 'title',
670
+ valueField: readTrimmed(input['categoryValueField']) || 'id',
671
+ };
672
+ }
673
+ function overlayInterfaces(content, args) {
674
+ const existing = content['interfaces'] ?? {};
675
+ const master = existing['master'] ?? {};
676
+ const existingList = master['list'] ?? {};
677
+ const existingCreate = master['create'] ?? {};
678
+ const existingSingle = master['single'] ?? {};
679
+ let sections = existingCreate['sections'];
680
+ let propertyLayouts = existingCreate['properties'];
681
+ if (args.layoutExplicit || args.schemaChanged) {
682
+ const sectionIds = resolveSectionIds(args.createSections, args.groups);
683
+ sections = sectionIds.map((id) => ({
684
+ id,
685
+ layout: { positions: { lg: { colSpan: 12 } } },
686
+ }));
687
+ propertyLayouts = resolvePropertyLayouts(args.createProperties, args.properties);
688
+ }
689
+ const listActions = args.listActions
690
+ ? args.listActions.map(mapAction).filter((action) => action.command)
691
+ : (existingList['actions'] ?? [...entityMasterCrudActions()]);
692
+ const singleActions = args.singleActions
693
+ ? args.singleActions.map(mapAction).filter((action) => action.command)
694
+ : (existingSingle['actions'] ?? [...entityMasterRecordActions()]);
695
+ content['interfaces'] = {
696
+ ...existing,
697
+ master: {
698
+ ...master,
699
+ list: {
700
+ ...existingList,
701
+ views: existingList['views'] ?? [createAllQueryView({ sorts: [{ name: 'name', dir: 'asc' }] })],
702
+ actions: listActions.length ? listActions : [...entityMasterCrudActions()],
703
+ },
704
+ create: {
705
+ ...existingCreate,
706
+ sections,
707
+ properties: propertyLayouts,
708
+ },
709
+ update: {
710
+ ...(master['update'] ?? {}),
711
+ sections,
712
+ properties: propertyLayouts,
713
+ },
714
+ single: {
715
+ ...existingSingle,
716
+ title: String(existingSingle['title'] ?? '{{ title || name }}') || '{{ title || name }}',
717
+ sections,
718
+ properties: propertyLayouts,
719
+ actions: singleActions.length ? singleActions : [...entityMasterRecordActions()],
720
+ },
721
+ },
722
+ };
723
+ }
724
+ function overlayJsonKey(content, input, formKey, contentKey) {
725
+ if (input[formKey] === undefined) {
726
+ return;
727
+ }
728
+ const parsed = parseJsonValue(input[formKey]);
729
+ if (parsed === undefined) {
730
+ return;
731
+ }
732
+ content[contentKey] = parsed;
733
+ }
734
+ //#endregion
735
+ //#region ----- Row mappers -----
736
+ function mapGroup(row) {
737
+ const id = readTrimmed(row['id']);
738
+ return {
739
+ id,
740
+ title: readTrimmed(row['title']) || id,
741
+ ...(readTrimmed(row['description']) ? { description: readTrimmed(row['description']) } : {}),
742
+ ...(readTrimmed(row['icon']) ? { icon: readTrimmed(row['icon']) } : {}),
743
+ };
744
+ }
745
+ function mapProperty(row, groups) {
746
+ const name = readTrimmed(row['name']);
747
+ const widget = mapWidgetInterface(row['interface']);
748
+ const dataType = readTrimmed(row['dataType']) || inferDataType(widget?.type) || 'string';
749
+ const required = row['required'] === true;
750
+ const unique = row['unique'] === true;
751
+ const groupId = readTrimmed(row['groupId']) || groups[0]?.id || 'basic-info';
752
+ const defaultValue = row['defaultValue'];
753
+ return {
754
+ name,
755
+ title: readTrimmed(row['title']) || name,
756
+ ...(readTrimmed(row['description']) ? { description: readTrimmed(row['description']) } : {}),
757
+ groupId,
758
+ schema: {
759
+ dataType,
760
+ ...(row['nullable'] === true ? { nullable: true } : {}),
761
+ ...(row['readonly'] === true ? { readonly: true } : {}),
762
+ ...(row['visible'] === false ? { visible: false } : {}),
763
+ ...(defaultValue !== undefined && defaultValue !== '' ? { defaultValue } : {}),
764
+ ...(unique ? { unique: { enabled: true } } : {}),
765
+ ...(widget ? { interface: widget } : { interface: { type: AXPWidgetsCatalog.text } }),
766
+ },
767
+ ...(required ? { validations: [{ rule: 'required' }] } : {}),
768
+ options: {
769
+ filter: { inline: { enabled: true }, advance: { enabled: true } },
770
+ sort: { enabled: true },
771
+ },
772
+ };
773
+ }
774
+ function mapWidgetInterface(value) {
775
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
776
+ return null;
777
+ }
778
+ const node = value;
779
+ const type = readTrimmed(node['type']);
780
+ if (!type) {
781
+ return null;
782
+ }
783
+ const mapped = { type };
784
+ if (node['options'] && typeof node['options'] === 'object' && !Array.isArray(node['options'])) {
785
+ mapped.options = node['options'];
786
+ }
787
+ if (Array.isArray(node['children'])) {
788
+ mapped.children = node['children'];
789
+ }
790
+ if (node['mode'] === 'view' || node['mode'] === 'edit') {
791
+ mapped.mode = node['mode'];
792
+ }
793
+ return mapped;
794
+ }
795
+ function inferDataType(widgetType) {
796
+ if (!widgetType) {
797
+ return undefined;
798
+ }
799
+ return WIDGET_DATA_TYPE[widgetType];
800
+ }
801
+ function mapPlugin(row) {
802
+ if (typeof row === 'string') {
803
+ return { name: row.trim() };
804
+ }
805
+ if (!row || typeof row !== 'object' || Array.isArray(row)) {
806
+ return { name: '' };
807
+ }
808
+ const record = row;
809
+ const name = readTrimmed(record['name']);
810
+ const options = parseJsonValue(record['options']);
811
+ if (options && typeof options === 'object' && !Array.isArray(options)) {
812
+ return { name, options: options };
813
+ }
814
+ return { name };
815
+ }
816
+ function mapColumn(row, properties) {
817
+ const name = readTrimmed(row['name']);
818
+ const property = properties.find((item) => item.name === name);
819
+ const title = readTrimmed(row['title']) || property?.title || name;
820
+ const widgetType = readTrimmed(row['widgetType']) ||
821
+ String(property?.schema?.interface?.type ?? AXPWidgetsCatalog.text);
822
+ return {
823
+ name,
824
+ title,
825
+ showAs: { type: widgetType },
826
+ };
827
+ }
828
+ function defaultColumns(properties) {
829
+ return properties
830
+ .filter((property) => property.schema?.visible !== false)
831
+ .slice(0, 6)
832
+ .map((property) => ({
833
+ name: property.name,
834
+ title: property.title,
835
+ showAs: { type: property.schema?.interface?.type || AXPWidgetsCatalog.text },
836
+ }));
837
+ }
838
+ function mapRelatedEntity(row) {
839
+ const layoutType = readTrimmed(row['layoutType']) || 'page-list';
840
+ const related = {
841
+ entity: readTrimmed(row['entity']),
842
+ ...(readTrimmed(row['title']) ? { title: readTrimmed(row['title']) } : {}),
843
+ ...(readTrimmed(row['icon']) ? { icon: readTrimmed(row['icon']) } : {}),
844
+ layout: {
845
+ type: layoutType,
846
+ position: 'after',
847
+ },
848
+ };
849
+ const persistence = {};
850
+ const foreignKey = readTrimmed(row['foreignKeyField']);
851
+ const dataPath = readTrimmed(row['dataPath']);
852
+ const idField = readTrimmed(row['idField']);
853
+ const strategy = readTrimmed(row['persistenceStrategy']);
854
+ if (foreignKey) {
855
+ persistence.foreignKeyField = foreignKey;
856
+ }
857
+ if (dataPath) {
858
+ persistence.dataPath = dataPath;
859
+ }
860
+ if (idField) {
861
+ persistence.idField = idField;
862
+ }
863
+ if (strategy === 'embedded' || strategy === 'referenced') {
864
+ persistence.strategy = strategy;
865
+ }
866
+ if (Object.keys(persistence).length) {
867
+ related.persistence = persistence;
868
+ }
869
+ if (row['appearOnCreate'] === true || row['appearOnUpdate'] === true) {
870
+ related.appearOn = {
871
+ ...(row['appearOnCreate'] === true ? { create: true } : {}),
872
+ ...(row['appearOnUpdate'] === true ? { update: true } : {}),
873
+ };
874
+ }
875
+ return related;
876
+ }
877
+ function mapAction(row) {
878
+ const command = readTrimmed(row['command']);
879
+ return {
880
+ title: readTrimmed(row['title']) || command,
881
+ command,
882
+ type: (readTrimmed(row['type']) || 'view'),
883
+ priority: (readTrimmed(row['priority']) || 'secondary'),
884
+ scope: (readTrimmed(row['scope']) || 'individual'),
885
+ ...(readTrimmed(row['icon']) ? { icon: readTrimmed(row['icon']) } : {}),
886
+ };
887
+ }
888
+ function mapPage(row) {
889
+ const order = Number(row['order']);
890
+ return {
891
+ componentKey: readTrimmed(row['componentKey']),
892
+ ...(readTrimmed(row['title']) ? { title: readTrimmed(row['title']) } : {}),
893
+ ...(readTrimmed(row['icon']) ? { icon: readTrimmed(row['icon']) } : {}),
894
+ ...(readTrimmed(row['field']) ? { field: readTrimmed(row['field']) } : {}),
895
+ ...(Number.isFinite(order) ? { layout: { order, position: 'after' } } : {}),
896
+ ...(row['appearOnCreate'] === true || row['appearOnUpdate'] === true
897
+ ? {
898
+ appearOn: {
899
+ ...(row['appearOnCreate'] === true ? { create: true } : {}),
900
+ ...(row['appearOnUpdate'] === true ? { update: true } : {}),
901
+ },
902
+ }
903
+ : {}),
904
+ };
905
+ }
906
+ function resolveSectionIds(createSections, groups) {
907
+ if (createSections?.length) {
908
+ return createSections.map((row) => readTrimmed(row['id'])).filter(Boolean);
909
+ }
910
+ if (groups.length) {
911
+ return groups.map((group) => group.id);
912
+ }
913
+ return ['basic-info'];
914
+ }
915
+ function resolvePropertyLayouts(createProperties, properties) {
916
+ const source = createProperties?.length
917
+ ? createProperties
918
+ : properties
919
+ .filter((property) => property.schema?.visible !== false)
920
+ .map((property) => ({ name: property.name, colSpan: 6 }));
921
+ return source
922
+ .map((row) => {
923
+ const name = readTrimmed(row['name']);
924
+ const colSpan = Number(row['colSpan']);
925
+ return {
926
+ name,
927
+ layout: {
928
+ positions: { lg: { colSpan: Number.isFinite(colSpan) && colSpan > 0 ? colSpan : 6 } },
929
+ },
930
+ };
931
+ })
932
+ .filter((row) => row.name);
933
+ }
934
+ //#endregion
935
+ //#region ----- Stub content -----
936
+ function buildStubEntityContent(identity) {
937
+ const sections = [{ id: 'basic-info', layout: { positions: { lg: { colSpan: 12 } } } }];
938
+ const propertyLayouts = [
939
+ { name: 'name', layout: { positions: { lg: { colSpan: 6 } } } },
940
+ { name: 'title', layout: { positions: { lg: { colSpan: 6 } } } },
941
+ ];
942
+ const stub = {
943
+ module: identity.module,
944
+ name: identity.name,
945
+ title: identity.title,
946
+ icon: identity.icon,
947
+ plugins: [],
948
+ formats: {
949
+ individual: identity.title,
950
+ plural: identity.title,
951
+ searchResult: {
952
+ title: '{{ name }}',
953
+ description: identity.module,
954
+ },
955
+ },
956
+ groups: [{ id: 'basic-info', title: '@general:terms.interface.basic-info' }],
957
+ properties: [
958
+ {
959
+ name: 'name',
960
+ title: '@general:terms.common.name',
961
+ groupId: 'basic-info',
962
+ schema: {
963
+ dataType: 'string',
964
+ interface: { type: AXPWidgetsCatalog.text },
965
+ },
966
+ validations: [{ rule: 'required' }],
967
+ },
968
+ {
969
+ name: 'title',
970
+ title: '@general:terms.common.title',
971
+ groupId: 'basic-info',
972
+ schema: {
973
+ dataType: 'string',
974
+ interface: { type: AXPWidgetsCatalog.text },
975
+ },
976
+ validations: [{ rule: 'required' }],
977
+ },
978
+ ],
979
+ columns: [
980
+ { name: 'name', title: '@general:terms.common.name', showAs: { type: AXPWidgetsCatalog.text } },
981
+ { name: 'title', title: '@general:terms.common.title', showAs: { type: AXPWidgetsCatalog.text } },
982
+ ],
983
+ interfaces: {
984
+ master: {
985
+ list: {
986
+ views: [createAllQueryView({ sorts: [{ name: 'name', dir: 'asc' }] })],
987
+ actions: [...entityMasterCrudActions()],
988
+ },
989
+ create: {
990
+ sections,
991
+ properties: propertyLayouts,
992
+ },
993
+ single: {
994
+ title: '{{ title || name }}',
995
+ sections,
996
+ properties: propertyLayouts,
997
+ actions: [...entityMasterRecordActions()],
998
+ },
999
+ },
1000
+ },
1001
+ };
1002
+ return stub;
1003
+ }
1004
+ function parseEntityName(rawName, moduleName) {
1005
+ if (!rawName.includes('.')) {
1006
+ return {
1007
+ moduleName,
1008
+ entityName: rawName,
1009
+ storeName: `${moduleName}.${rawName}`,
1010
+ };
1011
+ }
1012
+ const lastDot = rawName.lastIndexOf('.');
1013
+ const maybeModule = rawName.slice(0, lastDot).trim();
1014
+ const entityName = rawName.slice(lastDot + 1).trim();
1015
+ const resolvedModule = moduleName || maybeModule;
1016
+ return {
1017
+ moduleName: resolvedModule,
1018
+ entityName,
1019
+ storeName: `${resolvedModule}.${entityName}`,
1020
+ };
1021
+ }
1022
+ function readContent(input) {
1023
+ const value = input['content'];
1024
+ if (typeof value === 'string' && value.trim()) {
1025
+ try {
1026
+ const parsed = JSON.parse(value);
1027
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
1028
+ return parsed;
1029
+ }
1030
+ }
1031
+ catch {
1032
+ return null;
1033
+ }
1034
+ }
1035
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
1036
+ return value;
1037
+ }
1038
+ return null;
1039
+ }
1040
+ function omitDesignerFormFields(input) {
1041
+ const next = { ...input };
1042
+ for (const key of ENTITY_DEFINITION_DESIGNER_FORM_KEYS) {
1043
+ delete next[key];
1044
+ }
1045
+ return next;
1046
+ }
1047
+ function readArray(value) {
1048
+ if (!Array.isArray(value)) {
1049
+ return [];
1050
+ }
1051
+ return value.filter((item) => item && typeof item === 'object' && !Array.isArray(item));
1052
+ }
1053
+ function readExistingArray(value) {
1054
+ return Array.isArray(value) ? value : [];
1055
+ }
1056
+ function parseJsonValue(value) {
1057
+ if (value == null || value === '') {
1058
+ return undefined;
1059
+ }
1060
+ if (typeof value === 'string') {
1061
+ const trimmed = value.trim();
1062
+ if (!trimmed) {
1063
+ return undefined;
1064
+ }
1065
+ try {
1066
+ return JSON.parse(trimmed);
1067
+ }
1068
+ catch {
1069
+ return undefined;
1070
+ }
1071
+ }
1072
+ return value;
1073
+ }
1074
+ function readTrimmed(value) {
1075
+ return typeof value === 'string' ? value.trim() : '';
1076
+ }
1077
+ //#endregion
1078
+ //#region ----- Flatten content to designer form -----
1079
+ /**
1080
+ * Maps stored `AXPEntity` content back onto the wizard form fields
1081
+ * (repeaters, JSON editors, identity extras).
1082
+ */
1083
+ function flattenEntityContentToDesignerForm(content) {
1084
+ if (!content) {
1085
+ return {};
1086
+ }
1087
+ const formats = asRecord(content['formats']);
1088
+ const searchResult = asRecord(formats['searchResult']);
1089
+ const category = asRecord(content['category']);
1090
+ const interfaces = asRecord(content['interfaces']);
1091
+ const master = asRecord(interfaces['master']);
1092
+ const create = asRecord(master['create']);
1093
+ const list = asRecord(master['list']);
1094
+ const single = asRecord(master['single']);
1095
+ return {
1096
+ parentKey: readTrimmed(content['parentKey']),
1097
+ searchTags: Array.isArray(content['searchTags']) ? content['searchTags'] : [],
1098
+ formatIndividual: readTrimmed(formats['individual']),
1099
+ formatPlural: readTrimmed(formats['plural']),
1100
+ formatDisplayName: readTrimmed(formats['displayName']),
1101
+ formatSearchTitle: readTrimmed(searchResult['title']),
1102
+ formatSearchDescription: readTrimmed(searchResult['description']),
1103
+ categoryEntity: readTrimmed(category['entity']),
1104
+ categoryTextField: readTrimmed(category['textField']) || 'title',
1105
+ categoryValueField: readTrimmed(category['valueField']) || 'id',
1106
+ plugins: flattenPlugins(content['plugins']),
1107
+ groups: readArray(content['groups']),
1108
+ properties: flattenProperties(content['properties']),
1109
+ columns: flattenColumns(content['columns']),
1110
+ relatedEntities: flattenRelatedEntities(content['relatedEntities']),
1111
+ createSections: flattenSections(create['sections']),
1112
+ createProperties: flattenPropertyLayouts(create['properties']),
1113
+ listActions: flattenActions(list['actions']),
1114
+ singleActions: flattenActions(single['actions']),
1115
+ pages: flattenPages(content['pages']),
1116
+ rules: stringifyJson(content['rules']),
1117
+ validations: stringifyJson(content['validations']),
1118
+ commandsJson: stringifyJson(content['commands']),
1119
+ queriesJson: stringifyJson(content['queries']),
1120
+ };
1121
+ }
1122
+ function flattenProperties(value) {
1123
+ return readArray(value).map((row) => {
1124
+ const schema = asRecord(row['schema']);
1125
+ if (!Object.keys(schema).length) {
1126
+ return row;
1127
+ }
1128
+ const unique = asRecord(schema['unique']);
1129
+ const validations = Array.isArray(row['validations']) ? row['validations'] : [];
1130
+ const required = validations.some((item) => item && typeof item === 'object' && item['rule'] === 'required');
1131
+ return {
1132
+ name: readTrimmed(row['name']),
1133
+ title: readTrimmed(row['title']) || readTrimmed(row['name']),
1134
+ description: readTrimmed(row['description']),
1135
+ groupId: readTrimmed(row['groupId']),
1136
+ interface: schema['interface'] ?? { type: AXPWidgetsCatalog.text },
1137
+ dataType: readTrimmed(schema['dataType']) || 'string',
1138
+ required,
1139
+ nullable: schema['nullable'] === true,
1140
+ readonly: schema['readonly'] === true,
1141
+ unique: unique['enabled'] === true,
1142
+ visible: schema['visible'] !== false,
1143
+ defaultValue: schema['defaultValue'] ?? '',
1144
+ };
1145
+ });
1146
+ }
1147
+ function flattenPlugins(value) {
1148
+ if (!Array.isArray(value)) {
1149
+ return [];
1150
+ }
1151
+ const rows = [];
1152
+ for (const item of value) {
1153
+ if (typeof item === 'string') {
1154
+ const name = item.trim();
1155
+ if (name) {
1156
+ rows.push({ name, options: '' });
1157
+ }
1158
+ continue;
1159
+ }
1160
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
1161
+ continue;
1162
+ }
1163
+ const row = item;
1164
+ const name = readTrimmed(row['name']);
1165
+ if (!name) {
1166
+ continue;
1167
+ }
1168
+ rows.push({
1169
+ name,
1170
+ options: stringifyJson(row['options']),
1171
+ });
1172
+ }
1173
+ return rows;
1174
+ }
1175
+ function flattenColumns(value) {
1176
+ return readArray(value).map((row) => {
1177
+ const showAs = asRecord(row['showAs']);
1178
+ return {
1179
+ name: readTrimmed(row['name']),
1180
+ title: readTrimmed(row['title']),
1181
+ widgetType: readTrimmed(row['widgetType']) || readTrimmed(showAs['type']),
1182
+ };
1183
+ });
1184
+ }
1185
+ function flattenRelatedEntities(value) {
1186
+ return readArray(value).map((row) => {
1187
+ const layout = asRecord(row['layout']);
1188
+ const persistence = asRecord(row['persistence']);
1189
+ const appearOn = asRecord(row['appearOn']);
1190
+ return {
1191
+ entity: readTrimmed(row['entity']),
1192
+ title: readTrimmed(row['title']),
1193
+ icon: readTrimmed(row['icon']),
1194
+ layoutType: readTrimmed(layout['type']) || 'page-list',
1195
+ foreignKeyField: readTrimmed(persistence['foreignKeyField']),
1196
+ dataPath: readTrimmed(persistence['dataPath']),
1197
+ idField: readTrimmed(persistence['idField']),
1198
+ persistenceStrategy: readTrimmed(persistence['strategy']),
1199
+ appearOnCreate: appearOn['create'] === true,
1200
+ appearOnUpdate: appearOn['update'] === true,
1201
+ };
1202
+ });
1203
+ }
1204
+ function flattenSections(value) {
1205
+ return readArray(value).map((row) => ({ id: readTrimmed(row['id']) })).filter((row) => row.id);
1206
+ }
1207
+ function flattenPropertyLayouts(value) {
1208
+ return readArray(value).map((row) => {
1209
+ const layout = asRecord(row['layout']);
1210
+ const positions = asRecord(layout['positions']);
1211
+ const lg = asRecord(positions['lg']);
1212
+ const colSpan = Number(lg['colSpan']);
1213
+ return {
1214
+ name: readTrimmed(row['name']),
1215
+ colSpan: Number.isFinite(colSpan) && colSpan > 0 ? colSpan : 6,
1216
+ };
1217
+ });
1218
+ }
1219
+ function flattenActions(value) {
1220
+ return readArray(value).map((row) => {
1221
+ const command = row['command'];
1222
+ const commandName = typeof command === 'string'
1223
+ ? command
1224
+ : command && typeof command === 'object' && !Array.isArray(command)
1225
+ ? readTrimmed(command['name'])
1226
+ : '';
1227
+ return {
1228
+ title: readTrimmed(row['title']),
1229
+ command: commandName,
1230
+ icon: readTrimmed(row['icon']),
1231
+ type: readTrimmed(row['type']) || 'view',
1232
+ priority: readTrimmed(row['priority']) || 'secondary',
1233
+ scope: readTrimmed(row['scope']) || 'individual',
1234
+ };
1235
+ });
1236
+ }
1237
+ function flattenPages(value) {
1238
+ return readArray(value).map((row) => {
1239
+ const appearOn = asRecord(row['appearOn']);
1240
+ const layout = asRecord(row['layout']);
1241
+ return {
1242
+ componentKey: readTrimmed(row['componentKey']),
1243
+ title: readTrimmed(row['title']),
1244
+ icon: readTrimmed(row['icon']),
1245
+ field: readTrimmed(row['field']),
1246
+ order: layout['order'] ?? '',
1247
+ appearOnCreate: appearOn['create'] === true,
1248
+ appearOnUpdate: appearOn['update'] === true,
1249
+ };
1250
+ });
1251
+ }
1252
+ function stringifyJson(value) {
1253
+ if (value == null || value === '') {
1254
+ return '';
1255
+ }
1256
+ if (typeof value === 'string') {
1257
+ return value;
1258
+ }
1259
+ try {
1260
+ return JSON.stringify(value, null, 2);
1261
+ }
1262
+ catch {
1263
+ return '';
1264
+ }
1265
+ }
1266
+ function asRecord(value) {
1267
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
1268
+ return value;
1269
+ }
1270
+ return {};
1271
+ }
1272
+ //#endregion
1273
+
1274
+ //#region ----- Imports -----
1275
+ //#endregion
1276
+ //#region ----- Constants -----
1277
+ const LIST_FILTER_SORT = {
1278
+ filter: { inline: { enabled: true }, advance: { enabled: true } },
1279
+ sort: { enabled: true },
1280
+ };
1281
+ const i18nScope = RootConfig.config.i18n;
1282
+ function fieldTitle(name) {
1283
+ return `@${i18nScope}:entity-definitions.entities.entity-definition.fields.${name}.title`;
1284
+ }
1285
+ function groupTitle(name) {
1286
+ return `@${i18nScope}:entity-definitions.entities.entity-definition.groups.${name}`;
1287
+ }
1288
+ function pageTitle(name) {
1289
+ return `@${i18nScope}:entity-definitions.entities.entity-definition.pages.${name}.title`;
1290
+ }
1291
+ function repeaterProperty(name, groupId, children) {
1292
+ return {
1293
+ name,
1294
+ title: fieldTitle(name),
1295
+ groupId,
1296
+ schema: {
1297
+ dataType: 'array',
1298
+ defaultValue: [],
1299
+ interface: {
1300
+ type: AXPWidgetsList.Layouts.RepeaterLayout,
1301
+ options: { hasControls: true, allowReorder: true },
1302
+ children: children,
1303
+ },
1304
+ },
1305
+ };
1306
+ }
1307
+ //#endregion
1308
+ //#region ----- Entity -----
92
1309
  function buildEntityDefinitionEntity() {
93
- const i18n = RootConfig.config.i18n;
1310
+ const identityLayout = [
1311
+ { name: 'name', layout: { positions: { lg: { colSpan: 6 } } } },
1312
+ { name: 'module', layout: { positions: { lg: { colSpan: 6 } } } },
1313
+ { name: 'title', layout: { positions: { lg: { colSpan: 6 } } } },
1314
+ { name: 'icon', layout: { positions: { lg: { colSpan: 6 } } } },
1315
+ { name: 'parentKey', layout: { positions: { lg: { colSpan: 6 } } } },
1316
+ { name: 'searchTags', layout: { positions: { lg: { colSpan: 6 } } } },
1317
+ { name: 'formatIndividual', layout: { positions: { lg: { colSpan: 6 } } } },
1318
+ { name: 'formatPlural', layout: { positions: { lg: { colSpan: 6 } } } },
1319
+ { name: 'formatDisplayName', layout: { positions: { lg: { colSpan: 6 } } } },
1320
+ { name: 'formatSearchTitle', layout: { positions: { lg: { colSpan: 6 } } } },
1321
+ { name: 'formatSearchDescription', layout: { positions: { lg: { colSpan: 12 } } } },
1322
+ { name: 'categoryEntity', layout: { positions: { lg: { colSpan: 6 } } } },
1323
+ { name: 'categoryTextField', layout: { positions: { lg: { colSpan: 3 } } } },
1324
+ { name: 'categoryValueField', layout: { positions: { lg: { colSpan: 3 } } } },
1325
+ ];
94
1326
  const entityDef = {
95
1327
  module: RootConfig.module.name,
96
1328
  name: RootConfig.entities.entityDefinition.name,
@@ -105,16 +1337,40 @@ function buildEntityDefinitionEntity() {
105
1337
  },
106
1338
  },
107
1339
  plugins: [],
108
- groups: [
1340
+ pages: [
109
1341
  {
110
- id: 'basic-info',
111
- title: `@${i18n}:entity-definitions.entities.entity-definition.groups.basic-info`,
1342
+ componentKey: ENTITY_DEFINITION_SCHEMA_PAGE_COMPONENT_KEY,
1343
+ field: 'properties',
1344
+ title: pageTitle('schema'),
1345
+ icon: 'fa-light fa-list',
1346
+ layout: { order: 1, position: 'after' },
1347
+ appearOn: { create: true, update: true },
1348
+ options: { propertyNames: [...ENTITY_DEFINITION_SCHEMA_PROPERTY_NAMES] },
112
1349
  },
113
1350
  {
114
- id: 'schema',
115
- title: `@${i18n}:entity-definitions.entities.entity-definition.groups.schema`,
1351
+ componentKey: ENTITY_DEFINITION_SURFACES_PAGE_COMPONENT_KEY,
1352
+ field: 'interfaces',
1353
+ title: pageTitle('surfaces'),
1354
+ icon: 'fa-light fa-table-columns',
1355
+ layout: { order: 2, position: 'after' },
1356
+ appearOn: { create: true, update: true },
1357
+ options: { propertyNames: [...ENTITY_DEFINITION_SURFACES_PROPERTY_NAMES] },
116
1358
  },
117
1359
  ],
1360
+ groups: [
1361
+ { id: 'basic-info', title: groupTitle('basic-info') },
1362
+ { id: 'formats', title: groupTitle('formats') },
1363
+ { id: 'category', title: groupTitle('category') },
1364
+ { id: 'plugins', title: groupTitle('plugins') },
1365
+ { id: 'groups', title: groupTitle('groups') },
1366
+ { id: 'properties', title: groupTitle('properties') },
1367
+ { id: 'columns', title: groupTitle('columns') },
1368
+ { id: 'related-entities', title: groupTitle('related-entities') },
1369
+ { id: 'layouts', title: groupTitle('layouts') },
1370
+ { id: 'actions', title: groupTitle('actions') },
1371
+ { id: 'advanced', title: groupTitle('advanced') },
1372
+ { id: 'schema', title: groupTitle('schema') },
1373
+ ],
118
1374
  properties: [
119
1375
  {
120
1376
  name: 'id',
@@ -133,27 +1389,31 @@ function buildEntityDefinitionEntity() {
133
1389
  groupId: 'basic-info',
134
1390
  schema: {
135
1391
  dataType: 'string',
136
- readonly: true,
137
1392
  interface: { type: AXPWidgetsCatalog.text },
138
1393
  },
139
- options: {
140
- filter: { inline: { enabled: true }, advance: { enabled: true } },
141
- sort: { enabled: true },
142
- },
1394
+ validations: [{ rule: 'required' }],
1395
+ options: LIST_FILTER_SORT,
143
1396
  },
144
1397
  {
145
1398
  name: 'module',
146
- title: `@${i18n}:entity-definitions.entities.entity-definition.fields.module-id.title`,
1399
+ title: fieldTitle('module-id'),
147
1400
  groupId: 'basic-info',
148
1401
  schema: {
149
1402
  dataType: 'string',
150
- readonly: true,
151
- interface: { type: AXPWidgetsCatalog.text },
152
- },
153
- options: {
154
- filter: { inline: { enabled: true }, advance: { enabled: true } },
155
- sort: { enabled: true },
1403
+ interface: {
1404
+ type: AXPWidgetsCatalog.lookup,
1405
+ options: {
1406
+ entity: MODULE_DEFINITION_ENTITY,
1407
+ textField: 'title',
1408
+ valueField: 'name',
1409
+ look: 'select',
1410
+ allowSearch: true,
1411
+ columns: ['title', 'name'],
1412
+ },
1413
+ },
156
1414
  },
1415
+ validations: [{ rule: 'required' }],
1416
+ options: LIST_FILTER_SORT,
157
1417
  },
158
1418
  {
159
1419
  name: 'title',
@@ -161,13 +1421,10 @@ function buildEntityDefinitionEntity() {
161
1421
  groupId: 'basic-info',
162
1422
  schema: {
163
1423
  dataType: 'string',
164
- readonly: true,
165
1424
  interface: { type: AXPWidgetsCatalog.text },
166
1425
  },
167
- options: {
168
- filter: { inline: { enabled: true }, advance: { enabled: true } },
169
- sort: { enabled: true },
170
- },
1426
+ validations: [{ rule: 'required' }],
1427
+ options: LIST_FILTER_SORT,
171
1428
  },
172
1429
  {
173
1430
  name: 'icon',
@@ -175,13 +1432,199 @@ function buildEntityDefinitionEntity() {
175
1432
  groupId: 'basic-info',
176
1433
  schema: {
177
1434
  dataType: 'string',
178
- readonly: true,
179
1435
  interface: { type: AXPWidgetsCatalog.iconChooser },
180
1436
  },
181
1437
  },
1438
+ {
1439
+ name: 'parentKey',
1440
+ title: fieldTitle('parent-key'),
1441
+ groupId: 'basic-info',
1442
+ schema: {
1443
+ dataType: 'string',
1444
+ interface: { type: AXPWidgetsCatalog.text },
1445
+ },
1446
+ },
1447
+ {
1448
+ name: 'searchTags',
1449
+ title: fieldTitle('search-tags'),
1450
+ groupId: 'basic-info',
1451
+ schema: {
1452
+ dataType: 'array',
1453
+ defaultValue: [],
1454
+ interface: { type: AXPWidgetsList.Editors.TagEditor },
1455
+ },
1456
+ },
1457
+ {
1458
+ name: 'formatIndividual',
1459
+ title: fieldTitle('format-individual'),
1460
+ groupId: 'formats',
1461
+ schema: {
1462
+ dataType: 'string',
1463
+ interface: { type: AXPWidgetsCatalog.text },
1464
+ },
1465
+ },
1466
+ {
1467
+ name: 'formatPlural',
1468
+ title: fieldTitle('format-plural'),
1469
+ groupId: 'formats',
1470
+ schema: {
1471
+ dataType: 'string',
1472
+ interface: { type: AXPWidgetsCatalog.text },
1473
+ },
1474
+ },
1475
+ {
1476
+ name: 'formatDisplayName',
1477
+ title: fieldTitle('format-display-name'),
1478
+ groupId: 'formats',
1479
+ schema: {
1480
+ dataType: 'string',
1481
+ interface: { type: AXPWidgetsCatalog.text },
1482
+ },
1483
+ },
1484
+ {
1485
+ name: 'formatSearchTitle',
1486
+ title: fieldTitle('format-search-title'),
1487
+ groupId: 'formats',
1488
+ schema: {
1489
+ dataType: 'string',
1490
+ interface: { type: AXPWidgetsCatalog.text },
1491
+ },
1492
+ },
1493
+ {
1494
+ name: 'formatSearchDescription',
1495
+ title: fieldTitle('format-search-description'),
1496
+ groupId: 'formats',
1497
+ schema: {
1498
+ dataType: 'string',
1499
+ interface: { type: AXPWidgetsCatalog.largeText, options: { rows: 2 } },
1500
+ },
1501
+ },
1502
+ {
1503
+ name: 'categoryEntity',
1504
+ title: fieldTitle('category-entity'),
1505
+ groupId: 'category',
1506
+ schema: {
1507
+ dataType: 'string',
1508
+ interface: {
1509
+ type: AXPWidgetsCatalog.lookup,
1510
+ options: {
1511
+ entity: `${RootConfig.module.name}.${RootConfig.entities.entityDefinition.name}`,
1512
+ textField: 'name',
1513
+ valueField: 'name',
1514
+ look: 'select',
1515
+ allowSearch: true,
1516
+ columns: ['name'],
1517
+ },
1518
+ },
1519
+ },
1520
+ },
1521
+ {
1522
+ name: 'categoryTextField',
1523
+ title: fieldTitle('category-text-field'),
1524
+ groupId: 'category',
1525
+ schema: {
1526
+ dataType: 'string',
1527
+ defaultValue: 'title',
1528
+ interface: { type: AXPWidgetsCatalog.text },
1529
+ },
1530
+ },
1531
+ {
1532
+ name: 'categoryValueField',
1533
+ title: fieldTitle('category-value-field'),
1534
+ groupId: 'category',
1535
+ schema: {
1536
+ dataType: 'string',
1537
+ defaultValue: 'id',
1538
+ interface: { type: AXPWidgetsCatalog.text },
1539
+ },
1540
+ },
1541
+ {
1542
+ ...repeaterProperty('plugins', 'plugins', PLUGIN_REPEATER_CHILDREN),
1543
+ },
1544
+ {
1545
+ ...repeaterProperty('groups', 'groups', GROUP_REPEATER_CHILDREN),
1546
+ },
1547
+ {
1548
+ ...repeaterProperty('properties', 'properties', PROPERTY_REPEATER_CHILDREN),
1549
+ },
1550
+ {
1551
+ ...repeaterProperty('columns', 'columns', COLUMN_REPEATER_CHILDREN),
1552
+ },
1553
+ {
1554
+ ...repeaterProperty('relatedEntities', 'related-entities', RELATED_ENTITY_REPEATER_CHILDREN),
1555
+ title: fieldTitle('related-entities'),
1556
+ },
1557
+ {
1558
+ ...repeaterProperty('createSections', 'layouts', CREATE_SECTION_REPEATER_CHILDREN),
1559
+ title: fieldTitle('create-sections'),
1560
+ },
1561
+ {
1562
+ ...repeaterProperty('createProperties', 'layouts', CREATE_PROPERTY_LAYOUT_REPEATER_CHILDREN),
1563
+ title: fieldTitle('create-properties'),
1564
+ },
1565
+ {
1566
+ ...repeaterProperty('listActions', 'actions', ACTION_REPEATER_CHILDREN),
1567
+ title: fieldTitle('list-actions'),
1568
+ },
1569
+ {
1570
+ ...repeaterProperty('singleActions', 'actions', ACTION_REPEATER_CHILDREN),
1571
+ title: fieldTitle('single-actions'),
1572
+ },
1573
+ {
1574
+ ...repeaterProperty('pages', 'advanced', PAGE_REPEATER_CHILDREN),
1575
+ title: fieldTitle('pages'),
1576
+ },
1577
+ {
1578
+ name: 'rules',
1579
+ title: fieldTitle('rules'),
1580
+ groupId: 'advanced',
1581
+ schema: {
1582
+ dataType: 'object',
1583
+ interface: {
1584
+ type: AXPWidgetsList.Advanced.CodeEditor,
1585
+ options: { language: 'json', height: 'h-40' },
1586
+ },
1587
+ },
1588
+ },
1589
+ {
1590
+ name: 'validations',
1591
+ title: fieldTitle('validations'),
1592
+ groupId: 'advanced',
1593
+ schema: {
1594
+ dataType: 'object',
1595
+ interface: {
1596
+ type: AXPWidgetsList.Advanced.CodeEditor,
1597
+ options: { language: 'json', height: 'h-40' },
1598
+ },
1599
+ },
1600
+ },
1601
+ {
1602
+ name: 'commandsJson',
1603
+ title: fieldTitle('commands'),
1604
+ groupId: 'advanced',
1605
+ schema: {
1606
+ dataType: 'object',
1607
+ interface: {
1608
+ type: AXPWidgetsList.Advanced.CodeEditor,
1609
+ options: { language: 'json', height: 'h-40' },
1610
+ },
1611
+ },
1612
+ },
1613
+ {
1614
+ name: 'queriesJson',
1615
+ title: fieldTitle('queries'),
1616
+ groupId: 'advanced',
1617
+ schema: {
1618
+ dataType: 'object',
1619
+ interface: {
1620
+ type: AXPWidgetsList.Advanced.CodeEditor,
1621
+ options: { language: 'json', height: 'h-40' },
1622
+ },
1623
+ },
1624
+ },
182
1625
  {
183
1626
  name: 'content',
184
- title: `@${i18n}:entity-definitions.entities.entity-definition.fields.content.title`,
1627
+ title: fieldTitle('content'),
185
1628
  groupId: 'schema',
186
1629
  schema: {
187
1630
  dataType: 'object',
@@ -197,7 +1640,7 @@ function buildEntityDefinitionEntity() {
197
1640
  { name: 'name', title: '@general:terms.common.name', showAs: { type: AXPWidgetsCatalog.text } },
198
1641
  {
199
1642
  name: 'module',
200
- title: `@${i18n}:entity-definitions.entities.entity-definition.fields.module-id.title`,
1643
+ title: fieldTitle('module-id'),
201
1644
  showAs: { type: AXPWidgetsCatalog.text },
202
1645
  options: { dataPath: 'content.module' },
203
1646
  },
@@ -218,16 +1661,41 @@ function buildEntityDefinitionEntity() {
218
1661
  master: {
219
1662
  list: {
220
1663
  views: [createAllQueryView({ sorts: [{ name: 'name', dir: 'asc' }] })],
221
- actions: [entityMasterViewAction()],
1664
+ actions: [entityMasterCreateAction(), entityMasterViewAction()],
1665
+ },
1666
+ create: {
1667
+ sections: [
1668
+ { id: 'basic-info', layout: { positions: { lg: { colSpan: 12 } } } },
1669
+ { id: 'formats', layout: { positions: { lg: { colSpan: 12 } } } },
1670
+ { id: 'category', layout: { positions: { lg: { colSpan: 12 } } } },
1671
+ ],
1672
+ properties: identityLayout,
1673
+ },
1674
+ update: {
1675
+ sections: [
1676
+ { id: 'basic-info', layout: { positions: { lg: { colSpan: 12 } } } },
1677
+ { id: 'formats', layout: { positions: { lg: { colSpan: 12 } } } },
1678
+ { id: 'category', layout: { positions: { lg: { colSpan: 12 } } } },
1679
+ ],
1680
+ properties: identityLayout,
222
1681
  },
223
1682
  single: {
224
1683
  title: '{{ name }}',
225
- sections: [{ id: 'basic-info' }, { id: 'schema' }],
1684
+ sections: [
1685
+ { id: 'basic-info' },
1686
+ { id: 'formats' },
1687
+ { id: 'schema' },
1688
+ ],
226
1689
  properties: [
227
1690
  { name: 'name', dataPath: 'content.name', layout: { positions: { lg: { colSpan: 6 } } } },
228
1691
  { name: 'module', dataPath: 'content.module', layout: { positions: { lg: { colSpan: 6 } } } },
229
1692
  { name: 'title', dataPath: 'content.title', layout: { positions: { lg: { colSpan: 6 } } } },
230
1693
  { name: 'icon', dataPath: 'content.icon', layout: { positions: { lg: { colSpan: 6 } } } },
1694
+ {
1695
+ name: 'parentKey',
1696
+ dataPath: 'content.parentKey',
1697
+ layout: { positions: { lg: { colSpan: 6 } } },
1698
+ },
231
1699
  { name: 'content', layout: { positions: { lg: { colSpan: 12 } } } },
232
1700
  ],
233
1701
  actions: [...entityMasterRecordActions()],
@@ -240,6 +1708,7 @@ function buildEntityDefinitionEntity() {
240
1708
  async function entityDefinitionEntityFactory() {
241
1709
  return buildEntityDefinitionEntity();
242
1710
  }
1711
+ //#endregion
243
1712
 
244
1713
  /**
245
1714
  * Generated bundle index. Do not edit.