@acorex-platform/module-communication-management-client 0.0.37 → 0.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{acorex-platform-module-communication-management-client-acorex-platform-module-communication-management-client-CZh_tBTN.mjs → acorex-platform-module-communication-management-client-acorex-platform-module-communication-management-client-BJvTWpBc.mjs} +268 -91
- package/fesm2022/acorex-platform-module-communication-management-client-acorex-platform-module-communication-management-client-BJvTWpBc.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-email-send.command-Bnqy-YMs.mjs → acorex-platform-module-communication-management-client-communication-email-send.command-CR4RjM-X.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-email-send.command-Bnqy-YMs.mjs.map → acorex-platform-module-communication-management-client-communication-email-send.command-CR4RjM-X.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-in-app-inbox-page.component-D4o0Bhce.mjs → acorex-platform-module-communication-management-client-communication-in-app-inbox-page.component-yaRijsuh.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-in-app-inbox-page.component-D4o0Bhce.mjs.map → acorex-platform-module-communication-management-client-communication-in-app-inbox-page.component-yaRijsuh.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-send.command-BH9jjHfA.mjs → acorex-platform-module-communication-management-client-communication-send.command-D19heywC.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-send.command-BH9jjHfA.mjs.map → acorex-platform-module-communication-management-client-communication-send.command-D19heywC.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-test-smtp.command-BMsTVFBN.mjs → acorex-platform-module-communication-management-client-communication-test-smtp.command-Bck8R4as.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-communication-management-client-communication-test-smtp.command-BMsTVFBN.mjs.map → acorex-platform-module-communication-management-client-communication-test-smtp.command-Bck8R4as.mjs.map} +1 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entities-communication-delivery.mjs +25 -0
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entities-communication-delivery.mjs.map +1 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entities-communication.mjs +25 -0
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entities-communication.mjs.map +1 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entities-entity-change-notify-policy.mjs +195 -0
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entities-entity-change-notify-policy.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-communication-management-client-contracts-entity-catalog-acorex-platform-module-communication-management-client-contracts-entity-catalog-BvLoGDK5.mjs → acorex-platform-module-communication-management-client-contracts-entity-catalog-acorex-platform-module-communication-management-client-contracts-entity-catalog-DTHjzWFn.mjs} +15 -3
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-acorex-platform-module-communication-management-client-contracts-entity-catalog-DTHjzWFn.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-communication-management-client-contracts-entity-catalog-communication-delivery.entity-DPCU8P32.mjs → acorex-platform-module-communication-management-client-contracts-entity-catalog-communication-delivery.entity-DN0_CPBO.mjs} +16 -2
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-communication-delivery.entity-DN0_CPBO.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-communication-management-client-contracts-entity-catalog-communication.entity-DGj9OD3Z.mjs → acorex-platform-module-communication-management-client-contracts-entity-catalog-communication.entity-BAa4oCXu.mjs} +16 -2
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-communication.entity-BAa4oCXu.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-entity-change-notify-policy.entity-DmM894ok.mjs +144 -0
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-entity-change-notify-policy.entity-DmM894ok.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog.mjs +1 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts.mjs +29 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts.mjs.map +1 -1
- package/fesm2022/acorex-platform-module-communication-management-client-local-entities.mjs +1 -0
- package/fesm2022/acorex-platform-module-communication-management-client-local-entities.mjs.map +1 -1
- package/fesm2022/acorex-platform-module-communication-management-client.mjs +1 -1
- package/package.json +7 -3
- package/types/acorex-platform-module-communication-management-client-contracts-entities-entity-change-notify-policy.d.ts +5 -0
- package/types/acorex-platform-module-communication-management-client-contracts.d.ts +48 -2
- package/types/acorex-platform-module-communication-management-client.d.ts +17 -0
- package/fesm2022/acorex-platform-module-communication-management-client-acorex-platform-module-communication-management-client-CZh_tBTN.mjs.map +0 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-acorex-platform-module-communication-management-client-contracts-entity-catalog-BvLoGDK5.mjs.map +0 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-communication-delivery.entity-DPCU8P32.mjs.map +0 -1
- package/fesm2022/acorex-platform-module-communication-management-client-contracts-entity-catalog-communication.entity-DGj9OD3Z.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/auth';
|
|
2
|
-
import { AXPLocalEntityEngine, AXPLocalEntityRealtimeBridge, AXP_IN_APP_NOTIFICATION_SERVICE, AXPSearchCommandProvider, AXP_PROTECTED_ROUTE_GUARDS, AXP_MENU_PROVIDER, AXP_STATUS_PROVIDERS, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
2
|
+
import { AXPLocalEntityEngine, AXPLocalEntityRealtimeBridge, AXPLocalEntityOutboxService, AXPNetworkConnectivityService, axpLocalEntitySupportsOfflineWrite, axpIsLikelyNetworkFailure, AXP_IN_APP_NOTIFICATION_SERVICE, AXPSearchCommandProvider, AXP_PROTECTED_ROUTE_GUARDS, AXP_MENU_PROVIDER, AXP_STATUS_PROVIDERS, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
3
3
|
import * as i1$2 from '@acorex-platform/framework-client/core';
|
|
4
|
-
import { provideAppStartUpTask, AXP_APP_STARTUP_PRIORITY, AXPComponentSlotModule
|
|
4
|
+
import { provideAppStartUpTask, AXP_APP_STARTUP_PRIORITY, AXPComponentSlotModule } from '@acorex-platform/framework-client/core';
|
|
5
5
|
import { AXPUserAvatarComponent, AXPUserCardDirective, AXPStateMessageComponent, AXP_TASK_BADGE_PROVIDERS } from '@acorex-platform/framework-client/layout/components';
|
|
6
6
|
import { AXPRootLayoutComponent } from '@acorex-platform/framework-client/themes/default';
|
|
7
7
|
import { AXPCommandService, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
|
|
@@ -342,12 +342,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
342
342
|
const AXP_IN_APP_INBOX_PORT = new InjectionToken('AXP_IN_APP_INBOX_PORT');
|
|
343
343
|
//#endregion
|
|
344
344
|
|
|
345
|
+
//#region ----- Inbox outbox actions -----
|
|
346
|
+
const AXP_IN_APP_INBOX_OUTBOX_ACTIONS = {
|
|
347
|
+
markSeen: 'markSeen',
|
|
348
|
+
markRead: 'markRead',
|
|
349
|
+
markAllRead: 'markAllRead',
|
|
350
|
+
togglePin: 'togglePin',
|
|
351
|
+
archive: 'archive',
|
|
352
|
+
delete: 'delete',
|
|
353
|
+
};
|
|
354
|
+
//#endregion
|
|
355
|
+
|
|
345
356
|
//#region ----- Imports -----
|
|
346
357
|
//#endregion
|
|
347
358
|
//#region ----- Shared in-app inbox connector -----
|
|
348
359
|
/**
|
|
349
360
|
* Single source of truth for active in-app inbox UI.
|
|
350
361
|
* Active items live in the shared local-entity engine (max 100) and sync via realtime / reconnect.
|
|
362
|
+
* Offline writes enqueue on the local-entity outbox and flush over HTTP on reconnect.
|
|
351
363
|
* Archived views always load from the API.
|
|
352
364
|
*/
|
|
353
365
|
class AXPInAppInboxConnectorService {
|
|
@@ -356,6 +368,8 @@ class AXPInAppInboxConnectorService {
|
|
|
356
368
|
this.realtime = inject(AXPInAppInboxRealtimeService);
|
|
357
369
|
this.engine = inject(AXPLocalEntityEngine);
|
|
358
370
|
this.localBridge = inject(AXPLocalEntityRealtimeBridge);
|
|
371
|
+
this.outbox = inject(AXPLocalEntityOutboxService);
|
|
372
|
+
this.connectivity = inject(AXPNetworkConnectivityService);
|
|
359
373
|
this.sessionService = inject(AXPSessionService);
|
|
360
374
|
this.destroyRef = inject(DestroyRef);
|
|
361
375
|
this.entityKey = AXP_IN_APP_INBOX_LOCAL_ENTITY_KEY;
|
|
@@ -419,7 +433,7 @@ class AXPInAppInboxConnectorService {
|
|
|
419
433
|
this.unreadCount = computed(() => this.readLocalItems().filter((item) => isInAppInboxUnread(item.readAt)).length, /* @ts-ignore */
|
|
420
434
|
...(ngDevMode ? [{ debugName: "unreadCount" }] : /* istanbul ignore next */ []));
|
|
421
435
|
this.engine.registerPolicy(this.entityKey, {
|
|
422
|
-
mode: '
|
|
436
|
+
mode: 'offline-write',
|
|
423
437
|
maxItems: AXP_IN_APP_INBOX_LOCAL_MAX_ITEMS,
|
|
424
438
|
sortField: 'createdAt',
|
|
425
439
|
role: 'entity',
|
|
@@ -428,6 +442,10 @@ class AXPInAppInboxConnectorService {
|
|
|
428
442
|
fetchByIds: this.port.loadByIds ? (ids) => this.fetchActiveByIds(ids) : undefined,
|
|
429
443
|
fetchHot: () => this.fetchActiveHot(),
|
|
430
444
|
});
|
|
445
|
+
this.outbox.register(this.entityKey, {
|
|
446
|
+
flush: (op) => this.flushOutboxOp(op),
|
|
447
|
+
revert: (op) => this.revertOutboxOp(op),
|
|
448
|
+
});
|
|
431
449
|
this.sessionService.isReadyForAppScopedApi$
|
|
432
450
|
.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
|
|
433
451
|
.subscribe((isReady) => {
|
|
@@ -495,13 +513,16 @@ class AXPInAppInboxConnectorService {
|
|
|
495
513
|
}
|
|
496
514
|
const now = new Date().toISOString();
|
|
497
515
|
await this.engine.patchMany(this.entityKey, unseenIds, (item) => item['seenAt'] ? item : { ...item, seenAt: now });
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
this.
|
|
503
|
-
|
|
504
|
-
|
|
516
|
+
await this.commitOrEnqueue({
|
|
517
|
+
action: AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markSeen,
|
|
518
|
+
recordIds: unseenIds,
|
|
519
|
+
payload: { seenAt: now },
|
|
520
|
+
commit: () => this.port.markSeen(unseenIds),
|
|
521
|
+
revert: async () => {
|
|
522
|
+
await this.syncActiveFromServer();
|
|
523
|
+
},
|
|
524
|
+
failureMessage: 'Failed to mark inbox as seen',
|
|
525
|
+
});
|
|
505
526
|
}
|
|
506
527
|
async markAsRead(ids) {
|
|
507
528
|
if (ids.length === 0 || !this.port.capabilities.readTracking || !this.canLoadInbox()) {
|
|
@@ -514,13 +535,14 @@ class AXPInAppInboxConnectorService {
|
|
|
514
535
|
seenAt: item['seenAt'] ?? now,
|
|
515
536
|
readAt: item['readAt'] ?? now,
|
|
516
537
|
}));
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
this.
|
|
522
|
-
|
|
523
|
-
|
|
538
|
+
await this.commitOrEnqueue({
|
|
539
|
+
action: AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markRead,
|
|
540
|
+
recordIds: ids,
|
|
541
|
+
payload: { readAt: now, seenAt: now },
|
|
542
|
+
commit: () => this.port.markRead(ids),
|
|
543
|
+
revert: () => this.localBridge.apply({ entityKey: this.entityKey, type: 'upsert', ids }),
|
|
544
|
+
failureMessage: 'Failed to mark inbox as read',
|
|
545
|
+
});
|
|
524
546
|
}
|
|
525
547
|
async markAllAsRead() {
|
|
526
548
|
if (!this.port.capabilities.readTracking || !this.canLoadInbox()) {
|
|
@@ -535,13 +557,16 @@ class AXPInAppInboxConnectorService {
|
|
|
535
557
|
}
|
|
536
558
|
return { ...item, readAt: now, seenAt: item['seenAt'] ?? now };
|
|
537
559
|
});
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
this.
|
|
543
|
-
|
|
544
|
-
|
|
560
|
+
await this.commitOrEnqueue({
|
|
561
|
+
action: AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markAllRead,
|
|
562
|
+
recordIds: [],
|
|
563
|
+
payload: { readAt: now, seenAt: now },
|
|
564
|
+
commit: () => this.port.markAllRead(),
|
|
565
|
+
revert: async () => {
|
|
566
|
+
await this.syncActiveFromServer();
|
|
567
|
+
},
|
|
568
|
+
failureMessage: 'Failed to mark all as read',
|
|
569
|
+
});
|
|
545
570
|
}
|
|
546
571
|
async togglePin(id) {
|
|
547
572
|
if (!this.port.capabilities.pinSupport || !this.port.togglePin || !this.canLoadInbox()) {
|
|
@@ -549,20 +574,24 @@ class AXPInAppInboxConnectorService {
|
|
|
549
574
|
}
|
|
550
575
|
await this.ensureReady();
|
|
551
576
|
const current = this.readLocalItems().find((item) => item.id === id);
|
|
577
|
+
const nextPinned = current ? !current.isPinned : true;
|
|
552
578
|
if (current) {
|
|
553
579
|
await this.engine.patchMany(this.entityKey, [id], (item) => ({
|
|
554
580
|
...item,
|
|
555
|
-
isPinned:
|
|
581
|
+
isPinned: nextPinned,
|
|
556
582
|
}));
|
|
557
583
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
584
|
+
await this.commitOrEnqueue({
|
|
585
|
+
action: AXP_IN_APP_INBOX_OUTBOX_ACTIONS.togglePin,
|
|
586
|
+
recordIds: [id],
|
|
587
|
+
payload: { isPinned: nextPinned },
|
|
588
|
+
commit: async () => {
|
|
589
|
+
await this.port.togglePin?.(id);
|
|
590
|
+
await this.localBridge.apply({ entityKey: this.entityKey, type: 'upsert', ids: [id] });
|
|
591
|
+
},
|
|
592
|
+
revert: () => this.localBridge.apply({ entityKey: this.entityKey, type: 'upsert', ids: [id] }),
|
|
593
|
+
failureMessage: 'Failed to toggle pin',
|
|
594
|
+
});
|
|
566
595
|
}
|
|
567
596
|
async archive(ids) {
|
|
568
597
|
if (!this.port.archive || ids.length === 0 || !this.canLoadInbox()) {
|
|
@@ -570,13 +599,19 @@ class AXPInAppInboxConnectorService {
|
|
|
570
599
|
}
|
|
571
600
|
await this.ensureReady();
|
|
572
601
|
await this.engine.removeMany(this.entityKey, ids);
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
602
|
+
await this.commitOrEnqueue({
|
|
603
|
+
action: AXP_IN_APP_INBOX_OUTBOX_ACTIONS.archive,
|
|
604
|
+
recordIds: ids,
|
|
605
|
+
commit: async () => {
|
|
606
|
+
if (this.port.archive) {
|
|
607
|
+
await this.port.archive(ids);
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
revert: async () => {
|
|
611
|
+
await this.syncActiveFromServer();
|
|
612
|
+
},
|
|
613
|
+
failureMessage: 'Failed to archive inbox items',
|
|
614
|
+
});
|
|
580
615
|
const query = this.pageQuery();
|
|
581
616
|
if (query?.mode === 'archive') {
|
|
582
617
|
await this.loadArchivePage(query.filters, query.skip, query.take);
|
|
@@ -586,20 +621,30 @@ class AXPInAppInboxConnectorService {
|
|
|
586
621
|
if (!this.port.deleteDeliveries || !this.canLoadInbox()) {
|
|
587
622
|
return;
|
|
588
623
|
}
|
|
624
|
+
const deleteDeliveries = this.port.deleteDeliveries;
|
|
589
625
|
await this.ensureReady();
|
|
590
626
|
await this.engine.removeMany(this.entityKey, [id]);
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
627
|
+
await this.commitOrEnqueue({
|
|
628
|
+
action: AXP_IN_APP_INBOX_OUTBOX_ACTIONS.delete,
|
|
629
|
+
recordIds: [id],
|
|
630
|
+
commit: async () => {
|
|
631
|
+
if (!deleteDeliveries) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
try {
|
|
635
|
+
await deleteDeliveries([id]);
|
|
636
|
+
}
|
|
637
|
+
catch (err) {
|
|
638
|
+
if (!this.isBenignDeliveryDeleteError(err)) {
|
|
639
|
+
throw err;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
revert: async () => {
|
|
644
|
+
await this.syncActiveFromServer();
|
|
645
|
+
},
|
|
646
|
+
failureMessage: 'Failed to delete inbox item',
|
|
647
|
+
});
|
|
603
648
|
this.realtime.notifyChanged({ type: 'deleted', ids: [id] });
|
|
604
649
|
const query = this.pageQuery();
|
|
605
650
|
if (query?.mode === 'archive') {
|
|
@@ -734,6 +779,7 @@ class AXPInAppInboxConnectorService {
|
|
|
734
779
|
const response = await this.fetchActiveHot();
|
|
735
780
|
const items = sortInAppInboxItems(response.items.map((item) => normalizeInAppInboxItem(item)));
|
|
736
781
|
await this.engine.replaceAll(this.entityKey, items.map((item) => this.toPayload(item)));
|
|
782
|
+
await this.reapplyPendingOutboxOps();
|
|
737
783
|
const local = this.readLocalItems();
|
|
738
784
|
return { items: local, total: local.length };
|
|
739
785
|
}
|
|
@@ -851,6 +897,127 @@ class AXPInAppInboxConnectorService {
|
|
|
851
897
|
await this.localBridge.apply({ entityKey: this.entityKey, type: 'invalidate' });
|
|
852
898
|
}
|
|
853
899
|
//#endregion
|
|
900
|
+
//#region ----- Outbox -----
|
|
901
|
+
canQueueWrites() {
|
|
902
|
+
return axpLocalEntitySupportsOfflineWrite(this.engine.getPolicy(this.entityKey)?.mode);
|
|
903
|
+
}
|
|
904
|
+
async commitOrEnqueue(options) {
|
|
905
|
+
if (!this.connectivity.online && this.canQueueWrites()) {
|
|
906
|
+
await this.outbox.enqueue({
|
|
907
|
+
entityKey: this.entityKey,
|
|
908
|
+
action: options.action,
|
|
909
|
+
recordIds: options.recordIds,
|
|
910
|
+
payload: options.payload,
|
|
911
|
+
});
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
try {
|
|
915
|
+
await options.commit();
|
|
916
|
+
}
|
|
917
|
+
catch (err) {
|
|
918
|
+
if (this.canQueueWrites() && axpIsLikelyNetworkFailure(err)) {
|
|
919
|
+
await this.outbox.enqueue({
|
|
920
|
+
entityKey: this.entityKey,
|
|
921
|
+
action: options.action,
|
|
922
|
+
recordIds: options.recordIds,
|
|
923
|
+
payload: options.payload,
|
|
924
|
+
});
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
this.error.set(err instanceof Error ? err.message : options.failureMessage);
|
|
928
|
+
await options.revert();
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
async flushOutboxOp(op) {
|
|
932
|
+
switch (op.action) {
|
|
933
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markSeen:
|
|
934
|
+
if (op.recordIds.length > 0) {
|
|
935
|
+
await this.port.markSeen(op.recordIds);
|
|
936
|
+
}
|
|
937
|
+
return;
|
|
938
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markRead:
|
|
939
|
+
if (op.recordIds.length > 0) {
|
|
940
|
+
await this.port.markRead(op.recordIds);
|
|
941
|
+
}
|
|
942
|
+
return;
|
|
943
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markAllRead:
|
|
944
|
+
await this.port.markAllRead();
|
|
945
|
+
return;
|
|
946
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.togglePin:
|
|
947
|
+
if (op.recordIds[0] && this.port.togglePin) {
|
|
948
|
+
await this.port.togglePin(op.recordIds[0]);
|
|
949
|
+
}
|
|
950
|
+
return;
|
|
951
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.archive:
|
|
952
|
+
if (op.recordIds.length > 0 && this.port.archive) {
|
|
953
|
+
await this.port.archive(op.recordIds);
|
|
954
|
+
}
|
|
955
|
+
return;
|
|
956
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.delete:
|
|
957
|
+
if (op.recordIds.length > 0 && this.port.deleteDeliveries) {
|
|
958
|
+
try {
|
|
959
|
+
await this.port.deleteDeliveries(op.recordIds);
|
|
960
|
+
}
|
|
961
|
+
catch (err) {
|
|
962
|
+
if (!this.isBenignDeliveryDeleteError(err)) {
|
|
963
|
+
throw err;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return;
|
|
968
|
+
default:
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
async revertOutboxOp(op) {
|
|
973
|
+
if (op.action === AXP_IN_APP_INBOX_OUTBOX_ACTIONS.delete ||
|
|
974
|
+
op.action === AXP_IN_APP_INBOX_OUTBOX_ACTIONS.archive ||
|
|
975
|
+
op.action === AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markAllRead) {
|
|
976
|
+
await this.syncActiveFromServer();
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
if (op.recordIds.length > 0) {
|
|
980
|
+
await this.localBridge.apply({ entityKey: this.entityKey, type: 'upsert', ids: op.recordIds });
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
async reapplyPendingOutboxOps() {
|
|
984
|
+
const ops = this.outbox.pendingFor(this.entityKey);
|
|
985
|
+
for (const op of ops) {
|
|
986
|
+
await this.applyOutboxOpLocally(op);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
async applyOutboxOpLocally(op) {
|
|
990
|
+
const seenAt = typeof op.payload?.['seenAt'] === 'string' ? op.payload['seenAt'] : new Date().toISOString();
|
|
991
|
+
const readAt = typeof op.payload?.['readAt'] === 'string' ? op.payload['readAt'] : new Date().toISOString();
|
|
992
|
+
switch (op.action) {
|
|
993
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markSeen:
|
|
994
|
+
await this.engine.patchMany(this.entityKey, op.recordIds, (item) => item['seenAt'] ? item : { ...item, seenAt });
|
|
995
|
+
return;
|
|
996
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markRead:
|
|
997
|
+
await this.engine.patchMany(this.entityKey, op.recordIds, (item) => ({
|
|
998
|
+
...item,
|
|
999
|
+
seenAt: item['seenAt'] ?? seenAt,
|
|
1000
|
+
readAt: item['readAt'] ?? readAt,
|
|
1001
|
+
}));
|
|
1002
|
+
return;
|
|
1003
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.markAllRead:
|
|
1004
|
+
await this.engine.patchAll(this.entityKey, (item) => item['readAt'] != null ? item : { ...item, readAt, seenAt: item['seenAt'] ?? seenAt });
|
|
1005
|
+
return;
|
|
1006
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.togglePin:
|
|
1007
|
+
await this.engine.patchMany(this.entityKey, op.recordIds, (item) => ({
|
|
1008
|
+
...item,
|
|
1009
|
+
isPinned: Boolean(op.payload?.['isPinned']),
|
|
1010
|
+
}));
|
|
1011
|
+
return;
|
|
1012
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.archive:
|
|
1013
|
+
case AXP_IN_APP_INBOX_OUTBOX_ACTIONS.delete:
|
|
1014
|
+
await this.engine.removeMany(this.entityKey, op.recordIds);
|
|
1015
|
+
return;
|
|
1016
|
+
default:
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
//#endregion
|
|
854
1021
|
//#region ----- Local helpers -----
|
|
855
1022
|
canLoadInbox() {
|
|
856
1023
|
return this.sessionService.isReadyForAppScopedApi;
|
|
@@ -1044,6 +1211,7 @@ const communicationInAppInboxI18n = {
|
|
|
1044
1211
|
selectItems: '@communication-management:in-app.actions.select-items',
|
|
1045
1212
|
clearFilters: '@communication-management:in-app.actions.clear-filters',
|
|
1046
1213
|
liveUpdatesOffline: '@communication-management:in-app.live-updates-offline',
|
|
1214
|
+
pendingSync: '@communication-management:in-app.pending-sync',
|
|
1047
1215
|
};
|
|
1048
1216
|
//#endregion
|
|
1049
1217
|
|
|
@@ -1427,20 +1595,25 @@ const RECONNECT_REFRESH_DELAY_MS = 250;
|
|
|
1427
1595
|
//#region ---- In-app inbox fallback sync ----
|
|
1428
1596
|
/**
|
|
1429
1597
|
* Keeps the inbox fresh when Socket.IO is down: poll while disconnected,
|
|
1430
|
-
* refresh on reconnect and when the tab becomes visible again.
|
|
1598
|
+
* refresh on reconnect and when the tab becomes visible again while disconnected.
|
|
1431
1599
|
*/
|
|
1432
1600
|
function provideCommunicationInAppInboxFallbackSync() {
|
|
1433
1601
|
return [
|
|
1434
1602
|
provideAppStartUpTask(() => {
|
|
1435
1603
|
const connector = inject(AXPInAppInboxConnectorService);
|
|
1436
1604
|
const sessionService = inject(AXPSessionService);
|
|
1605
|
+
const outbox = inject(AXPLocalEntityOutboxService);
|
|
1437
1606
|
const syncStatus = inject(AXMCommunicationInAppInboxSyncStatusService);
|
|
1438
1607
|
const connection = inject(AXPRealtimeConnectionService, { optional: true });
|
|
1439
1608
|
const destroyRef = inject(DestroyRef);
|
|
1440
1609
|
const refreshIfAuthorized = () => {
|
|
1441
|
-
if (sessionService.isReadyForAppScopedApi) {
|
|
1442
|
-
|
|
1610
|
+
if (!sessionService.isReadyForAppScopedApi) {
|
|
1611
|
+
return;
|
|
1443
1612
|
}
|
|
1613
|
+
void (async () => {
|
|
1614
|
+
await outbox.flushAll();
|
|
1615
|
+
await connector.refresh();
|
|
1616
|
+
})();
|
|
1444
1617
|
};
|
|
1445
1618
|
return {
|
|
1446
1619
|
name: 'communication-in-app-inbox-fallback',
|
|
@@ -1476,8 +1649,7 @@ function provideCommunicationInAppInboxFallbackSync() {
|
|
|
1476
1649
|
refreshIfAuthorized();
|
|
1477
1650
|
});
|
|
1478
1651
|
document.addEventListener('visibilitychange', () => {
|
|
1479
|
-
if (document.visibilityState === 'visible') {
|
|
1480
|
-
// Re-sync active inbox in case realtime was missed while hidden.
|
|
1652
|
+
if (document.visibilityState === 'visible' && !connection.isSocketConnected()) {
|
|
1481
1653
|
refreshIfAuthorized();
|
|
1482
1654
|
}
|
|
1483
1655
|
}, { passive: true });
|
|
@@ -1765,7 +1937,7 @@ class AXPInAppInboxPanelComponent {
|
|
|
1765
1937
|
];
|
|
1766
1938
|
}
|
|
1767
1939
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPInAppInboxPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1768
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPInAppInboxPanelComponent, isStandalone: true, selector: "axp-in-app-inbox-panel", outputs: { unreadCountChange: "unreadCountChange", closePopover: "closePopover" }, ngImport: i0, template: "<div class=\"axp-in-app-inbox-panel__header\">\n <span class=\"axp-in-app-inbox-panel__title\">\n {{ i18n.panelTitle | translate | async }}\n </span>\n @if (config.settingsRoute) {\n <ax-button color=\"default\" look=\"blank\" (onClick)=\"openSettings()\">\n <ax-icon><i class=\"fa-regular fa-gear fa-lg\"></i></ax-icon>\n </ax-button>\n }\n</div>\n<ax-tabs [content]=\"tabContent\" look=\"with-line\" location=\"bottom\">\n @for (tab of tabItems(); track tab.key) {\n <ax-tab-item\n [text]=\"(tab.labelKey | translate | async) ?? ''\"\n [active]=\"activeTab() === tab.key\"\n (activeChange)=\"changeActiveTab(tab.key)\"\n >\n <ax-suffix>\n @if (tab.count && tab.key === 'Unread') {\n <ax-badge [color]=\"activeTab() === tab.key ? 'primary' : 'ghost'\" [text]=\"tab.count.toString()\"></ax-badge>\n }\n </ax-suffix>\n <ax-content>\n <div class=\"axp-in-app-inbox-panel__list\">\n @if (isLoading()) {\n <div class=\"axp-in-app-inbox-panel__loading\">\n @for (_ of [1, 2, 3]; track $index) {\n <div class=\"axp-in-app-inbox-panel__skeleton\">\n <div class=\"axp-in-app-inbox-panel__skeleton-avatar\"></div>\n <div class=\"axp-in-app-inbox-panel__skeleton-lines\">\n <div class=\"axp-in-app-inbox-panel__skeleton-line --wide\"></div>\n <div class=\"axp-in-app-inbox-panel__skeleton-line\"></div>\n </div>\n </div>\n }\n </div>\n } @else if (getItems(tab.key).length === 0) {\n <axp-state-message\n icon=\"fa-regular fa-bell-slash\"\n [title]=\"i18n.emptyTitle\"\n [description]=\"i18n.emptyDescription\"\n />\n } @else {\n @for (item of getItems(tab.key); track item.id) {\n <axp-in-app-inbox-item\n [data]=\"item\"\n [highlightUnreadBackground]=\"tab.key === 'All'\"\n [showPin]=\"showPin()\"\n [pinLabelKey]=\"i18n.pin\"\n [unpinLabelKey]=\"i18n.unpin\"\n [markAsReadLabelKey]=\"i18n.markAsRead\"\n (itemPress)=\"openInboxItem($event)\"\n (markAsRead)=\"dismissUnread($event)\"\n (togglePin)=\"togglePin($event)\"\n (closePopover)=\"closePopover.emit()\"\n />\n }\n }\n </div>\n <div class=\"axp-in-app-inbox-panel__footer\">\n <ax-button\n class=\"ax-sm\"\n [disabled]=\"(tabItems()[0]?.count ?? 0) === 0\"\n look=\"outline\"\n color=\"default\"\n [text]=\"(i18n.markAllAsRead | translate | async) ?? ''\"\n (onClick)=\"markAllAsRead()\"\n />\n <ax-button\n class=\"ax-sm\"\n look=\"outline\"\n color=\"primary\"\n [text]=\"(i18n.viewAll | translate | async) ?? ''\"\n (onClick)=\"viewAll()\"\n />\n </div>\n </ax-content>\n </ax-tab-item>\n }\n</ax-tabs>\n\n<ng-template [axTabContent] #tabContent=\"axTabContent\"></ng-template>\n", styles: ["@reference \"@acorex/styles/themes/default.css\";.axp-in-app-inbox-panel__header{@apply p-4 flex justify-between items-center;}.axp-in-app-inbox-panel__title{@apply text-xl font-semibold;color:rgb(var(--ax-sys-color-on-surface))}.axp-in-app-inbox-panel__list{@apply max-h-[50vh] md:w-[32rem] overflow-y-auto flex flex-col;}.axp-in-app-inbox-panel__footer{@apply flex gap-4 justify-between p-4 border-t;border-color:rgb(var(--ax-sys-color-border-surface))}.axp-in-app-inbox-panel__loading{@apply p-2 space-y-2;}.axp-in-app-inbox-panel__skeleton{@apply flex gap-4 p-4 animate-pulse;}.axp-in-app-inbox-panel__skeleton-avatar{@apply w-12 h-12 rounded-full shrink-0;background:rgb(var(--ax-sys-color-lighter-surface))}.axp-in-app-inbox-panel__skeleton-lines{@apply flex-1 space-y-2 py-1;}.axp-in-app-inbox-panel__skeleton-line{@apply h-3 rounded-md;background:rgb(var(--ax-sys-color-lighter-surface))}.axp-in-app-inbox-panel__skeleton-line.--wide{@apply w-3/4;}.axp-in-app-inbox-panel__skeleton-line:not(.--wide){@apply w-1/2;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "reorderable", "reorderDelay", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged", "onTabsReordered"] }, { kind: "component", type: i2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "directive", type: i2.AXTabContentDirective, selector: "[axTabContent]", inputs: ["axTabContent"], exportAs: ["axTabContent"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPInAppInboxItemComponent, selector: "axp-in-app-inbox-item", inputs: ["data", "showAvatar", "showDate", "showPin", "pinLabelKey", "unpinLabelKey", "highlightUnreadBackground", "showDismissUnread", "markAsReadLabelKey"], outputs: ["itemPress", "markAsRead", "togglePin", "closePopover"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1940
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPInAppInboxPanelComponent, isStandalone: true, selector: "axp-in-app-inbox-panel", outputs: { unreadCountChange: "unreadCountChange", closePopover: "closePopover" }, ngImport: i0, template: "<div class=\"axp-in-app-inbox-panel__header\">\n <span class=\"axp-in-app-inbox-panel__title\">\n {{ i18n.panelTitle | translate | async }}\n </span>\n @if (config.settingsRoute) {\n <ax-button color=\"default\" look=\"blank\" (onClick)=\"openSettings()\">\n <ax-icon><i class=\"fa-regular fa-gear fa-lg\"></i></ax-icon>\n </ax-button>\n }\n</div>\n<ax-tabs [content]=\"tabContent\" look=\"with-line\" location=\"bottom\">\n @for (tab of tabItems(); track tab.key) {\n <ax-tab-item\n [text]=\"(tab.labelKey | translate | async) ?? ''\"\n [active]=\"activeTab() === tab.key\"\n (activeChange)=\"changeActiveTab(tab.key)\"\n >\n <ax-suffix>\n @if (tab.count && tab.key === 'Unread') {\n <ax-badge [color]=\"activeTab() === tab.key ? 'primary' : 'ghost'\" [text]=\"tab.count.toString()\"></ax-badge>\n }\n </ax-suffix>\n <ax-content>\n <div class=\"axp-in-app-inbox-panel__list\">\n @if (isLoading()) {\n <div class=\"axp-in-app-inbox-panel__loading\">\n @for (_ of [1, 2, 3]; track $index) {\n <div class=\"axp-in-app-inbox-panel__skeleton\">\n <div class=\"axp-in-app-inbox-panel__skeleton-avatar\"></div>\n <div class=\"axp-in-app-inbox-panel__skeleton-lines\">\n <div class=\"axp-in-app-inbox-panel__skeleton-line --wide\"></div>\n <div class=\"axp-in-app-inbox-panel__skeleton-line\"></div>\n </div>\n </div>\n }\n </div>\n } @else if (getItems(tab.key).length === 0) {\n <axp-state-message\n icon=\"fa-regular fa-bell-slash\"\n [title]=\"i18n.emptyTitle\"\n [description]=\"i18n.emptyDescription\"\n />\n } @else {\n @for (item of getItems(tab.key); track item.id) {\n <axp-in-app-inbox-item\n [data]=\"item\"\n [highlightUnreadBackground]=\"tab.key === 'All'\"\n [showPin]=\"showPin()\"\n [pinLabelKey]=\"i18n.pin\"\n [unpinLabelKey]=\"i18n.unpin\"\n [markAsReadLabelKey]=\"i18n.markAsRead\"\n (itemPress)=\"openInboxItem($event)\"\n (markAsRead)=\"dismissUnread($event)\"\n (togglePin)=\"togglePin($event)\"\n (closePopover)=\"closePopover.emit()\"\n />\n }\n }\n </div>\n <div class=\"axp-in-app-inbox-panel__footer\">\n <ax-button\n class=\"ax-sm\"\n [disabled]=\"(tabItems()[0]?.count ?? 0) === 0\"\n look=\"outline\"\n color=\"default\"\n [text]=\"(i18n.markAllAsRead | translate | async) ?? ''\"\n (onClick)=\"markAllAsRead()\"\n />\n <ax-button\n class=\"ax-sm\"\n look=\"outline\"\n color=\"primary\"\n [text]=\"(i18n.viewAll | translate | async) ?? ''\"\n (onClick)=\"viewAll()\"\n />\n </div>\n </ax-content>\n </ax-tab-item>\n }\n</ax-tabs>\n\n<ng-template [axTabContent] #tabContent=\"axTabContent\"></ng-template>\n", styles: ["@reference \"@acorex/styles/themes/default.css\";.axp-in-app-inbox-panel__header{@apply p-4 flex justify-between items-center;}.axp-in-app-inbox-panel__title{@apply text-xl font-semibold;color:rgb(var(--ax-sys-color-on-surface))}.axp-in-app-inbox-panel__list{@apply max-h-[50vh] md:w-[32rem] overflow-y-auto flex flex-col;}.axp-in-app-inbox-panel__footer{@apply flex gap-4 justify-between p-4 border-t;border-color:rgb(var(--ax-sys-color-border-surface))}.axp-in-app-inbox-panel__loading{@apply p-2 space-y-2;}.axp-in-app-inbox-panel__skeleton{@apply flex gap-4 p-4 animate-pulse;}.axp-in-app-inbox-panel__skeleton-avatar{@apply w-12 h-12 rounded-full shrink-0;background:rgb(var(--ax-sys-color-lighter-surface))}.axp-in-app-inbox-panel__skeleton-lines{@apply flex-1 space-y-2 py-1;}.axp-in-app-inbox-panel__skeleton-line{@apply h-3 rounded-md;background:rgb(var(--ax-sys-color-lighter-surface))}.axp-in-app-inbox-panel__skeleton-line.--wide{@apply w-3/4;}.axp-in-app-inbox-panel__skeleton-line:not(.--wide){@apply w-1/2;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "reorderable", "reorderDelay", "renderMode", "stacked", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged", "onTabsReordered"] }, { kind: "component", type: i2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "directive", type: i2.AXTabContentDirective, selector: "[axTabContent]", inputs: ["axTabContent"], exportAs: ["axTabContent"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPInAppInboxItemComponent, selector: "axp-in-app-inbox-item", inputs: ["data", "showAvatar", "showDate", "showPin", "pinLabelKey", "unpinLabelKey", "highlightUnreadBackground", "showDismissUnread", "markAsReadLabelKey"], outputs: ["itemPress", "markAsRead", "togglePin", "closePopover"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1769
1941
|
}
|
|
1770
1942
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPInAppInboxPanelComponent, decorators: [{
|
|
1771
1943
|
type: Component,
|
|
@@ -1788,9 +1960,22 @@ class AXPInAppInboxSlotComponent {
|
|
|
1788
1960
|
this.i18n = inject(AXP_IN_APP_INBOX_I18N);
|
|
1789
1961
|
this.themeStore = inject(AXPLayoutThemeService);
|
|
1790
1962
|
this.connector = inject(AXPInAppInboxConnectorService);
|
|
1963
|
+
this.outbox = inject(AXPLocalEntityOutboxService);
|
|
1791
1964
|
this.syncStatus = inject(AXP_IN_APP_INBOX_SYNC_STATUS, { optional: true });
|
|
1792
1965
|
this.liveUpdatesOffline = computed(() => this.syncStatus != null && !this.syncStatus.liveUpdatesConnected(), /* @ts-ignore */
|
|
1793
1966
|
...(ngDevMode ? [{ debugName: "liveUpdatesOffline" }] : /* istanbul ignore next */ []));
|
|
1967
|
+
this.pendingSync = computed(() => this.outbox.pendingCount() > 0, /* @ts-ignore */
|
|
1968
|
+
...(ngDevMode ? [{ debugName: "pendingSync" }] : /* istanbul ignore next */ []));
|
|
1969
|
+
this.statusTitleKey = computed(() => {
|
|
1970
|
+
if (this.pendingSync()) {
|
|
1971
|
+
return this.i18n.pendingSync;
|
|
1972
|
+
}
|
|
1973
|
+
if (this.liveUpdatesOffline()) {
|
|
1974
|
+
return this.i18n.liveUpdatesOffline;
|
|
1975
|
+
}
|
|
1976
|
+
return '';
|
|
1977
|
+
}, /* @ts-ignore */
|
|
1978
|
+
...(ngDevMode ? [{ debugName: "statusTitleKey" }] : /* istanbul ignore next */ []));
|
|
1794
1979
|
this.badgeDisplay = computed(() => {
|
|
1795
1980
|
const total = this.connector.unreadCount();
|
|
1796
1981
|
if (total <= 0) {
|
|
@@ -1806,7 +1991,7 @@ class AXPInAppInboxSlotComponent {
|
|
|
1806
1991
|
this.popover()?.close();
|
|
1807
1992
|
}
|
|
1808
1993
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPInAppInboxSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1809
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPInAppInboxSlotComponent, isStandalone: true, selector: "axp-in-app-inbox-slot", viewQueries: [{ propertyName: "popover", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<ax-button\n [iconOnly]=\"true\"\n class=\"relative axp-in-app-inbox-slot__button\"\n [color]=\"themeStore.headerButtonColor()\"\n [look]=\"themeStore.headerButtonLook()\"\n #inboxTrigger\n [title]=\"
|
|
1994
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPInAppInboxSlotComponent, isStandalone: true, selector: "axp-in-app-inbox-slot", viewQueries: [{ propertyName: "popover", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<ax-button\n [iconOnly]=\"true\"\n class=\"relative axp-in-app-inbox-slot__button\"\n [color]=\"themeStore.headerButtonColor()\"\n [look]=\"themeStore.headerButtonLook()\"\n #inboxTrigger\n [title]=\"statusTitleKey() ? ((statusTitleKey() | translate | async) ?? '') : ''\"\n>\n <ax-icon>\n <i [class]=\"config.headerIconClass\"></i>\n </ax-icon>\n</ax-button>\n\n<div\n class=\"axp-in-app-inbox-slot__badge\"\n [class.--xs]=\"badgeDisplay().length > 2\"\n>\n @if (badgeDisplay()) {\n <ax-badge color=\"danger\" [text]=\"badgeDisplay()\"></ax-badge>\n }\n</div>\n<ax-popover\n [target]=\"inboxTrigger\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n [adaptivityEnabled]=\"true\"\n>\n <div class=\"bg-lightest rounded-md w-full\">\n <axp-in-app-inbox-panel (closePopover)=\"closePopover()\" />\n </div>\n</ax-popover>\n", styles: ["@reference \"@acorex/styles/themes/default.css\";axp-in-app-inbox-slot{@apply relative;}axp-in-app-inbox-slot .axp-in-app-inbox-slot__badge{@apply absolute top-[-.25rem] end-[-.25rem];pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i4$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPInAppInboxPanelComponent, selector: "axp-in-app-inbox-panel", outputs: ["unreadCountChange", "closePopover"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1810
1995
|
}
|
|
1811
1996
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPInAppInboxSlotComponent, decorators: [{
|
|
1812
1997
|
type: Component,
|
|
@@ -1818,7 +2003,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
1818
2003
|
AXPopoverModule,
|
|
1819
2004
|
AXTranslationModule,
|
|
1820
2005
|
AXPInAppInboxPanelComponent,
|
|
1821
|
-
], template: "<ax-button\n [iconOnly]=\"true\"\n class=\"relative axp-in-app-inbox-slot__button\"\n [color]=\"themeStore.headerButtonColor()\"\n [look]=\"themeStore.headerButtonLook()\"\n #inboxTrigger\n [title]=\"
|
|
2006
|
+
], template: "<ax-button\n [iconOnly]=\"true\"\n class=\"relative axp-in-app-inbox-slot__button\"\n [color]=\"themeStore.headerButtonColor()\"\n [look]=\"themeStore.headerButtonLook()\"\n #inboxTrigger\n [title]=\"statusTitleKey() ? ((statusTitleKey() | translate | async) ?? '') : ''\"\n>\n <ax-icon>\n <i [class]=\"config.headerIconClass\"></i>\n </ax-icon>\n</ax-button>\n\n<div\n class=\"axp-in-app-inbox-slot__badge\"\n [class.--xs]=\"badgeDisplay().length > 2\"\n>\n @if (badgeDisplay()) {\n <ax-badge color=\"danger\" [text]=\"badgeDisplay()\"></ax-badge>\n }\n</div>\n<ax-popover\n [target]=\"inboxTrigger\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n [adaptivityEnabled]=\"true\"\n>\n <div class=\"bg-lightest rounded-md w-full\">\n <axp-in-app-inbox-panel (closePopover)=\"closePopover()\" />\n </div>\n</ax-popover>\n", styles: ["@reference \"@acorex/styles/themes/default.css\";axp-in-app-inbox-slot{@apply relative;}axp-in-app-inbox-slot .axp-in-app-inbox-slot__badge{@apply absolute top-[-.25rem] end-[-.25rem];pointer-events:none}\n"] }]
|
|
1822
2007
|
}], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPopoverComponent), { isSignal: true }] }] } });
|
|
1823
2008
|
|
|
1824
2009
|
const I18N$2 = '@communication-management:settings.user-notifications';
|
|
@@ -1854,17 +2039,6 @@ class AXMCommunicationUserNotificationsSettingProvider {
|
|
|
1854
2039
|
}
|
|
1855
2040
|
//#endregion
|
|
1856
2041
|
|
|
1857
|
-
const CommunicationManagementManifest = {
|
|
1858
|
-
name: RootConfig.module.name,
|
|
1859
|
-
version: '0.0.1',
|
|
1860
|
-
title: RootConfig.module.title,
|
|
1861
|
-
icon: RootConfig.module.icon,
|
|
1862
|
-
i18n: RootConfig.config.i18n,
|
|
1863
|
-
type: 'domain',
|
|
1864
|
-
domain: 'communication',
|
|
1865
|
-
required: false,
|
|
1866
|
-
};
|
|
1867
|
-
|
|
1868
2042
|
class AXMCommunicationManagementMenuProvider {
|
|
1869
2043
|
constructor() {
|
|
1870
2044
|
this.entityService = inject(AXPEntityService);
|
|
@@ -1897,6 +2071,19 @@ class AXMCommunicationManagementMenuProvider {
|
|
|
1897
2071
|
},
|
|
1898
2072
|
},
|
|
1899
2073
|
]);
|
|
2074
|
+
context.find(AXPCommonMenuKeys.Administration).addItems([
|
|
2075
|
+
{
|
|
2076
|
+
name: AXMCommunicationManagementMenuKeys.EntityChangeNotifyPolicies,
|
|
2077
|
+
text: RootConfig.entities.entityChangeNotifyPolicy.titlePlural,
|
|
2078
|
+
path: this.entityService.createPath(module, RootConfig.entities.entityChangeNotifyPolicy.name),
|
|
2079
|
+
icon: RootConfig.entities.entityChangeNotifyPolicy.icon,
|
|
2080
|
+
priority: 42,
|
|
2081
|
+
policy: {
|
|
2082
|
+
features: [module],
|
|
2083
|
+
permissions: [AXPCollaborationPermissionKeys.MaintainCommunications],
|
|
2084
|
+
},
|
|
2085
|
+
},
|
|
2086
|
+
]);
|
|
1900
2087
|
}
|
|
1901
2088
|
}
|
|
1902
2089
|
|
|
@@ -2337,7 +2524,7 @@ function routesFactory() {
|
|
|
2337
2524
|
children: [
|
|
2338
2525
|
{
|
|
2339
2526
|
path: '',
|
|
2340
|
-
loadComponent: () => import('./acorex-platform-module-communication-management-client-communication-in-app-inbox-page.component-
|
|
2527
|
+
loadComponent: () => import('./acorex-platform-module-communication-management-client-communication-in-app-inbox-page.component-yaRijsuh.mjs').then((m) => m.AXMCommunicationInAppInboxPageComponent),
|
|
2341
2528
|
data: { reuse: true },
|
|
2342
2529
|
},
|
|
2343
2530
|
],
|
|
@@ -2351,11 +2538,11 @@ class AXMCommunicationManagementModule {
|
|
|
2351
2538
|
provideCommandSetups([
|
|
2352
2539
|
{
|
|
2353
2540
|
key: AXMCommunicationManagementCommandKeys$1.Send,
|
|
2354
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-send.command-
|
|
2541
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-send.command-D19heywC.mjs').then((m) => m.CommunicationSendCommand),
|
|
2355
2542
|
},
|
|
2356
2543
|
{
|
|
2357
2544
|
key: AXMCommunicationManagementCommandKeys$1.TestSmtp,
|
|
2358
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-test-smtp.command-
|
|
2545
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-test-smtp.command-Bck8R4as.mjs').then((m) => m.CommunicationTestSmtpCommand),
|
|
2359
2546
|
},
|
|
2360
2547
|
{
|
|
2361
2548
|
key: AXMCommunicationManagementCommandKeys$1.EmailShowDialog,
|
|
@@ -2363,7 +2550,7 @@ class AXMCommunicationManagementModule {
|
|
|
2363
2550
|
},
|
|
2364
2551
|
{
|
|
2365
2552
|
key: AXMCommunicationManagementCommandKeys$1.EmailSend,
|
|
2366
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-
|
|
2553
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-CR4RjM-X.mjs').then((m) => m.CommunicationManagementEmailSendCommand),
|
|
2367
2554
|
},
|
|
2368
2555
|
{
|
|
2369
2556
|
key: AXMCommunicationManagementCommandKeys$1.ShowSentMessage,
|
|
@@ -2375,14 +2562,9 @@ class AXMCommunicationManagementModule {
|
|
|
2375
2562
|
},
|
|
2376
2563
|
{
|
|
2377
2564
|
key: LEGACY_NOTIFICATION_EMAIL_SEND_COMMAND_KEY,
|
|
2378
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-
|
|
2565
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-CR4RjM-X.mjs').then((m) => m.CommunicationManagementEmailSendCommand),
|
|
2379
2566
|
},
|
|
2380
2567
|
]),
|
|
2381
|
-
{
|
|
2382
|
-
provide: AXP_MODULE_MANIFEST_PROVIDER,
|
|
2383
|
-
useValue: CommunicationManagementManifest,
|
|
2384
|
-
multi: true,
|
|
2385
|
-
},
|
|
2386
2568
|
{
|
|
2387
2569
|
provide: AXP_PERMISSION_DEFINITION_PROVIDER,
|
|
2388
2570
|
useClass: AXMCommunicationManagementPermissionDefinitionProvider,
|
|
@@ -2479,11 +2661,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
2479
2661
|
provideCommandSetups([
|
|
2480
2662
|
{
|
|
2481
2663
|
key: AXMCommunicationManagementCommandKeys$1.Send,
|
|
2482
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-send.command-
|
|
2664
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-send.command-D19heywC.mjs').then((m) => m.CommunicationSendCommand),
|
|
2483
2665
|
},
|
|
2484
2666
|
{
|
|
2485
2667
|
key: AXMCommunicationManagementCommandKeys$1.TestSmtp,
|
|
2486
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-test-smtp.command-
|
|
2668
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-test-smtp.command-Bck8R4as.mjs').then((m) => m.CommunicationTestSmtpCommand),
|
|
2487
2669
|
},
|
|
2488
2670
|
{
|
|
2489
2671
|
key: AXMCommunicationManagementCommandKeys$1.EmailShowDialog,
|
|
@@ -2491,7 +2673,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
2491
2673
|
},
|
|
2492
2674
|
{
|
|
2493
2675
|
key: AXMCommunicationManagementCommandKeys$1.EmailSend,
|
|
2494
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-
|
|
2676
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-CR4RjM-X.mjs').then((m) => m.CommunicationManagementEmailSendCommand),
|
|
2495
2677
|
},
|
|
2496
2678
|
{
|
|
2497
2679
|
key: AXMCommunicationManagementCommandKeys$1.ShowSentMessage,
|
|
@@ -2503,14 +2685,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
2503
2685
|
},
|
|
2504
2686
|
{
|
|
2505
2687
|
key: LEGACY_NOTIFICATION_EMAIL_SEND_COMMAND_KEY,
|
|
2506
|
-
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-
|
|
2688
|
+
command: () => import('./acorex-platform-module-communication-management-client-communication-email-send.command-CR4RjM-X.mjs').then((m) => m.CommunicationManagementEmailSendCommand),
|
|
2507
2689
|
},
|
|
2508
2690
|
]),
|
|
2509
|
-
{
|
|
2510
|
-
provide: AXP_MODULE_MANIFEST_PROVIDER,
|
|
2511
|
-
useValue: CommunicationManagementManifest,
|
|
2512
|
-
multi: true,
|
|
2513
|
-
},
|
|
2514
2691
|
{
|
|
2515
2692
|
provide: AXP_PERMISSION_DEFINITION_PROVIDER,
|
|
2516
2693
|
useClass: AXMCommunicationManagementPermissionDefinitionProvider,
|
|
@@ -2624,4 +2801,4 @@ function resolveCommunicationDeliveryChannelsSettingsSection(context) {
|
|
|
2624
2801
|
*/
|
|
2625
2802
|
|
|
2626
2803
|
export { AXPInAppInboxConnectorService as A, isInAppInboxUnseen as B, normalizeInAppInboxItem as C, resolveCommunicationDeliveryChannelsSettingsSection as D, sortInAppInboxItems as E, AXPInAppInboxActionService as a, AXP_IN_APP_INBOX_I18N as b, AXPInAppInboxItemComponent as c, AXPCommunicationManagementClient as d, AXPInAppInboxRealtimeService as e, AXMCommunicationManagementMenuProvider as f, AXMCommunicationManagementModule as g, AXMCommunicationManagementPermissionDefinitionProvider as h, AXMCommunicationManagementSearchCommandProvider as i, AXPCommunicationInAppInboxWidgetViewComponent as j, AXPInAppInboxPanelComponent as k, AXPInAppInboxSlotComponent as l, AXPMyInAppInboxDashboardWidget as m, AXP_IN_APP_INBOX_CONFIG as n, AXP_IN_APP_INBOX_LEGACY_DB_NAME as o, AXP_IN_APP_INBOX_LOCAL_ENTITY_KEY as p, AXP_IN_APP_INBOX_LOCAL_MAX_ITEMS as q, AXP_IN_APP_INBOX_PORT as r, AXP_IN_APP_INBOX_SYNC_STATUS as s, AXP_MY_IN_APP_INBOX_DASHBOARD_DIMENSIONS as t, buildMyInAppInboxDashboardWidget as u, dedupeInAppInboxItems as v, filterInAppInboxItemsLocally as w, getInAppInboxPriorityClass as x, isArchiveCategoryFilter as y, isInAppInboxUnread as z };
|
|
2627
|
-
//# sourceMappingURL=acorex-platform-module-communication-management-client-acorex-platform-module-communication-management-client-
|
|
2804
|
+
//# sourceMappingURL=acorex-platform-module-communication-management-client-acorex-platform-module-communication-management-client-BJvTWpBc.mjs.map
|