@acorex-platform/module-conversation-client 0.0.59 → 0.0.60
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-conversation-client-acorex-platform-module-conversation-client-1tv00m7Y.mjs → acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-CmRULmpl.mjs} +379 -276
- package/fesm2022/acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-CmRULmpl.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-conversation-client-after-message-sent.command-e_3t71gw.mjs → acorex-platform-module-conversation-client-after-message-sent.command-JjZrYD2R.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-after-message-sent.command-e_3t71gw.mjs.map → acorex-platform-module-conversation-client-after-message-sent.command-JjZrYD2R.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-BmfLuUaU.mjs → acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-BhED754u.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-BmfLuUaU.mjs.map → acorex-platform-module-conversation-client-assist-delegated-agent-detail-popup.component-BhED754u.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-assist-message-renderer.component-jsHo7NZq.mjs → acorex-platform-module-conversation-client-assist-message-renderer.component-CR4OxDV6.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-conversation-client-assist-message-renderer.component-jsHo7NZq.mjs.map → acorex-platform-module-conversation-client-assist-message-renderer.component-CR4OxDV6.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-chat-call-session-page.component-ePQikBd2.mjs → acorex-platform-module-conversation-client-chat-call-session-page.component-DJreBgNo.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-chat-call-session-page.component-ePQikBd2.mjs.map → acorex-platform-module-conversation-client-chat-call-session-page.component-DJreBgNo.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-chat-call-start-popup.component-ooiJkC8U.mjs → acorex-platform-module-conversation-client-chat-call-start-popup.component-BEa8wEJt.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-chat-call-start-popup.component-ooiJkC8U.mjs.map → acorex-platform-module-conversation-client-chat-call-start-popup.component-BEa8wEJt.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-comments-page.component-BW_XRzT6.mjs → acorex-platform-module-conversation-client-comments-page.component-BsE6bCZT.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-comments-page.component-BW_XRzT6.mjs.map → acorex-platform-module-conversation-client-comments-page.component-BsE6bCZT.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-mark-conversation-unread.command-Cdd6Cxkf.mjs → acorex-platform-module-conversation-client-mark-conversation-unread.command-B1mvtbaA.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-mark-conversation-unread.command-Cdd6Cxkf.mjs.map → acorex-platform-module-conversation-client-mark-conversation-unread.command-B1mvtbaA.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-open-chat.command-TfSLQn3K.mjs → acorex-platform-module-conversation-client-open-chat.command-CbJ0gXZq.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-open-chat.command-TfSLQn3K.mjs.map → acorex-platform-module-conversation-client-open-chat.command-CbJ0gXZq.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-retry-assist-response.command-CC0jPXGP.mjs → acorex-platform-module-conversation-client-retry-assist-response.command-BvzWaKX4.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-retry-assist-response.command-CC0jPXGP.mjs.map → acorex-platform-module-conversation-client-retry-assist-response.command-BvzWaKX4.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-conversation-client-sync-read-state.command-BUtdyniC.mjs → acorex-platform-module-conversation-client-sync-read-state.command-DQXezGRu.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-conversation-client-sync-read-state.command-BUtdyniC.mjs.map → acorex-platform-module-conversation-client-sync-read-state.command-DQXezGRu.mjs.map} +1 -1
- package/fesm2022/acorex-platform-module-conversation-client.mjs +1 -1
- package/i18n/en-AU/conversation.json +6 -1
- package/i18n/en-US/conversation.json +6 -1
- package/i18n/fa-IR/conversation.json +6 -1
- package/package.json +2 -2
- package/types/acorex-platform-module-conversation-client.d.ts +41 -44
- package/fesm2022/acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-1tv00m7Y.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/auth';
|
|
2
|
-
import { AXPFilterOperatorMiddlewareService, AXPSearchCommandProvider, createEntityCommandOptions, AXP_PROTECTED_ROUTE_GUARDS, AXPBackgroundOperationHandler, AXP_BACKGROUND_OPERATION_HANDLERS, AXPSettingsService, AXPCommonSettings, AXP_IN_APP_NOTIFICATION_SERVICE, AXPFileStorageService, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
2
|
+
import { AXPFilterOperatorMiddlewareService, AXPSearchCommandProvider, createEntityCommandOptions, AXP_PROTECTED_ROUTE_GUARDS, AXPBackgroundOperationHandler, AXP_BACKGROUND_OPERATION_HANDLERS, AXPSettingsService, AXPCommonSettings, AXP_IN_APP_NOTIFICATION_SERVICE, AXPFileStorageService, normalizeStoredImageRef, isStoredImageFileId, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
3
3
|
import { AXPEntityBroadcastService, AXPTagService, AXPPageContextRegistry, AXPDialogOpener, AXPDeviceService, provideAppStartUpTask, AXP_APP_STARTUP_PRIORITY, AXP_HOOK_PROVIDER } from '@acorex-platform/framework-client/core';
|
|
4
4
|
import { USER_CARD_ITEMS_HOOK, AXPTaskBadgeProvider, AXPFileViewerService, AXPUserAvatarService, AXPUserAvatarComponent, AXPUserCardDirective, mergeInfiniteScrollPage, AXPThemeLayoutBlockComponent, AXPInfiniteScrollDirective, AXPStateMessageComponent, AXPAvatarComponent, AXPMarkdownViewerComponent, AXPTaskBadgeService, AXPThemeLayoutStartSideComponent, AXP_PAGE_COMPONENT_PROVIDER, AXP_TASK_BADGE_PROVIDERS } from '@acorex-platform/framework-client/layout/components';
|
|
5
5
|
import { AXPEntityService, AXPFileListComponent, AXPEntityDefinitionRegistryService, cloneLayoutArrays, ensureLayoutSection, ensureLayoutPropertyView, resolveEntityPluginDetailPageOrder, ensureListActions, actionExists, AXP_ENTITY_ACTION_PLUGIN } from '@acorex-platform/framework-client/layout/entity';
|
|
@@ -34,7 +34,7 @@ import { AXBadgeModule } from '@acorex/components/badge';
|
|
|
34
34
|
import * as i2 from '@acorex/components/decorators';
|
|
35
35
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
36
36
|
import * as i5 from '@acorex/core/format';
|
|
37
|
-
import { AXFormatModule } from '@acorex/core/format';
|
|
37
|
+
import { AXFormatModule, AXFormatService } from '@acorex/core/format';
|
|
38
38
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
39
39
|
import { AXPopupService, AXPopupCaptionIconComponent, AXPopupComponentBase, AXPopupDockComponent } from '@acorex/components/popup';
|
|
40
40
|
import { AXDragHandleDirective } from '@acorex/cdk/drag-drop';
|
|
@@ -46,21 +46,14 @@ import { AXPlatform } from '@acorex/core/platform';
|
|
|
46
46
|
import { AXFabComponent, AXFabItemComponent } from '@acorex/components/fab';
|
|
47
47
|
import { AXPInAppInboxConnectorService, isInAppInboxUnread, AXPCommunicationManagementClient, AXPInAppInboxRealtimeService } from '@acorex-platform/module-communication-management-client';
|
|
48
48
|
import { axpAiChatMessageIsDelegatedReflectionExcluded, axpAiExtractChatWidgetNodeFromUnknown, axpAiDelegatedAgentResultSegments, AXPAiManagerService, AXPAiChatToolRunContextService, AXPAiPlatformRuntimeContextBuilder, AIMANAGEMENT_STRUCTURED_TEXT_COMPLETION_COMMAND_KEY, axpAiChatTextMessage, persistAiChatAttachmentImage, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AXPAiAssistChatModelCatalogService } from '@acorex-platform/module-ai-management-client';
|
|
49
|
-
import * as i1$3 from '@acorex/components/text-editor';
|
|
50
|
-
import { AXTextEditorModule } from '@acorex/components/text-editor';
|
|
51
|
-
import { trigger, transition, style, animate } from '@angular/animations';
|
|
52
|
-
import { DomSanitizer } from '@angular/platform-browser';
|
|
53
|
-
import { AXAvatarModule } from '@acorex/components/avatar';
|
|
54
49
|
import * as i4 from '@acorex/components/comment';
|
|
55
|
-
import { AXCommentModule } from '@acorex/components/comment';
|
|
56
|
-
import * as i7 from '@acorex/components/dropdown';
|
|
57
|
-
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
50
|
+
import { AXCommentViewComponent, AXCommentContainerComponent, AXCommentModule } from '@acorex/components/comment';
|
|
51
|
+
import * as i7 from '@acorex/components/dropdown-button';
|
|
58
52
|
import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
|
|
59
|
-
import
|
|
60
|
-
import { AXImageModule } from '@acorex/components/image';
|
|
61
|
-
import * as i6 from '@acorex/components/loading';
|
|
53
|
+
import * as i8 from '@acorex/components/loading';
|
|
62
54
|
import { AXLoadingModule } from '@acorex/components/loading';
|
|
63
|
-
import
|
|
55
|
+
import * as i1$3 from '@acorex/components/text-editor';
|
|
56
|
+
import { AXTextEditorComponent, AXTextEditorModule } from '@acorex/components/text-editor';
|
|
64
57
|
import * as i1$4 from '@angular/forms';
|
|
65
58
|
import { FormsModule } from '@angular/forms';
|
|
66
59
|
import { AXPEntityCommandScope } from '@acorex-platform/framework-shared/entity';
|
|
@@ -12393,11 +12386,16 @@ function buildCommentInAppNotificationRequest(thread, comment, receiver) {
|
|
|
12393
12386
|
}
|
|
12394
12387
|
//#endregion
|
|
12395
12388
|
|
|
12396
|
-
|
|
12389
|
+
//#region ----- Imports -----
|
|
12390
|
+
//#endregion
|
|
12391
|
+
//#region ----- Constants -----
|
|
12397
12392
|
const SUBMIT_COOLDOWN_MS = 100;
|
|
12393
|
+
const AVATAR_COLORS = ['primary', 'success', 'warning', 'danger'];
|
|
12394
|
+
//#endregion
|
|
12395
|
+
//#region ----- Component -----
|
|
12398
12396
|
class AXMCommentComponent {
|
|
12399
12397
|
constructor() {
|
|
12400
|
-
//#region
|
|
12398
|
+
//#region ----- Inputs -----
|
|
12401
12399
|
this.refrenceType = input.required(/* @ts-ignore */
|
|
12402
12400
|
...(ngDevMode ? [{ debugName: "refrenceType" }] : /* istanbul ignore next */ []));
|
|
12403
12401
|
this.refrenceId = input.required(/* @ts-ignore */
|
|
@@ -12405,45 +12403,41 @@ class AXMCommentComponent {
|
|
|
12405
12403
|
this.subject = input.required(/* @ts-ignore */
|
|
12406
12404
|
...(ngDevMode ? [{ debugName: "subject" }] : /* istanbul ignore next */ []));
|
|
12407
12405
|
//#endregion
|
|
12408
|
-
//#region
|
|
12406
|
+
//#region ----- State Signals -----
|
|
12409
12407
|
this.moduleName = signal(undefined, /* @ts-ignore */
|
|
12410
12408
|
...(ngDevMode ? [{ debugName: "moduleName" }] : /* istanbul ignore next */ []));
|
|
12411
12409
|
this.entityName = signal(undefined, /* @ts-ignore */
|
|
12412
12410
|
...(ngDevMode ? [{ debugName: "entityName" }] : /* istanbul ignore next */ []));
|
|
12413
12411
|
this.hasCooldown = signal(false, /* @ts-ignore */
|
|
12414
12412
|
...(ngDevMode ? [{ debugName: "hasCooldown" }] : /* istanbul ignore next */ []));
|
|
12415
|
-
this.
|
|
12416
|
-
...(ngDevMode ? [{ debugName: "
|
|
12413
|
+
this.draft = signal('', /* @ts-ignore */
|
|
12414
|
+
...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
12417
12415
|
this.isSubmitting = signal(false, /* @ts-ignore */
|
|
12418
12416
|
...(ngDevMode ? [{ debugName: "isSubmitting" }] : /* istanbul ignore next */ []));
|
|
12419
|
-
this.isReplyingMode = signal(false, /* @ts-ignore */
|
|
12420
|
-
...(ngDevMode ? [{ debugName: "isReplyingMode" }] : /* istanbul ignore next */ []));
|
|
12421
|
-
this.isEditingMode = signal(false, /* @ts-ignore */
|
|
12422
|
-
...(ngDevMode ? [{ debugName: "isEditingMode" }] : /* istanbul ignore next */ []));
|
|
12423
12417
|
this.isLoading = signal(true, /* @ts-ignore */
|
|
12424
12418
|
...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
12425
|
-
this.
|
|
12426
|
-
...(ngDevMode ? [{ debugName: "
|
|
12427
|
-
this.
|
|
12428
|
-
...(ngDevMode ? [{ debugName: "
|
|
12429
|
-
this.highlightedCommentId = signal(null, /* @ts-ignore */
|
|
12430
|
-
...(ngDevMode ? [{ debugName: "highlightedCommentId" }] : /* istanbul ignore next */ []));
|
|
12419
|
+
this.replyingTo = signal(null, /* @ts-ignore */
|
|
12420
|
+
...(ngDevMode ? [{ debugName: "replyingTo" }] : /* istanbul ignore next */ []));
|
|
12421
|
+
this.editing = signal(null, /* @ts-ignore */
|
|
12422
|
+
...(ngDevMode ? [{ debugName: "editing" }] : /* istanbul ignore next */ []));
|
|
12431
12423
|
this.expandedCommentIds = signal(new Set(), /* @ts-ignore */
|
|
12432
12424
|
...(ngDevMode ? [{ debugName: "expandedCommentIds" }] : /* istanbul ignore next */ []));
|
|
12433
12425
|
this.comments = signal([], /* @ts-ignore */
|
|
12434
12426
|
...(ngDevMode ? [{ debugName: "comments" }] : /* istanbul ignore next */ []));
|
|
12427
|
+
this.commentItems = signal([], /* @ts-ignore */
|
|
12428
|
+
...(ngDevMode ? [{ debugName: "commentItems" }] : /* istanbul ignore next */ []));
|
|
12435
12429
|
this.thread = signal(undefined, /* @ts-ignore */
|
|
12436
12430
|
...(ngDevMode ? [{ debugName: "thread" }] : /* istanbul ignore next */ []));
|
|
12437
|
-
this.
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
...(ngDevMode ? [{ debugName: "editorOptions" }] : /* istanbul ignore next */ []));
|
|
12431
|
+
this.commentActions = signal([], /* @ts-ignore */
|
|
12432
|
+
...(ngDevMode ? [{ debugName: "commentActions" }] : /* istanbul ignore next */ []));
|
|
12433
|
+
this.refreshGeneration = 0;
|
|
12441
12434
|
//#endregion
|
|
12442
|
-
//#region
|
|
12443
|
-
this.
|
|
12444
|
-
...(ngDevMode ?
|
|
12435
|
+
//#region ----- View Children -----
|
|
12436
|
+
this.commentsView = viewChild('commentsView', { ...(ngDevMode ? { debugName: "commentsView" } : /* istanbul ignore next */ {}), read: AXCommentViewComponent });
|
|
12437
|
+
this.commentContainer = viewChild('commentContainer', { ...(ngDevMode ? { debugName: "commentContainer" } : /* istanbul ignore next */ {}), read: AXCommentContainerComponent });
|
|
12438
|
+
this.editor = viewChild('commentEditor', { ...(ngDevMode ? { debugName: "editor" } : /* istanbul ignore next */ {}), read: AXTextEditorComponent });
|
|
12445
12439
|
//#endregion
|
|
12446
|
-
//#region
|
|
12440
|
+
//#region ----- Services & Dependencies -----
|
|
12447
12441
|
this.commentService = inject(AXMCommentManagementService);
|
|
12448
12442
|
this.realtimeService = inject(AXMCommentRealtimeService);
|
|
12449
12443
|
this.sessionService = inject(AXPSessionService);
|
|
@@ -12452,39 +12446,43 @@ class AXMCommentComponent {
|
|
|
12452
12446
|
this.inAppNotificationService = inject(AXP_IN_APP_NOTIFICATION_SERVICE, {
|
|
12453
12447
|
optional: true,
|
|
12454
12448
|
});
|
|
12455
|
-
this.router = inject(Router);
|
|
12456
12449
|
this.activatedRoute = inject(ActivatedRoute);
|
|
12457
|
-
this.sanitizer = inject(DomSanitizer);
|
|
12458
12450
|
this.translationService = inject(AXTranslationService);
|
|
12459
12451
|
this.destroyRef = inject(DestroyRef);
|
|
12460
|
-
this.
|
|
12452
|
+
this.userAvatarService = inject(AXPUserAvatarService);
|
|
12453
|
+
this.fileStorage = inject(AXPFileStorageService);
|
|
12454
|
+
this.formatService = inject(AXFormatService);
|
|
12455
|
+
this.profileCache = new Map();
|
|
12461
12456
|
}
|
|
12462
12457
|
//#endregion
|
|
12463
|
-
//#region
|
|
12458
|
+
//#region ----- Lifecycle -----
|
|
12464
12459
|
ngOnInit() {
|
|
12465
12460
|
this.moduleName.set(this.activatedRoute.snapshot.params['module'] || null);
|
|
12466
12461
|
this.entityName.set(this.activatedRoute.snapshot.params['entity'] || null);
|
|
12467
|
-
this.
|
|
12468
|
-
setTimeout(() => this.isLoading.set(false), 250);
|
|
12469
|
-
});
|
|
12462
|
+
void this.initialize();
|
|
12470
12463
|
this.realtimeService.comment$
|
|
12471
12464
|
.pipe(takeUntilDestroyed(this.destroyRef), filter((event) => !!event))
|
|
12472
12465
|
.subscribe((event) => {
|
|
12473
12466
|
switch (event.type) {
|
|
12474
12467
|
case 'add':
|
|
12475
|
-
this.handleAddComment(event.payload);
|
|
12468
|
+
void this.handleAddComment(event.payload);
|
|
12476
12469
|
break;
|
|
12477
12470
|
case 'update':
|
|
12478
|
-
this.handleUpdateComment(event.payload);
|
|
12471
|
+
void this.handleUpdateComment(event.payload);
|
|
12479
12472
|
break;
|
|
12480
12473
|
case 'remove':
|
|
12481
|
-
this.removeMessageById(event.payload);
|
|
12474
|
+
void this.removeMessageById(event.payload);
|
|
12482
12475
|
break;
|
|
12483
12476
|
}
|
|
12484
12477
|
});
|
|
12485
12478
|
}
|
|
12486
12479
|
//#endregion
|
|
12487
|
-
//#region
|
|
12480
|
+
//#region ----- Data Loading -----
|
|
12481
|
+
async initialize() {
|
|
12482
|
+
await this.loadActionItems();
|
|
12483
|
+
await this.loadComments();
|
|
12484
|
+
this.isLoading.set(false);
|
|
12485
|
+
}
|
|
12488
12486
|
async loadComments() {
|
|
12489
12487
|
try {
|
|
12490
12488
|
const entityRef = {
|
|
@@ -12503,44 +12501,138 @@ class AXMCommentComponent {
|
|
|
12503
12501
|
this.thread.set(newThread);
|
|
12504
12502
|
this.comments.set(newThread.comments || []);
|
|
12505
12503
|
}
|
|
12504
|
+
await this.refreshItems();
|
|
12506
12505
|
}
|
|
12507
12506
|
catch (error) {
|
|
12508
12507
|
console.error('Failed to load comments:', error);
|
|
12509
12508
|
this.showTranslatedToast('messages.error.load-comments', 'danger');
|
|
12510
12509
|
this.comments.set([]);
|
|
12510
|
+
this.commentItems.set([]);
|
|
12511
12511
|
}
|
|
12512
12512
|
}
|
|
12513
12513
|
//#endregion
|
|
12514
|
-
//#region
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
this.
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
12526
|
-
}
|
|
12527
|
-
/** Opens reply mode, optionally mentioning a specific reply author. */
|
|
12528
|
-
replyMessage(comment, reply, userName) {
|
|
12529
|
-
this.isEditingMode.set(false);
|
|
12530
|
-
this.activeEditComment.set(undefined);
|
|
12531
|
-
this.isReplyingMode.set(true);
|
|
12532
|
-
this.activeReplyComment.set({ ...comment, userName: userName || '' });
|
|
12533
|
-
if (reply) {
|
|
12534
|
-
const mention = `<strong><a data-id="${reply.senderId}">@${userName || reply.senderId}</a></strong> `;
|
|
12535
|
-
this.commentContent.set(mention);
|
|
12536
|
-
this.setEditorContent(mention);
|
|
12537
|
-
this.editorRef()?.focus();
|
|
12538
|
-
}
|
|
12539
|
-
this.editorRef()
|
|
12540
|
-
.getHostElement()
|
|
12541
|
-
.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
12514
|
+
//#region ----- Event Handlers -----
|
|
12515
|
+
onReply(event) {
|
|
12516
|
+
const wasEditing = this.editing();
|
|
12517
|
+
this.editing.set(null);
|
|
12518
|
+
this.replyingTo.set(event.item);
|
|
12519
|
+
if (wasEditing) {
|
|
12520
|
+
this.draft.set('');
|
|
12521
|
+
this.editor()?.setContent('', true);
|
|
12522
|
+
return;
|
|
12523
|
+
}
|
|
12524
|
+
setTimeout(() => this.editor()?.focus());
|
|
12542
12525
|
}
|
|
12543
|
-
|
|
12526
|
+
cancelReply() {
|
|
12527
|
+
this.replyingTo.set(null);
|
|
12528
|
+
}
|
|
12529
|
+
cancelEdit() {
|
|
12530
|
+
this.editing.set(null);
|
|
12531
|
+
this.draft.set('');
|
|
12532
|
+
this.editor()?.setContent('', false);
|
|
12533
|
+
}
|
|
12534
|
+
onLikeChange(event) {
|
|
12535
|
+
void this.persistLikeChange(event);
|
|
12536
|
+
}
|
|
12537
|
+
onRepliesToggle(event) {
|
|
12538
|
+
this.onRepliesExpandedChange(String(event.item.id), event.expanded);
|
|
12539
|
+
}
|
|
12540
|
+
onAction(event) {
|
|
12541
|
+
if (event.action.name === 'edit') {
|
|
12542
|
+
this.edit(event.item);
|
|
12543
|
+
}
|
|
12544
|
+
if (event.action.name === 'delete') {
|
|
12545
|
+
void this.remove(event.item);
|
|
12546
|
+
}
|
|
12547
|
+
}
|
|
12548
|
+
commentSenderId(item) {
|
|
12549
|
+
const data = item.data;
|
|
12550
|
+
return data?.senderId ?? '';
|
|
12551
|
+
}
|
|
12552
|
+
onOverflowAction(item, name) {
|
|
12553
|
+
if (name === 'edit') {
|
|
12554
|
+
this.edit(item);
|
|
12555
|
+
}
|
|
12556
|
+
if (name === 'delete') {
|
|
12557
|
+
void this.remove(item);
|
|
12558
|
+
}
|
|
12559
|
+
}
|
|
12560
|
+
scrollToCommentContext(item) {
|
|
12561
|
+
this.commentContainer()?.scrollToReply(String(item.id));
|
|
12562
|
+
}
|
|
12563
|
+
commentContextPreview(content) {
|
|
12564
|
+
return stripHtmlToPlainText(content ?? '');
|
|
12565
|
+
}
|
|
12566
|
+
async submitComment() {
|
|
12567
|
+
this.isSubmitting.set(true);
|
|
12568
|
+
try {
|
|
12569
|
+
const currentThread = this.thread();
|
|
12570
|
+
if (!currentThread) {
|
|
12571
|
+
return;
|
|
12572
|
+
}
|
|
12573
|
+
const content = this.readEditorHtml();
|
|
12574
|
+
if (stripHtmlToPlainText(content).length === 0) {
|
|
12575
|
+
return;
|
|
12576
|
+
}
|
|
12577
|
+
if (this.editing()?.id) {
|
|
12578
|
+
const commentId = String(this.editing().id);
|
|
12579
|
+
const updated = await this.commentService.editComment(commentId, content);
|
|
12580
|
+
await this.handleUpdateComment(updated);
|
|
12581
|
+
this.hasCooldown.set(true);
|
|
12582
|
+
this.editing.set(null);
|
|
12583
|
+
}
|
|
12584
|
+
else {
|
|
12585
|
+
const parent = this.replyingTo();
|
|
12586
|
+
const parentCommentId = parent ? String(parent.id) : undefined;
|
|
12587
|
+
if (parent && this.commentsView() && !this.commentsView()?.findItem(parentCommentId)) {
|
|
12588
|
+
return;
|
|
12589
|
+
}
|
|
12590
|
+
const newComment = await this.commentService.addComment(currentThread.id, content, parentCommentId);
|
|
12591
|
+
this.hasCooldown.set(true);
|
|
12592
|
+
if (parentCommentId) {
|
|
12593
|
+
this.expandReplies(parentCommentId);
|
|
12594
|
+
this.replyingTo.set(null);
|
|
12595
|
+
}
|
|
12596
|
+
if (newComment?.id) {
|
|
12597
|
+
await this.refreshItems();
|
|
12598
|
+
setTimeout(() => this.commentContainer()?.scrollToReply(String(newComment.id)));
|
|
12599
|
+
}
|
|
12600
|
+
}
|
|
12601
|
+
this.draft.set('');
|
|
12602
|
+
this.editor()?.setContent('', false);
|
|
12603
|
+
setTimeout(() => this.hasCooldown.set(false), SUBMIT_COOLDOWN_MS);
|
|
12604
|
+
}
|
|
12605
|
+
catch (error) {
|
|
12606
|
+
console.error('Error submitting comment:', error);
|
|
12607
|
+
if (typeof error === 'string') {
|
|
12608
|
+
this.showToast(error, 'danger');
|
|
12609
|
+
}
|
|
12610
|
+
else {
|
|
12611
|
+
this.showTranslatedToast('messages.error.submit-comment', 'danger');
|
|
12612
|
+
}
|
|
12613
|
+
}
|
|
12614
|
+
finally {
|
|
12615
|
+
this.isSubmitting.set(false);
|
|
12616
|
+
}
|
|
12617
|
+
}
|
|
12618
|
+
isCommentDraftEmpty() {
|
|
12619
|
+
const service = this.editor()?.getEditorService();
|
|
12620
|
+
if (service) {
|
|
12621
|
+
return service.isEmpty() || service.getText().trim().length === 0;
|
|
12622
|
+
}
|
|
12623
|
+
return stripHtmlToPlainText(this.draft()).length === 0;
|
|
12624
|
+
}
|
|
12625
|
+
//#endregion
|
|
12626
|
+
//#region ----- Edit & Delete -----
|
|
12627
|
+
edit(item) {
|
|
12628
|
+
this.replyingTo.set(null);
|
|
12629
|
+
this.editing.set(item);
|
|
12630
|
+
const html = item.content ?? '';
|
|
12631
|
+
this.draft.set(html);
|
|
12632
|
+
this.editor()?.setContent(html, true);
|
|
12633
|
+
}
|
|
12634
|
+
async remove(item) {
|
|
12635
|
+
const commentId = String(item.id);
|
|
12544
12636
|
const [dialogTitle, dialogMessage, deleteText, deletingText, cancelText] = await Promise.all([
|
|
12545
12637
|
this.t('confirmations.delete-comment.title'),
|
|
12546
12638
|
this.t('confirmations.delete-comment.message'),
|
|
@@ -12548,6 +12640,13 @@ class AXMCommentComponent {
|
|
|
12548
12640
|
this.t('confirmations.delete-comment.deleting'),
|
|
12549
12641
|
this.t('actions.cancel.title'),
|
|
12550
12642
|
]);
|
|
12643
|
+
const cancelButton = {
|
|
12644
|
+
text: cancelText,
|
|
12645
|
+
color: 'default',
|
|
12646
|
+
autofocus: true,
|
|
12647
|
+
disabled: false,
|
|
12648
|
+
onClick: () => dialog.close(),
|
|
12649
|
+
};
|
|
12551
12650
|
const dialog = this.dialogService.open({
|
|
12552
12651
|
icon: 'fa-regular fa-warning',
|
|
12553
12652
|
content: dialogMessage,
|
|
@@ -12559,21 +12658,30 @@ class AXMCommentComponent {
|
|
|
12559
12658
|
text: deleteText,
|
|
12560
12659
|
color: 'danger',
|
|
12561
12660
|
onClick: async (e) => {
|
|
12661
|
+
if (!e) {
|
|
12662
|
+
return;
|
|
12663
|
+
}
|
|
12562
12664
|
e.handled = true;
|
|
12563
12665
|
e.source.text = deletingText;
|
|
12564
12666
|
e.source.disabled = true;
|
|
12565
12667
|
e.source.loading = true;
|
|
12668
|
+
cancelButton.disabled = true;
|
|
12566
12669
|
try {
|
|
12567
12670
|
await this.commentService.deleteComment(commentId);
|
|
12568
|
-
this.removeMessageById(commentId);
|
|
12569
12671
|
this.showTranslatedToast('messages.success.comment-deleted', 'success');
|
|
12570
|
-
if (this.
|
|
12571
|
-
this.
|
|
12572
|
-
|
|
12672
|
+
if (this.editing()?.id === commentId) {
|
|
12673
|
+
this.cancelEdit();
|
|
12674
|
+
}
|
|
12675
|
+
if (this.replyingTo()?.id === commentId) {
|
|
12676
|
+
this.cancelReply();
|
|
12573
12677
|
}
|
|
12574
12678
|
dialog.close();
|
|
12575
12679
|
}
|
|
12576
12680
|
catch (error) {
|
|
12681
|
+
cancelButton.disabled = false;
|
|
12682
|
+
e.source.text = deleteText;
|
|
12683
|
+
e.source.disabled = false;
|
|
12684
|
+
e.source.loading = false;
|
|
12577
12685
|
if (typeof error === 'string') {
|
|
12578
12686
|
this.showToast(error, 'danger');
|
|
12579
12687
|
}
|
|
@@ -12583,98 +12691,43 @@ class AXMCommentComponent {
|
|
|
12583
12691
|
}
|
|
12584
12692
|
},
|
|
12585
12693
|
},
|
|
12586
|
-
|
|
12587
|
-
text: cancelText,
|
|
12588
|
-
color: 'default',
|
|
12589
|
-
autofocus: true,
|
|
12590
|
-
onClick: () => dialog.close(),
|
|
12591
|
-
},
|
|
12694
|
+
cancelButton,
|
|
12592
12695
|
],
|
|
12593
12696
|
closeButton: false,
|
|
12594
12697
|
});
|
|
12595
12698
|
}
|
|
12596
|
-
resetReplyEditState() {
|
|
12597
|
-
this.isEditingMode.set(false);
|
|
12598
|
-
this.activeEditComment.set(undefined);
|
|
12599
|
-
this.isReplyingMode.set(false);
|
|
12600
|
-
this.activeReplyComment.set(undefined);
|
|
12601
|
-
this.commentContent.set('');
|
|
12602
|
-
this.clearEditorContent();
|
|
12603
|
-
}
|
|
12604
|
-
async submitComment() {
|
|
12605
|
-
this.isSubmitting.set(true);
|
|
12606
|
-
try {
|
|
12607
|
-
const currentThread = this.thread();
|
|
12608
|
-
if (!currentThread)
|
|
12609
|
-
return;
|
|
12610
|
-
if (this.isEditingMode() && this.activeEditComment()?.id) {
|
|
12611
|
-
await this.commentService.editComment(this.activeEditComment().id, this.commentContent());
|
|
12612
|
-
this.hasCooldown.set(true);
|
|
12613
|
-
this.isEditingMode.set(false);
|
|
12614
|
-
this.activeEditComment.set(undefined);
|
|
12615
|
-
}
|
|
12616
|
-
else {
|
|
12617
|
-
const parentCommentId = this.activeReplyComment()?.id;
|
|
12618
|
-
const newComment = await this.commentService.addComment(currentThread.id, this.commentContent(), parentCommentId);
|
|
12619
|
-
this.hasCooldown.set(true);
|
|
12620
|
-
if (parentCommentId) {
|
|
12621
|
-
this.expandReplies(parentCommentId);
|
|
12622
|
-
}
|
|
12623
|
-
this.isReplyingMode.set(false);
|
|
12624
|
-
this.activeReplyComment.set(undefined);
|
|
12625
|
-
if (newComment?.id) {
|
|
12626
|
-
this.scrollToAndHighlight(newComment.id);
|
|
12627
|
-
}
|
|
12628
|
-
}
|
|
12629
|
-
this.commentContent.set('');
|
|
12630
|
-
this.clearEditorContent();
|
|
12631
|
-
setTimeout(() => this.hasCooldown.set(false), SUBMIT_COOLDOWN_MS);
|
|
12632
|
-
}
|
|
12633
|
-
catch (error) {
|
|
12634
|
-
console.error('Error submitting comment:', error);
|
|
12635
|
-
if (typeof error === 'string') {
|
|
12636
|
-
this.showToast(error, 'danger');
|
|
12637
|
-
}
|
|
12638
|
-
else {
|
|
12639
|
-
this.showTranslatedToast('messages.error.submit-comment', 'danger');
|
|
12640
|
-
}
|
|
12641
|
-
}
|
|
12642
|
-
finally {
|
|
12643
|
-
this.isSubmitting.set(false);
|
|
12644
|
-
}
|
|
12645
|
-
}
|
|
12646
12699
|
//#endregion
|
|
12647
|
-
//#region
|
|
12648
|
-
async
|
|
12649
|
-
const
|
|
12650
|
-
this.updateLikeStatus(comment.id, !isLiked);
|
|
12700
|
+
//#region ----- Reactions -----
|
|
12701
|
+
async persistLikeChange(event) {
|
|
12702
|
+
const commentId = String(event.item.id);
|
|
12651
12703
|
try {
|
|
12652
|
-
if (
|
|
12653
|
-
await this.commentService.
|
|
12704
|
+
if (event.liked) {
|
|
12705
|
+
await this.commentService.likeComment(commentId);
|
|
12654
12706
|
}
|
|
12655
12707
|
else {
|
|
12656
|
-
await this.commentService.
|
|
12708
|
+
await this.commentService.unlikeComment(commentId);
|
|
12657
12709
|
}
|
|
12658
12710
|
}
|
|
12659
12711
|
catch (error) {
|
|
12660
12712
|
console.error('Failed to toggle like:', error);
|
|
12661
|
-
this.
|
|
12713
|
+
this.commentsView()?.updateItem(commentId, {
|
|
12714
|
+
liked: !event.liked,
|
|
12715
|
+
likes: event.liked ? Math.max(0, (event.likes ?? 1) - 1) : (event.likes ?? 0) + 1,
|
|
12716
|
+
});
|
|
12662
12717
|
}
|
|
12663
12718
|
}
|
|
12664
12719
|
isLikedByUser(comment) {
|
|
12665
12720
|
const user = this.getCurrentUser();
|
|
12666
|
-
if (!user)
|
|
12721
|
+
if (!user) {
|
|
12667
12722
|
return false;
|
|
12723
|
+
}
|
|
12668
12724
|
return (comment.reactions || []).some((r) => r.userId === user.id && r.emoji === AXM_COMMENT_LIKE_EMOJI);
|
|
12669
12725
|
}
|
|
12670
12726
|
getReactionsCount(comment) {
|
|
12671
12727
|
return (comment.reactions || []).filter((r) => r.emoji === AXM_COMMENT_LIKE_EMOJI).length;
|
|
12672
12728
|
}
|
|
12673
12729
|
//#endregion
|
|
12674
|
-
//#region
|
|
12675
|
-
isRepliesExpanded(commentId) {
|
|
12676
|
-
return this.expandedCommentIds().has(commentId);
|
|
12677
|
-
}
|
|
12730
|
+
//#region ----- Replies Expansion -----
|
|
12678
12731
|
onRepliesExpandedChange(commentId, expanded) {
|
|
12679
12732
|
this.expandedCommentIds.update((ids) => {
|
|
12680
12733
|
const next = new Set(ids);
|
|
@@ -12695,66 +12748,22 @@ class AXMCommentComponent {
|
|
|
12695
12748
|
});
|
|
12696
12749
|
}
|
|
12697
12750
|
//#endregion
|
|
12698
|
-
//#region
|
|
12699
|
-
|
|
12700
|
-
* Scrolls to the referenced comment and triggers a highlight pulse animation.
|
|
12701
|
-
* Expands parent replies if needed to ensure the target is in the DOM.
|
|
12702
|
-
*/
|
|
12703
|
-
scrollMain() {
|
|
12704
|
-
const comment = this.isReplyingMode()
|
|
12705
|
-
? this.activeReplyComment()
|
|
12706
|
-
: this.activeEditComment();
|
|
12707
|
-
if (!comment?.id)
|
|
12708
|
-
return;
|
|
12709
|
-
if (comment.replyTo?.id) {
|
|
12710
|
-
this.expandReplies(comment.replyTo.id);
|
|
12711
|
-
}
|
|
12712
|
-
this.scrollToAndHighlight(comment.id);
|
|
12713
|
-
}
|
|
12714
|
-
/**
|
|
12715
|
-
* Scrolls to a comment element and applies a highlight pulse animation.
|
|
12716
|
-
* Uses setTimeout to wait for Angular to render after signal updates.
|
|
12717
|
-
*/
|
|
12718
|
-
scrollToAndHighlight(commentId) {
|
|
12719
|
-
this.highlightedCommentId.set(null);
|
|
12720
|
-
setTimeout(() => {
|
|
12721
|
-
const el = this.elementRef.nativeElement.querySelector(`ax-comment-item[id="${commentId}"]`);
|
|
12722
|
-
if (!el)
|
|
12723
|
-
return;
|
|
12724
|
-
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
12725
|
-
this.highlightedCommentId.set(commentId);
|
|
12726
|
-
setTimeout(() => this.highlightedCommentId.set(null), HIGHLIGHT_DURATION_MS);
|
|
12727
|
-
});
|
|
12728
|
-
}
|
|
12729
|
-
//#endregion
|
|
12730
|
-
//#region ---- HTML Sanitization ----
|
|
12731
|
-
sanitizeHtml(htmlContent) {
|
|
12732
|
-
if (!htmlContent)
|
|
12733
|
-
return this.sanitizer.bypassSecurityTrustHtml('');
|
|
12734
|
-
return this.sanitizer.bypassSecurityTrustHtml(htmlContent);
|
|
12735
|
-
}
|
|
12736
|
-
//#endregion
|
|
12737
|
-
//#region ---- Realtime Event Handlers ----
|
|
12738
|
-
handleAddComment(comment) {
|
|
12751
|
+
//#region ----- Realtime Event Handlers -----
|
|
12752
|
+
async handleAddComment(comment) {
|
|
12739
12753
|
if (comment.senderId !== this.getCurrentUser()?.id && this.thread()) {
|
|
12740
12754
|
void this.inAppNotificationService?.create(buildCommentInAppNotificationRequest(this.thread(), comment, this.sessionService.user));
|
|
12741
12755
|
}
|
|
12742
12756
|
const parentId = comment.replyTo?.id;
|
|
12743
12757
|
if (parentId) {
|
|
12744
12758
|
this.expandReplies(parentId);
|
|
12745
|
-
this.comments.update((comments) => comments
|
|
12746
|
-
if (c.id === parentId) {
|
|
12747
|
-
const newReplies = c.replies ? [...c.replies, comment] : [comment];
|
|
12748
|
-
return { ...c, replies: newReplies, replyCount: newReplies.length };
|
|
12749
|
-
}
|
|
12750
|
-
return c;
|
|
12751
|
-
}));
|
|
12759
|
+
this.comments.update((comments) => insertReply(comments, parentId, comment));
|
|
12752
12760
|
}
|
|
12753
12761
|
else {
|
|
12754
12762
|
this.comments.update((comments) => [...comments, comment]);
|
|
12755
12763
|
}
|
|
12764
|
+
await this.refreshItems();
|
|
12756
12765
|
}
|
|
12757
|
-
handleUpdateComment(updatedComment) {
|
|
12766
|
+
async handleUpdateComment(updatedComment) {
|
|
12758
12767
|
const update = (list) => list.map((c) => {
|
|
12759
12768
|
if (c.id === updatedComment.id) {
|
|
12760
12769
|
return {
|
|
@@ -12771,39 +12780,15 @@ class AXMCommentComponent {
|
|
|
12771
12780
|
return c;
|
|
12772
12781
|
});
|
|
12773
12782
|
this.comments.update((comments) => update(comments));
|
|
12783
|
+
await this.refreshItems();
|
|
12774
12784
|
}
|
|
12775
12785
|
//#endregion
|
|
12776
|
-
//#region
|
|
12786
|
+
//#region ----- Private Helpers -----
|
|
12777
12787
|
getCurrentUser() {
|
|
12778
12788
|
const user = this.sessionService.user;
|
|
12779
12789
|
return user ? { id: user.id, type: 'user' } : null;
|
|
12780
12790
|
}
|
|
12781
|
-
|
|
12782
|
-
const findAndToggle = (comments) => comments.map((c) => {
|
|
12783
|
-
if (c.id === commentId) {
|
|
12784
|
-
const user = this.getCurrentUser();
|
|
12785
|
-
if (!user)
|
|
12786
|
-
return c;
|
|
12787
|
-
const reactions = willBeLiked
|
|
12788
|
-
? [
|
|
12789
|
-
...(c.reactions || []),
|
|
12790
|
-
{
|
|
12791
|
-
emoji: AXM_COMMENT_LIKE_EMOJI,
|
|
12792
|
-
userId: user.id,
|
|
12793
|
-
timestamp: new Date(),
|
|
12794
|
-
},
|
|
12795
|
-
]
|
|
12796
|
-
: (c.reactions || []).filter((r) => r.userId !== user.id || r.emoji !== AXM_COMMENT_LIKE_EMOJI);
|
|
12797
|
-
return { ...c, reactions };
|
|
12798
|
-
}
|
|
12799
|
-
if (c.replies?.length) {
|
|
12800
|
-
return { ...c, replies: findAndToggle(c.replies) };
|
|
12801
|
-
}
|
|
12802
|
-
return c;
|
|
12803
|
-
});
|
|
12804
|
-
this.comments.update((comments) => findAndToggle(comments));
|
|
12805
|
-
}
|
|
12806
|
-
removeMessageById(commentId) {
|
|
12791
|
+
async removeMessageById(commentId) {
|
|
12807
12792
|
const filterOut = (comments) => comments
|
|
12808
12793
|
.filter((c) => c.id !== commentId)
|
|
12809
12794
|
.map((c) => {
|
|
@@ -12813,14 +12798,107 @@ class AXMCommentComponent {
|
|
|
12813
12798
|
return c;
|
|
12814
12799
|
});
|
|
12815
12800
|
this.comments.update((comments) => filterOut(comments));
|
|
12801
|
+
await this.refreshItems();
|
|
12802
|
+
}
|
|
12803
|
+
readEditorHtml() {
|
|
12804
|
+
const service = this.editor()?.getEditorService();
|
|
12805
|
+
if (service && !service.isEmpty()) {
|
|
12806
|
+
return service.getHTML();
|
|
12807
|
+
}
|
|
12808
|
+
return this.draft();
|
|
12809
|
+
}
|
|
12810
|
+
async loadActionItems() {
|
|
12811
|
+
const [editText, deleteText] = await Promise.all([this.t('actions.edit.title'), this.t('actions.delete.title')]);
|
|
12812
|
+
this.commentActions.set([
|
|
12813
|
+
{ name: 'edit', text: editText, icon: 'fa-light fa-pen', break: true },
|
|
12814
|
+
{ name: 'delete', text: deleteText, icon: 'fa-light fa-trash-can', color: 'danger' },
|
|
12815
|
+
]);
|
|
12816
|
+
}
|
|
12817
|
+
async refreshItems() {
|
|
12818
|
+
const generation = ++this.refreshGeneration;
|
|
12819
|
+
const items = await Promise.all(this.comments().map((comment) => this.mapComment(comment)));
|
|
12820
|
+
if (generation !== this.refreshGeneration) {
|
|
12821
|
+
return;
|
|
12822
|
+
}
|
|
12823
|
+
this.commentItems.set(items);
|
|
12824
|
+
}
|
|
12825
|
+
async mapComment(comment) {
|
|
12826
|
+
const profile = await this.resolveProfile(comment.senderId);
|
|
12827
|
+
const currentUserId = this.getCurrentUser()?.id;
|
|
12828
|
+
const replies = comment.replies?.length ? await Promise.all(comment.replies.map((reply) => this.mapComment(reply))) : undefined;
|
|
12829
|
+
const isYou = !!currentUserId && comment.senderId === currentUserId;
|
|
12830
|
+
const editedAt = comment.editedAt;
|
|
12831
|
+
return {
|
|
12832
|
+
id: comment.id,
|
|
12833
|
+
author: profile.author,
|
|
12834
|
+
avatar: profile.avatar,
|
|
12835
|
+
initials: profile.initials,
|
|
12836
|
+
color: profile.color,
|
|
12837
|
+
date: this.formatCommentDate(comment.timestamp),
|
|
12838
|
+
edited: !!editedAt,
|
|
12839
|
+
editedAt: editedAt ? this.formatCommentDate(editedAt) : undefined,
|
|
12840
|
+
content: axmExtractTextFromPayload(comment.payload),
|
|
12841
|
+
likes: this.getReactionsCount(comment),
|
|
12842
|
+
liked: this.isLikedByUser(comment),
|
|
12843
|
+
isYou,
|
|
12844
|
+
repliesExpanded: this.expandedCommentIds().has(comment.id),
|
|
12845
|
+
replies,
|
|
12846
|
+
replyCount: comment.replyCount ?? replies?.length ?? 0,
|
|
12847
|
+
actions: isYou ? this.commentActions() : undefined,
|
|
12848
|
+
data: comment,
|
|
12849
|
+
};
|
|
12850
|
+
}
|
|
12851
|
+
async resolveProfile(userId) {
|
|
12852
|
+
const cached = this.profileCache.get(userId);
|
|
12853
|
+
if (cached) {
|
|
12854
|
+
return cached;
|
|
12855
|
+
}
|
|
12856
|
+
try {
|
|
12857
|
+
const info = await this.userAvatarService.getUserInfo(userId);
|
|
12858
|
+
const author = resolveDisplayName(info) || userId;
|
|
12859
|
+
const avatar = this.resolveAvatarUrl(info.avatarUrl, userId) || undefined;
|
|
12860
|
+
const profile = {
|
|
12861
|
+
author,
|
|
12862
|
+
initials: toInitials(author),
|
|
12863
|
+
avatar,
|
|
12864
|
+
color: colorForUser(userId),
|
|
12865
|
+
};
|
|
12866
|
+
this.profileCache.set(userId, profile);
|
|
12867
|
+
return profile;
|
|
12868
|
+
}
|
|
12869
|
+
catch {
|
|
12870
|
+
return {
|
|
12871
|
+
author: userId,
|
|
12872
|
+
initials: toInitials(userId),
|
|
12873
|
+
color: colorForUser(userId),
|
|
12874
|
+
};
|
|
12875
|
+
}
|
|
12816
12876
|
}
|
|
12817
|
-
|
|
12818
|
-
this.
|
|
12877
|
+
resolveAvatarUrl(avatarUrl, userId) {
|
|
12878
|
+
const sessionUser = this.sessionService.user;
|
|
12879
|
+
const isSessionUser = sessionUser?.id === userId;
|
|
12880
|
+
let ref = isSessionUser ? normalizeStoredImageRef(sessionUser.avatar) : null;
|
|
12881
|
+
if (!ref) {
|
|
12882
|
+
ref = normalizeStoredImageRef(avatarUrl);
|
|
12883
|
+
}
|
|
12884
|
+
if (!ref) {
|
|
12885
|
+
return '';
|
|
12886
|
+
}
|
|
12887
|
+
if (!isStoredImageFileId(ref)) {
|
|
12888
|
+
return ref;
|
|
12889
|
+
}
|
|
12890
|
+
return this.userAvatarService.resolveAvatarDisplayUrl(ref, (fileId) => this.fileStorage.getDownloadUrl(fileId));
|
|
12819
12891
|
}
|
|
12820
|
-
|
|
12821
|
-
|
|
12892
|
+
formatCommentDate(timestamp) {
|
|
12893
|
+
if (!timestamp) {
|
|
12894
|
+
return '';
|
|
12895
|
+
}
|
|
12896
|
+
const date = timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
12897
|
+
if (Number.isNaN(date.getTime())) {
|
|
12898
|
+
return '';
|
|
12899
|
+
}
|
|
12900
|
+
return this.formatService.format(date, 'timeleft');
|
|
12822
12901
|
}
|
|
12823
|
-
/** Shorthand translator scoped to the comments feature */
|
|
12824
12902
|
t(key) {
|
|
12825
12903
|
return this.translationService.translateAsync(`@conversation:comments.${key}`);
|
|
12826
12904
|
}
|
|
@@ -12838,50 +12916,75 @@ class AXMCommentComponent {
|
|
|
12838
12916
|
const content = await this.t(key);
|
|
12839
12917
|
this.showToast(content, color);
|
|
12840
12918
|
}
|
|
12841
|
-
getCommentText(comment) {
|
|
12842
|
-
return axmExtractTextFromPayload(comment.payload);
|
|
12843
|
-
}
|
|
12844
12919
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCommentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
12845
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editorRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axm-comment size-full flex flex-col overflow-hidden\">\n <div class=\"axm-comment__list flex-1 min-h-0 overflow-y-auto\">\n <ax-comment-container>\n @if (isLoading()) {\n <div class=\"axm-comment__skeleton\">\n <ax-skeleton class=\"size-10 shrink-0 rounded-full\"></ax-skeleton>\n <div class=\"axm-comment__skeleton-body\">\n <ax-skeleton class=\"h-4 w-32 rounded\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-full rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-11/12 rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-4/5 rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (comments().length > 0) {\n <ax-comment-view class=\"axm-comment__view\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [repliesExpanded]=\"isRepliesExpanded(comment.id!)\"\n (repliesExpandedChange)=\"\n onRepliesExpandedChange(comment.id!, $event)\n \"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #user\n [size]=\"36\"\n [userId]=\"comment.senderId\"\n [axpUserCard]=\"comment.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"comment.senderId\">{{\n user.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ comment.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.title())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(comment.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(comment))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(comment)\"\n [like]=\"isLikedByUser(comment)\"\n >\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.title())\"\n ></ax-comment-reply-text>\n\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item\n [id]=\"reply.id\"\n [class.highlighted]=\"highlightedCommentId() === reply.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #replyUser\n [size]=\"36\"\n [userId]=\"reply.senderId\"\n [axpUserCard]=\"reply.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"reply.senderId\">{{\n replyUser.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ reply.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"\n editMessage(comment, reply, replyUser.title())\n \"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(reply.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(reply))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(reply)\"\n [like]=\"isLikedByUser(reply)\"\n >\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, replyUser.title())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n }\n <!-- ----- Empty state when no comments exist ----- -->\n @else {\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.title'\n \"\n [description]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.description'\n \"\n >\n </axp-state-message>\n }\n </ax-comment-container>\n </div>\n\n <div class=\"axm-comment__composer\">\n @if (isReplyingMode() || isEditingMode()) {\n <div class=\"axm-comment__context\">\n <button\n type=\"button\"\n class=\"axm-comment__context-main\"\n (click)=\"scrollMain()\"\n >\n <i\n class=\"fa-light axm-comment__context-icon\"\n [class.fa-reply]=\"isReplyingMode()\"\n [class.fa-pen]=\"isEditingMode()\"\n ></i>\n <div class=\"axm-comment__context-copy\">\n <p class=\"axm-comment__context-label\">\n @if (isReplyingMode()) {\n {{\n '@conversation:comments.actions.reply-to' | translate | async\n }}\n <span>{{ activeReplyComment()?.userName }}</span>\n } @else {\n {{\n '@conversation:comments.actions.edit-message'\n | translate\n | async\n }}\n }\n </p>\n <div\n class=\"axm-comment__context-preview\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(getCommentText(activeReplyComment()!))\n : sanitizeHtml(getCommentText(activeEditComment()!))\n \"\n ></div>\n </div>\n </button>\n <button\n type=\"button\"\n class=\"axm-comment__context-close\"\n (click)=\"resetReplyEditState()\"\n [attr.aria-label]=\"\n ('@conversation:comments.actions.cancel.title'\n | translate\n | async) ?? 'Cancel'\n \"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <div class=\"axm-comment__editor\">\n <ax-text-editor\n #editorRef\n outputFormat=\"html\"\n [look]=\"editorOptions().look\"\n [(ngModel)]=\"commentContent\"\n >\n <ax-text-editor-content class=\"min-h-24\"></ax-text-editor-content>\n <ax-text-editor-toolbar>\n <ax-prefix>\n <ax-text-editor-history></ax-text-editor-history>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-text-editor-colors></ax-text-editor-colors>\n <ax-text-editor-list></ax-text-editor-list>\n <ax-text-editor-alignment></ax-text-editor-alignment>\n </ax-prefix>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n <!-- ----- Send sits under the editor, aligned to the inline end ----- -->\n <div class=\"axm-comment__editor-actions\">\n <ax-button\n look=\"solid\"\n color=\"primary\"\n class=\"ax-sm\"\n [disabled]=\"hasCooldown() || !commentContent()\"\n (click)=\"submitComment()\"\n [text]=\"\n '@conversation:comments.actions.send.title' | translate | async\n \"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;:host{display:block;height:100%;min-height:0px;width:100%}.axm-comment{min-height:0px;height:calc(100vh - 210px);background-color:rgb(var(--ax-sys-color-lightest-surface))}.axm-comment .axm-comment__list{min-height:0px}.axm-comment .axm-comment__skeleton{display:flex;align-items:flex-start;gap:.875rem;padding:1.25rem 1.25rem 1.5rem}.axm-comment .axm-comment__skeleton-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-comment .axm-comment__composer{flex-shrink:0;background-color:rgb(var(--ax-sys-color-surface-surface))}.axm-comment .axm-comment__context{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding:.625rem .75rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));border-bottom:none;border-inline-start:3px solid rgb(var(--ax-sys-color-primary-surface));background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.35);font-size:.8125rem;line-height:1.4}.axm-comment .axm-comment__context-main{display:flex;min-width:0px;flex:1;cursor:pointer;align-items:center;gap:.625rem}.axm-comment .axm-comment__context-icon{flex-shrink:0;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-copy{display:flex;min-width:0px;flex-direction:column;gap:.125rem}.axm-comment .axm-comment__context-label{margin:0;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;color:rgb(var(--ax-sys-color-neutral-600-surface, 107 114 128))}.axm-comment .axm-comment__context-close{flex-shrink:0;cursor:pointer;border-radius:var(--radius-md, .375rem);--tw-border-style: none;border-style:none;padding:.25rem;background:transparent;color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128));font-size:1rem;line-height:1}.axm-comment .axm-comment__context-close:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.8)}.axm-comment .axm-comment__editor{overflow:hidden;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background-color:rgb(var(--ax-sys-color-lightest-surface));box-shadow:0 1px 2px #0f172a0a}.axm-comment .axm-comment__editor-actions{display:flex;justify-content:flex-end;padding:.5rem .75rem;border-top:1px solid rgb(var(--ax-sys-color-border-light-surface))}.axm-comment .axm-comment__author{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}.axm-comment .axm-comment__date{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128))}.axm-comment .axm-comment__menu-btn{opacity:0;transition:opacity .15s ease}ax-comment-item{border-radius:.75rem;transition:background-color .2s ease}ax-comment-item:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.45)}ax-comment-item:hover .axm-comment__menu-btn{opacity:1}ax-comment-item.highlighted{animation:axm-comment-highlight 2.5s cubic-bezier(.4,0,.2,1) forwards}ax-text-editor{flex-shrink:0}ax-text-editor .ax-editor-container{border:none!important;border-radius:0!important;box-shadow:none!important}ax-text-editor .ax-error-message{padding-inline-start:.75rem}@keyframes axm-comment-highlight{0%{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}10%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5);box-shadow:inset 3px 0 rgb(var(--ax-sys-color-primary-surface))}35%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.3);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lighter-surface),.8)}60%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.4);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lightest-surface),.6)}to{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXTextEditorModule }, { kind: "component", type: i1$3.AXTextEditorComponent, selector: "ax-text-editor", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "look", "placeHolder", "outputFormat", "line", "initialLine", "maxLine"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange"] }, { kind: "component", type: i1$3.AXTextEditorToolbarComponent, selector: "ax-text-editor-toolbar", inputs: ["orientation"] }, { kind: "component", type: i1$3.AXTextEditorContentComponent, selector: "ax-text-editor-content" }, { kind: "component", type: i1$3.AXTextEditorHistoryComponent, selector: "ax-text-editor-history" }, { kind: "component", type: i1$3.AXTextEditorFontStyleComponent, selector: "ax-text-editor-font-style" }, { kind: "component", type: i1$3.AXTextEditorAlignmentComponent, selector: "ax-text-editor-alignment" }, { kind: "component", type: i1$3.AXTextEditorColorsComponent, selector: "ax-text-editor-colors" }, { kind: "component", type: i1$3.AXTextEditorListComponent, selector: "ax-text-editor-list" }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXCommentModule }, { kind: "component", type: i4.AXCommentViewComponent, selector: "ax-comment-view", inputs: ["datasource", "itemTemplate"], outputs: ["datasourceChange", "onReply", "onLikeChange", "onRepliesToggle", "onAction"] }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AXCommentItemComponent, selector: "ax-comment-item", inputs: ["item", "replyCount", "repliesExpanded", "loading", "itemTemplate", "itemContext"], outputs: ["repliesExpandedChange", "likeChange", "replyClick", "actionClick"] }, { kind: "component", type: i4.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["like"], outputs: ["likeChange"] }, { kind: "component", type: i4.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { 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: "component", type: i1$1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId", "showPresence", "displayName", "displayAvatar"] }, { kind: "directive", type: AXPUserCardDirective, selector: "[axpUserCard]", inputs: ["axpUserCard", "axpUserCardDisabled", "axpUserCardTrigger"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "pipe", type: i5.AXFormatPipe, name: "format" }, { kind: "pipe", type: i1$2.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
12846
|
-
trigger('fadeIn', [
|
|
12847
|
-
transition(':enter', [
|
|
12848
|
-
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
12849
|
-
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
12850
|
-
]),
|
|
12851
|
-
]),
|
|
12852
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
12920
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "commentsView", first: true, predicate: ["commentsView"], descendants: true, read: AXCommentViewComponent, isSignal: true }, { propertyName: "commentContainer", first: true, predicate: ["commentContainer"], descendants: true, read: AXCommentContainerComponent, isSignal: true }, { propertyName: "editor", first: true, predicate: ["commentEditor"], descendants: true, read: AXTextEditorComponent, isSignal: true }], ngImport: i0, template: "<div class=\"axm-comment\">\n <ax-comment-container #commentContainer>\n <!-- ----- Loading skeleton while comments are fetched ----- -->\n @if (isLoading()) {\n <div class=\"axm-comment__list axm-comment__list--loading\">\n @for (skeleton of [0, 1, 2]; track skeleton) {\n <div class=\"axm-comment__skeleton\" [class.axm-comment__skeleton--compact]=\"skeleton > 0\">\n <ax-skeleton class=\"size-9 shrink-0 rounded-full\"></ax-skeleton>\n <div class=\"axm-comment__skeleton-body\">\n <ax-skeleton class=\"h-3.5 w-28 rounded\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-full rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-11/12 rounded-full\"></ax-skeleton>\n <!--------------------------------------------------------------->\n <!-- ----- Extra skeleton line on first row ----- -->\n @if (skeleton === 0) {\n <ax-skeleton class=\"h-3 w-2/3 rounded-full\"></ax-skeleton>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- ----- Empty state when the thread has no comments ----- -->\n @else if (comments().length === 0) {\n <div class=\"axm-comment__empty\">\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"'@conversation:comments.components.comment.empty-states.no-comments.title'\"\n [description]=\"'@conversation:comments.components.comment.empty-states.no-comments.description'\"\n ></axp-state-message>\n </div>\n }\n <!-- ----- Comment thread from the mapped datasource ----- -->\n @else {\n <div class=\"axm-comment__list\">\n <ax-comment-view #commentsView [datasource]=\"commentItems()\" (onReply)=\"onReply($event)\" (onLikeChange)=\"onLikeChange($event)\" (onRepliesToggle)=\"onRepliesToggle($event)\" (onAction)=\"onAction($event)\">\n <ng-template axCommentItem let-item>\n <div class=\"flex min-w-0 items-start gap-2\">\n <axp-user-avatar class=\"shrink-0\" [size]=\"42\" [userId]=\"commentSenderId(item)\" [axpUserCard]=\"commentSenderId(item)\"></axp-user-avatar>\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex min-w-0 items-center justify-between gap-2\">\n <div class=\"flex min-w-0 flex-wrap items-center\">\n <ax-title [axpUserCard]=\"commentSenderId(item)\">{{ item.author }}</ax-title>\n <!--------------------------------------------------------------->\n <!-- ----- You badge for the current user's comment ----- -->\n @if (item.isYou) {\n <ax-badge class=\"ax-sm ax-pill ax-comment-you-badge\" look=\"twotone\" color=\"primary\" [text]=\"('@acorex:comment.you' | translate | async) ?? 'You'\"></ax-badge>\n }\n <!--------------------------------------------------------------->\n <!-- ----- Edited label (before timestamp) ----- -->\n @if (item.edited) {\n <ax-comment-edited [editedAt]=\"item.editedAt\" />\n }\n <!--------------------------------------------------------------->\n <!-- ----- Relative timestamp for this comment ----- -->\n @if (item.date) {\n <ax-comment-date>{{ item.date }}</ax-comment-date>\n }\n </div>\n <!--------------------------------------------------------------->\n <!-- ----- Overflow menu from item actions ----- -->\n @if (item.actions?.length) {\n <ax-dropdown-button class=\"ax-sm\" mode=\"dropdown\" look=\"blank\" [iconOnly]=\"true\" [text]=\"('@conversation:comments.actions.more' | translate | async) ?? ''\">\n <ax-prefix>\n <ax-icon icon=\"ax-icon ax-icon-more-horizontal\"></ax-icon>\n </ax-prefix>\n <ax-button-item-list>\n @for (action of item.actions; track action.name ?? action.text) {\n <ax-button-item [text]=\"action.text\" [color]=\"action.color\" (onClick)=\"onOverflowAction(item, action.name ?? action.text)\">\n <!--------------------------------------------------------------->\n <!-- ----- Action icon when the menu item has one ----- -->\n @if (action.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-button>\n }\n </div>\n <ax-content>\n <div [innerHTML]=\"item.content\"></div>\n </ax-content>\n </div>\n </div>\n </ng-template>\n </ax-comment-view>\n </div>\n }\n\n <ax-footer style=\"padding: 0.1rem\">\n <!-- ----- Edit context above the composer ----- -->\n @if (editing(); as editItem) {\n <div class=\"axm-comment__context-bar\" tabindex=\"0\" (click)=\"scrollToCommentContext(editItem)\" (keydown.enter)=\"scrollToCommentContext(editItem)\" (keydown.space)=\"$event.preventDefault(); scrollToCommentContext(editItem)\">\n <div class=\"axm-comment__context-bar-body\">\n <i class=\"fa-light fa-pen axm-comment__context-bar-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-comment__context-bar-copy\">\n <span class=\"axm-comment__context-bar-label\">{{ '@conversation:comments.actions.edit-message' | translate | async }}</span>\n @if (commentContextPreview(editItem.content); as preview) {\n <span class=\"axm-comment__context-bar-preview\" [title]=\"preview\">{{ preview }}</span>\n }\n </span>\n </div>\n <button type=\"button\" class=\"axm-comment__context-bar-close\" (click)=\"$event.stopPropagation(); cancelEdit()\" [attr.aria-label]=\"('@conversation:comments.actions.cancel.title' | translate | async) ?? 'Cancel'\">\n <i class=\"fa-light fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n <!-- ----- Reply context above the composer ----- -->\n @else if (replyingTo(); as replyItem) {\n <div class=\"axm-comment__context-bar\" tabindex=\"0\" (click)=\"scrollToCommentContext(replyItem)\" (keydown.enter)=\"scrollToCommentContext(replyItem)\" (keydown.space)=\"$event.preventDefault(); scrollToCommentContext(replyItem)\">\n <div class=\"axm-comment__context-bar-body\">\n <i class=\"fa-light fa-reply axm-comment__context-bar-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-comment__context-bar-copy\">\n <span class=\"axm-comment__context-bar-label\">\n {{ '@conversation:comments.actions.reply-to' | translate | async }}\n <span class=\"axm-comment__context-bar-name\">\n @if (replyItem.isYou) {\n {{ '@acorex:comment.you' | translate | async }}\n } @else {\n {{ replyItem.author }}\n }\n </span>\n </span>\n @if (commentContextPreview(replyItem.content); as preview) {\n <span class=\"axm-comment__context-bar-preview\" [title]=\"preview\">{{ preview }}</span>\n }\n </span>\n </div>\n <button type=\"button\" class=\"axm-comment__context-bar-close\" (click)=\"$event.stopPropagation(); cancelReply()\" [attr.aria-label]=\"('@conversation:comments.actions.cancel.title' | translate | async) ?? 'Cancel'\">\n <i class=\"fa-light fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <ax-comment-reply>\n <ax-text-editor\n #commentEditor\n look=\"solid\"\n outputFormat=\"html\"\n [initialLine]=\"3\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event)\"\n [placeHolder]=\"((editing() ? '@conversation:comments.actions.edit-message' : replyingTo() ? '@conversation:comments.composer.reply-placeholder' : '@conversation:comments.composer.placeholder') | translate | async) ?? ''\"\n >\n <ax-footer>\n <div class=\"axm-comment__editor-actions\">\n <ax-button\n class=\"axm-comment__send ax-sm\"\n look=\"solid\"\n color=\"primary\"\n [disabled]=\"hasCooldown() || isCommentDraftEmpty() || isSubmitting()\"\n [text]=\"(editing() ? '@conversation:comments.actions.edit.title' : '@conversation:comments.actions.send.title') | translate | async\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n } @else {\n <!-- ----- Send icon when not submitting ----- -->\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-paper-plane-top\"></ax-icon>\n </ax-prefix>\n }\n </ax-button>\n </div>\n </ax-footer>\n <ax-text-editor-toolbar class=\"border-b\">\n <ax-text-editor-history></ax-text-editor-history>\n <ax-divider></ax-divider>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-divider></ax-divider>\n <ax-text-editor-colors></ax-text-editor-colors>\n <ax-divider></ax-divider>\n <ax-text-editor-list></ax-text-editor-list>\n <ax-divider></ax-divider>\n <ax-text-editor-alignment></ax-text-editor-alignment>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n </ax-comment-reply>\n </ax-footer>\n </ax-comment-container>\n</div>\n", styles: ["@layer properties;:host{display:block;height:100%;min-height:0px;width:100%}ax-comment-container{display:flex;flex-direction:column;justify-content:space-between;height:100%}.axm-comment{display:flex;width:100%;height:100%;min-height:0px;flex-direction:column;overflow:hidden;background-color:rgb(var(--ax-sys-color-lightest-surface))}.axm-comment .axm-comment__list{min-height:0px;flex:1;overflow-y:auto;padding:1rem 1rem 1.25rem;scroll-behavior:smooth}.axm-comment .axm-comment__list.axm-comment__list--loading{display:flex;flex-direction:column;gap:1.25rem}.axm-comment .axm-comment__empty{display:flex;min-height:min(16rem,40vh);flex:1;flex-direction:column;align-items:center;justify-content:center;padding:2rem 1.25rem}.axm-comment .axm-comment__skeleton{display:flex;align-items:flex-start;gap:.75rem}.axm-comment .axm-comment__skeleton.axm-comment__skeleton--compact .axm-comment__skeleton-body{gap:.375rem}.axm-comment .axm-comment__skeleton-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-comment .axm-comment__context-bar{display:flex;min-width:0px;cursor:pointer;align-items:flex-start;gap:calc(var(--spacing, .25rem) * 2);margin-block-end:8px;padding:.5rem .75rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));border-radius:6px;border-inline-start:3px solid rgb(var(--ax-sys-color-primary-surface));background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.4);font-size:.8125rem;line-height:1.45}.axm-comment .axm-comment__context-bar:hover{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.55)}.axm-comment .axm-comment__context-bar:focus-visible{outline:2px solid rgb(var(--ax-sys-color-primary-surface));outline-offset:2px}.axm-comment .axm-comment__context-bar-body{display:flex;min-width:0px;flex:1;align-items:flex-start;text-align:start;gap:.625rem;overflow:hidden;pointer-events:none}.axm-comment .axm-comment__context-bar-icon{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: 1;line-height:1;margin-top:.125rem;color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-bar-copy{display:flex;min-width:0px;flex:1;flex-direction:column;gap:.125rem;overflow:hidden}.axm-comment .axm-comment__context-bar-label{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);color:rgb(var(--ax-sys-color-neutral-700-surface, 55 65 81))}.axm-comment .axm-comment__context-bar-name{--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-neutral-900-surface, 17 24 39))}.axm-comment .axm-comment__context-bar-preview{min-width:0px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);color:rgb(var(--ax-sys-color-neutral-600-surface, 107 114 128))}.axm-comment .axm-comment__context-bar-close{position:relative;z-index:1;display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;align-self:flex-start;border-radius:var(--radius-sm, .25rem);width:1.75rem;height:1.75rem;margin-inline-start:-.25rem;padding:0;border:none;background:transparent;color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128));font-size:1rem;line-height:1;cursor:pointer}.axm-comment .axm-comment__context-bar-close:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.9);color:rgb(var(--ax-sys-color-neutral-700-surface, 55 65 81))}.axm-comment .axm-comment__context-bar-close:focus-visible{outline:2px solid rgb(var(--ax-sys-color-primary-surface));outline-offset:2px}.axm-comment .axm-comment__editor-actions{display:flex;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding:var(--spacing, .25rem)}.axm-comment .axm-comment__send{min-width:5.5rem}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXTextEditorModule }, { kind: "component", type: i1$3.AXTextEditorComponent, selector: "ax-text-editor", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "look", "placeHolder", "outputFormat", "line", "initialLine", "maxLine"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange"] }, { kind: "component", type: i1$3.AXTextEditorToolbarComponent, selector: "ax-text-editor-toolbar", inputs: ["orientation"] }, { kind: "component", type: i1$3.AXTextEditorHistoryComponent, selector: "ax-text-editor-history" }, { kind: "component", type: i1$3.AXTextEditorFontStyleComponent, selector: "ax-text-editor-font-style" }, { kind: "component", type: i1$3.AXTextEditorAlignmentComponent, selector: "ax-text-editor-alignment" }, { kind: "component", type: i1$3.AXTextEditorColorsComponent, selector: "ax-text-editor-colors" }, { kind: "component", type: i1$3.AXTextEditorListComponent, selector: "ax-text-editor-list" }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXCommentModule }, { kind: "component", type: i4.AXCommentViewComponent, selector: "ax-comment-view", inputs: ["datasource", "itemTemplate"], outputs: ["datasourceChange", "onReply", "onLikeChange", "onRepliesToggle", "onAction"] }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AXCommentReplyComponent, selector: "ax-comment-reply", inputs: ["item"], outputs: ["onClose", "onTargetClick"] }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "component", type: i4.AXCommentEditedComponent, selector: "ax-comment-edited", inputs: ["editedAt"] }, { kind: "directive", type: i4.AXCommentItemTemplateDirective, selector: "ng-template[axCommentItem]" }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { 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: "component", type: i1$1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i7.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "text", "selected", "color", "look", "type", "mode", "iconOnly"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i8.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId", "showPresence", "displayName", "displayAvatar"] }, { kind: "directive", type: AXPUserCardDirective, selector: "[axpUserCard]", inputs: ["axpUserCard", "axpUserCardDisabled", "axpUserCardTrigger"] }, { kind: "pipe", type: i1$2.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
12853
12921
|
}
|
|
12854
12922
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCommentComponent, decorators: [{
|
|
12855
12923
|
type: Component,
|
|
12856
|
-
args: [{ selector: 'axm-comment', encapsulation: ViewEncapsulation.None,
|
|
12857
|
-
trigger('fadeIn', [
|
|
12858
|
-
transition(':enter', [
|
|
12859
|
-
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
12860
|
-
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
12861
|
-
]),
|
|
12862
|
-
]),
|
|
12863
|
-
], imports: [
|
|
12924
|
+
args: [{ selector: 'axm-comment', encapsulation: ViewEncapsulation.None, imports: [
|
|
12864
12925
|
AXTextEditorModule,
|
|
12865
12926
|
AXSkeletonModule,
|
|
12866
12927
|
AXDecoratorModule,
|
|
12867
12928
|
AXCommentModule,
|
|
12929
|
+
AXBadgeModule,
|
|
12868
12930
|
AXButtonModule,
|
|
12869
|
-
|
|
12870
|
-
AXImageModule,
|
|
12931
|
+
AXDropdownButtonModule,
|
|
12871
12932
|
AXLoadingModule,
|
|
12872
|
-
AXDropdownModule,
|
|
12873
|
-
AXFormatModule,
|
|
12874
12933
|
AXTranslationModule,
|
|
12875
12934
|
AsyncPipe,
|
|
12876
|
-
AXFormModule,
|
|
12877
|
-
AXToolBarModule,
|
|
12878
12935
|
FormsModule,
|
|
12879
|
-
|
|
12936
|
+
AXPStateMessageComponent,
|
|
12880
12937
|
AXPUserAvatarComponent,
|
|
12881
12938
|
AXPUserCardDirective,
|
|
12882
|
-
AXPStateMessageComponent,
|
|
12883
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axm-comment size-full flex flex-col overflow-hidden\">\n <div class=\"axm-comment__list flex-1 min-h-0 overflow-y-auto\">\n <ax-comment-container>\n @if (isLoading()) {\n <div class=\"axm-comment__skeleton\">\n <ax-skeleton class=\"size-10 shrink-0 rounded-full\"></ax-skeleton>\n <div class=\"axm-comment__skeleton-body\">\n <ax-skeleton class=\"h-4 w-32 rounded\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-full rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-11/12 rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-4/5 rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (comments().length > 0) {\n <ax-comment-view class=\"axm-comment__view\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [repliesExpanded]=\"isRepliesExpanded(comment.id!)\"\n (repliesExpandedChange)=\"\n onRepliesExpandedChange(comment.id!, $event)\n \"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #user\n [size]=\"36\"\n [userId]=\"comment.senderId\"\n [axpUserCard]=\"comment.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"comment.senderId\">{{\n user.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ comment.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.title())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(comment.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(comment))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(comment)\"\n [like]=\"isLikedByUser(comment)\"\n >\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.title())\"\n ></ax-comment-reply-text>\n\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item\n [id]=\"reply.id\"\n [class.highlighted]=\"highlightedCommentId() === reply.id\"\n [@fadeIn]\n >\n <axp-user-avatar\n #replyUser\n [size]=\"36\"\n [userId]=\"reply.senderId\"\n [axpUserCard]=\"reply.senderId\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title class=\"axm-comment__author\" [axpUserCard]=\"reply.senderId\">{{\n replyUser.title()\n }}</ax-title>\n <ax-comment-date class=\"axm-comment__date\">\n {{ reply.timestamp | format: 'timeleft' | async }}\n </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button\n class=\"axm-comment__menu-btn ax-sm\"\n look=\"blank\"\n color=\"neutral\"\n >\n <ax-icon icon=\"fa-regular fa-ellipsis\"></ax-icon>\n </ax-button>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.edit.title'\n | translate\n | async) ?? ''\n \"\n color=\"neutral\"\n (click)=\"\n editMessage(comment, reply, replyUser.title())\n \"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"\n ('@conversation:comments.actions.delete.title'\n | translate\n | async) ?? ''\n \"\n color=\"danger\"\n (click)=\"deleteComment(reply.id!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content\n [innerHTML]=\"sanitizeHtml(getCommentText(reply))\"\n ></ax-content>\n <ax-comment-like\n (click)=\"toggleLike(reply)\"\n [like]=\"isLikedByUser(reply)\"\n >\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, replyUser.title())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n }\n <!-- ----- Empty state when no comments exist ----- -->\n @else {\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.title'\n \"\n [description]=\"\n '@conversation:comments.components.comment.empty-states.no-comments.description'\n \"\n >\n </axp-state-message>\n }\n </ax-comment-container>\n </div>\n\n <div class=\"axm-comment__composer\">\n @if (isReplyingMode() || isEditingMode()) {\n <div class=\"axm-comment__context\">\n <button\n type=\"button\"\n class=\"axm-comment__context-main\"\n (click)=\"scrollMain()\"\n >\n <i\n class=\"fa-light axm-comment__context-icon\"\n [class.fa-reply]=\"isReplyingMode()\"\n [class.fa-pen]=\"isEditingMode()\"\n ></i>\n <div class=\"axm-comment__context-copy\">\n <p class=\"axm-comment__context-label\">\n @if (isReplyingMode()) {\n {{\n '@conversation:comments.actions.reply-to' | translate | async\n }}\n <span>{{ activeReplyComment()?.userName }}</span>\n } @else {\n {{\n '@conversation:comments.actions.edit-message'\n | translate\n | async\n }}\n }\n </p>\n <div\n class=\"axm-comment__context-preview\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(getCommentText(activeReplyComment()!))\n : sanitizeHtml(getCommentText(activeEditComment()!))\n \"\n ></div>\n </div>\n </button>\n <button\n type=\"button\"\n class=\"axm-comment__context-close\"\n (click)=\"resetReplyEditState()\"\n [attr.aria-label]=\"\n ('@conversation:comments.actions.cancel.title'\n | translate\n | async) ?? 'Cancel'\n \"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <div class=\"axm-comment__editor\">\n <ax-text-editor\n #editorRef\n outputFormat=\"html\"\n [look]=\"editorOptions().look\"\n [(ngModel)]=\"commentContent\"\n >\n <ax-text-editor-content class=\"min-h-24\"></ax-text-editor-content>\n <ax-text-editor-toolbar>\n <ax-prefix>\n <ax-text-editor-history></ax-text-editor-history>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-text-editor-colors></ax-text-editor-colors>\n <ax-text-editor-list></ax-text-editor-list>\n <ax-text-editor-alignment></ax-text-editor-alignment>\n </ax-prefix>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n <!-- ----- Send sits under the editor, aligned to the inline end ----- -->\n <div class=\"axm-comment__editor-actions\">\n <ax-button\n look=\"solid\"\n color=\"primary\"\n class=\"ax-sm\"\n [disabled]=\"hasCooldown() || !commentContent()\"\n (click)=\"submitComment()\"\n [text]=\"\n '@conversation:comments.actions.send.title' | translate | async\n \"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;:host{display:block;height:100%;min-height:0px;width:100%}.axm-comment{min-height:0px;height:calc(100vh - 210px);background-color:rgb(var(--ax-sys-color-lightest-surface))}.axm-comment .axm-comment__list{min-height:0px}.axm-comment .axm-comment__skeleton{display:flex;align-items:flex-start;gap:.875rem;padding:1.25rem 1.25rem 1.5rem}.axm-comment .axm-comment__skeleton-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-comment .axm-comment__composer{flex-shrink:0;background-color:rgb(var(--ax-sys-color-surface-surface))}.axm-comment .axm-comment__context{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding:.625rem .75rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));border-bottom:none;border-inline-start:3px solid rgb(var(--ax-sys-color-primary-surface));background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.35);font-size:.8125rem;line-height:1.4}.axm-comment .axm-comment__context-main{display:flex;min-width:0px;flex:1;cursor:pointer;align-items:center;gap:.625rem}.axm-comment .axm-comment__context-icon{flex-shrink:0;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-copy{display:flex;min-width:0px;flex-direction:column;gap:.125rem}.axm-comment .axm-comment__context-label{margin:0;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;color:rgb(var(--ax-sys-color-neutral-600-surface, 107 114 128))}.axm-comment .axm-comment__context-close{flex-shrink:0;cursor:pointer;border-radius:var(--radius-md, .375rem);--tw-border-style: none;border-style:none;padding:.25rem;background:transparent;color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128));font-size:1rem;line-height:1}.axm-comment .axm-comment__context-close:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.8)}.axm-comment .axm-comment__editor{overflow:hidden;border:1px solid rgb(var(--ax-sys-color-border-light-surface));background-color:rgb(var(--ax-sys-color-lightest-surface));box-shadow:0 1px 2px #0f172a0a}.axm-comment .axm-comment__editor-actions{display:flex;justify-content:flex-end;padding:.5rem .75rem;border-top:1px solid rgb(var(--ax-sys-color-border-light-surface))}.axm-comment .axm-comment__author{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}.axm-comment .axm-comment__date{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128))}.axm-comment .axm-comment__menu-btn{opacity:0;transition:opacity .15s ease}ax-comment-item{border-radius:.75rem;transition:background-color .2s ease}ax-comment-item:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.45)}ax-comment-item:hover .axm-comment__menu-btn{opacity:1}ax-comment-item.highlighted{animation:axm-comment-highlight 2.5s cubic-bezier(.4,0,.2,1) forwards}ax-text-editor{flex-shrink:0}ax-text-editor .ax-editor-container{border:none!important;border-radius:0!important;box-shadow:none!important}ax-text-editor .ax-error-message{padding-inline-start:.75rem}@keyframes axm-comment-highlight{0%{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}10%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5);box-shadow:inset 3px 0 rgb(var(--ax-sys-color-primary-surface))}35%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.3);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lighter-surface),.8)}60%{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.4);box-shadow:inset 3px 0 rgba(var(--ax-sys-color-primary-lightest-surface),.6)}to{background-color:transparent;box-shadow:inset 3px 0 0 0 transparent}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
|
|
12884
|
-
|
|
12939
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axm-comment\">\n <ax-comment-container #commentContainer>\n <!-- ----- Loading skeleton while comments are fetched ----- -->\n @if (isLoading()) {\n <div class=\"axm-comment__list axm-comment__list--loading\">\n @for (skeleton of [0, 1, 2]; track skeleton) {\n <div class=\"axm-comment__skeleton\" [class.axm-comment__skeleton--compact]=\"skeleton > 0\">\n <ax-skeleton class=\"size-9 shrink-0 rounded-full\"></ax-skeleton>\n <div class=\"axm-comment__skeleton-body\">\n <ax-skeleton class=\"h-3.5 w-28 rounded\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-full rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"h-3 w-11/12 rounded-full\"></ax-skeleton>\n <!--------------------------------------------------------------->\n <!-- ----- Extra skeleton line on first row ----- -->\n @if (skeleton === 0) {\n <ax-skeleton class=\"h-3 w-2/3 rounded-full\"></ax-skeleton>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- ----- Empty state when the thread has no comments ----- -->\n @else if (comments().length === 0) {\n <div class=\"axm-comment__empty\">\n <axp-state-message\n icon=\"fa-light fa-comments\"\n [title]=\"'@conversation:comments.components.comment.empty-states.no-comments.title'\"\n [description]=\"'@conversation:comments.components.comment.empty-states.no-comments.description'\"\n ></axp-state-message>\n </div>\n }\n <!-- ----- Comment thread from the mapped datasource ----- -->\n @else {\n <div class=\"axm-comment__list\">\n <ax-comment-view #commentsView [datasource]=\"commentItems()\" (onReply)=\"onReply($event)\" (onLikeChange)=\"onLikeChange($event)\" (onRepliesToggle)=\"onRepliesToggle($event)\" (onAction)=\"onAction($event)\">\n <ng-template axCommentItem let-item>\n <div class=\"flex min-w-0 items-start gap-2\">\n <axp-user-avatar class=\"shrink-0\" [size]=\"42\" [userId]=\"commentSenderId(item)\" [axpUserCard]=\"commentSenderId(item)\"></axp-user-avatar>\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex min-w-0 items-center justify-between gap-2\">\n <div class=\"flex min-w-0 flex-wrap items-center\">\n <ax-title [axpUserCard]=\"commentSenderId(item)\">{{ item.author }}</ax-title>\n <!--------------------------------------------------------------->\n <!-- ----- You badge for the current user's comment ----- -->\n @if (item.isYou) {\n <ax-badge class=\"ax-sm ax-pill ax-comment-you-badge\" look=\"twotone\" color=\"primary\" [text]=\"('@acorex:comment.you' | translate | async) ?? 'You'\"></ax-badge>\n }\n <!--------------------------------------------------------------->\n <!-- ----- Edited label (before timestamp) ----- -->\n @if (item.edited) {\n <ax-comment-edited [editedAt]=\"item.editedAt\" />\n }\n <!--------------------------------------------------------------->\n <!-- ----- Relative timestamp for this comment ----- -->\n @if (item.date) {\n <ax-comment-date>{{ item.date }}</ax-comment-date>\n }\n </div>\n <!--------------------------------------------------------------->\n <!-- ----- Overflow menu from item actions ----- -->\n @if (item.actions?.length) {\n <ax-dropdown-button class=\"ax-sm\" mode=\"dropdown\" look=\"blank\" [iconOnly]=\"true\" [text]=\"('@conversation:comments.actions.more' | translate | async) ?? ''\">\n <ax-prefix>\n <ax-icon icon=\"ax-icon ax-icon-more-horizontal\"></ax-icon>\n </ax-prefix>\n <ax-button-item-list>\n @for (action of item.actions; track action.name ?? action.text) {\n <ax-button-item [text]=\"action.text\" [color]=\"action.color\" (onClick)=\"onOverflowAction(item, action.name ?? action.text)\">\n <!--------------------------------------------------------------->\n <!-- ----- Action icon when the menu item has one ----- -->\n @if (action.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-button>\n }\n </div>\n <ax-content>\n <div [innerHTML]=\"item.content\"></div>\n </ax-content>\n </div>\n </div>\n </ng-template>\n </ax-comment-view>\n </div>\n }\n\n <ax-footer style=\"padding: 0.1rem\">\n <!-- ----- Edit context above the composer ----- -->\n @if (editing(); as editItem) {\n <div class=\"axm-comment__context-bar\" tabindex=\"0\" (click)=\"scrollToCommentContext(editItem)\" (keydown.enter)=\"scrollToCommentContext(editItem)\" (keydown.space)=\"$event.preventDefault(); scrollToCommentContext(editItem)\">\n <div class=\"axm-comment__context-bar-body\">\n <i class=\"fa-light fa-pen axm-comment__context-bar-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-comment__context-bar-copy\">\n <span class=\"axm-comment__context-bar-label\">{{ '@conversation:comments.actions.edit-message' | translate | async }}</span>\n @if (commentContextPreview(editItem.content); as preview) {\n <span class=\"axm-comment__context-bar-preview\" [title]=\"preview\">{{ preview }}</span>\n }\n </span>\n </div>\n <button type=\"button\" class=\"axm-comment__context-bar-close\" (click)=\"$event.stopPropagation(); cancelEdit()\" [attr.aria-label]=\"('@conversation:comments.actions.cancel.title' | translate | async) ?? 'Cancel'\">\n <i class=\"fa-light fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n <!-- ----- Reply context above the composer ----- -->\n @else if (replyingTo(); as replyItem) {\n <div class=\"axm-comment__context-bar\" tabindex=\"0\" (click)=\"scrollToCommentContext(replyItem)\" (keydown.enter)=\"scrollToCommentContext(replyItem)\" (keydown.space)=\"$event.preventDefault(); scrollToCommentContext(replyItem)\">\n <div class=\"axm-comment__context-bar-body\">\n <i class=\"fa-light fa-reply axm-comment__context-bar-icon\" aria-hidden=\"true\"></i>\n <span class=\"axm-comment__context-bar-copy\">\n <span class=\"axm-comment__context-bar-label\">\n {{ '@conversation:comments.actions.reply-to' | translate | async }}\n <span class=\"axm-comment__context-bar-name\">\n @if (replyItem.isYou) {\n {{ '@acorex:comment.you' | translate | async }}\n } @else {\n {{ replyItem.author }}\n }\n </span>\n </span>\n @if (commentContextPreview(replyItem.content); as preview) {\n <span class=\"axm-comment__context-bar-preview\" [title]=\"preview\">{{ preview }}</span>\n }\n </span>\n </div>\n <button type=\"button\" class=\"axm-comment__context-bar-close\" (click)=\"$event.stopPropagation(); cancelReply()\" [attr.aria-label]=\"('@conversation:comments.actions.cancel.title' | translate | async) ?? 'Cancel'\">\n <i class=\"fa-light fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <ax-comment-reply>\n <ax-text-editor\n #commentEditor\n look=\"solid\"\n outputFormat=\"html\"\n [initialLine]=\"3\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event)\"\n [placeHolder]=\"((editing() ? '@conversation:comments.actions.edit-message' : replyingTo() ? '@conversation:comments.composer.reply-placeholder' : '@conversation:comments.composer.placeholder') | translate | async) ?? ''\"\n >\n <ax-footer>\n <div class=\"axm-comment__editor-actions\">\n <ax-button\n class=\"axm-comment__send ax-sm\"\n look=\"solid\"\n color=\"primary\"\n [disabled]=\"hasCooldown() || isCommentDraftEmpty() || isSubmitting()\"\n [text]=\"(editing() ? '@conversation:comments.actions.edit.title' : '@conversation:comments.actions.send.title') | translate | async\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n } @else {\n <!-- ----- Send icon when not submitting ----- -->\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-paper-plane-top\"></ax-icon>\n </ax-prefix>\n }\n </ax-button>\n </div>\n </ax-footer>\n <ax-text-editor-toolbar class=\"border-b\">\n <ax-text-editor-history></ax-text-editor-history>\n <ax-divider></ax-divider>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-divider></ax-divider>\n <ax-text-editor-colors></ax-text-editor-colors>\n <ax-divider></ax-divider>\n <ax-text-editor-list></ax-text-editor-list>\n <ax-divider></ax-divider>\n <ax-text-editor-alignment></ax-text-editor-alignment>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n </ax-comment-reply>\n </ax-footer>\n </ax-comment-container>\n</div>\n", styles: ["@layer properties;:host{display:block;height:100%;min-height:0px;width:100%}ax-comment-container{display:flex;flex-direction:column;justify-content:space-between;height:100%}.axm-comment{display:flex;width:100%;height:100%;min-height:0px;flex-direction:column;overflow:hidden;background-color:rgb(var(--ax-sys-color-lightest-surface))}.axm-comment .axm-comment__list{min-height:0px;flex:1;overflow-y:auto;padding:1rem 1rem 1.25rem;scroll-behavior:smooth}.axm-comment .axm-comment__list.axm-comment__list--loading{display:flex;flex-direction:column;gap:1.25rem}.axm-comment .axm-comment__empty{display:flex;min-height:min(16rem,40vh);flex:1;flex-direction:column;align-items:center;justify-content:center;padding:2rem 1.25rem}.axm-comment .axm-comment__skeleton{display:flex;align-items:flex-start;gap:.75rem}.axm-comment .axm-comment__skeleton.axm-comment__skeleton--compact .axm-comment__skeleton-body{gap:.375rem}.axm-comment .axm-comment__skeleton-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-comment .axm-comment__context-bar{display:flex;min-width:0px;cursor:pointer;align-items:flex-start;gap:calc(var(--spacing, .25rem) * 2);margin-block-end:8px;padding:.5rem .75rem;border:1px solid rgb(var(--ax-sys-color-border-light-surface));border-radius:6px;border-inline-start:3px solid rgb(var(--ax-sys-color-primary-surface));background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.4);font-size:.8125rem;line-height:1.45}.axm-comment .axm-comment__context-bar:hover{background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.55)}.axm-comment .axm-comment__context-bar:focus-visible{outline:2px solid rgb(var(--ax-sys-color-primary-surface));outline-offset:2px}.axm-comment .axm-comment__context-bar-body{display:flex;min-width:0px;flex:1;align-items:flex-start;text-align:start;gap:.625rem;overflow:hidden;pointer-events:none}.axm-comment .axm-comment__context-bar-icon{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: 1;line-height:1;margin-top:.125rem;color:rgb(var(--ax-sys-color-primary-surface))}.axm-comment .axm-comment__context-bar-copy{display:flex;min-width:0px;flex:1;flex-direction:column;gap:.125rem;overflow:hidden}.axm-comment .axm-comment__context-bar-label{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);color:rgb(var(--ax-sys-color-neutral-700-surface, 55 65 81))}.axm-comment .axm-comment__context-bar-name{--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-neutral-900-surface, 17 24 39))}.axm-comment .axm-comment__context-bar-preview{min-width:0px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);color:rgb(var(--ax-sys-color-neutral-600-surface, 107 114 128))}.axm-comment .axm-comment__context-bar-close{position:relative;z-index:1;display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;align-self:flex-start;border-radius:var(--radius-sm, .25rem);width:1.75rem;height:1.75rem;margin-inline-start:-.25rem;padding:0;border:none;background:transparent;color:rgb(var(--ax-sys-color-neutral-500-surface, 107 114 128));font-size:1rem;line-height:1;cursor:pointer}.axm-comment .axm-comment__context-bar-close:hover{background-color:rgba(var(--ax-sys-color-neutral-100-surface, 243 244 246),.9);color:rgb(var(--ax-sys-color-neutral-700-surface, 55 65 81))}.axm-comment .axm-comment__context-bar-close:focus-visible{outline:2px solid rgb(var(--ax-sys-color-primary-surface));outline-offset:2px}.axm-comment .axm-comment__editor-actions{display:flex;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding:var(--spacing, .25rem)}.axm-comment .axm-comment__send{min-width:5.5rem}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
|
|
12940
|
+
}], propDecorators: { refrenceType: [{ type: i0.Input, args: [{ isSignal: true, alias: "refrenceType", required: true }] }], refrenceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "refrenceId", required: true }] }], subject: [{ type: i0.Input, args: [{ isSignal: true, alias: "subject", required: true }] }], commentsView: [{ type: i0.ViewChild, args: ['commentsView', { ...{ read: AXCommentViewComponent }, isSignal: true }] }], commentContainer: [{ type: i0.ViewChild, args: ['commentContainer', { ...{ read: AXCommentContainerComponent }, isSignal: true }] }], editor: [{ type: i0.ViewChild, args: ['commentEditor', { ...{ read: AXTextEditorComponent }, isSignal: true }] }] } });
|
|
12941
|
+
//#endregion
|
|
12942
|
+
//#region ----- Local helpers -----
|
|
12943
|
+
function stripHtmlToPlainText(html) {
|
|
12944
|
+
return html
|
|
12945
|
+
.replace(/<[^>]+>/g, '')
|
|
12946
|
+
.replace(/ /gi, ' ')
|
|
12947
|
+
.trim();
|
|
12948
|
+
}
|
|
12949
|
+
function toInitials(name) {
|
|
12950
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
12951
|
+
if (parts.length === 0) {
|
|
12952
|
+
return '?';
|
|
12953
|
+
}
|
|
12954
|
+
if (parts.length === 1) {
|
|
12955
|
+
return parts[0].slice(0, 1).toUpperCase();
|
|
12956
|
+
}
|
|
12957
|
+
return (parts[0].slice(0, 1) + parts[1].slice(0, 1)).toUpperCase();
|
|
12958
|
+
}
|
|
12959
|
+
function colorForUser(userId) {
|
|
12960
|
+
let hash = 0;
|
|
12961
|
+
for (let i = 0; i < userId.length; i++) {
|
|
12962
|
+
hash = (hash + userId.charCodeAt(i)) % AVATAR_COLORS.length;
|
|
12963
|
+
}
|
|
12964
|
+
return AVATAR_COLORS[hash];
|
|
12965
|
+
}
|
|
12966
|
+
function insertReply(list, parentId, comment) {
|
|
12967
|
+
return list.map((c) => {
|
|
12968
|
+
if (c.id === parentId) {
|
|
12969
|
+
const newReplies = c.replies ? [...c.replies, comment] : [comment];
|
|
12970
|
+
return { ...c, replies: newReplies, replyCount: newReplies.length };
|
|
12971
|
+
}
|
|
12972
|
+
if (c.replies?.length) {
|
|
12973
|
+
return { ...c, replies: insertReply(c.replies, parentId, comment) };
|
|
12974
|
+
}
|
|
12975
|
+
return c;
|
|
12976
|
+
});
|
|
12977
|
+
}
|
|
12978
|
+
function resolveDisplayName(info) {
|
|
12979
|
+
if (!info) {
|
|
12980
|
+
return '';
|
|
12981
|
+
}
|
|
12982
|
+
const parts = [info.firstName, info.lastName].map((part) => part?.trim()).filter(Boolean);
|
|
12983
|
+
if (parts.length > 0) {
|
|
12984
|
+
return parts.join(' ');
|
|
12985
|
+
}
|
|
12986
|
+
return info.username?.trim() || '';
|
|
12987
|
+
}
|
|
12885
12988
|
|
|
12886
12989
|
var comment_component = /*#__PURE__*/Object.freeze({
|
|
12887
12990
|
__proto__: null,
|
|
@@ -14190,7 +14293,7 @@ class AXMChatVoiceRecorderComponent {
|
|
|
14190
14293
|
this.discardActiveRecorder();
|
|
14191
14294
|
}
|
|
14192
14295
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatVoiceRecorderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
14193
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMChatVoiceRecorderComponent, isStandalone: true, selector: "axm-chat-voice-recorder", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null }, service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: false, transformFunction: null }, initialFiles: { classPropertyName: "initialFiles", publicName: "initialFiles", isSignal: true, isRequired: false, transformFunction: null }, autoRun: { classPropertyName: "autoRun", publicName: "autoRun", isSignal: true, isRequired: false, transformFunction: null }, __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null }, __actionSheet__: { classPropertyName: "__actionSheet__", publicName: "__actionSheet__", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { recordingComplete: "recordingComplete", recordingCancelled: "recordingCancelled" }, viewQueries: [{ propertyName: "waveWrapRef", first: true, predicate: ["waveWrap"], descendants: true, isSignal: true }, { propertyName: "waveRef", first: true, predicate: AXAudioWaveComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"voice-recorder\" [class.voice-recorder--preview]=\"isPreview()\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"translation.translateSync('@conversation:chat.voice-recorder.title')\">\n @if (isUploading()) {\n <!-- ----- Upload progress while the voice file is sent ----- -->\n <div class=\"voice-recorder__upload\">\n <span class=\"voice-recorder__upload-label\">{{ getUploadingLabel() }}</span>\n <ax-progress-bar [progress]=\"uploadProgress()\" [mode]=\"'determinate'\" [height]=\"6\" />\n </div>\n }\n <!-- ----- Speech-to-text overlay while the recording is transcribed ----- -->\n @else if (isTranscribing()) {\n <div class=\"voice-recorder__upload\">\n <ax-loading></ax-loading>\n <span class=\"voice-recorder__upload-label\">{{ '@conversation:chat.voice-recorder.transcribing' | translate | async }}</span>\n </div>\n }\n <!-- ----- Idle microphone before recording starts ----- -->\n @else if (!isRecording() && !isPreview()) {\n <div class=\"voice-recorder__idle\">\n <button type=\"button\" class=\"voice-recorder__mic\" [attr.aria-label]=\"translation.translateSync('@conversation:chat.voice-recorder.tap-to-start')\" (click)=\"startRecording()\">\n <i class=\"fa-light fa-microphone\" aria-hidden=\"true\"></i>\n </button>\n <span class=\"voice-recorder__hint\">{{ '@conversation:chat.voice-recorder.tap-to-start' | translate | async }}</span>\n </div>\n }\n <!-- ----- Live waveform or paused preview with send actions ----- -->\n @else {\n <div class=\"voice-recorder__body\">\n <div class=\"voice-recorder__visual\">\n <div class=\"voice-recorder__wave-wrap\" #waveWrap>\n <!-- ----- Live bars while the microphone is capturing ----- -->\n @if (isRecording()) {\n <div class=\"voice-recorder__live-wave\" aria-hidden=\"true\">\n @for (bar of liveDisplayBars(); track bar.index) {\n <span class=\"voice-recorder__bar\" [class.voice-recorder__bar--recorded]=\"bar.recorded\" [style.height.px]=\"bar.height\"></span>\n }\n </div>\n }\n <!-- ----- Preview waveform after recording is paused ----- -->\n @else if (waveConfig(); as config) {\n <ax-audio-wave class=\"voice-recorder__audio-wave\" [config]=\"config\" (onStatusChanged)=\"onWaveStatusChanged($event)\" />\n }\n </div>\n <!-- ----- Play or pause the recorded preview ----- -->\n @if (isPreview()) {\n <ax-button\n class=\"voice-recorder__play rounded-full\"\n look=\"twotone\"\n [iconOnly]=\"true\"\n [text]=\"isPlayingPreview() ? translation.translateSync('@conversation:chat.media.pause') : translation.translateSync('@conversation:chat.media.play')\"\n (onClick)=\"togglePreview()\"\n >\n <ax-icon>\n <i class=\"fa-solid\" [class.fa-pause]=\"isPlayingPreview()\" [class.fa-play]=\"!isPlayingPreview()\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n\n <div class=\"voice-recorder__time\" aria-live=\"polite\">\n {{ formattedTime() }}\n <span class=\"sr-only\">{{ '@conversation:chat.voice-recorder.recording' | translate | async }}</span>\n </div>\n </div>\n\n <footer class=\"voice-recorder__footer\">\n <div class=\"voice-recorder__footer-start\">\n <!-- ----- Delete the current recording ----- -->\n @if (isPreview()) {\n <ax-button class=\"voice-recorder__delete\" look=\"blank\" color=\"danger\" [iconOnly]=\"true\" [text]=\"translation.translateSync('@acorex:chat.actions.delete')\" (onClick)=\"deleteRecording()\">\n <ax-icon><i class=\"fa-light fa-trash-can\"></i></ax-icon>\n </ax-button>\n }\n <!-- ----- Pause recording or continue from preview ----- -->\n @if (isRecording() || isPreview()) {\n <ax-button\n class=\"voice-recorder__stop\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"isPreview() ? translation.translateSync('@conversation:chat.voice-recorder.continue-recording') : translation.translateSync('@conversation:chat.voice-recorder.stop-recording')\"\n (onClick)=\"toggleStopOrContinue()\"\n >\n <ax-icon>\n <i class=\"fa-solid\" [class.fa-pause]=\"isRecording()\" [class.fa-microphone]=\"isPreview()\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n\n <div class=\"voice-recorder__footer-end\">\n <!-- ----- Convert the paused recording into composer text ----- -->\n @if (isPreview()) {\n <ax-button class=\"voice-recorder__transcribe\" look=\"outline\" color=\"secondary\" [text]=\"translation.translateSync('@conversation:chat.voice-recorder.transcribe')\" [disabled]=\"!canTranscribe()\" (onClick)=\"applySpeechToText()\">\n <ax-prefix>\n <ax-icon><i class=\"fa-light fa-waveform-lines\"></i></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n <ax-button class=\"voice-recorder__send\" look=\"solid\" color=\"primary\" [text]=\"translation.translateSync('@acorex:chat.actions.send')\" [disabled]=\"!canSend()\" (onClick)=\"sendRecording()\">\n <ax-prefix>\n <ax-icon><i class=\"fa-light fa-paper-plane-top\"></i></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n </footer>\n }\n</div>\n", styles: ["@layer properties;@layer components{axm-chat-voice-recorder{display:flex;width:100%;flex-direction:column;container-type:inline-size}axm-chat-voice-recorder .voice-recorder{display:flex;width:100%;flex-direction:column;background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 5);padding-top:calc(var(--spacing, .25rem) * 5);padding-bottom:calc(var(--spacing, .25rem) * 5)}axm-chat-voice-recorder .voice-recorder__idle,axm-chat-voice-recorder .voice-recorder__upload{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 6);text-align:center}axm-chat-voice-recorder .voice-recorder__mic{display:flex;height:calc(var(--spacing, .25rem) * 16);width:calc(var(--spacing, .25rem) * 16);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;padding:0;font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));color:rgb(var(--ax-sys-color-on-primary-500));background:rgb(var(--ax-sys-color-primary-500));box-shadow:0 .5rem 1.25rem rgba(var(--ax-sys-color-primary-500),.28)}axm-chat-voice-recorder .voice-recorder__mic:hover,axm-chat-voice-recorder .voice-recorder__mic:focus-visible{--tw-outline-style: none;outline-style:none;background:rgb(var(--ax-sys-color-primary-600))}axm-chat-voice-recorder .voice-recorder__hint,axm-chat-voice-recorder .voice-recorder__upload-label{margin:0;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);color:rgba(var(--ax-sys-color-on-surface),.62)}axm-chat-voice-recorder .voice-recorder__upload{width:100%;max-width:calc(var(--spacing, .25rem) * 72);gap:calc(var(--spacing, .25rem) * 2.5)}axm-chat-voice-recorder .voice-recorder__body{display:flex;width:100%;flex-direction:column;align-items:center}axm-chat-voice-recorder .voice-recorder__visual{display:flex;width:100%;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}axm-chat-voice-recorder .voice-recorder__wave-wrap{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 14);min-width:0px;flex:1;align-items:center}axm-chat-voice-recorder .voice-recorder--preview .voice-recorder__wave-wrap{border-radius:var(--radius-xl, .75rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);background:rgba(var(--ax-sys-color-primary-500),.08)}axm-chat-voice-recorder .voice-recorder__live-wave{display:flex;height:calc(var(--spacing, .25rem) * 9);width:100%;min-width:0px;align-items:center;gap:2px}axm-chat-voice-recorder .voice-recorder__bar{display:block;flex:1 1 0;min-width:0;border-radius:2px;background:rgba(var(--ax-sys-color-on-surface),.16);transform-origin:center}axm-chat-voice-recorder .voice-recorder__bar--recorded{background:rgb(var(--ax-sys-color-primary-500))}axm-chat-voice-recorder .voice-recorder__audio-wave{display:block;min-height:calc(var(--spacing, .25rem) * 9);width:100%;min-width:0px;flex:1}axm-chat-voice-recorder .voice-recorder__audio-wave .ax-audio-wave,axm-chat-voice-recorder .voice-recorder__audio-wave .ax-audio-wave-host{display:block;width:100%}axm-chat-voice-recorder .voice-recorder__play{position:relative;z-index:1;flex-shrink:0}axm-chat-voice-recorder .voice-recorder__play .fa-play{padding-inline-start:.12rem;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-chat-voice-recorder .voice-recorder__play .fa-pause{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-chat-voice-recorder .voice-recorder__time{margin-top:calc(var(--spacing, .25rem) * 4);font-size:1.25rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}axm-chat-voice-recorder .voice-recorder__footer{margin-top:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3)}axm-chat-voice-recorder .voice-recorder__footer:dir(rtl){flex-direction:row-reverse}axm-chat-voice-recorder .voice-recorder__footer-start,axm-chat-voice-recorder .voice-recorder__footer-end{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}axm-chat-voice-recorder .voice-recorder__footer-end,axm-chat-voice-recorder .voice-recorder__transcribe,axm-chat-voice-recorder .voice-recorder__send{min-width:0px}axm-chat-voice-recorder .voice-recorder__transcribe>button,axm-chat-voice-recorder .voice-recorder__send>button{display:flex;height:calc(var(--spacing, .25rem) * 12);align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-xl, .75rem);padding-inline:calc(var(--spacing, .25rem) * 3);font-size:.9375rem;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);box-shadow:none;background-image:none}axm-chat-voice-recorder .voice-recorder__send .fa-paper-plane-top:dir(rtl){transform:scaleX(-1)}axm-chat-voice-recorder .voice-recorder__delete,axm-chat-voice-recorder .voice-recorder__stop{flex-shrink:0}axm-chat-voice-recorder .voice-recorder__delete>button,axm-chat-voice-recorder .voice-recorder__stop>button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);align-items:center;justify-content:center;border-radius:var(--radius-xl, .75rem);--tw-border-style: none;border-style:none;padding:0;font-size:var(--text-lg, 1.125rem);line-height:var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));box-shadow:none}axm-chat-voice-recorder .voice-recorder__delete>button{color:rgb(var(--ax-sys-color-danger-600));background:rgba(var(--ax-sys-color-danger-500),.14)}axm-chat-voice-recorder .voice-recorder__stop>button{color:rgb(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.08)}axm-chat-voice-recorder .voice-recorder__delete:hover>button,axm-chat-voice-recorder .voice-recorder__delete>button:hover{background:rgba(var(--ax-sys-color-danger-500),.22)}axm-chat-voice-recorder .voice-recorder__stop:hover>button,axm-chat-voice-recorder .voice-recorder__stop>button:hover{background:rgba(var(--ax-sys-color-on-surface),.14)}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXAudioWaveComponent, selector: "ax-audio-wave", inputs: ["config"], outputs: ["onStatusChanged"] }, { kind: "component", type: 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: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXLoadingModule }, { kind: "component", type: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXProgressBarModule }, { kind: "component", type: i3$1.AXProgressBarComponent, selector: "ax-progress-bar", inputs: ["color", "mode", "progress", "height"], outputs: ["ValueChange", "sizeChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
14296
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMChatVoiceRecorderComponent, isStandalone: true, selector: "axm-chat-voice-recorder", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null }, service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: false, transformFunction: null }, initialFiles: { classPropertyName: "initialFiles", publicName: "initialFiles", isSignal: true, isRequired: false, transformFunction: null }, autoRun: { classPropertyName: "autoRun", publicName: "autoRun", isSignal: true, isRequired: false, transformFunction: null }, __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null }, __actionSheet__: { classPropertyName: "__actionSheet__", publicName: "__actionSheet__", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { recordingComplete: "recordingComplete", recordingCancelled: "recordingCancelled" }, viewQueries: [{ propertyName: "waveWrapRef", first: true, predicate: ["waveWrap"], descendants: true, isSignal: true }, { propertyName: "waveRef", first: true, predicate: AXAudioWaveComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"voice-recorder\" [class.voice-recorder--preview]=\"isPreview()\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"translation.translateSync('@conversation:chat.voice-recorder.title')\">\n @if (isUploading()) {\n <!-- ----- Upload progress while the voice file is sent ----- -->\n <div class=\"voice-recorder__upload\">\n <span class=\"voice-recorder__upload-label\">{{ getUploadingLabel() }}</span>\n <ax-progress-bar [progress]=\"uploadProgress()\" [mode]=\"'determinate'\" [height]=\"6\" />\n </div>\n }\n <!-- ----- Speech-to-text overlay while the recording is transcribed ----- -->\n @else if (isTranscribing()) {\n <div class=\"voice-recorder__upload\">\n <ax-loading></ax-loading>\n <span class=\"voice-recorder__upload-label\">{{ '@conversation:chat.voice-recorder.transcribing' | translate | async }}</span>\n </div>\n }\n <!-- ----- Idle microphone before recording starts ----- -->\n @else if (!isRecording() && !isPreview()) {\n <div class=\"voice-recorder__idle\">\n <button type=\"button\" class=\"voice-recorder__mic\" [attr.aria-label]=\"translation.translateSync('@conversation:chat.voice-recorder.tap-to-start')\" (click)=\"startRecording()\">\n <i class=\"fa-light fa-microphone\" aria-hidden=\"true\"></i>\n </button>\n <span class=\"voice-recorder__hint\">{{ '@conversation:chat.voice-recorder.tap-to-start' | translate | async }}</span>\n </div>\n }\n <!-- ----- Live waveform or paused preview with send actions ----- -->\n @else {\n <div class=\"voice-recorder__body\">\n <div class=\"voice-recorder__visual\">\n <div class=\"voice-recorder__wave-wrap\" #waveWrap>\n <!-- ----- Live bars while the microphone is capturing ----- -->\n @if (isRecording()) {\n <div class=\"voice-recorder__live-wave\" aria-hidden=\"true\">\n @for (bar of liveDisplayBars(); track bar.index) {\n <span class=\"voice-recorder__bar\" [class.voice-recorder__bar--recorded]=\"bar.recorded\" [style.height.px]=\"bar.height\"></span>\n }\n </div>\n }\n <!-- ----- Preview waveform after recording is paused ----- -->\n @else if (waveConfig(); as config) {\n <ax-audio-wave class=\"voice-recorder__audio-wave\" [config]=\"config\" (onStatusChanged)=\"onWaveStatusChanged($event)\" />\n }\n </div>\n <!-- ----- Play or pause the recorded preview ----- -->\n @if (isPreview()) {\n <ax-button\n class=\"voice-recorder__play rounded-full\"\n look=\"twotone\"\n [iconOnly]=\"true\"\n [text]=\"isPlayingPreview() ? translation.translateSync('@conversation:chat.media.pause') : translation.translateSync('@conversation:chat.media.play')\"\n (onClick)=\"togglePreview()\"\n >\n <ax-icon>\n <i class=\"fa-solid\" [class.fa-pause]=\"isPlayingPreview()\" [class.fa-play]=\"!isPlayingPreview()\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n\n <div class=\"voice-recorder__time\" aria-live=\"polite\">\n {{ formattedTime() }}\n <span class=\"sr-only\">{{ '@conversation:chat.voice-recorder.recording' | translate | async }}</span>\n </div>\n </div>\n\n <footer class=\"voice-recorder__footer\">\n <div class=\"voice-recorder__footer-start\">\n <!-- ----- Delete the current recording ----- -->\n @if (isPreview()) {\n <ax-button class=\"voice-recorder__delete\" look=\"blank\" color=\"danger\" [iconOnly]=\"true\" [text]=\"translation.translateSync('@acorex:chat.actions.delete')\" (onClick)=\"deleteRecording()\">\n <ax-icon><i class=\"fa-light fa-trash-can\"></i></ax-icon>\n </ax-button>\n }\n <!-- ----- Pause recording or continue from preview ----- -->\n @if (isRecording() || isPreview()) {\n <ax-button\n class=\"voice-recorder__stop\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"isPreview() ? translation.translateSync('@conversation:chat.voice-recorder.continue-recording') : translation.translateSync('@conversation:chat.voice-recorder.stop-recording')\"\n (onClick)=\"toggleStopOrContinue()\"\n >\n <ax-icon>\n <i class=\"fa-solid\" [class.fa-pause]=\"isRecording()\" [class.fa-microphone]=\"isPreview()\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n\n <div class=\"voice-recorder__footer-end\">\n <!-- ----- Convert the paused recording into composer text ----- -->\n @if (isPreview()) {\n <ax-button class=\"voice-recorder__transcribe\" look=\"outline\" color=\"secondary\" [text]=\"translation.translateSync('@conversation:chat.voice-recorder.transcribe')\" [disabled]=\"!canTranscribe()\" (onClick)=\"applySpeechToText()\">\n <ax-prefix>\n <ax-icon><i class=\"fa-light fa-waveform-lines\"></i></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n <ax-button class=\"voice-recorder__send\" look=\"solid\" color=\"primary\" [text]=\"translation.translateSync('@acorex:chat.actions.send')\" [disabled]=\"!canSend()\" (onClick)=\"sendRecording()\">\n <ax-prefix>\n <ax-icon><i class=\"fa-light fa-paper-plane-top\"></i></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n </footer>\n }\n</div>\n", styles: ["@layer properties;@layer components{axm-chat-voice-recorder{display:flex;width:100%;flex-direction:column;container-type:inline-size}axm-chat-voice-recorder .voice-recorder{display:flex;width:100%;flex-direction:column;background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 5);padding-top:calc(var(--spacing, .25rem) * 5);padding-bottom:calc(var(--spacing, .25rem) * 5)}axm-chat-voice-recorder .voice-recorder__idle,axm-chat-voice-recorder .voice-recorder__upload{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 6);text-align:center}axm-chat-voice-recorder .voice-recorder__mic{display:flex;height:calc(var(--spacing, .25rem) * 16);width:calc(var(--spacing, .25rem) * 16);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;padding:0;font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));color:rgb(var(--ax-sys-color-on-primary-500));background:rgb(var(--ax-sys-color-primary-500));box-shadow:0 .5rem 1.25rem rgba(var(--ax-sys-color-primary-500),.28)}axm-chat-voice-recorder .voice-recorder__mic:hover,axm-chat-voice-recorder .voice-recorder__mic:focus-visible{--tw-outline-style: none;outline-style:none;background:rgb(var(--ax-sys-color-primary-600))}axm-chat-voice-recorder .voice-recorder__hint,axm-chat-voice-recorder .voice-recorder__upload-label{margin:0;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);color:rgba(var(--ax-sys-color-on-surface),.62)}axm-chat-voice-recorder .voice-recorder__upload{width:100%;max-width:calc(var(--spacing, .25rem) * 72);gap:calc(var(--spacing, .25rem) * 2.5)}axm-chat-voice-recorder .voice-recorder__body{display:flex;width:100%;flex-direction:column;align-items:center}axm-chat-voice-recorder .voice-recorder__visual{display:flex;width:100%;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}axm-chat-voice-recorder .voice-recorder__wave-wrap{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 14);min-width:0px;flex:1;align-items:center}axm-chat-voice-recorder .voice-recorder--preview .voice-recorder__wave-wrap{border-radius:var(--radius-xl, .75rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);background:rgba(var(--ax-sys-color-primary-500),.08)}axm-chat-voice-recorder .voice-recorder__live-wave{display:flex;height:calc(var(--spacing, .25rem) * 9);width:100%;min-width:0px;align-items:center;gap:2px}axm-chat-voice-recorder .voice-recorder__bar{display:block;flex:1 1 0;min-width:0;border-radius:2px;background:rgba(var(--ax-sys-color-on-surface),.16);transform-origin:center}axm-chat-voice-recorder .voice-recorder__bar--recorded{background:rgb(var(--ax-sys-color-primary-500))}axm-chat-voice-recorder .voice-recorder__audio-wave{display:block;min-height:calc(var(--spacing, .25rem) * 9);width:100%;min-width:0px;flex:1}axm-chat-voice-recorder .voice-recorder__audio-wave .ax-audio-wave,axm-chat-voice-recorder .voice-recorder__audio-wave .ax-audio-wave-host{display:block;width:100%}axm-chat-voice-recorder .voice-recorder__play{position:relative;z-index:1;flex-shrink:0}axm-chat-voice-recorder .voice-recorder__play .fa-play{padding-inline-start:.12rem;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-chat-voice-recorder .voice-recorder__play .fa-pause{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-chat-voice-recorder .voice-recorder__time{margin-top:calc(var(--spacing, .25rem) * 4);font-size:1.25rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}axm-chat-voice-recorder .voice-recorder__footer{margin-top:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3)}axm-chat-voice-recorder .voice-recorder__footer:dir(rtl){flex-direction:row-reverse}axm-chat-voice-recorder .voice-recorder__footer-start,axm-chat-voice-recorder .voice-recorder__footer-end{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}axm-chat-voice-recorder .voice-recorder__footer-end,axm-chat-voice-recorder .voice-recorder__transcribe,axm-chat-voice-recorder .voice-recorder__send{min-width:0px}axm-chat-voice-recorder .voice-recorder__transcribe>button,axm-chat-voice-recorder .voice-recorder__send>button{display:flex;height:calc(var(--spacing, .25rem) * 12);align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-xl, .75rem);padding-inline:calc(var(--spacing, .25rem) * 3);font-size:.9375rem;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);box-shadow:none;background-image:none}axm-chat-voice-recorder .voice-recorder__send .fa-paper-plane-top:dir(rtl){transform:scaleX(-1)}axm-chat-voice-recorder .voice-recorder__delete,axm-chat-voice-recorder .voice-recorder__stop{flex-shrink:0}axm-chat-voice-recorder .voice-recorder__delete>button,axm-chat-voice-recorder .voice-recorder__stop>button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);align-items:center;justify-content:center;border-radius:var(--radius-xl, .75rem);--tw-border-style: none;border-style:none;padding:0;font-size:var(--text-lg, 1.125rem);line-height:var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));box-shadow:none}axm-chat-voice-recorder .voice-recorder__delete>button{color:rgb(var(--ax-sys-color-danger-600));background:rgba(var(--ax-sys-color-danger-500),.14)}axm-chat-voice-recorder .voice-recorder__stop>button{color:rgb(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.08)}axm-chat-voice-recorder .voice-recorder__delete:hover>button,axm-chat-voice-recorder .voice-recorder__delete>button:hover{background:rgba(var(--ax-sys-color-danger-500),.22)}axm-chat-voice-recorder .voice-recorder__stop:hover>button,axm-chat-voice-recorder .voice-recorder__stop>button:hover{background:rgba(var(--ax-sys-color-on-surface),.14)}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXAudioWaveComponent, selector: "ax-audio-wave", inputs: ["config"], outputs: ["onStatusChanged"] }, { kind: "component", type: 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: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXLoadingModule }, { kind: "component", type: i8.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXProgressBarModule }, { kind: "component", type: i3$1.AXProgressBarComponent, selector: "ax-progress-bar", inputs: ["color", "mode", "progress", "height"], outputs: ["ValueChange", "sizeChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
14194
14297
|
}
|
|
14195
14298
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMChatVoiceRecorderComponent, decorators: [{
|
|
14196
14299
|
type: Component,
|
|
@@ -14315,7 +14418,7 @@ async function axmOpenChatCallStartDialog(options) {
|
|
|
14315
14418
|
const dialogOpener = options.dialogOpener ?? inject(AXPDialogOpener);
|
|
14316
14419
|
const data = { conversation };
|
|
14317
14420
|
await dialogOpener.openPopup({
|
|
14318
|
-
load: () => import('./acorex-platform-module-conversation-client-chat-call-start-popup.component-
|
|
14421
|
+
load: () => import('./acorex-platform-module-conversation-client-chat-call-start-popup.component-BEa8wEJt.mjs').then((module) => module.AXMChatCallStartPopupComponent),
|
|
14319
14422
|
data: { conversationId: conversation.id },
|
|
14320
14423
|
show: (component) => popupService.open(component, {
|
|
14321
14424
|
header: false,
|
|
@@ -14597,7 +14700,7 @@ const AXM_CHAT_INFO_BAR_CALL_ACTION = {
|
|
|
14597
14700
|
*/
|
|
14598
14701
|
const AXM_CONVERSATION_BOT_RENDERER = {
|
|
14599
14702
|
type: 'assist-response',
|
|
14600
|
-
componentLoader: () => import('./acorex-platform-module-conversation-client-assist-message-renderer.component-
|
|
14703
|
+
componentLoader: () => import('./acorex-platform-module-conversation-client-assist-message-renderer.component-CR4OxDV6.mjs').then(function (n) { return n.b; }).then((m) => m.AXMAssistMessageRendererComponent),
|
|
14601
14704
|
canHandle: (message) => message.type === 'assist-response' || !!message.metadata?.['isAssistResponse'],
|
|
14602
14705
|
capabilities: {
|
|
14603
14706
|
supportsReactions: false,
|
|
@@ -14741,7 +14844,7 @@ async function axmOpenChatCallSessionDialog(options) {
|
|
|
14741
14844
|
let scopedCallId = options.callId?.trim() || '';
|
|
14742
14845
|
try {
|
|
14743
14846
|
const opened = await dialogOpener.openPopup({
|
|
14744
|
-
load: () => import('./acorex-platform-module-conversation-client-chat-call-session-page.component-
|
|
14847
|
+
load: () => import('./acorex-platform-module-conversation-client-chat-call-session-page.component-DJreBgNo.mjs').then((module) => module.AXMChatCallSessionPageComponent),
|
|
14745
14848
|
data: {
|
|
14746
14849
|
conversationId: conversation.id,
|
|
14747
14850
|
callId: scopedCallId,
|
|
@@ -16861,7 +16964,7 @@ class AXMCommentsPageComponentProvider {
|
|
|
16861
16964
|
return [
|
|
16862
16965
|
{
|
|
16863
16966
|
key: COMMENTS_PAGE_COMPONENT_KEY,
|
|
16864
|
-
loader: () => import('./acorex-platform-module-conversation-client-comments-page.component-
|
|
16967
|
+
loader: () => import('./acorex-platform-module-conversation-client-comments-page.component-BsE6bCZT.mjs').then((m) => m.AXMCommentsPageComponent),
|
|
16865
16968
|
},
|
|
16866
16969
|
];
|
|
16867
16970
|
}
|
|
@@ -17167,19 +17270,19 @@ class AXMConversationModule {
|
|
|
17167
17270
|
provideCommandSetups([
|
|
17168
17271
|
{
|
|
17169
17272
|
key: CONVERSATION_AFTER_MESSAGE_SENT_COMMAND,
|
|
17170
|
-
command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-
|
|
17273
|
+
command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-JjZrYD2R.mjs').then((m) => m.AXMConversationAfterMessageSentCommand),
|
|
17171
17274
|
},
|
|
17172
17275
|
{
|
|
17173
17276
|
key: CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND,
|
|
17174
|
-
command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-
|
|
17277
|
+
command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-BvzWaKX4.mjs').then((m) => m.AXMConversationRetryAssistResponseCommand),
|
|
17175
17278
|
},
|
|
17176
17279
|
{
|
|
17177
17280
|
key: CONVERSATION_SYNC_READ_STATE_COMMAND,
|
|
17178
|
-
command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-
|
|
17281
|
+
command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-DQXezGRu.mjs').then((m) => m.AXMConversationSyncReadStateCommand),
|
|
17179
17282
|
},
|
|
17180
17283
|
{
|
|
17181
17284
|
key: CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND,
|
|
17182
|
-
command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-
|
|
17285
|
+
command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-B1mvtbaA.mjs').then((m) => m.AXMConversationMarkConversationUnreadCommand),
|
|
17183
17286
|
},
|
|
17184
17287
|
{
|
|
17185
17288
|
key: CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND,
|
|
@@ -17191,7 +17294,7 @@ class AXMConversationModule {
|
|
|
17191
17294
|
},
|
|
17192
17295
|
{
|
|
17193
17296
|
key: CONVERSATION_OPEN_CHAT_COMMAND,
|
|
17194
|
-
command: () => import('./acorex-platform-module-conversation-client-open-chat.command-
|
|
17297
|
+
command: () => import('./acorex-platform-module-conversation-client-open-chat.command-CbJ0gXZq.mjs').then((m) => m.AXMConversationOpenChatCommand),
|
|
17195
17298
|
},
|
|
17196
17299
|
{
|
|
17197
17300
|
key: 'show-comment-popup',
|
|
@@ -17310,19 +17413,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
17310
17413
|
provideCommandSetups([
|
|
17311
17414
|
{
|
|
17312
17415
|
key: CONVERSATION_AFTER_MESSAGE_SENT_COMMAND,
|
|
17313
|
-
command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-
|
|
17416
|
+
command: () => import('./acorex-platform-module-conversation-client-after-message-sent.command-JjZrYD2R.mjs').then((m) => m.AXMConversationAfterMessageSentCommand),
|
|
17314
17417
|
},
|
|
17315
17418
|
{
|
|
17316
17419
|
key: CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND,
|
|
17317
|
-
command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-
|
|
17420
|
+
command: () => import('./acorex-platform-module-conversation-client-retry-assist-response.command-BvzWaKX4.mjs').then((m) => m.AXMConversationRetryAssistResponseCommand),
|
|
17318
17421
|
},
|
|
17319
17422
|
{
|
|
17320
17423
|
key: CONVERSATION_SYNC_READ_STATE_COMMAND,
|
|
17321
|
-
command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-
|
|
17424
|
+
command: () => import('./acorex-platform-module-conversation-client-sync-read-state.command-DQXezGRu.mjs').then((m) => m.AXMConversationSyncReadStateCommand),
|
|
17322
17425
|
},
|
|
17323
17426
|
{
|
|
17324
17427
|
key: CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND,
|
|
17325
|
-
command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-
|
|
17428
|
+
command: () => import('./acorex-platform-module-conversation-client-mark-conversation-unread.command-B1mvtbaA.mjs').then((m) => m.AXMConversationMarkConversationUnreadCommand),
|
|
17326
17429
|
},
|
|
17327
17430
|
{
|
|
17328
17431
|
key: CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND,
|
|
@@ -17334,7 +17437,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
17334
17437
|
},
|
|
17335
17438
|
{
|
|
17336
17439
|
key: CONVERSATION_OPEN_CHAT_COMMAND,
|
|
17337
|
-
command: () => import('./acorex-platform-module-conversation-client-open-chat.command-
|
|
17440
|
+
command: () => import('./acorex-platform-module-conversation-client-open-chat.command-CbJ0gXZq.mjs').then((m) => m.AXMConversationOpenChatCommand),
|
|
17338
17441
|
},
|
|
17339
17442
|
{
|
|
17340
17443
|
key: 'show-comment-popup',
|
|
@@ -17370,4 +17473,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
17370
17473
|
*/
|
|
17371
17474
|
|
|
17372
17475
|
export { axmShouldForkPrivateToGroup as $, AXMConversationEntityStoreService as A, axmSanitizeAssistUserAnswerText as B, axmAssistUserVisibleItemsForLine as C, axmReadAssistFollowUpStatus as D, axmReadPlainTextMessagePayload as E, AXMNodeMessageRendererComponent as F, AXMAssistSuggestionChipsComponent as G, AXMChatCallActiveSessionService as H, axmResolveConversationListAvatar as I, axmEnsureChatCallRtcReady as J, axmOpenChatCallSessionDialog as K, axmChatCallMediaRoomName as L, axmResolveChatCallLiveKitServerUrl as M, axmChatCallRoomConnectOptions as N, loadLiveKitClient as O, AXM_CHAT_CALL_RTC_API_PROVIDERS as P, AXMConversationAppearanceSyncService as Q, axmCancelAssistComposerGeneration as R, AXMChatEmptyStateHostComponent as S, AXMChatComposerEnsureAssistConversationDirective as T, AXMChatUserApi as U, AXMChatEntityConversationApi as V, AXMChatConversationApi as W, AXMChatCallRtcSignalInboxService as X, AXMChatCallEventsService as Y, AXMConversationRealtimeBus as Z, axmReadChatCallLog as _, AXM_CONVERSATION_ASSIST_RESPONSE_PORT as a, CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND as a$, axmIsConversationParticipant as a0, axmBuildChatCallLogMessage as a1, axmMatchesForkedGroupForCall as a2, axmAssistWidgetNodeFromUnknown as a3, AXMAddReactionCommand as a4, AXMChannelFeedItemComponent as a5, AXMChannelFeedPage as a6, AXMChatAnnouncementChannelService as a7, AXMChatComponent as a8, AXMChatComposerAssistPickerComponent as a9, AXMMiniChatPanelService as aA, AXMMiniChatPopupWindowComponent as aB, AXMShowCommentPopupCommand as aC, AXM_AI_MANAGEMENT_ASSIST_ENTITY_NAME as aD, AXM_ASSIST_DEFAULT_RESOLVER_PORT as aE, AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE as aF, AXM_CHAT_ASSIST_CATALOG_PORT as aG, AXM_CHAT_EMPTY_STATE_COMPONENT as aH, AXM_CHAT_SIDEBAR_ACTION_PROVIDER as aI, AXM_CONVERSATION_ASSIST_BACKGROUND_OPERATION_HANDLERS as aJ, AXM_CONVERSATION_ASSIST_BACKGROUND_OPERATION_KEY as aK, AXM_CONVERSATION_CHAT_ATTACHMENT_CATEGORY as aL, AXM_CONVERSATION_CHAT_ATTACHMENT_REF_TYPE as aM, AXM_CONVERSATION_TAB_BOT as aN, AXM_ENTITY_LIST_CHAT_ID as aO, AXM_MINI_CHAT_INBOX_CONVERSATION_FILTER as aP, AXM_MINI_CHAT_INBOX_SESSION_KEY as aQ, AXM_MINI_CHAT_POPUP_DOCK as aR, AXM_MINI_CHAT_SCOPE_ENTITY as aS, AXM_MINI_CHAT_SCOPE_METADATA_KEY as aT, AXPCommentWidget as aU, COMMENTS_PAGE_COMPONENT_KEY as aV, CONVERSATION_AFTER_MESSAGE_SENT_COMMAND as aW, CONVERSATION_EMIT_TYPING_INDICATOR_COMMAND as aX, CONVERSATION_MARK_CONVERSATION_UNREAD_COMMAND as aY, CONVERSATION_OPEN_CHAT_COMMAND as aZ, CONVERSATION_RETRY_ASSIST_RESPONSE_COMMAND as a_, AXMChatEmptyAssistSessionService as aa, AXMChatEntityConversationFocusHandler as ab, AXMChatEntityConversationRoomQueryService as ac, AXMChatEntityMessageApi as ad, AXMChatEntityRealtimeApi as ae, AXMChatEntityUserApi as af, AXMChatRealtimeApi as ag, AXMCommentManagementService as ah, AXMCommentPopupComponent as ai, AXMCommentRealtimeService as aj, AXMCommentRealtimeServiceImpl as ak, AXMCommentService as al, AXMCommentServiceImpl as am, AXMCommentWidgetViewComponent as an, AXMConversationAssistBackgroundOperationHandler as ao, AXMConversationModule as ap, AXMEntityChatService as aq, AXMMiniChatComponent as ar, AXMMiniChatFileDropService as as, AXMMiniChatFooterDockComponent as at, AXMMiniChatHeaderSlotComponent as au, AXMMiniChatHistoryComponent as av, AXMMiniChatInboxHistoryComponent as aw, AXMMiniChatLauncherComponent as ax, AXMMiniChatPageActionComponent as ay, AXMMiniChatPanelComponent as az, AXM_CONVERSATION_REGULAR_AUTO_REPLY_PORT as b, axmResolveChatAiTargetText as b$, CONVERSATION_START_ASSIST_CHAT_COMMAND as b0, CONVERSATION_START_DIRECT_CHAT_COMMAND as b1, CONVERSATION_SYNC_READ_STATE_COMMAND as b2, axmApplyAnswerTextToAssistPayloadLine as b3, axmAssistFollowUpItemsFromUnknown as b4, axmAssistLastTranscriptLine as b5, axmAssistNormalizeFollowUpItemForConversation as b6, axmAssistNormalizeFollowUpItemsForConversation as b7, axmAssistPersistedMessageLooksComplete as b8, axmAssistResolveFollowUpCommandName as b9, axmExtractAssistSnapshotFromMetadata as bA, axmExtractDirectAgentIdFromMetadata as bB, axmExtractEntityRefFromMetadata as bC, axmExtractModelEntityIdFromMetadata as bD, axmExtractTextFromPayload as bE, axmFilterChatAiTargets as bF, axmFlattenConversationCreateMetadata as bG, axmHydrateRealtimeConversationMessage as bH, axmInboxConversationTab as bI, axmIsAssistBotConversation as bJ, axmIsAssistPeerParticipant as bK, axmIsAssistResponseMessage as bL, axmIsAssistStreamingMessage as bM, axmIsAssistTerminalStatus as bN, axmIsUnsupportedLegacyAgentAssistConversation as bO, axmLoadChatAiTargets as bP, axmMessageEntityToMessage as bQ, axmMiniChatHistoryScopeFromDraft as bR, axmMiniChatHistoryScopeFromOpen as bS, axmMiniChatHistoryScopeKey as bT, axmMiniChatWindowOwnsRoute as bU, axmNormalizeAssistTranscriptForChatUi as bV, axmNormalizeAssistTranscriptLineResponses as bW, axmPreferLocalUnreadCount as bX, axmReadReplyToUserMessageId as bY, axmRemoveMiniChatHistoryItem as bZ, axmResolveAssistFinalAnswerText as b_, axmAssistStarterPromptChipItems as ba, axmAssistSuggestionIconForLabel as bb, axmAssistWidgetNodeDedupeKey as bc, axmBuildAiChatConversationMetadata as bd, axmBuildAssistPeerParticipantFromCreateData as be, axmBuildAssistPeerParticipantFromId as bf, axmBuildAssistTranscriptLinePayload as bg, axmBuildAutoTitleFromUserText as bh, axmBuildEntityChatConversationMetadata as bi, axmBuildEntityChatRoomEntityRef as bj, axmChatAiPeerParticipantId as bk, axmChatAiTargetAvatarUrl as bl, axmChatAiTargetDisplayDescription as bm, axmChatAiTargetDisplayName as bn, axmChatAiTargetShortcutDescriptionKey as bo, axmCoerceDate as bp, axmCoerceTimestampMs as bq, axmComputeConversationUnreadCount as br, axmConversationIsEntityChat as bs, axmConversationIsGlobalChat as bt, axmConversationMatchesEntity as bu, axmConversationMatchesHistoryScope as bv, axmEntityRefForMiniChatPageContext as bw, axmEntityRefFromLaunchContext as bx, axmExcludeEntityChatConversations as by, axmExtractAssistIdFromMetadata as bz, axmConversationHasAiChat$1 as c, axmRoomEntityToConversation as c0, axmRoomIsEntityChat as c1, axmRoomLaunchContext as c2, axmRoomMatchesEntity as c3, axmRoomWithAssistPeerDisplayName as c4, axmShouldPreferPersistedAssistOverLiveCache as c5, axmSortMessagesNewestFirst as c6, axmSyncAssistPeerDisplayName as c7, axmUpsertMiniChatHistoryItem as c8, axmUserRowToParticipant as c9, axpShowCommentPopupCommandDefinition as ca, channelFeedPageRoutes as cb, commentsPlugin as cc, createConversationServiceSessionAdapter as cd, persistChatAttachment as ce, AXMConversationFocusService as d, AXMConversationInAppNotificationSyncService as e, axmMessageCountsTowardUnread as f, buildConversationChatInAppCorrelationPrefix as g, AXMCommentComponent as h, axmResolveI18nLabel as i, axmSyntheticEmbedMessage as j, axmChatRenderableAssistWidgetNode as k, axmPartitionAssistAnswerText as l, axmParseAssistTranscriptTextEnvelope as m, AXMAssistChatDebugModeService as n, AXMChatMessageApi as o, AXM_AI_MANAGEMENT_MODULE_NAME as p, AXM_AI_MANAGEMENT_AGENT_ENTITY_NAME as q, axmReadAssistResponseStatus as r, axmIsAssistRetryableStatus as s, axmReadAssistResponseError as t, axmReadAssistAiTranscript as u, axmParseAssistTranscriptLinePayload as v, axmReadAssistAiTranscriptRaw as w, axmAssistUserFacingPayloadLine as x, axmIsAssistStreamingStatus as y, axmAssistHasFinalizeMetadata as z };
|
|
17373
|
-
//# sourceMappingURL=acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-
|
|
17476
|
+
//# sourceMappingURL=acorex-platform-module-conversation-client-acorex-platform-module-conversation-client-CmRULmpl.mjs.map
|