@acorex/modules 21.0.0-next.55 → 21.0.0-next.57
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-modules-ai-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-application-management.mjs +1 -1
- package/fesm2022/acorex-modules-application-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-auth-acorex-modules-auth-NPUjHz-F.mjs → acorex-modules-auth-acorex-modules-auth-wfCSNwXC.mjs} +14 -14
- package/fesm2022/{acorex-modules-auth-acorex-modules-auth-NPUjHz-F.mjs.map → acorex-modules-auth-acorex-modules-auth-wfCSNwXC.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-app-chooser.component-h61xNtRT.mjs → acorex-modules-auth-app-chooser.component-BY281-Cl.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-app-chooser.component-h61xNtRT.mjs.map → acorex-modules-auth-app-chooser.component-BY281-Cl.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-login.module-DF5AHqYe.mjs → acorex-modules-auth-login.module-CjgYlyOv.mjs} +4 -4
- package/fesm2022/{acorex-modules-auth-login.module-DF5AHqYe.mjs.map → acorex-modules-auth-login.module-CjgYlyOv.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-master.layout-00ZTMhc3.mjs → acorex-modules-auth-master.layout-Clx8QDYW.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-master.layout-00ZTMhc3.mjs.map → acorex-modules-auth-master.layout-Clx8QDYW.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-Ce5Fw8Qd.mjs → acorex-modules-auth-oauth-callback.component-CGnGAPJ2.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-Ce5Fw8Qd.mjs.map → acorex-modules-auth-oauth-callback.component-CGnGAPJ2.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-DQYCm8wg.mjs → acorex-modules-auth-password.component-8eEX0lRP.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-password.component-DQYCm8wg.mjs.map → acorex-modules-auth-password.component-8eEX0lRP.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-CU0AY-Ia.mjs → acorex-modules-auth-password.component-CUxwThnN.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-password.component-CU0AY-Ia.mjs.map → acorex-modules-auth-password.component-CUxwThnN.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-routes-CM4fRaWb.mjs → acorex-modules-auth-routes-CYLKJm9g.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-routes-CM4fRaWb.mjs.map → acorex-modules-auth-routes-CYLKJm9g.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-BBztdcvq.mjs → acorex-modules-auth-tenant-chooser.component-DDK1KW-8.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-BBztdcvq.mjs.map → acorex-modules-auth-tenant-chooser.component-DDK1KW-8.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-two-factor.module-C9AafF86.mjs → acorex-modules-auth-two-factor.module-Iw2U7Cy5.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-two-factor.module-C9AafF86.mjs.map → acorex-modules-auth-two-factor.module-Iw2U7Cy5.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-user-sessions.component-Qw2sgsEe.mjs → acorex-modules-auth-user-sessions.component-sKDANprs.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-user-sessions.component-Qw2sgsEe.mjs.map → acorex-modules-auth-user-sessions.component-sKDANprs.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth.mjs +1 -1
- package/fesm2022/{acorex-modules-common-audit-info-column.component-SiqKcBMQ.mjs → acorex-modules-common-audit-info-column.component-MSYPMPZJ.mjs} +2 -2
- package/fesm2022/{acorex-modules-common-audit-info-column.component-SiqKcBMQ.mjs.map → acorex-modules-common-audit-info-column.component-MSYPMPZJ.mjs.map} +1 -1
- package/fesm2022/acorex-modules-common.mjs +1 -1
- package/fesm2022/{acorex-modules-conversation-acorex-modules-conversation-UNhA-qi5.mjs → acorex-modules-conversation-acorex-modules-conversation-DlteA_jC.mjs} +343 -1008
- package/fesm2022/acorex-modules-conversation-acorex-modules-conversation-DlteA_jC.mjs.map +1 -0
- package/fesm2022/{acorex-modules-conversation-assist-delegated-agent-detail-popup.component-Be58gcns.mjs → acorex-modules-conversation-assist-delegated-agent-detail-popup.component-BAgBuxlz.mjs} +2 -2
- package/fesm2022/{acorex-modules-conversation-assist-delegated-agent-detail-popup.component-Be58gcns.mjs.map → acorex-modules-conversation-assist-delegated-agent-detail-popup.component-BAgBuxlz.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-conversation-comments-page.component-3XBLeMW8.mjs → acorex-modules-conversation-comments-page.component-BrwP9l7M.mjs} +2 -2
- package/fesm2022/{acorex-modules-conversation-comments-page.component-3XBLeMW8.mjs.map → acorex-modules-conversation-comments-page.component-BrwP9l7M.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-conversation-send-assist-chat-message.command-CSu-lJuu.mjs → acorex-modules-conversation-send-assist-chat-message.command-BzKawEoN.mjs} +2 -2
- package/fesm2022/{acorex-modules-conversation-send-assist-chat-message.command-CSu-lJuu.mjs.map → acorex-modules-conversation-send-assist-chat-message.command-BzKawEoN.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-conversation-start-assist-chat.command-CyoncQB1.mjs → acorex-modules-conversation-start-assist-chat.command-BUOGUMl0.mjs} +2 -2
- package/fesm2022/{acorex-modules-conversation-start-assist-chat.command-CyoncQB1.mjs.map → acorex-modules-conversation-start-assist-chat.command-BUOGUMl0.mjs.map} +1 -1
- package/fesm2022/acorex-modules-conversation.mjs +1 -1
- package/fesm2022/acorex-modules-locale-management.mjs +27 -22
- package/fesm2022/acorex-modules-locale-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-notification-management.mjs +1 -1
- package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-platform-dev-tools.mjs +2 -2
- package/fesm2022/acorex-modules-platform-dev-tools.mjs.map +1 -1
- package/fesm2022/acorex-modules-report-management.mjs +1 -1
- package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-settings-management-acorex-modules-settings-management-Di6Sxtq3.mjs → acorex-modules-settings-management-acorex-modules-settings-management-B4Ee8USF.mjs} +6 -6
- package/fesm2022/{acorex-modules-settings-management-acorex-modules-settings-management-Di6Sxtq3.mjs.map → acorex-modules-settings-management-acorex-modules-settings-management-B4Ee8USF.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-settings-management-permission-definition.provider-Bml5VZUT.mjs → acorex-modules-settings-management-permission-definition.provider-nNhEFyc-.mjs} +2 -2
- package/fesm2022/{acorex-modules-settings-management-permission-definition.provider-Bml5VZUT.mjs.map → acorex-modules-settings-management-permission-definition.provider-nNhEFyc-.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-settings-management-setting-page.component-lN-7sTpD.mjs → acorex-modules-settings-management-setting-page.component-CEvWwS_a.mjs} +2 -2
- package/fesm2022/{acorex-modules-settings-management-setting-page.component-lN-7sTpD.mjs.map → acorex-modules-settings-management-setting-page.component-CEvWwS_a.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-settings-management-setting-view.component-D17G4RNQ.mjs → acorex-modules-settings-management-setting-view.component-C6ftmjuK.mjs} +2 -2
- package/fesm2022/{acorex-modules-settings-management-setting-view.component-D17G4RNQ.mjs.map → acorex-modules-settings-management-setting-view.component-C6ftmjuK.mjs.map} +1 -1
- package/fesm2022/acorex-modules-settings-management.mjs +1 -1
- package/fesm2022/{acorex-modules-task-management-acorex-modules-task-management-LQn5gZ6p.mjs → acorex-modules-task-management-acorex-modules-task-management-CrybKNgo.mjs} +2 -2
- package/fesm2022/{acorex-modules-task-management-acorex-modules-task-management-LQn5gZ6p.mjs.map → acorex-modules-task-management-acorex-modules-task-management-CrybKNgo.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-task-management-task-board.page-BokG-G6Z.mjs → acorex-modules-task-management-task-board.page-B2xxXscG.mjs} +4 -4
- package/fesm2022/{acorex-modules-task-management-task-board.page-BokG-G6Z.mjs.map → acorex-modules-task-management-task-board.page-B2xxXscG.mjs.map} +1 -1
- package/fesm2022/acorex-modules-task-management.mjs +1 -1
- package/fesm2022/{acorex-modules-workflow-management-index-BxqOP8AA.mjs → acorex-modules-workflow-management-index-RRzkvrNM.mjs} +102 -21
- package/fesm2022/acorex-modules-workflow-management-index-RRzkvrNM.mjs.map +1 -0
- package/fesm2022/acorex-modules-workflow-management.mjs +2 -2
- package/package.json +2 -2
- package/types/acorex-modules-ai-management.d.ts +4 -0
- package/types/acorex-modules-conversation.d.ts +35 -198
- package/fesm2022/acorex-modules-conversation-acorex-modules-conversation-UNhA-qi5.mjs.map +0 -1
- package/fesm2022/acorex-modules-workflow-management-index-BxqOP8AA.mjs.map +0 -1
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
import { AXConversationModule } from '@acorex/components/conversation';
|
|
2
2
|
import { AXPSessionService, AXPAuthGuard, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
|
|
3
3
|
import { createAllQueryView, AXPEntityQueryType, AXPSettingsService, AXPCommonSettings, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, AXPFileStorageService, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
|
|
4
|
-
import { AXPSystemActionType,
|
|
4
|
+
import { AXPSystemActionType, AXPPlatformScope, AXPDeviceService, AXP_MODULE_MANIFEST_PROVIDER } from '@acorex/platform/core';
|
|
5
5
|
import { AXPMarkdownViewerComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutStartSideComponent, AXPUserAvatarComponent, AXPMarkdownTemplateDirective, AXP_PAGE_COMPONENT_PROVIDER, AXP_TASK_BADGE_PROVIDERS } from '@acorex/platform/layout/components';
|
|
6
|
-
import {
|
|
6
|
+
import { AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions, AXPEntityDefinitionRegistryService, AXPEntityService, cloneLayoutArrays, ensureLayoutSection, ensureLayoutPropertyView, resolveEntityPluginDetailPageOrder, ensureListActions, actionExists, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
7
|
+
import { AXPCommandService, provideCommandSetups } from '@acorex/platform/runtime';
|
|
7
8
|
import { AXPRootLayoutComponent } from '@acorex/platform/themes/default';
|
|
8
9
|
import * as i5 from '@angular/common';
|
|
9
10
|
import { AsyncPipe, CommonModule, isPlatformBrowser, DecimalPipe, DatePipe } from '@angular/common';
|
|
10
|
-
import { AXPCommandService, provideCommandSetups } from '@acorex/platform/runtime';
|
|
11
11
|
import * as i0 from '@angular/core';
|
|
12
|
-
import {
|
|
12
|
+
import { Injectable, NgModule, inject, computed, input, ChangeDetectionStrategy, Component, signal, effect, untracked, output, viewChild, afterNextRender, DestroyRef, ElementRef, ViewEncapsulation, PLATFORM_ID, Injector, importProvidersFrom } from '@angular/core';
|
|
13
13
|
import { Router, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
|
|
14
|
+
import * as i1$2 from '@acorex/platform/layout/widget-core';
|
|
15
|
+
import { AXPWidgetsCatalog, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetCoreModule, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
14
16
|
import { sortBy } from 'lodash-es';
|
|
15
17
|
import { RootConfig as RootConfig$1, axpAiAssistStarterPromptLabels, axpAiAssistInitialMessagesToTranscript, axpAiChatMessageGetText, AXPAiManagerService, axpAiChatMessageIsDelegatedReflectionExcluded, axpAiDelegatedAgentResultSegments, axpAiChatTextMessage, AXPAiChatToolRunContextService, AXPAiPlatformRuntimeContextBuilder, AIMANAGEMENT_STRUCTURED_TEXT_COMPLETION_COMMAND_KEY, persistAiChatAttachmentImage, AIMANAGEMENT_CHAT_TRANSCRIBE_SPEECH_COMMAND_KEY, AXPAiAssistChatModelCatalogService, axpAiParseSupervisorAgentToolName, axpAiDelegatedAgentPromptPreview, axpAiChatToolOrAgentResultBodyJson, axpAiDelegatedAgentOutcomeResponsesPlainText } from '@acorex/modules/ai-management';
|
|
16
18
|
import { AXConversationService, AXUserApi, AXConversationApi, AXMessageApi, AXRealtimeApi, conversationSharedStorage, AXNewConversationDialogComponent, AXComposerService, AXInfoBarService, AXConversationContainerDirective, AXSidebarComponent, AXInfoBarComponent, AXMessageListComponent, AXComposerComponent, axConversationIndexedDbStorage, AXImageRendererComponent, AXTextRendererComponent, provideConversation, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_INFO_BAR_INFO_ACTION, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_VOICE_RENDERER, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_STICKER_RENDERER } from '@acorex/components/conversation2';
|
|
17
19
|
import { AXToastService } from '@acorex/components/toast';
|
|
18
20
|
import * as i3 from '@acorex/core/translation';
|
|
19
21
|
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
20
|
-
import * as i1$2 from '@acorex/platform/layout/widget-core';
|
|
21
|
-
import { AXPWidgetsCatalog, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetCoreModule, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
22
22
|
import * as i1$5 from '@acorex/platform/workflow';
|
|
23
23
|
import { AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
24
|
-
import { AXMNotificationConnectorService, AXP_NOTIFICATION_DEFINITION_PROVIDER } from '@acorex/modules/notification-management';
|
|
25
|
-
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
26
|
-
import { Subject, map, filter, merge, auditTime } from 'rxjs';
|
|
27
24
|
import * as i2 from '@acorex/components/button';
|
|
28
25
|
import { AXButtonModule, AXButtonComponent } from '@acorex/components/button';
|
|
29
26
|
import * as i2$1 from '@acorex/components/decorators';
|
|
@@ -31,6 +28,7 @@ import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
|
31
28
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
32
29
|
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent } from '@acorex/platform/layout/views';
|
|
33
30
|
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
31
|
+
import { map, Subject, filter } from 'rxjs';
|
|
34
32
|
import * as i3$1 from '@acorex/components/dropdown';
|
|
35
33
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
36
34
|
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
@@ -44,6 +42,7 @@ import { AXImageComponent, AXImageModule } from '@acorex/components/image';
|
|
|
44
42
|
import { AXListComponent } from '@acorex/components/list';
|
|
45
43
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
46
44
|
import { AXSearchBoxComponent } from '@acorex/components/search-box';
|
|
45
|
+
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
47
46
|
import * as i1$1 from '@acorex/components/wysiwyg';
|
|
48
47
|
import { AXWysiwygModule } from '@acorex/components/wysiwyg';
|
|
49
48
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
@@ -59,6 +58,7 @@ import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
|
59
58
|
import { AXToolBarModule } from '@acorex/components/toolbar';
|
|
60
59
|
import * as i9 from '@acorex/core/format';
|
|
61
60
|
import { AXFormatModule } from '@acorex/core/format';
|
|
61
|
+
import { AXMNotificationConnectorService, AXP_NOTIFICATION_DEFINITION_PROVIDER } from '@acorex/modules/notification-management';
|
|
62
62
|
import { AXPLayoutBuilderService, AXPLayoutRendererComponent } from '@acorex/platform/layout/builder';
|
|
63
63
|
import { AXLabelModule } from '@acorex/components/label';
|
|
64
64
|
import * as i1$4 from '@acorex/cdk/accordion';
|
|
@@ -101,283 +101,18 @@ const RootConfig = {
|
|
|
101
101
|
},
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
const CONVERSATION_START_ASSIST_CHAT_COMMAND = 'Conversation:StartAssistChat';
|
|
106
|
-
/** Sends a user text message in the active assist chat, or starts a chat when {@code assistId} is provided. */
|
|
107
|
-
const CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND = 'Conversation:SendAssistChatMessage';
|
|
108
|
-
|
|
109
|
-
//#region ---- Imports ----
|
|
110
|
-
//#endregion
|
|
111
|
-
//#region ---- Participant & metadata ----
|
|
112
|
-
/** Synthetic bot participant id for assist chats. */
|
|
113
|
-
function axmChatAiPeerParticipantId(catalogId) {
|
|
114
|
-
return `assist-${catalogId.trim()}`;
|
|
115
|
-
}
|
|
116
|
-
/** Conversation metadata for starting an AI chat from a picker row. */
|
|
117
|
-
function axmBuildAiChatConversationMetadata(row) {
|
|
118
|
-
return { assistId: row.id };
|
|
119
|
-
}
|
|
120
|
-
/** True when conversation metadata targets an assist row. */
|
|
121
|
-
function axmConversationHasAiChat(conversation) {
|
|
122
|
-
const assistId = conversation?.metadata?.['assistId'];
|
|
123
|
-
return typeof assistId === 'string' && assistId.trim().length > 0;
|
|
124
|
-
}
|
|
125
|
-
/** Loads assist rows for Conversation AI chat pickers. */
|
|
126
|
-
async function axmLoadChatAiTargets(entityRegistry) {
|
|
127
|
-
const assists = await axmQueryEntityList(entityRegistry, RootConfig$1.entities.assist.name);
|
|
128
|
-
return assists
|
|
129
|
-
.map((raw) => ({
|
|
130
|
-
id: String(raw['id'] ?? ''),
|
|
131
|
-
name: String(raw['name'] ?? ''),
|
|
132
|
-
title: raw['title'],
|
|
133
|
-
description: raw['description'],
|
|
134
|
-
professionImageUrl: typeof raw['professionImageUrl'] === 'string' ? raw['professionImageUrl'] : undefined,
|
|
135
|
-
}))
|
|
136
|
-
.filter((row) => row.id.trim().length > 0)
|
|
137
|
-
.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }));
|
|
138
|
-
}
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region ---- Display & filter (dialog + global search) ----
|
|
141
|
-
/** Resolves ML or plain string for search/display. */
|
|
142
|
-
function axmResolveChatAiTargetText(resolveMl, value) {
|
|
143
|
-
if (!value) {
|
|
144
|
-
return '';
|
|
145
|
-
}
|
|
146
|
-
if (typeof value === 'string') {
|
|
147
|
-
return value;
|
|
148
|
-
}
|
|
149
|
-
return resolveMl(value) ?? '';
|
|
150
|
-
}
|
|
151
|
-
function axmChatAiTargetDisplayName(resolveMl, row) {
|
|
152
|
-
return axmResolveChatAiTargetText(resolveMl, row.title).trim() || row.name.trim() || row.id;
|
|
153
|
-
}
|
|
154
|
-
function axmChatAiTargetDisplayDescription(resolveMl, row) {
|
|
155
|
-
if (!row.description) {
|
|
156
|
-
return undefined;
|
|
157
|
-
}
|
|
158
|
-
const text = axmResolveChatAiTargetText(resolveMl, row.description).trim();
|
|
159
|
-
return text || undefined;
|
|
160
|
-
}
|
|
161
|
-
function axmChatAiTargetAvatarUrl(row) {
|
|
162
|
-
const url = row.professionImageUrl?.trim();
|
|
163
|
-
return url ? url : null;
|
|
164
|
-
}
|
|
165
|
-
/** Fallback i18n key for rows with no catalog description. */
|
|
166
|
-
function axmChatAiTargetShortcutDescriptionKey() {
|
|
167
|
-
return '@conversation:search.assist.shortcut-description';
|
|
168
|
-
}
|
|
169
|
-
/** Same filter as {@link AXMChatWithAssistDialogComponent} target list search. */
|
|
170
|
-
function axmFilterChatAiTargets(resolveMl, rows, query) {
|
|
171
|
-
const q = query.trim().toLowerCase();
|
|
172
|
-
if (!q) {
|
|
173
|
-
return rows;
|
|
174
|
-
}
|
|
175
|
-
return rows.filter((r) => {
|
|
176
|
-
const titleText = axmResolveChatAiTargetText(resolveMl, r.title).toLowerCase();
|
|
177
|
-
return (r.name.toLowerCase().includes(q) ||
|
|
178
|
-
titleText.includes(q) ||
|
|
179
|
-
axmResolveChatAiTargetText(resolveMl, r.description).toLowerCase().includes(q));
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
//#endregion
|
|
183
|
-
//#region ---- Entity list query ----
|
|
184
|
-
async function axmQueryEntityList(entityRegistry, entityName) {
|
|
185
|
-
const entity = await entityRegistry.resolve(RootConfig$1.module.name, entityName);
|
|
186
|
-
const execute = entity.queries?.list?.execute;
|
|
187
|
-
if (!execute) {
|
|
188
|
-
throw new Error(`${entityName} entity has no list query.`);
|
|
189
|
-
}
|
|
190
|
-
const res = await execute({
|
|
191
|
-
skip: 0,
|
|
192
|
-
take: 500,
|
|
193
|
-
sort: [{ name: 'name', dir: 'asc' }],
|
|
194
|
-
});
|
|
195
|
-
return res.items ?? [];
|
|
196
|
-
}
|
|
197
|
-
//#endregion
|
|
198
|
-
|
|
199
|
-
//#region ---- Imports ----
|
|
200
|
-
//#endregion
|
|
201
|
-
//#region ---- Service ----
|
|
202
|
-
/**
|
|
203
|
-
* Starts bot conversations from catalog assist rows,
|
|
204
|
-
* shared by global search shortcuts and {@link AXMConversationStartAssistChatCommand}.
|
|
205
|
-
*/
|
|
206
|
-
class AXMChatAssistLauncherService {
|
|
207
|
-
constructor() {
|
|
208
|
-
this.conversationService = inject(AXConversationService);
|
|
209
|
-
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
210
|
-
this.translationService = inject(AXTranslationService);
|
|
211
|
-
this.sessionService = inject(AXPSessionService);
|
|
212
|
-
this.router = inject(Router);
|
|
213
|
-
this.toastService = inject(AXToastService);
|
|
214
|
-
this.targetsCache = null;
|
|
215
|
-
this.loadPromise = null;
|
|
216
|
-
}
|
|
217
|
-
async loadTargets(force = false) {
|
|
218
|
-
if (!force && this.targetsCache) {
|
|
219
|
-
return this.targetsCache;
|
|
220
|
-
}
|
|
221
|
-
if (!force && this.loadPromise) {
|
|
222
|
-
return this.loadPromise;
|
|
223
|
-
}
|
|
224
|
-
this.loadPromise = axmLoadChatAiTargets(this.entityRegistry);
|
|
225
|
-
try {
|
|
226
|
-
this.targetsCache = await this.loadPromise;
|
|
227
|
-
return this.targetsCache;
|
|
228
|
-
}
|
|
229
|
-
finally {
|
|
230
|
-
this.loadPromise = null;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
displayName(row) {
|
|
234
|
-
return axmChatAiTargetDisplayName(this.#resolveMl.bind(this), row);
|
|
235
|
-
}
|
|
236
|
-
displayDescription(row) {
|
|
237
|
-
return axmChatAiTargetDisplayDescription(this.#resolveMl.bind(this), row);
|
|
238
|
-
}
|
|
239
|
-
targetAvatarUrl(row) {
|
|
240
|
-
return axmChatAiTargetAvatarUrl(row);
|
|
241
|
-
}
|
|
242
|
-
filterTargets(rows, query) {
|
|
243
|
-
return axmFilterChatAiTargets(this.#resolveMl.bind(this), rows, query);
|
|
244
|
-
}
|
|
245
|
-
async startAssistChat(options) {
|
|
246
|
-
const targetId = (options.targetId ?? options.assistId)?.trim();
|
|
247
|
-
if (!targetId) {
|
|
248
|
-
return null;
|
|
249
|
-
}
|
|
250
|
-
const rows = await this.loadTargets();
|
|
251
|
-
const row = rows.find((r) => r.id === targetId);
|
|
252
|
-
if (!row) {
|
|
253
|
-
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.start-chat');
|
|
254
|
-
this.toastService.danger(message);
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
try {
|
|
258
|
-
const conversation = await this.#createTargetConversation(row);
|
|
259
|
-
await this.conversationService.selectConversation(conversation.id);
|
|
260
|
-
if (options.navigate !== false) {
|
|
261
|
-
await this.router.navigate([this.#applicationRouteSegment(), 'chat', conversation.id]);
|
|
262
|
-
}
|
|
263
|
-
return { conversation };
|
|
264
|
-
}
|
|
265
|
-
catch (error) {
|
|
266
|
-
console.error('Failed to start AI chat:', error);
|
|
267
|
-
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.start-chat');
|
|
268
|
-
this.toastService.danger(message);
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
async #createTargetConversation(row) {
|
|
273
|
-
const participantId = axmChatAiPeerParticipantId(row.id);
|
|
274
|
-
const title = this.displayName(row);
|
|
275
|
-
const avatar = this.targetAvatarUrl(row);
|
|
276
|
-
return this.conversationService.createConversation([participantId], 'bot', {
|
|
277
|
-
title,
|
|
278
|
-
...(avatar ? { avatar } : {}),
|
|
279
|
-
icon: 'fa-solid fa-robot',
|
|
280
|
-
metadata: axmBuildAiChatConversationMetadata(row),
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
#resolveMl(value) {
|
|
284
|
-
return this.translationService.resolve(value);
|
|
285
|
-
}
|
|
286
|
-
#applicationRouteSegment() {
|
|
287
|
-
return this.sessionService.application?.name ?? 'platform';
|
|
288
|
-
}
|
|
289
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
290
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, providedIn: 'root' }); }
|
|
104
|
+
class AXMConversationTabService extends AXMEntityCrudServiceImpl {
|
|
291
105
|
}
|
|
292
|
-
|
|
293
|
-
type: Injectable,
|
|
294
|
-
args: [{ providedIn: 'root' }]
|
|
295
|
-
}] });
|
|
296
|
-
|
|
297
|
-
/** Search group key — AI chat targets (assists), not conversation history. */
|
|
298
|
-
const AXM_CONVERSATION_ASSIST_SEARCH_GROUP = 'conversation-assist';
|
|
299
|
-
//#endregion
|
|
300
|
-
//#region ---- Provider ----
|
|
301
|
-
/**
|
|
302
|
-
* Global search entries to start a new AI chat — same catalog as
|
|
303
|
-
* {@link AXMChatWithAssistDialogComponent} / {@link AXMChatSidebarNewActionsComponent}.
|
|
304
|
-
*
|
|
305
|
-
* Note: the shared global search popup only queries when the text length is > 2.
|
|
306
|
-
*/
|
|
307
|
-
class AXMConversationAssistSearchProvider {
|
|
106
|
+
class AXMConversationTabServiceImpl extends AXMConversationTabService {
|
|
308
107
|
constructor() {
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
async search(text) {
|
|
312
|
-
let rows;
|
|
313
|
-
try {
|
|
314
|
-
rows = await this.launcher.loadTargets();
|
|
315
|
-
}
|
|
316
|
-
catch (error) {
|
|
317
|
-
console.error('Failed to load AI chat targets for shortcut search:', error);
|
|
318
|
-
return [];
|
|
319
|
-
}
|
|
320
|
-
const filtered = this.launcher.filterTargets(rows, text);
|
|
321
|
-
const sorted = sortBy(filtered, (row) => this.launcher.displayName(row).toLowerCase());
|
|
322
|
-
return sorted.map((row) => ({
|
|
323
|
-
id: row.id,
|
|
324
|
-
group: AXM_CONVERSATION_ASSIST_SEARCH_GROUP,
|
|
325
|
-
title: row.title,
|
|
326
|
-
description: row.description ?? axmChatAiTargetShortcutDescriptionKey(),
|
|
327
|
-
icon: 'fa-solid fa-robot',
|
|
328
|
-
data: { id: row.id, name: row.name },
|
|
329
|
-
command: {
|
|
330
|
-
name: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
331
|
-
options: {
|
|
332
|
-
targetId: row.id,
|
|
333
|
-
},
|
|
334
|
-
},
|
|
335
|
-
}));
|
|
108
|
+
super(`${RootConfig.module.name}.${RootConfig.entities.tab.name}`);
|
|
336
109
|
}
|
|
337
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type:
|
|
338
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type:
|
|
110
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationTabServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
111
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationTabServiceImpl }); }
|
|
339
112
|
}
|
|
340
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type:
|
|
113
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationTabServiceImpl, decorators: [{
|
|
341
114
|
type: Injectable
|
|
342
|
-
}] });
|
|
343
|
-
|
|
344
|
-
//#endregion
|
|
345
|
-
//#region ---- Provider ----
|
|
346
|
-
/** Search group for AI assist shortcut picker (not chat/conversation history). */
|
|
347
|
-
class AXMConversationAssistSearchDefinitionProvider {
|
|
348
|
-
async provide(context) {
|
|
349
|
-
context.addDefinition(AXM_CONVERSATION_ASSIST_SEARCH_GROUP, '@conversation:search.assist.group-title', AXM_CONVERSATION_ASSIST_SEARCH_GROUP, 'fa-solid fa-robot', 4, {
|
|
350
|
-
format: {
|
|
351
|
-
id: '{{id}}',
|
|
352
|
-
},
|
|
353
|
-
actions: [
|
|
354
|
-
{
|
|
355
|
-
name: 'start-assist-chat',
|
|
356
|
-
type: AXPSystemActionType.View,
|
|
357
|
-
priority: 'primary',
|
|
358
|
-
},
|
|
359
|
-
],
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
363
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider }); }
|
|
364
|
-
}
|
|
365
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider, decorators: [{
|
|
366
|
-
type: Injectable
|
|
367
|
-
}] });
|
|
368
|
-
|
|
369
|
-
class AXMConversationTabService extends AXMEntityCrudServiceImpl {
|
|
370
|
-
}
|
|
371
|
-
class AXMConversationTabServiceImpl extends AXMConversationTabService {
|
|
372
|
-
constructor() {
|
|
373
|
-
super(`${RootConfig.module.name}.${RootConfig.entities.tab.name}`);
|
|
374
|
-
}
|
|
375
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationTabServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
376
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationTabServiceImpl }); }
|
|
377
|
-
}
|
|
378
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationTabServiceImpl, decorators: [{
|
|
379
|
-
type: Injectable
|
|
380
|
-
}], ctorParameters: () => [] });
|
|
115
|
+
}], ctorParameters: () => [] });
|
|
381
116
|
|
|
382
117
|
async function tabFactory(injector) {
|
|
383
118
|
const dataService = injector.get(AXMConversationTabService);
|
|
@@ -1168,708 +903,368 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1168
903
|
type: Injectable
|
|
1169
904
|
}], ctorParameters: () => [{ type: i0.Injector }] });
|
|
1170
905
|
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
* Conversation Module Manifest.
|
|
1176
|
-
* Defines module metadata, features, and provider references.
|
|
1177
|
-
*/
|
|
1178
|
-
const ConversationManifest = {
|
|
1179
|
-
name: RootConfig.module.name,
|
|
1180
|
-
version: '1.0.0',
|
|
1181
|
-
title: RootConfig.module.title,
|
|
1182
|
-
icon: RootConfig.module.icon,
|
|
1183
|
-
i18n: RootConfig.config.i18n,
|
|
1184
|
-
// Module dependencies
|
|
1185
|
-
dependencies: ['NotificationManagement'],
|
|
1186
|
-
};
|
|
1187
|
-
//#endregion
|
|
1188
|
-
|
|
1189
|
-
const AXPConversationMenuKeys = {
|
|
1190
|
-
Conversations: 'Conversation:Menu:Conversations',
|
|
1191
|
-
};
|
|
1192
|
-
|
|
1193
|
-
const AXMPermissionsKeys = {
|
|
1194
|
-
Conversation: {
|
|
1195
|
-
Management: 'Conversation:Permission:Management',
|
|
1196
|
-
},
|
|
1197
|
-
};
|
|
1198
|
-
|
|
1199
|
-
class AXMMenuProvider {
|
|
1200
|
-
constructor() {
|
|
1201
|
-
this.sessionService = inject(AXPSessionService);
|
|
1202
|
-
}
|
|
1203
|
-
async provide(context) {
|
|
1204
|
-
const module = RootConfig;
|
|
1205
|
-
const scope = RootConfig.config.i18n;
|
|
1206
|
-
context.addItems([
|
|
1207
|
-
{
|
|
1208
|
-
name: AXPConversationMenuKeys.Conversations,
|
|
1209
|
-
text: `@conversation:module.menus.conversations.title`,
|
|
1210
|
-
path: `${this.sessionService.application?.name}/${module.config.route}`,
|
|
1211
|
-
priority: 30,
|
|
1212
|
-
icon: RootConfig.entities.room.icon,
|
|
1213
|
-
badgeKey: 'badge-chat',
|
|
1214
|
-
policy: {
|
|
1215
|
-
permissions: [AXMPermissionsKeys.Conversation.Management],
|
|
1216
|
-
},
|
|
1217
|
-
},
|
|
1218
|
-
]);
|
|
1219
|
-
}
|
|
1220
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMMenuProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1221
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMMenuProvider }); }
|
|
1222
|
-
}
|
|
1223
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMMenuProvider, decorators: [{
|
|
1224
|
-
type: Injectable
|
|
1225
|
-
}] });
|
|
906
|
+
/** Starts a new bot conversation with the given AI assist model. */
|
|
907
|
+
const CONVERSATION_START_ASSIST_CHAT_COMMAND = 'Conversation:StartAssistChat';
|
|
908
|
+
/** Sends a user text message in the active assist chat, or starts a chat when {@code assistId} is provided. */
|
|
909
|
+
const CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND = 'Conversation:SendAssistChatMessage';
|
|
1226
910
|
|
|
911
|
+
//#region ---- Imports ----
|
|
1227
912
|
//#endregion
|
|
1228
|
-
//#region ----
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
const modulePermissions = '@conversation:module.permissions';
|
|
1233
|
-
context
|
|
1234
|
-
.addGroup(RootConfig.module.name, `${modulePermissions}.title`, `${modulePermissions}.description`)
|
|
1235
|
-
.addPermission(keys.Management, `${modulePermissions}.manage.title`, `${modulePermissions}.manage.description`)
|
|
1236
|
-
.endPermission()
|
|
1237
|
-
.endGroup();
|
|
1238
|
-
}
|
|
1239
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1240
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider }); }
|
|
913
|
+
//#region ---- Participant & metadata ----
|
|
914
|
+
/** Synthetic bot participant id for assist chats. */
|
|
915
|
+
function axmChatAiPeerParticipantId(catalogId) {
|
|
916
|
+
return `assist-${catalogId.trim()}`;
|
|
1241
917
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
function convertChatMessageToNotification(room, message, currentUser) {
|
|
1247
|
-
return {
|
|
1248
|
-
channel: 'InApp',
|
|
1249
|
-
template: {
|
|
1250
|
-
category: 'Inbox',
|
|
1251
|
-
prority: 'Notice',
|
|
1252
|
-
icon: 'fa-light fa-comment',
|
|
1253
|
-
isPinned: false,
|
|
1254
|
-
},
|
|
1255
|
-
title: room.title || '@conversation:chat.notification.new-message-title',
|
|
1256
|
-
body: message.message.content,
|
|
1257
|
-
sender: message.author,
|
|
1258
|
-
receiver: currentUser,
|
|
1259
|
-
content: message.message,
|
|
1260
|
-
readAt: null,
|
|
1261
|
-
type: 'Chat',
|
|
1262
|
-
data: {
|
|
1263
|
-
roomId: room.id,
|
|
1264
|
-
},
|
|
1265
|
-
};
|
|
918
|
+
/** Conversation metadata for starting an AI chat from a picker row. */
|
|
919
|
+
function axmBuildAiChatConversationMetadata(row) {
|
|
920
|
+
return { assistId: row.id };
|
|
1266
921
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
922
|
+
/** True when conversation metadata targets an assist row. */
|
|
923
|
+
function axmConversationHasAiChat(conversation) {
|
|
924
|
+
const assistId = conversation?.metadata?.['assistId'];
|
|
925
|
+
return typeof assistId === 'string' && assistId.trim().length > 0;
|
|
1269
926
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
}
|
|
1291
|
-
startTyping(user, roomId) {
|
|
1292
|
-
this._typingStatus$.next({ roomId, user, isTyping: true });
|
|
927
|
+
/** Loads assist rows for Conversation AI chat pickers. */
|
|
928
|
+
async function axmLoadChatAiTargets(entityRegistry) {
|
|
929
|
+
const assists = await axmQueryEntityList(entityRegistry, RootConfig$1.entities.assist.name);
|
|
930
|
+
return assists
|
|
931
|
+
.map((raw) => ({
|
|
932
|
+
id: String(raw['id'] ?? ''),
|
|
933
|
+
name: String(raw['name'] ?? ''),
|
|
934
|
+
title: raw['title'],
|
|
935
|
+
description: raw['description'],
|
|
936
|
+
professionImageUrl: typeof raw['professionImageUrl'] === 'string' ? raw['professionImageUrl'] : undefined,
|
|
937
|
+
}))
|
|
938
|
+
.filter((row) => row.id.trim().length > 0)
|
|
939
|
+
.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }));
|
|
940
|
+
}
|
|
941
|
+
//#endregion
|
|
942
|
+
//#region ---- Display & filter (dialog + global search) ----
|
|
943
|
+
/** Resolves ML or plain string for search/display. */
|
|
944
|
+
function axmResolveChatAiTargetText(resolveMl, value) {
|
|
945
|
+
if (!value) {
|
|
946
|
+
return '';
|
|
1293
947
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
948
|
+
if (typeof value === 'string') {
|
|
949
|
+
return value;
|
|
1296
950
|
}
|
|
1297
|
-
|
|
1298
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatRealtimeServiceImpl, providedIn: 'root' }); }
|
|
951
|
+
return resolveMl(value) ?? '';
|
|
1299
952
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
args: [{
|
|
1303
|
-
providedIn: 'root',
|
|
1304
|
-
}]
|
|
1305
|
-
}] });
|
|
1306
|
-
|
|
1307
|
-
class AXMChatService {
|
|
953
|
+
function axmChatAiTargetDisplayName(resolveMl, row) {
|
|
954
|
+
return axmResolveChatAiTargetText(resolveMl, row.title).trim() || row.name.trim() || row.id;
|
|
1308
955
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
this.roomService = inject(AXMRoomService);
|
|
1313
|
-
this.messageService = inject(AXMMessageService);
|
|
1314
|
-
this.tabService = inject(AXMConversationTabService);
|
|
1315
|
-
}
|
|
1316
|
-
createRoom(members, title, currentUser, avatar) {
|
|
1317
|
-
const resolvedTitle = title?.trim() || 'Chat';
|
|
1318
|
-
const room = {
|
|
1319
|
-
members,
|
|
1320
|
-
/** Required by `Conversation.Room` entity validation; stable programmatic key (UI uses {@link title}). */
|
|
1321
|
-
name: `room-${AXPDataGenerator.uuid()}`,
|
|
1322
|
-
title: resolvedTitle,
|
|
1323
|
-
topic: members.length > 2 ? 'group' : 'personal',
|
|
1324
|
-
auditInfo: {
|
|
1325
|
-
created: { at: new Date(), by: currentUser },
|
|
1326
|
-
updated: { at: new Date(), by: currentUser },
|
|
1327
|
-
},
|
|
1328
|
-
type: 'chat',
|
|
1329
|
-
avatar: avatar ?? null,
|
|
1330
|
-
};
|
|
1331
|
-
return this.roomService.insertOne(room).then((id) => this.roomService.getOne(id));
|
|
1332
|
-
}
|
|
1333
|
-
getRoom(roomId) {
|
|
1334
|
-
return this.roomService.getOne(roomId);
|
|
1335
|
-
}
|
|
1336
|
-
async listRooms(skip = 0, take = 100) {
|
|
1337
|
-
return this.roomService.query({
|
|
1338
|
-
skip,
|
|
1339
|
-
take,
|
|
1340
|
-
filter: { field: 'type', value: 'chat', operator: { type: 'equal' } },
|
|
1341
|
-
});
|
|
1342
|
-
}
|
|
1343
|
-
updateRoom(roomId, data, currentUser) {
|
|
1344
|
-
const update = { ...data, auditInfo: { updated: { at: new Date(), by: currentUser } } };
|
|
1345
|
-
return this.roomService.updateOne(roomId, update);
|
|
1346
|
-
}
|
|
1347
|
-
async deleteRoom(roomId) {
|
|
1348
|
-
await this.roomService.deleteOne(roomId);
|
|
1349
|
-
return true;
|
|
1350
|
-
}
|
|
1351
|
-
createTab(data) {
|
|
1352
|
-
return this.tabService.insertOne(data).then((id) => this.tabService.getOne(id));
|
|
1353
|
-
}
|
|
1354
|
-
getTab(tabId) {
|
|
1355
|
-
return this.tabService.getOne(tabId);
|
|
1356
|
-
}
|
|
1357
|
-
listTabs(skip = 0, take = 100) {
|
|
1358
|
-
return this.tabService.query({ skip, take });
|
|
1359
|
-
}
|
|
1360
|
-
updateTab(tabId, data) {
|
|
1361
|
-
return this.tabService.updateOne(tabId, data);
|
|
1362
|
-
}
|
|
1363
|
-
async deleteTab(tabId) {
|
|
1364
|
-
await this.tabService.deleteOne(tabId);
|
|
1365
|
-
return true;
|
|
1366
|
-
}
|
|
1367
|
-
sendMessage(roomId, content, author, contentType = 'text', replyId) {
|
|
1368
|
-
const messageContent = { content, contentType };
|
|
1369
|
-
const message = {
|
|
1370
|
-
roomId,
|
|
1371
|
-
message: messageContent,
|
|
1372
|
-
author,
|
|
1373
|
-
replyId,
|
|
1374
|
-
auditInfo: {
|
|
1375
|
-
created: { at: new Date(), by: author },
|
|
1376
|
-
updated: { at: new Date(), by: author },
|
|
1377
|
-
},
|
|
1378
|
-
reactions: [],
|
|
1379
|
-
seen: [],
|
|
1380
|
-
};
|
|
1381
|
-
return this.messageService.insertOne({ ...message }).then((id) => this.messageService.getOne(id));
|
|
1382
|
-
}
|
|
1383
|
-
async getMessages(roomId, skip = 0, take = 99) {
|
|
1384
|
-
return this.messageService.query({
|
|
1385
|
-
skip,
|
|
1386
|
-
take,
|
|
1387
|
-
filter: { field: 'roomId', value: roomId, operator: { type: 'equal' } },
|
|
1388
|
-
sort: [{ field: 'created.at', dir: 'desc' }],
|
|
1389
|
-
});
|
|
1390
|
-
}
|
|
1391
|
-
getMessage(messageId) {
|
|
1392
|
-
return this.messageService.getOne(messageId);
|
|
1393
|
-
}
|
|
1394
|
-
editMessage(messageId, content, currentUser, contentType = 'text') {
|
|
1395
|
-
const messageContent = { content, contentType };
|
|
1396
|
-
return this.messageService.updateOne(messageId, {
|
|
1397
|
-
message: messageContent,
|
|
1398
|
-
auditInfo: {
|
|
1399
|
-
updated: { at: new Date(), by: currentUser },
|
|
1400
|
-
},
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1403
|
-
async deleteMessage(messageId) {
|
|
1404
|
-
await this.messageService.deleteOne(messageId);
|
|
1405
|
-
return true;
|
|
1406
|
-
}
|
|
1407
|
-
pinMessage(messageId, isPinned, currentUser) {
|
|
1408
|
-
return this.messageService.updateOne(messageId, {
|
|
1409
|
-
isPinned,
|
|
1410
|
-
auditInfo: {
|
|
1411
|
-
updated: { at: new Date(), by: currentUser },
|
|
1412
|
-
},
|
|
1413
|
-
});
|
|
1414
|
-
}
|
|
1415
|
-
updateReactions(messageId, reactions, currentUser) {
|
|
1416
|
-
return this.messageService.updateOne(messageId, {
|
|
1417
|
-
reactions,
|
|
1418
|
-
auditInfo: {
|
|
1419
|
-
updated: { at: new Date(), by: currentUser },
|
|
1420
|
-
},
|
|
1421
|
-
});
|
|
1422
|
-
}
|
|
1423
|
-
getReactions(messageId) {
|
|
1424
|
-
return this.messageService.getOne(messageId).then((m) => m.reactions || []);
|
|
956
|
+
function axmChatAiTargetDisplayDescription(resolveMl, row) {
|
|
957
|
+
if (!row.description) {
|
|
958
|
+
return undefined;
|
|
1425
959
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
960
|
+
const text = axmResolveChatAiTargetText(resolveMl, row.description).trim();
|
|
961
|
+
return text || undefined;
|
|
962
|
+
}
|
|
963
|
+
function axmChatAiTargetAvatarUrl(row) {
|
|
964
|
+
const url = row.professionImageUrl?.trim();
|
|
965
|
+
return url ? url : null;
|
|
966
|
+
}
|
|
967
|
+
/** Fallback i18n key for rows with no catalog description. */
|
|
968
|
+
function axmChatAiTargetShortcutDescriptionKey() {
|
|
969
|
+
return '@conversation:search.assist.shortcut-description';
|
|
970
|
+
}
|
|
971
|
+
/** Same filter as {@link AXMChatWithAssistDialogComponent} target list search. */
|
|
972
|
+
function axmFilterChatAiTargets(resolveMl, rows, query) {
|
|
973
|
+
const q = query.trim().toLowerCase();
|
|
974
|
+
if (!q) {
|
|
975
|
+
return rows;
|
|
1433
976
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
977
|
+
return rows.filter((r) => {
|
|
978
|
+
const titleText = axmResolveChatAiTargetText(resolveMl, r.title).toLowerCase();
|
|
979
|
+
return (r.name.toLowerCase().includes(q) ||
|
|
980
|
+
titleText.includes(q) ||
|
|
981
|
+
axmResolveChatAiTargetText(resolveMl, r.description).toLowerCase().includes(q));
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
//#endregion
|
|
985
|
+
//#region ---- Entity list query ----
|
|
986
|
+
async function axmQueryEntityList(entityRegistry, entityName) {
|
|
987
|
+
const entity = await entityRegistry.resolve(RootConfig$1.module.name, entityName);
|
|
988
|
+
const execute = entity.queries?.list?.execute;
|
|
989
|
+
if (!execute) {
|
|
990
|
+
throw new Error(`${entityName} entity has no list query.`);
|
|
1436
991
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
992
|
+
const res = await execute({
|
|
993
|
+
skip: 0,
|
|
994
|
+
take: 500,
|
|
995
|
+
sort: [{ name: 'name', dir: 'asc' }],
|
|
996
|
+
});
|
|
997
|
+
return res.items ?? [];
|
|
1439
998
|
}
|
|
1440
|
-
|
|
1441
|
-
type: Injectable,
|
|
1442
|
-
args: [{
|
|
1443
|
-
providedIn: 'root',
|
|
1444
|
-
}]
|
|
1445
|
-
}] });
|
|
999
|
+
//#endregion
|
|
1446
1000
|
|
|
1447
|
-
|
|
1001
|
+
//#region ---- Imports ----
|
|
1002
|
+
//#endregion
|
|
1003
|
+
//#region ---- Service ----
|
|
1004
|
+
/**
|
|
1005
|
+
* Starts bot conversations from catalog assist rows,
|
|
1006
|
+
* shared by global search shortcuts and {@link AXMConversationStartAssistChatCommand}.
|
|
1007
|
+
*/
|
|
1008
|
+
class AXMChatAssistLauncherService {
|
|
1448
1009
|
constructor() {
|
|
1449
|
-
this.
|
|
1010
|
+
this.conversationService = inject(AXConversationService);
|
|
1011
|
+
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
1012
|
+
this.translationService = inject(AXTranslationService);
|
|
1450
1013
|
this.sessionService = inject(AXPSessionService);
|
|
1451
|
-
this.
|
|
1452
|
-
this.
|
|
1453
|
-
this.
|
|
1454
|
-
this.
|
|
1455
|
-
this.messagePageSize = 99;
|
|
1456
|
-
}
|
|
1457
|
-
getCurrentUser() {
|
|
1458
|
-
const user = this.sessionService.user;
|
|
1459
|
-
if (!user) {
|
|
1460
|
-
throw new Error('No authenticated user found.');
|
|
1461
|
-
}
|
|
1462
|
-
return {
|
|
1463
|
-
id: user.id,
|
|
1464
|
-
type: 'user',
|
|
1465
|
-
fullName: user.title?.trim(),
|
|
1466
|
-
username: user.name?.trim(),
|
|
1467
|
-
};
|
|
1468
|
-
}
|
|
1469
|
-
async getUserInfo(userId) {
|
|
1470
|
-
const cached = this.userCache.get(userId);
|
|
1471
|
-
if (cached) {
|
|
1472
|
-
return cached;
|
|
1473
|
-
}
|
|
1474
|
-
try {
|
|
1475
|
-
const user = await this.usersService.getOne(userId);
|
|
1476
|
-
const ref = {
|
|
1477
|
-
id: user.id,
|
|
1478
|
-
type: 'user',
|
|
1479
|
-
fullName: `${user.displayName}`.trim(),
|
|
1480
|
-
username: user.username?.trim(),
|
|
1481
|
-
};
|
|
1482
|
-
this.userCache.set(userId, ref);
|
|
1483
|
-
return ref;
|
|
1484
|
-
}
|
|
1485
|
-
catch (error) {
|
|
1486
|
-
console.error(`Failed to get user info for ID: ${userId}`, error);
|
|
1487
|
-
const fallback = {
|
|
1488
|
-
id: userId,
|
|
1489
|
-
type: 'user',
|
|
1490
|
-
fullName: 'Unknown User',
|
|
1491
|
-
username: 'Unknown User',
|
|
1492
|
-
};
|
|
1493
|
-
this.userCache.set(userId, fallback);
|
|
1494
|
-
return fallback;
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
async formatMessage(message) {
|
|
1498
|
-
if (message.author && !message.author.fullName) {
|
|
1499
|
-
const authorInfo = await this.getUserInfo(message.author.id);
|
|
1500
|
-
return {
|
|
1501
|
-
...message,
|
|
1502
|
-
author: authorInfo,
|
|
1503
|
-
};
|
|
1504
|
-
}
|
|
1505
|
-
return message;
|
|
1506
|
-
}
|
|
1507
|
-
async formatRoom(room) {
|
|
1508
|
-
const { items } = await this.getMessages(room.id, 0, this.messagePageSize);
|
|
1509
|
-
const lastMessage = items.length > 0 ? items[0] : undefined;
|
|
1510
|
-
const currentUserId = this.getCurrentUser().id;
|
|
1511
|
-
const unreadCount = items.filter((message) => {
|
|
1512
|
-
const isFromCurrentUser = message.author.id === currentUserId;
|
|
1513
|
-
const isReadByCurrentUser = (message.seen || []).some((seen) => seen.author.id === currentUserId);
|
|
1514
|
-
return !isFromCurrentUser && !isReadByCurrentUser;
|
|
1515
|
-
}).length;
|
|
1516
|
-
const members = await Promise.all(room.members.map(async (member) => {
|
|
1517
|
-
if (member.fullName) {
|
|
1518
|
-
return member;
|
|
1519
|
-
}
|
|
1520
|
-
return this.getUserInfo(member.id);
|
|
1521
|
-
}));
|
|
1522
|
-
return {
|
|
1523
|
-
...room,
|
|
1524
|
-
lastMessage,
|
|
1525
|
-
unreadCount,
|
|
1526
|
-
members: members.filter((m) => m.id !== currentUserId),
|
|
1527
|
-
};
|
|
1528
|
-
}
|
|
1529
|
-
async mapWithConcurrency(items, limit, fn) {
|
|
1530
|
-
const results = new Array(items.length);
|
|
1531
|
-
let i = 0;
|
|
1532
|
-
const worker = async () => {
|
|
1533
|
-
while (true) {
|
|
1534
|
-
const idx = i++;
|
|
1535
|
-
if (idx >= items.length)
|
|
1536
|
-
break;
|
|
1537
|
-
try {
|
|
1538
|
-
results[idx] = await fn(items[idx]);
|
|
1539
|
-
}
|
|
1540
|
-
catch (err) {
|
|
1541
|
-
console.error('AXMChatManagementService: item processing failed', err);
|
|
1542
|
-
results[idx] = undefined;
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
};
|
|
1546
|
-
const workers = Array(Math.min(limit, items.length))
|
|
1547
|
-
.fill(0)
|
|
1548
|
-
.map(() => worker());
|
|
1549
|
-
await Promise.all(workers);
|
|
1550
|
-
return results.filter((r) => r !== undefined);
|
|
1551
|
-
}
|
|
1552
|
-
async createRoom(memberIds, title, avatar) {
|
|
1553
|
-
if (memberIds.length === 0) {
|
|
1554
|
-
throw new Error('At least one member is required to create a room');
|
|
1555
|
-
}
|
|
1556
|
-
const currentUser = this.getCurrentUser();
|
|
1557
|
-
const allMemberIds = [...new Set([...memberIds, currentUser.id])];
|
|
1558
|
-
const memberReferences = await Promise.all(allMemberIds.map((id) => (id === currentUser.id ? Promise.resolve(currentUser) : this.getUserInfo(id))));
|
|
1559
|
-
const newRoom = await this.chatService.createRoom(memberReferences, title, currentUser, avatar || undefined);
|
|
1560
|
-
const newChatRoom = await this.formatRoom(newRoom);
|
|
1561
|
-
this.realtimeService.notifyRoom({ type: 'add', payload: newChatRoom });
|
|
1562
|
-
return newChatRoom;
|
|
1563
|
-
}
|
|
1564
|
-
async getRoom(roomId) {
|
|
1565
|
-
const room = await this.chatService.getRoom(roomId);
|
|
1566
|
-
if (!room) {
|
|
1567
|
-
throw new Error(`Chat room with ID ${roomId} not found.`);
|
|
1568
|
-
}
|
|
1569
|
-
return this.formatRoom(room);
|
|
1570
|
-
}
|
|
1571
|
-
async listRooms(skip = 0, take = 100) {
|
|
1572
|
-
const { items, total } = await this.chatService.listRooms(skip, take);
|
|
1573
|
-
const chatRooms = await this.mapWithConcurrency(items, 6, (room) => this.formatRoom(room));
|
|
1574
|
-
const sorted = [...chatRooms].sort((a, b) => {
|
|
1575
|
-
const ad = a.lastMessage?.auditInfo?.created?.at ? new Date(a.lastMessage.auditInfo.created.at).getTime() : 0;
|
|
1576
|
-
const bd = b.lastMessage?.auditInfo?.created?.at ? new Date(b.lastMessage.auditInfo.created.at).getTime() : 0;
|
|
1577
|
-
return bd - ad;
|
|
1578
|
-
});
|
|
1579
|
-
return { items: sorted, total };
|
|
1580
|
-
}
|
|
1581
|
-
async updateRoom(roomId, data) {
|
|
1582
|
-
const currentUser = this.getCurrentUser();
|
|
1583
|
-
const updated = await this.chatService.updateRoom(roomId, data, currentUser);
|
|
1584
|
-
try {
|
|
1585
|
-
const formatted = await this.formatRoom(updated);
|
|
1586
|
-
this.realtimeService.notifyRoom({ type: 'update', payload: formatted });
|
|
1587
|
-
}
|
|
1588
|
-
catch (err) {
|
|
1589
|
-
console.error('Failed to notify room update', err);
|
|
1590
|
-
}
|
|
1591
|
-
return updated;
|
|
1592
|
-
}
|
|
1593
|
-
async deleteRoom(roomId) {
|
|
1594
|
-
const result = await this.chatService.deleteRoom(roomId);
|
|
1595
|
-
if (result) {
|
|
1596
|
-
this.realtimeService.notifyRoom({ type: 'remove', payload: roomId });
|
|
1597
|
-
}
|
|
1598
|
-
return result;
|
|
1599
|
-
}
|
|
1600
|
-
async addParticipant(roomId, userId) {
|
|
1601
|
-
const room = await this.chatService.getRoom(roomId);
|
|
1602
|
-
if (room.members.some((m) => m.id === userId))
|
|
1603
|
-
return room;
|
|
1604
|
-
const userRef = await this.getUserInfo(userId);
|
|
1605
|
-
const updatedMembers = [...room.members, userRef];
|
|
1606
|
-
const currentUser = this.getCurrentUser();
|
|
1607
|
-
const updated = await this.chatService.updateRoom(roomId, { members: updatedMembers }, currentUser);
|
|
1608
|
-
try {
|
|
1609
|
-
const formatted = await this.formatRoom(updated);
|
|
1610
|
-
this.realtimeService.notifyRoom({ type: 'update', payload: formatted });
|
|
1611
|
-
}
|
|
1612
|
-
catch (err) {
|
|
1613
|
-
console.error('Failed to notify add participant', err);
|
|
1614
|
-
}
|
|
1615
|
-
return updated;
|
|
1014
|
+
this.router = inject(Router);
|
|
1015
|
+
this.toastService = inject(AXToastService);
|
|
1016
|
+
this.targetsCache = null;
|
|
1017
|
+
this.loadPromise = null;
|
|
1616
1018
|
}
|
|
1617
|
-
async
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
const currentUser = this.getCurrentUser();
|
|
1621
|
-
const updated = await this.chatService.updateRoom(roomId, { members: updatedMembers }, currentUser);
|
|
1622
|
-
try {
|
|
1623
|
-
const formatted = await this.formatRoom(updated);
|
|
1624
|
-
this.realtimeService.notifyRoom({ type: 'update', payload: formatted });
|
|
1019
|
+
async loadTargets(force = false) {
|
|
1020
|
+
if (!force && this.targetsCache) {
|
|
1021
|
+
return this.targetsCache;
|
|
1625
1022
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1023
|
+
if (!force && this.loadPromise) {
|
|
1024
|
+
return this.loadPromise;
|
|
1628
1025
|
}
|
|
1629
|
-
|
|
1630
|
-
}
|
|
1631
|
-
async createTab(data) {
|
|
1632
|
-
const newTab = await this.chatService.createTab(data);
|
|
1633
|
-
this.realtimeService.notifyTab({ type: 'add', payload: newTab });
|
|
1634
|
-
return newTab;
|
|
1635
|
-
}
|
|
1636
|
-
getTab(tabId) {
|
|
1637
|
-
return this.chatService.getTab(tabId);
|
|
1638
|
-
}
|
|
1639
|
-
listTabs(skip, take) {
|
|
1640
|
-
return this.chatService.listTabs(skip, take);
|
|
1641
|
-
}
|
|
1642
|
-
async updateTab(tabId, data) {
|
|
1643
|
-
const updated = await this.chatService.updateTab(tabId, data);
|
|
1026
|
+
this.loadPromise = axmLoadChatAiTargets(this.entityRegistry);
|
|
1644
1027
|
try {
|
|
1645
|
-
this.
|
|
1028
|
+
this.targetsCache = await this.loadPromise;
|
|
1029
|
+
return this.targetsCache;
|
|
1646
1030
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1031
|
+
finally {
|
|
1032
|
+
this.loadPromise = null;
|
|
1649
1033
|
}
|
|
1650
|
-
return updated;
|
|
1651
1034
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
if (result) {
|
|
1655
|
-
this.realtimeService.notifyTab({ type: 'remove', payload: tabId });
|
|
1656
|
-
}
|
|
1657
|
-
return result;
|
|
1035
|
+
displayName(row) {
|
|
1036
|
+
return axmChatAiTargetDisplayName(this.#resolveMl.bind(this), row);
|
|
1658
1037
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
const room = await this.chatService.getRoom(roomId);
|
|
1662
|
-
if (tab && room) {
|
|
1663
|
-
if (tab.includeRooms.some((r) => r.id === roomId)) {
|
|
1664
|
-
return tab;
|
|
1665
|
-
}
|
|
1666
|
-
const includeRooms = [...tab.includeRooms, room];
|
|
1667
|
-
const excludeRooms = tab.excludeRooms.filter((r) => r.id !== roomId);
|
|
1668
|
-
return this.updateTab(tabId, { includeRooms, excludeRooms });
|
|
1669
|
-
}
|
|
1670
|
-
else {
|
|
1671
|
-
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1672
|
-
}
|
|
1038
|
+
displayDescription(row) {
|
|
1039
|
+
return axmChatAiTargetDisplayDescription(this.#resolveMl.bind(this), row);
|
|
1673
1040
|
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
if (tab) {
|
|
1677
|
-
if (tab.includeRooms.some((r) => r.id === roomId)) {
|
|
1678
|
-
const updatedRooms = tab.includeRooms.filter((r) => r.id !== roomId);
|
|
1679
|
-
return this.updateTab(tabId, { includeRooms: updatedRooms });
|
|
1680
|
-
}
|
|
1681
|
-
else {
|
|
1682
|
-
throw new Error(`${tabId} tab does not include room with ID ${roomId}.`);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
else {
|
|
1686
|
-
throw new Error(`Tab with ID ${tabId} not found.`);
|
|
1687
|
-
}
|
|
1041
|
+
targetAvatarUrl(row) {
|
|
1042
|
+
return axmChatAiTargetAvatarUrl(row);
|
|
1688
1043
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
const room = await this.chatService.getRoom(roomId);
|
|
1692
|
-
if (tab && room) {
|
|
1693
|
-
if (tab.excludeRooms.some((r) => r.id === roomId)) {
|
|
1694
|
-
return tab;
|
|
1695
|
-
}
|
|
1696
|
-
const excludeRooms = [...tab.excludeRooms, room];
|
|
1697
|
-
const includeRooms = tab.includeRooms.filter((r) => r.id !== roomId);
|
|
1698
|
-
return this.updateTab(tabId, { excludeRooms, includeRooms });
|
|
1699
|
-
}
|
|
1700
|
-
else {
|
|
1701
|
-
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1702
|
-
}
|
|
1044
|
+
filterTargets(rows, query) {
|
|
1045
|
+
return axmFilterChatAiTargets(this.#resolveMl.bind(this), rows, query);
|
|
1703
1046
|
}
|
|
1704
|
-
async
|
|
1705
|
-
const
|
|
1706
|
-
if (
|
|
1707
|
-
|
|
1708
|
-
const updatedRooms = tab.excludeRooms.filter((r) => r.id !== roomId);
|
|
1709
|
-
return this.updateTab(tabId, { excludeRooms: updatedRooms });
|
|
1710
|
-
}
|
|
1711
|
-
else {
|
|
1712
|
-
throw new Error(`${tabId} tab does not exclude room with ID ${roomId}.`);
|
|
1713
|
-
}
|
|
1047
|
+
async startAssistChat(options) {
|
|
1048
|
+
const targetId = (options.targetId ?? options.assistId)?.trim();
|
|
1049
|
+
if (!targetId) {
|
|
1050
|
+
return null;
|
|
1714
1051
|
}
|
|
1715
|
-
|
|
1716
|
-
|
|
1052
|
+
const rows = await this.loadTargets();
|
|
1053
|
+
const row = rows.find((r) => r.id === targetId);
|
|
1054
|
+
if (!row) {
|
|
1055
|
+
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.start-chat');
|
|
1056
|
+
this.toastService.danger(message);
|
|
1057
|
+
return null;
|
|
1717
1058
|
}
|
|
1718
|
-
}
|
|
1719
|
-
async sendMessage(roomId, content, contentType = 'text', replyId, userId) {
|
|
1720
|
-
const author = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1721
|
-
const newMessage = await this.chatService.sendMessage(roomId, content, author, contentType, replyId);
|
|
1722
|
-
const formattedMessage = await this.formatMessage(newMessage);
|
|
1723
|
-
this.realtimeService.notifyMessage({ type: 'add', payload: formattedMessage });
|
|
1724
|
-
// Create a notification when a new message is sent by someone else
|
|
1725
1059
|
try {
|
|
1726
|
-
const
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
await this.notificationConnectorService.create({
|
|
1731
|
-
...notification,
|
|
1732
|
-
id: formattedMessage.id,
|
|
1733
|
-
entityName: 'notifications',
|
|
1734
|
-
createAt: new Date(),
|
|
1735
|
-
});
|
|
1060
|
+
const conversation = await this.#createTargetConversation(row);
|
|
1061
|
+
await this.conversationService.selectConversation(conversation.id);
|
|
1062
|
+
if (options.navigate !== false) {
|
|
1063
|
+
await this.router.navigate([this.#applicationRouteSegment(), 'chat', conversation.id]);
|
|
1736
1064
|
}
|
|
1065
|
+
return { conversation };
|
|
1737
1066
|
}
|
|
1738
1067
|
catch (error) {
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
}
|
|
1744
|
-
async getMessages(roomId, skip, take) {
|
|
1745
|
-
const result = await this.chatService.getMessages(roomId, skip, take);
|
|
1746
|
-
const formattedMessages = await Promise.all(result.items.map((m) => this.formatMessage(m)));
|
|
1747
|
-
return { items: formattedMessages, total: result.total };
|
|
1748
|
-
}
|
|
1749
|
-
async getMessage(messageId) {
|
|
1750
|
-
const message = await this.chatService.getMessage(messageId);
|
|
1751
|
-
return this.formatMessage(message);
|
|
1752
|
-
}
|
|
1753
|
-
async editMessage(messageId, content, contentType = 'text') {
|
|
1754
|
-
const currentUser = this.getCurrentUser();
|
|
1755
|
-
const updatedMessage = await this.chatService.editMessage(messageId, content, currentUser, contentType);
|
|
1756
|
-
this.realtimeService.notifyMessage({ type: 'update', payload: await this.formatMessage(updatedMessage) });
|
|
1757
|
-
return updatedMessage;
|
|
1758
|
-
}
|
|
1759
|
-
async deleteMessage(messageId) {
|
|
1760
|
-
const result = await this.chatService.deleteMessage(messageId);
|
|
1761
|
-
if (result) {
|
|
1762
|
-
this.realtimeService.notifyMessage({ type: 'remove', payload: messageId });
|
|
1763
|
-
}
|
|
1764
|
-
return result;
|
|
1765
|
-
}
|
|
1766
|
-
async replyMessage(replyToMessageId, content, contentType = 'text') {
|
|
1767
|
-
const originalMessage = await this.chatService.getMessage(replyToMessageId);
|
|
1768
|
-
return this.sendMessage(originalMessage.roomId, content, contentType, replyToMessageId);
|
|
1769
|
-
}
|
|
1770
|
-
async pinMessage(messageId) {
|
|
1771
|
-
const currentUser = this.getCurrentUser();
|
|
1772
|
-
return this.chatService.pinMessage(messageId, true, currentUser);
|
|
1773
|
-
}
|
|
1774
|
-
async unpinMessage(messageId) {
|
|
1775
|
-
const currentUser = this.getCurrentUser();
|
|
1776
|
-
return this.chatService.pinMessage(messageId, false, currentUser);
|
|
1777
|
-
}
|
|
1778
|
-
async addReaction(messageId, type) {
|
|
1779
|
-
const author = this.getCurrentUser();
|
|
1780
|
-
const message = await this.chatService.getMessage(messageId);
|
|
1781
|
-
const reactions = message.reactions || [];
|
|
1782
|
-
if (reactions.some((r) => r.author.id === author.id && r.type === type)) {
|
|
1783
|
-
return message;
|
|
1068
|
+
console.error('Failed to start AI chat:', error);
|
|
1069
|
+
const message = await this.translationService.translateAsync('@conversation:chat.assist-dialog.errors.start-chat');
|
|
1070
|
+
this.toastService.danger(message);
|
|
1071
|
+
return null;
|
|
1784
1072
|
}
|
|
1785
|
-
const updatedReactions = [...reactions, { author, type }];
|
|
1786
|
-
const res = await this.chatService.updateReactions(messageId, updatedReactions, author);
|
|
1787
|
-
this.realtimeService.notifyMessage({ type: 'update', payload: await this.formatMessage(res) });
|
|
1788
|
-
return res;
|
|
1789
1073
|
}
|
|
1790
|
-
async
|
|
1791
|
-
const
|
|
1792
|
-
const
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1074
|
+
async #createTargetConversation(row) {
|
|
1075
|
+
const participantId = axmChatAiPeerParticipantId(row.id);
|
|
1076
|
+
const title = this.displayName(row);
|
|
1077
|
+
const avatar = this.targetAvatarUrl(row);
|
|
1078
|
+
return this.conversationService.createConversation([participantId], 'bot', {
|
|
1079
|
+
title,
|
|
1080
|
+
...(avatar ? { avatar } : {}),
|
|
1081
|
+
icon: 'fa-solid fa-robot',
|
|
1082
|
+
metadata: axmBuildAiChatConversationMetadata(row),
|
|
1083
|
+
});
|
|
1797
1084
|
}
|
|
1798
|
-
|
|
1799
|
-
return this.
|
|
1085
|
+
#resolveMl(value) {
|
|
1086
|
+
return this.translationService.resolve(value);
|
|
1800
1087
|
}
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
const message = await this.chatService.getMessage(messageId);
|
|
1804
|
-
const seen = message.seen || [];
|
|
1805
|
-
if (seen.some((s) => s.author.id === author.id)) {
|
|
1806
|
-
return message;
|
|
1807
|
-
}
|
|
1808
|
-
const updatedSeen = [...seen, { author, type: 'read' }];
|
|
1809
|
-
const updatedMessage = await this.chatService.updateSeen(messageId, updatedSeen, author);
|
|
1810
|
-
if (notify) {
|
|
1811
|
-
this.realtimeService.notifyRoom({ type: 'seen', payload: updatedMessage.roomId });
|
|
1812
|
-
}
|
|
1813
|
-
return updatedMessage;
|
|
1088
|
+
#applicationRouteSegment() {
|
|
1089
|
+
return this.sessionService.application?.name ?? 'platform';
|
|
1814
1090
|
}
|
|
1815
|
-
|
|
1816
|
-
|
|
1091
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1092
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, providedIn: 'root' }); }
|
|
1093
|
+
}
|
|
1094
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatAssistLauncherService, decorators: [{
|
|
1095
|
+
type: Injectable,
|
|
1096
|
+
args: [{ providedIn: 'root' }]
|
|
1097
|
+
}] });
|
|
1098
|
+
|
|
1099
|
+
/** Search group key — AI chat targets (assists), not conversation history. */
|
|
1100
|
+
const AXM_CONVERSATION_ASSIST_SEARCH_GROUP = 'conversation-assist';
|
|
1101
|
+
//#endregion
|
|
1102
|
+
//#region ---- Provider ----
|
|
1103
|
+
/**
|
|
1104
|
+
* Global search entries to start a new AI chat — same catalog as
|
|
1105
|
+
* {@link AXMChatWithAssistDialogComponent} / {@link AXMChatSidebarNewActionsComponent}.
|
|
1106
|
+
*
|
|
1107
|
+
* Note: the shared global search popup only queries when the text length is > 2.
|
|
1108
|
+
*/
|
|
1109
|
+
class AXMConversationAssistSearchProvider {
|
|
1110
|
+
constructor() {
|
|
1111
|
+
this.launcher = inject(AXMChatAssistLauncherService);
|
|
1817
1112
|
}
|
|
1818
|
-
async
|
|
1113
|
+
async search(text) {
|
|
1114
|
+
let rows;
|
|
1819
1115
|
try {
|
|
1820
|
-
|
|
1821
|
-
return true;
|
|
1822
|
-
}
|
|
1823
|
-
const currentUserId = this.getCurrentUser().id;
|
|
1824
|
-
const take = this.messagePageSize;
|
|
1825
|
-
let skip = 0;
|
|
1826
|
-
let pageCount = 0;
|
|
1827
|
-
let processedAny = false;
|
|
1828
|
-
const maxPages = 10; // safety guard
|
|
1829
|
-
while (pageCount < maxPages) {
|
|
1830
|
-
const { items } = await this.getMessages(roomId, skip, take);
|
|
1831
|
-
if (items.length === 0) {
|
|
1832
|
-
break;
|
|
1833
|
-
}
|
|
1834
|
-
const unreadMessages = items.filter((message) => message.author.id !== currentUserId && !message.seen?.some((s) => s.author.id === currentUserId));
|
|
1835
|
-
if (unreadMessages.length > 0) {
|
|
1836
|
-
await Promise.all(unreadMessages.map((message) => this.markSeen(message.id, false)));
|
|
1837
|
-
processedAny = true;
|
|
1838
|
-
}
|
|
1839
|
-
if (items.length < take) {
|
|
1840
|
-
break;
|
|
1841
|
-
}
|
|
1842
|
-
skip += take;
|
|
1843
|
-
pageCount++;
|
|
1844
|
-
}
|
|
1845
|
-
if (processedAny) {
|
|
1846
|
-
this.realtimeService.notifyRoom({ type: 'seen', payload: roomId });
|
|
1847
|
-
}
|
|
1848
|
-
return true;
|
|
1116
|
+
rows = await this.launcher.loadTargets();
|
|
1849
1117
|
}
|
|
1850
1118
|
catch (error) {
|
|
1851
|
-
console.error(
|
|
1852
|
-
return
|
|
1119
|
+
console.error('Failed to load AI chat targets for shortcut search:', error);
|
|
1120
|
+
return [];
|
|
1853
1121
|
}
|
|
1122
|
+
const filtered = this.launcher.filterTargets(rows, text);
|
|
1123
|
+
const sorted = sortBy(filtered, (row) => this.launcher.displayName(row).toLowerCase());
|
|
1124
|
+
return sorted.map((row) => ({
|
|
1125
|
+
id: row.id,
|
|
1126
|
+
group: AXM_CONVERSATION_ASSIST_SEARCH_GROUP,
|
|
1127
|
+
title: row.title,
|
|
1128
|
+
description: row.description ?? axmChatAiTargetShortcutDescriptionKey(),
|
|
1129
|
+
icon: 'fa-solid fa-robot',
|
|
1130
|
+
data: { id: row.id, name: row.name },
|
|
1131
|
+
command: {
|
|
1132
|
+
name: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
1133
|
+
options: {
|
|
1134
|
+
targetId: row.id,
|
|
1135
|
+
},
|
|
1136
|
+
},
|
|
1137
|
+
}));
|
|
1138
|
+
}
|
|
1139
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1140
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchProvider }); }
|
|
1141
|
+
}
|
|
1142
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchProvider, decorators: [{
|
|
1143
|
+
type: Injectable
|
|
1144
|
+
}] });
|
|
1145
|
+
|
|
1146
|
+
//#endregion
|
|
1147
|
+
//#region ---- Provider ----
|
|
1148
|
+
/** Search group for AI assist shortcut picker (not chat/conversation history). */
|
|
1149
|
+
class AXMConversationAssistSearchDefinitionProvider {
|
|
1150
|
+
async provide(context) {
|
|
1151
|
+
context.addDefinition(AXM_CONVERSATION_ASSIST_SEARCH_GROUP, '@conversation:search.assist.group-title', AXM_CONVERSATION_ASSIST_SEARCH_GROUP, 'fa-solid fa-robot', 4, {
|
|
1152
|
+
format: {
|
|
1153
|
+
id: '{{id}}',
|
|
1154
|
+
},
|
|
1155
|
+
actions: [
|
|
1156
|
+
{
|
|
1157
|
+
name: 'start-assist-chat',
|
|
1158
|
+
type: AXPSystemActionType.View,
|
|
1159
|
+
priority: 'primary',
|
|
1160
|
+
},
|
|
1161
|
+
],
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1165
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider }); }
|
|
1166
|
+
}
|
|
1167
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationAssistSearchDefinitionProvider, decorators: [{
|
|
1168
|
+
type: Injectable
|
|
1169
|
+
}] });
|
|
1170
|
+
|
|
1171
|
+
//#region ---- Imports ----
|
|
1172
|
+
//#endregion
|
|
1173
|
+
//#region ---- Manifest Definition ----
|
|
1174
|
+
/**
|
|
1175
|
+
* Conversation Module Manifest.
|
|
1176
|
+
* Defines module metadata, features, and provider references.
|
|
1177
|
+
*/
|
|
1178
|
+
const ConversationManifest = {
|
|
1179
|
+
name: RootConfig.module.name,
|
|
1180
|
+
version: '1.0.0',
|
|
1181
|
+
title: RootConfig.module.title,
|
|
1182
|
+
icon: RootConfig.module.icon,
|
|
1183
|
+
i18n: RootConfig.config.i18n,
|
|
1184
|
+
// Module dependencies
|
|
1185
|
+
dependencies: ['NotificationManagement'],
|
|
1186
|
+
};
|
|
1187
|
+
//#endregion
|
|
1188
|
+
|
|
1189
|
+
const AXPConversationMenuKeys = {
|
|
1190
|
+
Conversations: 'Conversation:Menu:Conversations',
|
|
1191
|
+
};
|
|
1192
|
+
|
|
1193
|
+
const AXMPermissionsKeys = {
|
|
1194
|
+
Conversation: {
|
|
1195
|
+
Management: 'Conversation:Permission:Management',
|
|
1196
|
+
},
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
class AXMMenuProvider {
|
|
1200
|
+
constructor() {
|
|
1201
|
+
this.sessionService = inject(AXPSessionService);
|
|
1854
1202
|
}
|
|
1855
|
-
async
|
|
1856
|
-
const
|
|
1857
|
-
|
|
1203
|
+
async provide(context) {
|
|
1204
|
+
const module = RootConfig;
|
|
1205
|
+
const scope = RootConfig.config.i18n;
|
|
1206
|
+
context.addItems([
|
|
1207
|
+
{
|
|
1208
|
+
name: AXPConversationMenuKeys.Conversations,
|
|
1209
|
+
text: `@conversation:module.menus.conversations.title`,
|
|
1210
|
+
path: `${this.sessionService.application?.name}/${module.config.route}`,
|
|
1211
|
+
priority: 30,
|
|
1212
|
+
icon: RootConfig.entities.room.icon,
|
|
1213
|
+
badgeKey: 'badge-chat',
|
|
1214
|
+
policy: {
|
|
1215
|
+
permissions: [AXMPermissionsKeys.Conversation.Management],
|
|
1216
|
+
},
|
|
1217
|
+
},
|
|
1218
|
+
]);
|
|
1858
1219
|
}
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1220
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMMenuProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1221
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMMenuProvider }); }
|
|
1222
|
+
}
|
|
1223
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMMenuProvider, decorators: [{
|
|
1224
|
+
type: Injectable
|
|
1225
|
+
}] });
|
|
1226
|
+
|
|
1227
|
+
//#endregion
|
|
1228
|
+
//#region ---- Permission Definition Provider ----
|
|
1229
|
+
class AXMPermissionDefinitionProvider {
|
|
1230
|
+
async define(context) {
|
|
1231
|
+
const keys = AXMPermissionsKeys.Conversation;
|
|
1232
|
+
const modulePermissions = '@conversation:module.permissions';
|
|
1233
|
+
context
|
|
1234
|
+
.addGroup(RootConfig.module.name, `${modulePermissions}.title`, `${modulePermissions}.description`)
|
|
1235
|
+
.addPermission(keys.Management, `${modulePermissions}.manage.title`, `${modulePermissions}.manage.description`)
|
|
1236
|
+
.endPermission()
|
|
1237
|
+
.endGroup();
|
|
1862
1238
|
}
|
|
1863
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type:
|
|
1864
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type:
|
|
1239
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1240
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider }); }
|
|
1865
1241
|
}
|
|
1866
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type:
|
|
1867
|
-
type: Injectable
|
|
1868
|
-
args: [{
|
|
1869
|
-
providedIn: 'root',
|
|
1870
|
-
}]
|
|
1242
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMPermissionDefinitionProvider, decorators: [{
|
|
1243
|
+
type: Injectable
|
|
1871
1244
|
}] });
|
|
1872
1245
|
|
|
1246
|
+
//#region ---- Imports ----
|
|
1247
|
+
//#endregion
|
|
1248
|
+
//#region ---- Task Badge Provider ----
|
|
1249
|
+
/** Provides a live unread conversation count for header/task badges. */
|
|
1250
|
+
class AXMChatBadgeProviderSimple {
|
|
1251
|
+
//#endregion
|
|
1252
|
+
constructor() {
|
|
1253
|
+
//#region ---- Services & Dependencies ----
|
|
1254
|
+
this.conversationService = inject(AXConversationService);
|
|
1255
|
+
//#endregion
|
|
1256
|
+
//#region ---- Signals & Properties ----
|
|
1257
|
+
this.key = 'badge-chat';
|
|
1258
|
+
this.count = computed(() => this.conversationService.conversations().filter((conversation) => conversation.unreadCount > 0).length, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
1259
|
+
void this.conversationService.loadConversations();
|
|
1260
|
+
}
|
|
1261
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatBadgeProviderSimple, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1262
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatBadgeProviderSimple }); }
|
|
1263
|
+
}
|
|
1264
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatBadgeProviderSimple, decorators: [{
|
|
1265
|
+
type: Injectable
|
|
1266
|
+
}], ctorParameters: () => [] });
|
|
1267
|
+
|
|
1873
1268
|
//#region ---- Imports ----
|
|
1874
1269
|
//#endregion
|
|
1875
1270
|
//#region ---- Module cache (sync reads for action visibility) ----
|
|
@@ -3275,7 +2670,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
3275
2670
|
return this.activatedRoute.snapshot.parent?.paramMap.get('app') || 'platform';
|
|
3276
2671
|
}
|
|
3277
2672
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
3278
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", host: { listeners: { "keydown.escape": "onContainerEscape()" }, properties: { "tabindex": "\"-1\"" } }, usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container axConversationContainer>\n <!-- Sidebar: Always visible on desktop, visible on mobile only when no conversation is selected -->\n\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n <div class=\"ax-h-full ax-flex ax-flex-col ax-shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"ax-group\">\n <ax-suffix>\n <div class=\"ax-flex ax-h-14 ax-shrink-0 ax-items-center ax-justify-end ax-overflow-hidden\">\n <axm-chat-sidebar-new-actions\n class=\"group-hover:!ax-translate-y-0 !ax-translate-y-36 ax-transition-transform ax-duration-200\"\n (conversationCreated)=\"onConversationSelected($event)\"
|
|
2673
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", host: { listeners: { "keydown.escape": "onContainerEscape()" }, properties: { "tabindex": "\"-1\"" } }, usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container axConversationContainer>\n <!-- Sidebar: Always visible on desktop, visible on mobile only when no conversation is selected -->\n\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n <div class=\"ax-h-full ax-flex ax-flex-col ax-shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"ax-group\">\n <ax-suffix>\n <div class=\"ax-flex ax-h-14 ax-shrink-0 ax-items-center ax-justify-end ax-overflow-hidden\">\n <axm-chat-sidebar-new-actions\n class=\"group-hover:!ax-translate-y-0 !ax-translate-y-36 ax-transition-transform ax-duration-200\"\n (conversationCreated)=\"onConversationSelected($event)\"\n />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n\n <!-- Chat content: Always visible on desktop, visible on mobile only when a conversation is selected -->\n\n <axp-page-content class=\"ax-h-full ax-overflow-hidden !ax-p-0 ax-flex ax-min-h-0 ax-flex-col\">\n @if (showChatList()) {\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"ax-group\">\n <ax-suffix>\n <div class=\"ax-flex ax-h-14 ax-shrink-0 ax-items-center ax-justify-end ax-overflow-hidden\">\n <axm-chat-sidebar-new-actions\n class=\"group-hover:!ax-translate-y-0 !ax-translate-y-36 ax-transition-transform ax-duration-200\"\n (conversationCreated)=\"onConversationSelected($event)\"\n />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n } @else {\n <div class=\"ax-flex ax-h-full ax-min-h-0 ax-flex-1 ax-flex-col\">\n <ax-conversation-info-bar class=\"ax-shadow-md\">\n <ax-prefix>\n <!-- Back button visible only on mobile -->\n @if (deviceService.isMobileDevice()) {\n <ax-button look=\"blank\" (onClick)=\"openChatList()\">\n <ax-icon icon=\"fa-light fa-bars\"></ax-icon>\n </ax-button>\n } @else {\n <ax-button class=\"ax-rounded-full\" look=\"blank\" (onClick)=\"onContainerEscape()\" aria-label=\"Close Chat\">\n <ax-icon icon=\"fa-light fa-xmark ax-text-xl\"></ax-icon>\n </ax-button>\n }\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"ax-min-h-0 ax-flex-1 ax-overflow-hidden\" style=\"direction: ltr\">\n <div ax-conversation-message-list-no-active class=\"ax-block\" style=\"width: min(95%, 50rem)\">\n <axm-chat-empty-assist-composer (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty />\n </ax-conversation-message-list>\n </div>\n }\n </axp-page-content>\n\n <axp-page-footer class=\"ax-block\">\n <ax-conversation-composer></ax-conversation-composer>\n </axp-page-footer>\n</axp-page-layout>\n", styles: [":host ::ng-deep #axp-page-footer-container{padding:0!important}:host ::ng-deep .date-separator{z-index:50!important}:host ::ng-deep axp-layout-header{padding:0!important}\n"], dependencies: [{ kind: "directive", type: AXConversationContainerDirective, selector: "[axConversationContainer]" }, { kind: "component", type: AXSidebarComponent, selector: "ax-conversation-sidebar", outputs: ["conversationSelected"] }, { kind: "component", type: AXInfoBarComponent, selector: "ax-conversation-info-bar", outputs: ["avatarClick", "searchClick", "searchQuery", "menuItemAction"] }, { kind: "component", type: AXMessageListComponent, selector: "ax-conversation-message-list", inputs: ["avatarTemplate"], outputs: ["messageAction"] }, { kind: "component", type: AXComposerComponent, selector: "ax-conversation-composer", outputs: ["messageSent", "emojiClick", "attachClick", "voiceClick"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "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$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.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: AXTranslationModule }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXMChatSidebarNewActionsComponent, selector: "axm-chat-sidebar-new-actions", outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatEmptyAssistComposerComponent, selector: "axm-chat-empty-assist-composer", outputs: ["conversationCreated"] }, { kind: "component", type: AXMChatAssistComposerStarterPromptsComponent, selector: "axm-chat-assist-composer-starter-prompts" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3279
2674
|
}
|
|
3280
2675
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatComponent, decorators: [{
|
|
3281
2676
|
type: Component,
|
|
@@ -3297,7 +2692,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3297
2692
|
], host: {
|
|
3298
2693
|
'(keydown.escape)': 'onContainerEscape()',
|
|
3299
2694
|
'[tabindex]': '"-1"',
|
|
3300
|
-
}, template: "<axp-page-layout #container axConversationContainer>\n <!-- Sidebar: Always visible on desktop, visible on mobile only when no conversation is selected -->\n\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n <div class=\"ax-h-full ax-flex ax-flex-col ax-shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"ax-group\">\n <ax-suffix>\n <div class=\"ax-flex ax-h-14 ax-shrink-0 ax-items-center ax-justify-end ax-overflow-hidden\">\n <axm-chat-sidebar-new-actions\n class=\"group-hover:!ax-translate-y-0 !ax-translate-y-36 ax-transition-transform ax-duration-200\"\n (conversationCreated)=\"onConversationSelected($event)\"
|
|
2695
|
+
}, template: "<axp-page-layout #container axConversationContainer>\n <!-- Sidebar: Always visible on desktop, visible on mobile only when no conversation is selected -->\n\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n <div class=\"ax-h-full ax-flex ax-flex-col ax-shrink-0\">\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"ax-group\">\n <ax-suffix>\n <div class=\"ax-flex ax-h-14 ax-shrink-0 ax-items-center ax-justify-end ax-overflow-hidden\">\n <axm-chat-sidebar-new-actions\n class=\"group-hover:!ax-translate-y-0 !ax-translate-y-36 ax-transition-transform ax-duration-200\"\n (conversationCreated)=\"onConversationSelected($event)\"\n />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n\n <!-- Chat content: Always visible on desktop, visible on mobile only when a conversation is selected -->\n\n <axp-page-content class=\"ax-h-full ax-overflow-hidden !ax-p-0 ax-flex ax-min-h-0 ax-flex-col\">\n @if (showChatList()) {\n <ax-conversation-sidebar (conversationSelected)=\"onConversationSelected($event.id)\" class=\"ax-group\">\n <ax-suffix>\n <div class=\"ax-flex ax-h-14 ax-shrink-0 ax-items-center ax-justify-end ax-overflow-hidden\">\n <axm-chat-sidebar-new-actions\n class=\"group-hover:!ax-translate-y-0 !ax-translate-y-36 ax-transition-transform ax-duration-200\"\n (conversationCreated)=\"onConversationSelected($event)\"\n />\n </div>\n </ax-suffix>\n </ax-conversation-sidebar>\n } @else {\n <div class=\"ax-flex ax-h-full ax-min-h-0 ax-flex-1 ax-flex-col\">\n <ax-conversation-info-bar class=\"ax-shadow-md\">\n <ax-prefix>\n <!-- Back button visible only on mobile -->\n @if (deviceService.isMobileDevice()) {\n <ax-button look=\"blank\" (onClick)=\"openChatList()\">\n <ax-icon icon=\"fa-light fa-bars\"></ax-icon>\n </ax-button>\n } @else {\n <ax-button class=\"ax-rounded-full\" look=\"blank\" (onClick)=\"onContainerEscape()\" aria-label=\"Close Chat\">\n <ax-icon icon=\"fa-light fa-xmark ax-text-xl\"></ax-icon>\n </ax-button>\n }\n </ax-prefix>\n </ax-conversation-info-bar>\n <ax-conversation-message-list class=\"ax-min-h-0 ax-flex-1 ax-overflow-hidden\" style=\"direction: ltr\">\n <div ax-conversation-message-list-no-active class=\"ax-block\" style=\"width: min(95%, 50rem)\">\n <axm-chat-empty-assist-composer (conversationCreated)=\"onConversationSelected($event)\" />\n </div>\n <axm-chat-assist-composer-starter-prompts ax-conversation-message-list-empty />\n </ax-conversation-message-list>\n </div>\n }\n </axp-page-content>\n\n <axp-page-footer class=\"ax-block\">\n <ax-conversation-composer></ax-conversation-composer>\n </axp-page-footer>\n</axp-page-layout>\n", styles: [":host ::ng-deep #axp-page-footer-container{padding:0!important}:host ::ng-deep .date-separator{z-index:50!important}:host ::ng-deep axp-layout-header{padding:0!important}\n"] }]
|
|
3301
2696
|
}] });
|
|
3302
2697
|
|
|
3303
2698
|
var chat_component = /*#__PURE__*/Object.freeze({
|
|
@@ -4786,40 +4181,6 @@ const AXMCommentPopupWorkflow = {
|
|
|
4786
4181
|
},
|
|
4787
4182
|
};
|
|
4788
4183
|
|
|
4789
|
-
class AXMChatBadgeProviderSimple {
|
|
4790
|
-
constructor() {
|
|
4791
|
-
this.chatService = inject(AXMChatManagementService);
|
|
4792
|
-
this.realtime = inject(AXMChatRealtimeService);
|
|
4793
|
-
this.key = 'badge-chat';
|
|
4794
|
-
this.count = signal(0, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
4795
|
-
this._events = toSignal(merge(this.realtime.room$, this.realtime.message$).pipe(auditTime(150)), {
|
|
4796
|
-
initialValue: null,
|
|
4797
|
-
});
|
|
4798
|
-
// Initial load
|
|
4799
|
-
this.refresh();
|
|
4800
|
-
// Refresh on any room/message event
|
|
4801
|
-
effect(async () => {
|
|
4802
|
-
// track events
|
|
4803
|
-
this._events();
|
|
4804
|
-
try {
|
|
4805
|
-
await this.refresh();
|
|
4806
|
-
}
|
|
4807
|
-
catch (err) {
|
|
4808
|
-
console.error('AXMChatBadgeProviderSimple: refresh failed', err);
|
|
4809
|
-
}
|
|
4810
|
-
});
|
|
4811
|
-
}
|
|
4812
|
-
async refresh() {
|
|
4813
|
-
const response = await this.chatService.listRooms();
|
|
4814
|
-
this.count.set(response.items.filter((i) => i.unreadCount > 0).length);
|
|
4815
|
-
}
|
|
4816
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatBadgeProviderSimple, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4817
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatBadgeProviderSimple }); }
|
|
4818
|
-
}
|
|
4819
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMChatBadgeProviderSimple, decorators: [{
|
|
4820
|
-
type: Injectable
|
|
4821
|
-
}], ctorParameters: () => [] });
|
|
4822
|
-
|
|
4823
4184
|
//#region ---- Imports ----
|
|
4824
4185
|
//#endregion
|
|
4825
4186
|
//#region ---- Message classification ----
|
|
@@ -6234,7 +5595,7 @@ async function axmOpenAssistDelegatedAgentDetailDialog(options) {
|
|
|
6234
5595
|
options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.dialog-title-suffix'),
|
|
6235
5596
|
options.translationService.translateAsync('@conversation:chat.assist-renderer.delegated-agent.transcript-missing'),
|
|
6236
5597
|
]);
|
|
6237
|
-
const comp = (await import('./acorex-modules-conversation-assist-delegated-agent-detail-popup.component-
|
|
5598
|
+
const comp = (await import('./acorex-modules-conversation-assist-delegated-agent-detail-popup.component-BAgBuxlz.mjs'))
|
|
6238
5599
|
.AXMAssistDelegatedAgentDetailPopupComponent;
|
|
6239
5600
|
const data = {
|
|
6240
5601
|
messages: entry?.messages ?? [],
|
|
@@ -7194,13 +6555,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
7194
6555
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
7195
6556
|
}]
|
|
7196
6557
|
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], execute: [{ type: i0.Output, args: ["execute"] }] } });
|
|
7197
|
-
|
|
7198
|
-
//#region ---- Imports ----
|
|
7199
|
-
//#endregion
|
|
7200
|
-
//#region ---- Chat Notification Provider ----
|
|
7201
|
-
/**
|
|
7202
|
-
* Provides notification handling and content for Chat.
|
|
7203
|
-
*/
|
|
7204
6558
|
class AXMChatNotificationProvider {
|
|
7205
6559
|
constructor(injector) {
|
|
7206
6560
|
this.injector = injector;
|
|
@@ -7213,7 +6567,7 @@ class AXMChatNotificationProvider {
|
|
|
7213
6567
|
}
|
|
7214
6568
|
async execute(command, item) {
|
|
7215
6569
|
const router = this.injector.get(Router);
|
|
7216
|
-
const chatService = this.injector.get(
|
|
6570
|
+
const chatService = this.injector.get(AXConversationService);
|
|
7217
6571
|
const activatedRoute = this.injector.get(ActivatedRoute);
|
|
7218
6572
|
const roomId = item.data?.['roomId'];
|
|
7219
6573
|
if (!roomId) {
|
|
@@ -7223,14 +6577,14 @@ class AXMChatNotificationProvider {
|
|
|
7223
6577
|
const app = activatedRoute.snapshot.firstChild?.paramMap.get('app') || 'platform';
|
|
7224
6578
|
switch (command.name) {
|
|
7225
6579
|
case 'mark-as-seen':
|
|
7226
|
-
await chatService.
|
|
6580
|
+
await chatService.markAsRead(roomId);
|
|
7227
6581
|
break;
|
|
7228
6582
|
case 'go-to-chat':
|
|
7229
|
-
await chatService.
|
|
6583
|
+
await chatService.markAsRead(roomId);
|
|
7230
6584
|
router.navigate([app, 'chat', roomId]);
|
|
7231
6585
|
break;
|
|
7232
6586
|
case 'click':
|
|
7233
|
-
await chatService.
|
|
6587
|
+
await chatService.markAsRead(roomId);
|
|
7234
6588
|
router.navigate([app, 'chat', roomId]);
|
|
7235
6589
|
break;
|
|
7236
6590
|
default:
|
|
@@ -7251,7 +6605,6 @@ const AXM_CHAT_NOTIFICATION_PROVIDERS = [
|
|
|
7251
6605
|
multi: true,
|
|
7252
6606
|
},
|
|
7253
6607
|
];
|
|
7254
|
-
//#endregion
|
|
7255
6608
|
|
|
7256
6609
|
//#region ---- Imports ----
|
|
7257
6610
|
//#endregion
|
|
@@ -7309,7 +6662,7 @@ class AXMCommentsPageComponentProvider {
|
|
|
7309
6662
|
return [
|
|
7310
6663
|
{
|
|
7311
6664
|
key: COMMENTS_PAGE_COMPONENT_KEY,
|
|
7312
|
-
loader: () => import('./acorex-modules-conversation-comments-page.component-
|
|
6665
|
+
loader: () => import('./acorex-modules-conversation-comments-page.component-BrwP9l7M.mjs').then((m) => m.AXMCommentsPageComponent),
|
|
7313
6666
|
},
|
|
7314
6667
|
];
|
|
7315
6668
|
}
|
|
@@ -7404,15 +6757,6 @@ class AXMConversationModule {
|
|
|
7404
6757
|
// Modules
|
|
7405
6758
|
RouterModule] }); }
|
|
7406
6759
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMConversationModule, providers: [
|
|
7407
|
-
// Chat and Comment Services
|
|
7408
|
-
{
|
|
7409
|
-
provide: AXMChatService,
|
|
7410
|
-
useClass: AXMChatServiceImpl,
|
|
7411
|
-
},
|
|
7412
|
-
{
|
|
7413
|
-
provide: AXMChatRealtimeService,
|
|
7414
|
-
useClass: AXMChatRealtimeServiceImpl,
|
|
7415
|
-
},
|
|
7416
6760
|
{
|
|
7417
6761
|
provide: AXMCommentService,
|
|
7418
6762
|
useClass: AXMCommentServiceImpl,
|
|
@@ -7488,11 +6832,11 @@ class AXMConversationModule {
|
|
|
7488
6832
|
provideCommandSetups([
|
|
7489
6833
|
{
|
|
7490
6834
|
key: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
7491
|
-
command: () => import('./acorex-modules-conversation-start-assist-chat.command-
|
|
6835
|
+
command: () => import('./acorex-modules-conversation-start-assist-chat.command-BUOGUMl0.mjs').then((m) => m.AXMConversationStartAssistChatCommand),
|
|
7492
6836
|
},
|
|
7493
6837
|
{
|
|
7494
6838
|
key: CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND,
|
|
7495
|
-
command: () => import('./acorex-modules-conversation-send-assist-chat-message.command-
|
|
6839
|
+
command: () => import('./acorex-modules-conversation-send-assist-chat-message.command-BzKawEoN.mjs').then((m) => m.AXMConversationSendAssistChatMessageCommand),
|
|
7496
6840
|
},
|
|
7497
6841
|
]),
|
|
7498
6842
|
], imports: [AXPWidgetCoreModule,
|
|
@@ -7535,15 +6879,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
7535
6879
|
RouterModule,
|
|
7536
6880
|
],
|
|
7537
6881
|
providers: [
|
|
7538
|
-
// Chat and Comment Services
|
|
7539
|
-
{
|
|
7540
|
-
provide: AXMChatService,
|
|
7541
|
-
useClass: AXMChatServiceImpl,
|
|
7542
|
-
},
|
|
7543
|
-
{
|
|
7544
|
-
provide: AXMChatRealtimeService,
|
|
7545
|
-
useClass: AXMChatRealtimeServiceImpl,
|
|
7546
|
-
},
|
|
7547
6882
|
{
|
|
7548
6883
|
provide: AXMCommentService,
|
|
7549
6884
|
useClass: AXMCommentServiceImpl,
|
|
@@ -7619,11 +6954,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
7619
6954
|
provideCommandSetups([
|
|
7620
6955
|
{
|
|
7621
6956
|
key: CONVERSATION_START_ASSIST_CHAT_COMMAND,
|
|
7622
|
-
command: () => import('./acorex-modules-conversation-start-assist-chat.command-
|
|
6957
|
+
command: () => import('./acorex-modules-conversation-start-assist-chat.command-BUOGUMl0.mjs').then((m) => m.AXMConversationStartAssistChatCommand),
|
|
7623
6958
|
},
|
|
7624
6959
|
{
|
|
7625
6960
|
key: CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND,
|
|
7626
|
-
command: () => import('./acorex-modules-conversation-send-assist-chat-message.command-
|
|
6961
|
+
command: () => import('./acorex-modules-conversation-send-assist-chat-message.command-BzKawEoN.mjs').then((m) => m.AXMConversationSendAssistChatMessageCommand),
|
|
7627
6962
|
},
|
|
7628
6963
|
]),
|
|
7629
6964
|
],
|
|
@@ -7634,5 +6969,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
7634
6969
|
* Generated bundle index. Do not edit.
|
|
7635
6970
|
*/
|
|
7636
6971
|
|
|
7637
|
-
export {
|
|
7638
|
-
//# sourceMappingURL=acorex-modules-conversation-acorex-modules-conversation-
|
|
6972
|
+
export { tabFactory as $, AXMChatAssistLauncherService as A, AXMMessageEntityModule as B, CONVERSATION_SEND_ASSIST_CHAT_MESSAGE_COMMAND as C, AXMMessageService as D, AXMMessageServiceImpl as E, AXMPermissionsKeys as F, AXMRoomEntityModule as G, AXMRoomService as H, AXMRoomServiceImpl as I, AXM_ASSIST_TRANSCRIPT_LINE_PAYLOAD_TYPE as J, AXPCommentWidget as K, COMMENTS_PAGE_COMPONENT_KEY as L, axmAssistFollowUpItemsFromUnknown as M, axmAssistLastTranscriptLine as N, axmAssistUserFacingPayloadLine as O, axmAssistUserVisibleItemsForLine as P, axmBuildAssistTranscriptLinePayload as Q, RootConfig as R, axmIsAssistPeerParticipant as S, axmNormalizeAssistTranscriptForChatUi as T, axmNormalizeAssistTranscriptLineResponses as U, axmParseAssistTranscriptLinePayload as V, axmReadAssistAiTranscript as W, axmReadAssistAiTranscriptRaw as X, commentsPlugin as Y, messageFactory as Z, roomFactory as _, AXMCommentComponent as a, axmAssistSegmentDirection as b, axmParseAssistTranscriptTextEnvelope as c, axmAssistWidgetNodeFromUnknown as d, axmSyntheticEmbedMessage as e, AXMNodeMessageRendererComponent as f, AXMAssistBotImageLineComponent as g, AXMAssistSuggestionChipsComponent as h, AXMChatComponent as i, AXMChatConversationApi as j, AXMChatMessageApi as k, AXMChatRealtimeApi as l, AXMChatUserApi as m, AXMCommentManagementService as n, AXMCommentPopupComponent as o, AXMCommentPopupStartAction as p, AXMCommentPopupWorkflow as q, AXMCommentRealtimeService as r, AXMCommentRealtimeServiceImpl as s, AXMCommentService as t, AXMCommentServiceImpl as u, AXMCommentWidgetViewComponent as v, AXMConversationModule as w, AXMConversationTabEntityModule as x, AXMConversationTabService as y, AXMConversationTabServiceImpl as z };
|
|
6973
|
+
//# sourceMappingURL=acorex-modules-conversation-acorex-modules-conversation-DlteA_jC.mjs.map
|