@acorex/modules 19.4.12 → 19.4.14

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 (22) hide show
  1. package/content-management/index.d.ts +2 -0
  2. package/content-management/lib/entities/index.d.ts +1 -0
  3. package/content-management/lib/entities/promotion/index.d.ts +5 -0
  4. package/content-management/lib/features/index.d.ts +1 -0
  5. package/content-management/lib/features/promotion/components/index.d.ts +1 -0
  6. package/content-management/lib/features/promotion/index.d.ts +1 -0
  7. package/fesm2022/acorex-modules-content-management.mjs +1288 -1
  8. package/fesm2022/acorex-modules-content-management.mjs.map +1 -1
  9. package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-B8aACrqL.mjs → acorex-modules-platform-management-acorex-modules-platform-management-CzMi7CBH.mjs} +17 -31
  10. package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-CzMi7CBH.mjs.map +1 -0
  11. package/fesm2022/{acorex-modules-platform-management-list-version.component-DhSicYd3.mjs → acorex-modules-platform-management-list-version.component-DfbMc2hn.mjs} +2 -2
  12. package/fesm2022/{acorex-modules-platform-management-list-version.component-DhSicYd3.mjs.map → acorex-modules-platform-management-list-version.component-DfbMc2hn.mjs.map} +1 -1
  13. package/fesm2022/{acorex-modules-platform-management-settings.provider-CnGAUpof.mjs → acorex-modules-platform-management-settings.provider-B-19OJn0.mjs} +2 -2
  14. package/fesm2022/{acorex-modules-platform-management-settings.provider-CnGAUpof.mjs.map → acorex-modules-platform-management-settings.provider-B-19OJn0.mjs.map} +1 -1
  15. package/fesm2022/acorex-modules-platform-management.mjs +1 -1
  16. package/package.json +1 -1
  17. package/platform-management/lib/entities/data-source/datasource-provider.dynamic.d.ts +2 -0
  18. package/fesm2022/acorex-modules-content-management-acorex-modules-content-management-C23PlUCn.mjs +0 -392
  19. package/fesm2022/acorex-modules-content-management-acorex-modules-content-management-C23PlUCn.mjs.map +0 -1
  20. package/fesm2022/acorex-modules-content-management-promotion.entity-D3qRwZhQ.mjs +0 -892
  21. package/fesm2022/acorex-modules-content-management-promotion.entity-D3qRwZhQ.mjs.map +0 -1
  22. package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-B8aACrqL.mjs.map +0 -1
@@ -1,2 +1,1289 @@
1
- export { a as AXMContentManagementModule, b as AXMEntityProvider, c as AXMMenuProvider, d as AXMSearchCommandProvider, e as AXMSettingProvider, R as RootConfig } from './acorex-modules-content-management-acorex-modules-content-management-C23PlUCn.mjs';
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injector, Injectable, signal, Component, NgModule } from '@angular/core';
3
+ import { AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
4
+ import { AXPSearchCommandProvider, AXPFileStorageService, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, createAllQueryView, createQueryView, AXPEntityCommandScope, AXPEntityQueryType } from '@acorex/platform/common';
5
+ import { AXPEntityService, AXMEntityCrudServiceImpl, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
6
+ import * as i1 from '@acorex/platform/layout/components';
7
+ import { AXPComponentSlotModule } from '@acorex/platform/layout/components';
8
+ import { AXP_DATASOURCE_DEFINITION_PROVIDER } from '@acorex/platform/core';
9
+ import { AXDataSource } from '@acorex/cdk/common';
10
+ import { AXPWidgetsCatalog } from '@acorex/platform/layout/builder';
11
+ import { AXSafePipe } from '@acorex/core/pipes';
12
+ import { CommonModule } from '@angular/common';
13
+
14
+ const config = {
15
+ i18n: 'content-management',
16
+ };
17
+ const RootConfig = {
18
+ config,
19
+ module: {
20
+ module: 'ContentManagement',
21
+ name: 'ContentManagement',
22
+ title: `t('module-name', {scope:"${config.i18n}"})`,
23
+ icon: 'fa-light fa-file-invoice',
24
+ },
25
+ entities: {
26
+ promotion: {
27
+ name: 'Promotion',
28
+ title: `t("promotion", { scope: "${config.i18n}" })`,
29
+ titlePlural: `t("promotions", { scope: "${config.i18n}" })`,
30
+ icon: 'fa-light fa-megaphone',
31
+ },
32
+ },
33
+ };
34
+
35
+ class AXMMenuProvider {
36
+ constructor() {
37
+ this.entityService = inject(AXPEntityService);
38
+ }
39
+ async provide(context) {
40
+ const scope = RootConfig.config.i18n;
41
+ const module = RootConfig.module;
42
+ context.addItems([
43
+ {
44
+ priority: 100,
45
+ text: `t('module-name', {scope:"${scope}"})`,
46
+ icon: module.icon,
47
+ name: 'content-management-menu',
48
+ children: [
49
+ {
50
+ text: RootConfig.entities.promotion.title,
51
+ path: this.entityService.createPath(module.name, RootConfig.entities.promotion.name),
52
+ icon: RootConfig.entities.promotion.icon,
53
+ priority: 1,
54
+ name: 'content-management-promotion-menu-item'
55
+ }
56
+ ],
57
+ },
58
+ ]);
59
+ }
60
+ }
61
+
62
+ class AXMEntityProvider {
63
+ constructor() {
64
+ this.injector = inject(Injector);
65
+ }
66
+ preload() {
67
+ const module = RootConfig.module.name;
68
+ return Array.from(Object.values(RootConfig.entities)).map((entity) => ({
69
+ module: module,
70
+ entity: entity.name,
71
+ }));
72
+ }
73
+ async get(moduleName, entityName) {
74
+ if (moduleName == RootConfig.module.name) {
75
+ switch (entityName) {
76
+ // case RootConfig.entities.sample.name:
77
+ // return (await import('./entities/sample/sample.entity')).factory(this.injector);
78
+ case RootConfig.entities.promotion.name: {
79
+ const entity = (await Promise.resolve().then(function () { return promotion_entity; })).promotionEntityFactory;
80
+ return entity(this.injector);
81
+ }
82
+ }
83
+ }
84
+ return null;
85
+ }
86
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMEntityProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
87
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMEntityProvider }); }
88
+ }
89
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMEntityProvider, decorators: [{
90
+ type: Injectable
91
+ }] });
92
+
93
+ class AXMPermissionDefinitionProvider {
94
+ async define(context) {
95
+ // context.addPermissions([
96
+ // {
97
+ // name: 'view_templates',
98
+ // title: 'Permission to view templates',
99
+ // isArchived: false,
100
+ // },
101
+ // ]);
102
+ }
103
+ }
104
+
105
+ class AXMSettingProvider {
106
+ async provide(context) {
107
+ // context
108
+ // // Add Form Template Group
109
+ // .addGroup('form-template', 'Form Template', 'Settings related to form templates.', RootConfig.module.icon)
110
+ // // Start Interface Section
111
+ // .addSection('interface', 'UI Interface', 'Customize the user interface for forms.')
112
+ // .addSetting({
113
+ // key: 'history-panel',
114
+ // title: 'Show History Panel',
115
+ // scope: 'U',
116
+ // isInherited: true,
117
+ // defaultValue: false,
118
+ // widget: {
119
+ // type: AXPWidgetsCatalog.toggle,
120
+ // },
121
+ // description: 'Enable or disable the history panel for forms.',
122
+ // validationRules: [
123
+ // {
124
+ // rule: 'required',
125
+ // },
126
+ // ],
127
+ // })
128
+ // .endSection()
129
+ // .endGroup();
130
+ }
131
+ }
132
+
133
+ class AXMSearchCommandProvider extends AXPSearchCommandProvider {
134
+ constructor() {
135
+ super(...arguments);
136
+ this.commands = [
137
+ // {
138
+ // group: 'command',
139
+ // title: 'New Form Template',
140
+ // icon: RootConfig.entities.template.icon,
141
+ // description: 'Create a new form template for designing reusable forms.', // Added description
142
+ // commands: {
143
+ // 'create-entity': {
144
+ // entity: `${RootConfig.module.name}.${RootConfig.entities.template.name}`,
145
+ // },
146
+ // },
147
+ // }
148
+ ];
149
+ }
150
+ }
151
+
152
+ class AXMAppPromotionService extends AXMEntityCrudServiceImpl {
153
+ }
154
+ class AXMPromotionServiceImpl extends AXMEntityCrudServiceImpl {
155
+ constructor() {
156
+ super(`${RootConfig.module.name}.${RootConfig.entities.promotion.name}`);
157
+ }
158
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMPromotionServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
159
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMPromotionServiceImpl }); }
160
+ }
161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMPromotionServiceImpl, decorators: [{
162
+ type: Injectable
163
+ }], ctorParameters: () => [] });
164
+
165
+ class AXMPromotionDataSourceDefinition {
166
+ constructor() {
167
+ this.promotionService = inject(AXMAppPromotionService);
168
+ this.i18n = RootConfig.config.i18n;
169
+ }
170
+ items() {
171
+ return Promise.resolve([
172
+ {
173
+ name: 'promotion',
174
+ title: 'Promotion',
175
+ source: () => {
176
+ return new AXDataSource({
177
+ load: async (_) => {
178
+ try {
179
+ const res = await this.promotionService.query();
180
+ return {
181
+ items: res.items,
182
+ total: res.total,
183
+ };
184
+ }
185
+ catch (e) {
186
+ console.log(e);
187
+ throw e;
188
+ }
189
+ },
190
+ pageSize: 100,
191
+ });
192
+ },
193
+ columns: [
194
+ {
195
+ name: 'id',
196
+ title: 'ID',
197
+ datatype: 'uuid',
198
+ type: AXPWidgetsCatalog.text,
199
+ },
200
+ {
201
+ name: 'title',
202
+ //TODO translate
203
+ title: `Title`,
204
+ datatype: 'string',
205
+ type: AXPWidgetsCatalog.text,
206
+ },
207
+ {
208
+ name: 'body',
209
+ title: `Body`,
210
+ datatype: 'string',
211
+ type: AXPWidgetsCatalog.richText,
212
+ },
213
+ ],
214
+ textField: {
215
+ name: 'title',
216
+ title: 'Title',
217
+ },
218
+ valueField: {
219
+ name: 'id',
220
+ title: 'ID',
221
+ },
222
+ },
223
+ ]);
224
+ }
225
+ }
226
+
227
+ class AXMPromotionSlotComponent {
228
+ constructor() {
229
+ this.notificationChannelService = inject(AXMAppPromotionService);
230
+ this.listData = signal([]);
231
+ this.fileStorage = inject(AXPFileStorageService);
232
+ }
233
+ async ngOnInit() {
234
+ const channels = await this.notificationChannelService.query({
235
+ skip: 0,
236
+ take: 10000,
237
+ // filter: {
238
+ // field: 'type',
239
+ // operator: { type: 'equal' },
240
+ // value: 'promotion',
241
+ // },
242
+ });
243
+ const filteredItems = channels.items.filter((x) => x.placement?.name == this.location);
244
+ const mappedItems = await Promise.all(filteredItems.map(async (item) => {
245
+ if (item.imageId != null) {
246
+ const image = await this.fileStorage.getInfo(item.imageId);
247
+ return {
248
+ ...item,
249
+ image: image,
250
+ };
251
+ }
252
+ else {
253
+ return item;
254
+ }
255
+ }));
256
+ this.listData.set(mappedItems);
257
+ }
258
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMPromotionSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
259
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXMPromotionSlotComponent, isStandalone: true, selector: "acorex-platform-promotion-slot", ngImport: i0, template: "@for (item of listData(); track item.id) { @if (item.contentType?.name == 'media') {\n<img [src]=\"item.image?.url ?? ''\" class=\"ax-w-full ax-p-3 ax-border {{\n item.shape?.name == 'circle' ? 'ax-rounded-full' : 'ax-rounded-none'\n }}\" />\n} @if(item.contentType?.name == 'text'){\n<div class=\"ax-m-1 ax-px-6 ax-p-4 ax-border ax-bg-primary ax-rounded-lg\">\n <h1 class=\"ax-text-base/6\" [innerHTML]=\"item.body | safe : 'html'\"></h1>\n</div>\n\n} } ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: AXSafePipe, name: "safe" }] }); }
260
+ }
261
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMPromotionSlotComponent, decorators: [{
262
+ type: Component,
263
+ args: [{ selector: 'acorex-platform-promotion-slot', imports: [CommonModule, AXSafePipe], template: "@for (item of listData(); track item.id) { @if (item.contentType?.name == 'media') {\n<img [src]=\"item.image?.url ?? ''\" class=\"ax-w-full ax-p-3 ax-border {{\n item.shape?.name == 'circle' ? 'ax-rounded-full' : 'ax-rounded-none'\n }}\" />\n} @if(item.contentType?.name == 'text'){\n<div class=\"ax-m-1 ax-px-6 ax-p-4 ax-border ax-bg-primary ax-rounded-lg\">\n <h1 class=\"ax-text-base/6\" [innerHTML]=\"item.body | safe : 'html'\"></h1>\n</div>\n\n} } " }]
264
+ }] });
265
+
266
+ class AXMContentManagementModule {
267
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMContentManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
268
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: AXMContentManagementModule, imports: [i1.AXPComponentSlotModule] }); }
269
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMContentManagementModule, providers: [
270
+ {
271
+ provide: AXP_MENU_PROVIDER,
272
+ useClass: AXMMenuProvider,
273
+ multi: true,
274
+ },
275
+ {
276
+ provide: AXP_ENTITY_DEFINITION_LOADER,
277
+ useClass: AXMEntityProvider,
278
+ multi: true,
279
+ },
280
+ {
281
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
282
+ useClass: AXMSettingProvider,
283
+ multi: true,
284
+ },
285
+ {
286
+ provide: AXP_SEARCH_PROVIDER,
287
+ useClass: AXMSearchCommandProvider,
288
+ multi: true,
289
+ },
290
+ {
291
+ provide: AXP_PERMISSION_DEFINITION_PROVIDER,
292
+ useClass: AXMPermissionDefinitionProvider,
293
+ multi: true,
294
+ },
295
+ {
296
+ provide: AXMAppPromotionService,
297
+ useClass: AXMPromotionServiceImpl,
298
+ },
299
+ {
300
+ provide: AXP_DATASOURCE_DEFINITION_PROVIDER,
301
+ useClass: AXMPromotionDataSourceDefinition,
302
+ multi: true,
303
+ },
304
+ ], imports: [AXPComponentSlotModule.forChild({
305
+ 'side-menu-footer': [
306
+ {
307
+ name: 'side-menu-footer-promotion',
308
+ component: AXMPromotionSlotComponent,
309
+ options: {
310
+ location: 'side-menu-footer',
311
+ },
312
+ },
313
+ ],
314
+ 'side-menu-header': [
315
+ {
316
+ name: 'side-menu-header-promotion',
317
+ component: AXMPromotionSlotComponent,
318
+ priority: 2,
319
+ options: {
320
+ location: 'side-menu-header',
321
+ },
322
+ },
323
+ ],
324
+ })] }); }
325
+ }
326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMContentManagementModule, decorators: [{
327
+ type: NgModule,
328
+ args: [{
329
+ imports: [
330
+ AXPComponentSlotModule.forChild({
331
+ 'side-menu-footer': [
332
+ {
333
+ name: 'side-menu-footer-promotion',
334
+ component: AXMPromotionSlotComponent,
335
+ options: {
336
+ location: 'side-menu-footer',
337
+ },
338
+ },
339
+ ],
340
+ 'side-menu-header': [
341
+ {
342
+ name: 'side-menu-header-promotion',
343
+ component: AXMPromotionSlotComponent,
344
+ priority: 2,
345
+ options: {
346
+ location: 'side-menu-header',
347
+ },
348
+ },
349
+ ],
350
+ }),
351
+ ],
352
+ exports: [],
353
+ declarations: [],
354
+ providers: [
355
+ {
356
+ provide: AXP_MENU_PROVIDER,
357
+ useClass: AXMMenuProvider,
358
+ multi: true,
359
+ },
360
+ {
361
+ provide: AXP_ENTITY_DEFINITION_LOADER,
362
+ useClass: AXMEntityProvider,
363
+ multi: true,
364
+ },
365
+ {
366
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
367
+ useClass: AXMSettingProvider,
368
+ multi: true,
369
+ },
370
+ {
371
+ provide: AXP_SEARCH_PROVIDER,
372
+ useClass: AXMSearchCommandProvider,
373
+ multi: true,
374
+ },
375
+ {
376
+ provide: AXP_PERMISSION_DEFINITION_PROVIDER,
377
+ useClass: AXMPermissionDefinitionProvider,
378
+ multi: true,
379
+ },
380
+ {
381
+ provide: AXMAppPromotionService,
382
+ useClass: AXMPromotionServiceImpl,
383
+ },
384
+ {
385
+ provide: AXP_DATASOURCE_DEFINITION_PROVIDER,
386
+ useClass: AXMPromotionDataSourceDefinition,
387
+ multi: true,
388
+ },
389
+ ]
390
+ }]
391
+ }] });
392
+
393
+ /**
394
+ * Deeply sanitizes an object for storage in IndexedDB by removing non-serializable content
395
+ */
396
+ function sanitizeForStorage(obj) {
397
+ if (!obj) {
398
+ return obj;
399
+ }
400
+ // Handle primitive values
401
+ if (typeof obj !== 'object') {
402
+ return obj;
403
+ }
404
+ // Handle arrays
405
+ if (Array.isArray(obj)) {
406
+ return obj.map(item => sanitizeForStorage(item));
407
+ }
408
+ // Handle Date objects
409
+ if (obj instanceof Date) {
410
+ return obj;
411
+ }
412
+ // Handle File objects specially
413
+ if (obj instanceof File) {
414
+ // File objects are handled separately, return as is
415
+ return obj;
416
+ }
417
+ // Handle Blob objects
418
+ if (obj instanceof Blob) {
419
+ // Blob objects are handled separately
420
+ return obj;
421
+ }
422
+ // Handle regular objects
423
+ const cleanedObj = {};
424
+ for (const [key, value] of Object.entries(obj)) {
425
+ // Skip functions, symbols and other non-serializable types
426
+ if (typeof value === 'function' || typeof value === 'symbol') {
427
+ continue;
428
+ }
429
+ // Handle null values
430
+ if (value === null) {
431
+ cleanedObj[key] = null;
432
+ continue;
433
+ }
434
+ // Recursively sanitize objects
435
+ if (typeof value === 'object') {
436
+ cleanedObj[key] = sanitizeForStorage(value);
437
+ }
438
+ else {
439
+ cleanedObj[key] = value;
440
+ }
441
+ }
442
+ return cleanedObj;
443
+ }
444
+ async function promotionEntityFactory(injector) {
445
+ const dataService = injector.get(AXMAppPromotionService);
446
+ const fileStorageService = injector.get(AXPFileStorageService);
447
+ const i18n = RootConfig.config.i18n;
448
+ const entityDef = {
449
+ module: RootConfig.module.name,
450
+ name: RootConfig.entities.promotion.name,
451
+ source: '',
452
+ title: RootConfig.entities.promotion.title,
453
+ formats: {
454
+ individual: RootConfig.entities.promotion.title,
455
+ plural: RootConfig.entities.promotion.titlePlural,
456
+ searchResult: {
457
+ title: '{{ title }}',
458
+ description: RootConfig.module.title,
459
+ },
460
+ },
461
+ relatedEntities: [],
462
+ groups: [
463
+ {
464
+ id: 'promotion',
465
+ title: 'Promotion',
466
+ },
467
+ ],
468
+ properties: [
469
+ {
470
+ name: 'id',
471
+ title: 'ID',
472
+ schema: {
473
+ dataType: 'uuid',
474
+ hidden: true,
475
+ nullable: false,
476
+ readonly: true,
477
+ unique: {
478
+ enabled: true,
479
+ },
480
+ },
481
+ options: {
482
+ sort: {
483
+ enabled: true,
484
+ },
485
+ },
486
+ },
487
+ {
488
+ name: 'title',
489
+ title: `t("title", { scope: "common" })`,
490
+ groupId: 'promotion',
491
+ schema: {
492
+ dataType: 'string',
493
+ interface: {
494
+ type: AXPWidgetsCatalog.text,
495
+ },
496
+ },
497
+ options: {
498
+ sort: {
499
+ enabled: true,
500
+ },
501
+ filter: {
502
+ advance: {
503
+ enabled: true,
504
+ },
505
+ inline: {
506
+ enabled: true,
507
+ },
508
+ },
509
+ },
510
+ validations: [
511
+ {
512
+ rule: 'required',
513
+ },
514
+ ],
515
+ },
516
+ {
517
+ name: 'body',
518
+ title: `t("body", { scope: "${i18n}" })`,
519
+ groupId: 'promotion',
520
+ schema: {
521
+ dataType: 'string',
522
+ interface: {
523
+ type: AXPWidgetsCatalog.richText,
524
+ },
525
+ },
526
+ validations: [
527
+ {
528
+ rule: 'required',
529
+ },
530
+ ],
531
+ },
532
+ {
533
+ name: 'imageId',
534
+ title: `t("Gallery", { scope: "${i18n}" })`,
535
+ groupId: 'promotion',
536
+ schema: {
537
+ dataType: 'string',
538
+ interface: {
539
+ type: AXPWidgetsCatalog.fileUploader,
540
+ options: {
541
+ multiple: true,
542
+ },
543
+ },
544
+ },
545
+ },
546
+ {
547
+ name: 'contentType',
548
+ title: `t("contentType", { scope: "${i18n}" })`,
549
+ groupId: 'promotion',
550
+ schema: {
551
+ dataType: 'string',
552
+ interface: {
553
+ type: AXPWidgetsCatalog.select,
554
+ options: {
555
+ valueField: 'name',
556
+ textField: 'title',
557
+ dataSource: [
558
+ { title: 'Media', name: 'media' },
559
+ { title: 'Text', name: 'text' },
560
+ ],
561
+ direction: 'horizontal',
562
+ multiple: false,
563
+ },
564
+ },
565
+ },
566
+ options: {
567
+ sort: {
568
+ enabled: true,
569
+ },
570
+ filter: {
571
+ advance: {
572
+ enabled: true,
573
+ },
574
+ },
575
+ },
576
+ validations: [
577
+ {
578
+ rule: 'required',
579
+ },
580
+ ],
581
+ },
582
+ // {
583
+ // name: 'shape',
584
+ // title: `t("shape", { scope: "${i18n}" })`,
585
+ // groupId: 'promotion',
586
+ // schema: {
587
+ // dataType: 'string',
588
+ // interface: {
589
+ // type: AXPWidgetsCatalog.select,
590
+ // options: {
591
+ // valueField: 'name',
592
+ // textField: 'title',
593
+ // dataSource: [
594
+ // { title: 'Circle', name: 'circle' },
595
+ // { title: 'Square', name: 'square' },
596
+ // ],
597
+ // direction: 'horizontal',
598
+ // multiple: false,
599
+ // accept: '',
600
+ // },
601
+ // },
602
+ // },
603
+ // validations: [
604
+ // {
605
+ // rule: 'required',
606
+ // },
607
+ // ],
608
+ // },
609
+ {
610
+ name: 'placement',
611
+ title: `t("placement", { scope: "${i18n}" })`,
612
+ groupId: 'promotion',
613
+ schema: {
614
+ dataType: 'string',
615
+ interface: {
616
+ type: AXPWidgetsCatalog.select,
617
+ options: {
618
+ valueField: 'name',
619
+ textField: 'title',
620
+ dataSource: [
621
+ {
622
+ title: 'Side Menu Footer',
623
+ name: 'side-menu-footer',
624
+ options: [
625
+ {
626
+ type: 'text-editor',
627
+ mode: 'edit',
628
+ path: 'name',
629
+ options: {
630
+ placeholder: 'Name',
631
+ defaultValue: 'test',
632
+ },
633
+ },
634
+ ],
635
+ },
636
+ {
637
+ title: 'Side Menu Header',
638
+ name: 'side-menu-header',
639
+ options: [
640
+ {
641
+ type: 'text-editor',
642
+ mode: 'edit',
643
+ path: 'name',
644
+ options: {
645
+ placeholder: 'Name',
646
+ defaultValue: 'test',
647
+ },
648
+ },
649
+ ],
650
+ },
651
+ ],
652
+ direction: 'horizontal',
653
+ multiple: false,
654
+ },
655
+ },
656
+ },
657
+ validations: [
658
+ {
659
+ rule: 'required',
660
+ },
661
+ ],
662
+ },
663
+ // {
664
+ // name: "metadaata",
665
+ // title: "Meta Data",
666
+ // groupId: 'promotion',
667
+ // schema: {
668
+ // dataType: 'object',
669
+ // interface: {
670
+ // type: AXPWidgetsCatalog.text,
671
+ // // children: "{{ context.eval('placement').options }}" as any,
672
+ // },
673
+ // }
674
+ //},
675
+ // {
676
+ // name: 'metadata',
677
+ // title: `Meta Data`,
678
+ // groupId: 'promotion',
679
+ // schema: {
680
+ // dataType: 'object',
681
+ // interface: {
682
+ // type: AXPWidgetsCatalog.blockLayout,
683
+ // children: "{{ context.eval('placement')?.options ?? [] }}" as any,
684
+ // },
685
+ // },
686
+ // },
687
+ ],
688
+ columns: [{ name: 'title' }, { name: 'placement' }, { name: 'imageId' }],
689
+ commands: {
690
+ create: {
691
+ execute: async (data) => {
692
+ data = sanitizeForStorage(data);
693
+ const entityPayload = { ...data };
694
+ const filesToUploadAfterSave = [];
695
+ // const originalImageIdArray = Array.isArray(entityPayload.imageId) ? [...entityPayload.imageId] : [];
696
+ if (entityPayload.imageId && Array.isArray(entityPayload.imageId)) {
697
+ const processedImageIdForEntitySave = [];
698
+ for (const fileItem of entityPayload.imageId) {
699
+ if (fileItem.source?.kind === 'blob' && fileItem.source.value instanceof Blob) {
700
+ filesToUploadAfterSave.push({ fileItem, blob: fileItem.source.value });
701
+ processedImageIdForEntitySave.push({
702
+ tempId: fileItem.id,
703
+ name: fileItem.name,
704
+ size: fileItem.size,
705
+ type: fileItem.source.value.type, // Type from blob is reliable
706
+ status: 'pending_upload'
707
+ });
708
+ }
709
+ else if (fileItem.source?.kind === 'fileId' && fileItem.id && typeof fileItem.source.value === 'string') {
710
+ // If it's a fileId, we assume it's already processed. We don't have type directly on AXPFileListItem.
711
+ // We'll reconstruct it from fileStorageService or it should be part of what's saved if needed.
712
+ processedImageIdForEntitySave.push({
713
+ id: fileItem.id,
714
+ name: fileItem.name,
715
+ size: fileItem.size,
716
+ // type: fileItem.type, // Removed: AXPFileListItem does not have .type
717
+ status: 'uploaded',
718
+ source: { kind: 'fileId', value: fileItem.source.value }
719
+ });
720
+ }
721
+ else if (fileItem.id && fileItem.name) { // Fallback for items that might be from a previous save
722
+ processedImageIdForEntitySave.push({
723
+ id: fileItem.id,
724
+ name: fileItem.name,
725
+ size: fileItem.size,
726
+ // type: fileItem.type, // Removed: AXPFileListItem does not have .type
727
+ status: fileItem.status, // Preserve existing status
728
+ source: fileItem.source ? { kind: fileItem.source.kind, value: fileItem.source.value } : undefined
729
+ });
730
+ }
731
+ }
732
+ entityPayload.imageId = processedImageIdForEntitySave;
733
+ }
734
+ const savedEntityId = await dataService.insertOne(entityPayload);
735
+ // const entityId = savedEntity.id; // Corrected based on typical service return
736
+ const finalImageIdReferences = (entityPayload.imageId || [])
737
+ .filter((f) => f.status !== 'pending_upload');
738
+ for (const { fileItem, blob } of filesToUploadAfterSave) {
739
+ try {
740
+ if (!fileStorageService) {
741
+ throw new Error('fileStorageService is not available.');
742
+ }
743
+ const fileStorageInfo = await fileStorageService.save({
744
+ file: blob,
745
+ refId: savedEntityId,
746
+ refType: `${RootConfig.module.name}.${RootConfig.entities.promotion.name}`,
747
+ category: '',
748
+ name: blob.name,
749
+ });
750
+ finalImageIdReferences.push({
751
+ id: fileStorageInfo.fileId,
752
+ name: fileStorageInfo.name || blob.name,
753
+ size: fileStorageInfo.size || blob.size,
754
+ type: fileStorageInfo.mimeType || blob.type,
755
+ status: 'uploaded',
756
+ source: { kind: 'fileId', value: fileStorageInfo.fileId }
757
+ });
758
+ }
759
+ catch (err) { // Typed error
760
+ console.error('Error uploading file to FileStorage for entityId:', savedEntityId, 'file:', fileItem.name, err);
761
+ finalImageIdReferences.push({
762
+ tempId: fileItem.id,
763
+ name: fileItem.name,
764
+ size: fileItem.size,
765
+ type: blob.type, // Correctly access type from Blob/File
766
+ status: 'upload_failed',
767
+ error: err.message
768
+ });
769
+ }
770
+ }
771
+ if (filesToUploadAfterSave.length > 0) {
772
+ let needsUpdate = true;
773
+ if (entityPayload.imageId && entityPayload.imageId.length === finalImageIdReferences.length) {
774
+ const oldIds = entityPayload.imageId.map((f) => f.id || f.tempId).sort().join(',');
775
+ const newIds = finalImageIdReferences.map((f) => f.id || f.tempId).sort().join(',');
776
+ if (oldIds === newIds && !finalImageIdReferences.some((f) => f.status === 'upload_failed')) {
777
+ needsUpdate = false;
778
+ }
779
+ }
780
+ if (needsUpdate) {
781
+ // Assuming updateOne takes the ID and an object of fields to update
782
+ await dataService.updateOne(savedEntityId, { imageId: finalImageIdReferences });
783
+ }
784
+ }
785
+ return { id: savedEntityId };
786
+ },
787
+ },
788
+ delete: {
789
+ execute: async (id) => {
790
+ return await dataService.deleteOne(id);
791
+ },
792
+ },
793
+ update: {
794
+ execute: async (data) => {
795
+ const entityId = data.id;
796
+ const filesToUpload = [];
797
+ const processedImageReferences = []; // Will hold final file objects for DB
798
+ // Ensure fileStorageService is available (it's injected at the factory level)
799
+ // const fileStorageService = injector.get(AXPFileStorageService); // Already available in this scope from factory
800
+ if (data.imageId && Array.isArray(data.imageId)) {
801
+ for (const fileItem of data.imageId) {
802
+ if (fileItem.status === 'deleted') {
803
+ // File marked for deletion. Skip.
804
+ // Optionally, you might want to call fileStorageService.delete(fileId) here
805
+ // if fileItem.id points to an existing stored file and actual deletion is needed.
806
+ // For now, we just disassociate it from the entity.
807
+ continue;
808
+ }
809
+ if (fileItem.source?.kind === 'blob' && fileItem.source.value instanceof Blob) {
810
+ filesToUpload.push({ fileItem, blob: fileItem.source.value });
811
+ // Actual reference will be added to processedImageReferences after successful upload.
812
+ }
813
+ else if (fileItem.source?.kind === 'fileId' && fileItem.id && typeof fileItem.source.value === 'string') {
814
+ // This is an existing file, keep its reference.
815
+ processedImageReferences.push({
816
+ id: fileItem.id,
817
+ name: fileItem.name,
818
+ size: fileItem.size,
819
+ status: fileItem.status || 'uploaded', // Default to 'uploaded' if status is missing
820
+ source: { kind: 'fileId', value: fileItem.source.value }
821
+ // 'type' is not typically part of AXPFileListItem for existing fileIds in 'create'
822
+ });
823
+ }
824
+ else if (fileItem.id && fileItem.name) {
825
+ // Fallback for items that might be from a previous save state (already processed)
826
+ // These are likely already processed files that are being kept.
827
+ processedImageReferences.push({
828
+ id: fileItem.id,
829
+ name: fileItem.name,
830
+ size: fileItem.size,
831
+ status: fileItem.status || 'uploaded',
832
+ source: fileItem.source ? { kind: fileItem.source.kind, value: fileItem.source.value } : undefined
833
+ });
834
+ }
835
+ // Else: unknown fileItem structure, it will be ignored or you can log an error.
836
+ }
837
+ }
838
+ // Upload new files and add their successful/failed info to processedImageReferences
839
+ for (const { fileItem, blob } of filesToUpload) {
840
+ try {
841
+ if (!fileStorageService) {
842
+ throw new Error('fileStorageService is not available.');
843
+ }
844
+ const fileStorageInfo = await fileStorageService.save({
845
+ file: blob,
846
+ refId: entityId, // ID of the entity being updated
847
+ refType: `${RootConfig.module.name}.${RootConfig.entities.promotion.name}`,
848
+ category: '', // Add category if applicable
849
+ name: blob.name,
850
+ });
851
+ processedImageReferences.push({
852
+ id: fileStorageInfo.fileId,
853
+ name: fileStorageInfo.name || blob.name,
854
+ size: fileStorageInfo.size || blob.size,
855
+ type: fileStorageInfo.mimeType || blob.type, // Store MIME type
856
+ status: 'uploaded',
857
+ source: { kind: 'fileId', value: fileStorageInfo.fileId }
858
+ });
859
+ }
860
+ catch (err) {
861
+ console.error('Error uploading file to FileStorage during update for entityId:', entityId, 'file:', fileItem.name, err);
862
+ processedImageReferences.push({
863
+ tempId: fileItem.id, // Use fileItem.id if it's a unique temp client-side ID, or generate one
864
+ name: fileItem.name,
865
+ size: fileItem.size,
866
+ type: blob.type,
867
+ status: 'upload_failed',
868
+ error: err.message
869
+ });
870
+ }
871
+ }
872
+ // Construct the final data payload for the update.
873
+ // Create a mutable copy of the input data.
874
+ const finalUpdatePayload = { ...data };
875
+ // Replace the original imageId array with the newly processed one.
876
+ finalUpdatePayload.imageId = processedImageReferences;
877
+ // Sanitize the entire payload before sending it to dataService.updateOne.
878
+ // This ensures that the processedImageReferences (which are plain objects)
879
+ // and all other fields in the payload are clean and serializable.
880
+ const fullySanitizedPayload = sanitizeForStorage(finalUpdatePayload);
881
+ return await dataService.updateOne(entityId, fullySanitizedPayload);
882
+ },
883
+ },
884
+ },
885
+ queries: {
886
+ byKey: {
887
+ execute: async (id) => {
888
+ try {
889
+ // Debug the incoming ID parameter
890
+ console.log('byKey original id parameter:', id, typeof id);
891
+ // Ensure id is a valid key for IndexedDB - needs to be string or number
892
+ let validId;
893
+ // If id is an object (e.g., from router params or complex structure)
894
+ if (typeof id === 'object' && id !== null) {
895
+ if ('id' in id) {
896
+ validId = String(id.id);
897
+ }
898
+ else {
899
+ validId = String(id);
900
+ }
901
+ console.warn('Converted object id to string:', validId);
902
+ }
903
+ else if (id === undefined || id === null) {
904
+ console.error('Invalid id parameter: null or undefined');
905
+ return null;
906
+ }
907
+ else {
908
+ // Convert to string to ensure consistency
909
+ validId = String(id);
910
+ }
911
+ // Log the ID being used for the query
912
+ console.log('Fetching record with id:', validId, typeof validId);
913
+ try {
914
+ const data = await dataService.getOne(validId);
915
+ console.log('getOne result:', data ? 'Data found' : 'No data found');
916
+ // If no data was found
917
+ if (!data) {
918
+ console.warn(`No record found with id: ${validId}`);
919
+ return null;
920
+ }
921
+ return data;
922
+ }
923
+ catch (error) {
924
+ console.error(`Error fetching data with ID ${validId}:`, error);
925
+ // Return null instead of throwing to avoid cascading errors
926
+ return null;
927
+ }
928
+ }
929
+ catch (error) {
930
+ console.error('Critical error in byKey query:', error);
931
+ return null; // Return null instead of throwing to avoid UI errors
932
+ }
933
+ },
934
+ type: AXPEntityQueryType.Single,
935
+ },
936
+ list: {
937
+ execute: async (e) => {
938
+ return await dataService.query({ skip: e.skip, take: e.take, filter: e.filter });
939
+ },
940
+ type: AXPEntityQueryType.List,
941
+ },
942
+ },
943
+ interfaces: {
944
+ master: {
945
+ create: {
946
+ sections: [
947
+ {
948
+ id: 'promotion',
949
+ },
950
+ ],
951
+ properties: [
952
+ {
953
+ name: 'title',
954
+ layout: {
955
+ positions: {
956
+ lg: {
957
+ colSpan: 6,
958
+ order: 1,
959
+ },
960
+ },
961
+ },
962
+ },
963
+ {
964
+ name: 'body',
965
+ layout: {
966
+ positions: {
967
+ lg: {
968
+ colSpan: 12,
969
+ order: 5,
970
+ },
971
+ },
972
+ },
973
+ },
974
+ {
975
+ name: 'imageId',
976
+ layout: {
977
+ positions: {
978
+ lg: {
979
+ colSpan: 12,
980
+ order: 6,
981
+ },
982
+ },
983
+ },
984
+ },
985
+ {
986
+ name: 'contentType',
987
+ layout: {
988
+ positions: {
989
+ lg: {
990
+ colSpan: 6,
991
+ order: 2,
992
+ },
993
+ },
994
+ },
995
+ },
996
+ {
997
+ name: 'shape',
998
+ layout: {
999
+ positions: {
1000
+ lg: {
1001
+ colSpan: 6,
1002
+ order: 3,
1003
+ },
1004
+ },
1005
+ },
1006
+ },
1007
+ {
1008
+ name: 'placement',
1009
+ layout: {
1010
+ positions: {
1011
+ lg: {
1012
+ colSpan: 6,
1013
+ order: 4,
1014
+ },
1015
+ },
1016
+ },
1017
+ },
1018
+ {
1019
+ name: 'metadata',
1020
+ layout: {
1021
+ positions: {
1022
+ lg: {
1023
+ colSpan: 12,
1024
+ order: 10,
1025
+ },
1026
+ },
1027
+ },
1028
+ },
1029
+ ],
1030
+ },
1031
+ update: {
1032
+ sections: [
1033
+ {
1034
+ id: 'promotion',
1035
+ },
1036
+ ],
1037
+ properties: [
1038
+ {
1039
+ name: 'title',
1040
+ layout: {
1041
+ positions: {
1042
+ lg: {
1043
+ colSpan: 6,
1044
+ order: 1,
1045
+ },
1046
+ },
1047
+ },
1048
+ },
1049
+ {
1050
+ name: 'body',
1051
+ layout: {
1052
+ positions: {
1053
+ lg: {
1054
+ colSpan: 12,
1055
+ order: 5,
1056
+ },
1057
+ },
1058
+ },
1059
+ },
1060
+ {
1061
+ name: 'imageId',
1062
+ layout: {
1063
+ positions: {
1064
+ lg: {
1065
+ colSpan: 12,
1066
+ order: 6,
1067
+ },
1068
+ },
1069
+ },
1070
+ },
1071
+ {
1072
+ name: 'contentType',
1073
+ layout: {
1074
+ positions: {
1075
+ lg: {
1076
+ colSpan: 6,
1077
+ order: 2,
1078
+ },
1079
+ },
1080
+ },
1081
+ },
1082
+ {
1083
+ name: 'shape',
1084
+ layout: {
1085
+ positions: {
1086
+ lg: {
1087
+ colSpan: 6,
1088
+ order: 3,
1089
+ },
1090
+ },
1091
+ },
1092
+ },
1093
+ {
1094
+ name: 'placement',
1095
+ layout: {
1096
+ positions: {
1097
+ lg: {
1098
+ colSpan: 6,
1099
+ order: 4,
1100
+ },
1101
+ },
1102
+ },
1103
+ },
1104
+ // {
1105
+ // name: 'metadata',
1106
+ // layout: {
1107
+ // positions: {
1108
+ // lg: {
1109
+ // colSpan: 12,
1110
+ // order: 10,
1111
+ // },
1112
+ // },
1113
+ // },
1114
+ // },
1115
+ ],
1116
+ },
1117
+ single: {
1118
+ title: '{{title}}',
1119
+ sections: [
1120
+ {
1121
+ id: 'promotion',
1122
+ },
1123
+ ],
1124
+ properties: [
1125
+ {
1126
+ name: 'title',
1127
+ layout: {
1128
+ positions: {
1129
+ lg: {
1130
+ colSpan: 6,
1131
+ },
1132
+ },
1133
+ },
1134
+ },
1135
+ {
1136
+ name: 'body',
1137
+ layout: {
1138
+ positions: {
1139
+ lg: {
1140
+ colSpan: 6,
1141
+ },
1142
+ },
1143
+ },
1144
+ },
1145
+ {
1146
+ name: 'imageId',
1147
+ layout: {
1148
+ positions: {
1149
+ lg: {
1150
+ colSpan: 12,
1151
+ order: 2,
1152
+ },
1153
+ },
1154
+ },
1155
+ },
1156
+ {
1157
+ name: 'contentType',
1158
+ layout: {
1159
+ positions: {
1160
+ lg: {
1161
+ colSpan: 4,
1162
+ order: 4,
1163
+ },
1164
+ },
1165
+ },
1166
+ },
1167
+ {
1168
+ name: 'shape',
1169
+ layout: {
1170
+ positions: {
1171
+ lg: {
1172
+ colSpan: 4,
1173
+ order: 5,
1174
+ },
1175
+ },
1176
+ },
1177
+ },
1178
+ {
1179
+ name: 'placement',
1180
+ layout: {
1181
+ positions: {
1182
+ lg: {
1183
+ colSpan: 4,
1184
+ order: 6,
1185
+ },
1186
+ },
1187
+ },
1188
+ },
1189
+ ],
1190
+ actions: [],
1191
+ },
1192
+ list: {
1193
+ actions: [
1194
+ {
1195
+ title: `t("create", { scope: "common" })`,
1196
+ command: 'create-entity',
1197
+ priority: 'primary',
1198
+ type: 'create',
1199
+ scope: AXPEntityCommandScope.TypeLevel,
1200
+ },
1201
+ {
1202
+ title: 't("deleteItems", { scope: "common" })',
1203
+ command: 'delete-entity',
1204
+ priority: 'primary',
1205
+ type: 'delete',
1206
+ scope: AXPEntityCommandScope.Selected,
1207
+ },
1208
+ {
1209
+ title: 't("detail", { scope: "common" })',
1210
+ command: 'open-entity',
1211
+ priority: 'primary',
1212
+ type: 'view',
1213
+ scope: AXPEntityCommandScope.Individual,
1214
+ },
1215
+ {
1216
+ title: 't("delete", { scope: "common" })',
1217
+ command: 'delete-entity',
1218
+ priority: 'primary',
1219
+ type: 'delete',
1220
+ scope: AXPEntityCommandScope.Individual,
1221
+ },
1222
+ {
1223
+ title: 't("entity.modify", { scope: "common" })',
1224
+ command: 'quick-modify-entity',
1225
+ priority: 'secondary',
1226
+ type: 'update',
1227
+ scope: AXPEntityCommandScope.Individual,
1228
+ },
1229
+ //TODO: add this to the entity
1230
+ {
1231
+ title: 't("upload.title", { scope: "common" })',
1232
+ command: {
1233
+ name: 'show-file-uploader-popup',
1234
+ options: {
1235
+ id: '{{ context.eval("id") }}',
1236
+ files: '{{ context.eval("imageId") }}',
1237
+ multiple: true,
1238
+ accept: '.jpg,.jpeg,.png,.gif,.webp',
1239
+ key: 'imageId',
1240
+ }
1241
+ },
1242
+ priority: 'secondary',
1243
+ type: 'update',
1244
+ scope: AXPEntityCommandScope.Individual,
1245
+ },
1246
+ ],
1247
+ views: [
1248
+ createAllQueryView({ sorts: [{ name: 'title', dir: 'asc' }] }),
1249
+ createQueryView('media', `t("media", { scope: "${i18n}" })`, true, {
1250
+ conditions: [
1251
+ {
1252
+ name: 'contentType.name',
1253
+ operator: {
1254
+ type: 'equal',
1255
+ },
1256
+ value: 'media',
1257
+ },
1258
+ ],
1259
+ }),
1260
+ createQueryView('text', `t("text", { scope: "${i18n}" })`, true, {
1261
+ conditions: [
1262
+ {
1263
+ name: 'contentType.name',
1264
+ operator: {
1265
+ type: 'equal',
1266
+ },
1267
+ value: 'text',
1268
+ },
1269
+ ],
1270
+ }),
1271
+ ],
1272
+ },
1273
+ },
1274
+ },
1275
+ };
1276
+ return entityDef;
1277
+ }
1278
+
1279
+ var promotion_entity = /*#__PURE__*/Object.freeze({
1280
+ __proto__: null,
1281
+ promotionEntityFactory: promotionEntityFactory
1282
+ });
1283
+
1284
+ /**
1285
+ * Generated bundle index. Do not edit.
1286
+ */
1287
+
1288
+ export { AXMAppPromotionService, AXMContentManagementModule, AXMEntityProvider, AXMMenuProvider, AXMPromotionDataSourceDefinition, AXMPromotionServiceImpl, AXMPromotionSlotComponent, AXMSearchCommandProvider, AXMSettingProvider, RootConfig, promotionEntityFactory };
2
1289
  //# sourceMappingURL=acorex-modules-content-management.mjs.map