@aakash58/chatbot 1.1.15 → 1.1.17
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/esm2022/aakash58-chatbot.mjs +5 -0
- package/esm2022/lib/app/chat/chat-ui-state.service.mjs +170 -0
- package/esm2022/lib/app/chat/chat.service.mjs +445 -0
- package/esm2022/lib/app/chat/components/chat-button/chat-button.component.mjs +50 -0
- package/esm2022/lib/app/chat/components/chat-footer/chat-footer.component.mjs +12 -0
- package/esm2022/lib/app/chat/components/chat-header/chat-header.component.mjs +66 -0
- package/esm2022/lib/app/chat/components/chat-history-sidebar/chat-history-sidebar.component.mjs +186 -0
- package/esm2022/lib/app/chat/components/chat-window/chat-window.component.mjs +312 -0
- package/esm2022/lib/app/chat/components/message-input/message-input.component.mjs +36 -0
- package/esm2022/lib/app/chat/components/message-list/message-list.component.mjs +115 -0
- package/esm2022/lib/app/chat/model/chat-history.model.mjs +2 -0
- package/esm2022/lib/app/chat/model/chat-request.model.mjs +2 -0
- package/esm2022/lib/app/chat/model/chat-response.model.mjs +2 -0
- package/esm2022/lib/app/chat/model/chat-session.model.mjs +2 -0
- package/esm2022/lib/app/chat/model/chat-stream-message.model.mjs +2 -0
- package/esm2022/lib/app/chat/model/chat-stream-response.model.mjs +2 -0
- package/esm2022/lib/app/chat/services/chat-api.service.mjs +61 -0
- package/esm2022/lib/app/chat/services/chat-audio.service.mjs +50 -0
- package/esm2022/lib/app/chat/services/chat-history.service.mjs +252 -0
- package/esm2022/lib/app/login/login-form.component.mjs +46 -0
- package/esm2022/lib/app/personalization/personalization-dialog.component.mjs +194 -0
- package/esm2022/lib/app/personalization/personalization.service.mjs +149 -0
- package/esm2022/lib/app/personalization/sections/account/account-section.component.mjs +122 -0
- package/esm2022/lib/app/personalization/sections/preferences/color-picker-dialog.component.mjs +86 -0
- package/esm2022/lib/app/personalization/sections/preferences/preferences-section.component.mjs +115 -0
- package/esm2022/lib/app/personalization/sections/profile/profile-section.component.mjs +29 -0
- package/esm2022/lib/app/personalization/sections/settings/setting-section.component.mjs +30 -0
- package/esm2022/lib/app/personalization/sections/terms/terms-section.component.mjs +12 -0
- package/esm2022/lib/constant/doohbot-constant.mjs +28 -0
- package/esm2022/lib/constant/html-entities.mjs +9 -0
- package/esm2022/lib/constant/utf8.mjs +10 -0
- package/esm2022/lib/core/app-const.mjs +61 -0
- package/esm2022/lib/core/auth/account-api.service.mjs +40 -0
- package/esm2022/lib/core/auth/auth.service.mjs +391 -0
- package/esm2022/lib/core/auth/models/auth-result.model.mjs +3 -0
- package/esm2022/lib/core/auth/models/federated-login-request.model.mjs +6 -0
- package/esm2022/lib/core/auth/models/login-request.model.mjs +6 -0
- package/esm2022/lib/core/auth/storage.service.mjs +110 -0
- package/esm2022/lib/core/directives/draggable/draggable-dialog.directive.mjs +112 -0
- package/esm2022/lib/core/directives/fullscreen/fullscreen.directive.mjs +55 -0
- package/esm2022/lib/core/directives/resizable/resizable-dialog.directive.mjs +179 -0
- package/esm2022/lib/core/environments/environment.mjs +15 -0
- package/esm2022/lib/core/environments/environment.prod.mjs +15 -0
- package/esm2022/lib/core/helpers/crypto-helper.service.mjs +52 -0
- package/esm2022/lib/core/http/http-stream.service.mjs +97 -0
- package/esm2022/lib/core/http/http.service.mjs +103 -0
- package/esm2022/lib/core/interceptors/auth.interceptor.mjs +96 -0
- package/esm2022/lib/core/interceptors/license.interceptor.mjs +44 -0
- package/esm2022/lib/core/models/api-config.model.mjs +18 -0
- package/esm2022/lib/core/models/api-request.model.mjs +2 -0
- package/esm2022/lib/core/models/api-response.model.mjs +8 -0
- package/esm2022/lib/core/models/doohbot-config.model.mjs +18 -0
- package/esm2022/lib/core/models/license.model.mjs +2 -0
- package/esm2022/lib/core/models/message.mjs +2 -0
- package/esm2022/lib/core/models/theme-config.model.mjs +2 -0
- package/esm2022/lib/core/services/core-config.service.mjs +52 -0
- package/esm2022/lib/core/services/license.service.mjs +145 -0
- package/esm2022/lib/core/services/markdown.service.mjs +64 -0
- package/esm2022/lib/core/services/theme.service.mjs +248 -0
- package/esm2022/lib/core/types/auth-mode.type.mjs +2 -0
- package/esm2022/lib/core/types/auth-status.type.mjs +5 -0
- package/esm2022/lib/core/types/chat-stream.type.mjs +2 -0
- package/esm2022/lib/core/types/message-role.type.mjs +2 -0
- package/esm2022/lib/core/types/prompt-mode.type.mjs +5 -0
- package/esm2022/lib/core/types/snackbar-error.type.mjs +5 -0
- package/esm2022/lib/core/types/tenant-resolution-strategy.type.mjs +2 -0
- package/esm2022/lib/core/utils/logger.service.mjs +42 -0
- package/esm2022/lib/doohbot-input.mjs +20 -0
- package/esm2022/lib/doohbot.component.mjs +444 -0
- package/esm2022/lib/predefined_messages.mjs +15 -0
- package/esm2022/lib/shared/chips/chips.component.mjs +28 -0
- package/esm2022/lib/shared/dialog/dialog.component.mjs +36 -0
- package/esm2022/lib/shared/dialog/dialog.service.mjs +64 -0
- package/esm2022/lib/shared/dialog/dialog.utils.mjs +85 -0
- package/esm2022/lib/shared/dropdown-menu/dropdown-menu.component.mjs +29 -0
- package/esm2022/lib/shared/input-dialog/input-dialog.component.mjs +38 -0
- package/esm2022/lib/shared/menu-item/menu-item.component.mjs +24 -0
- package/esm2022/lib/shared/pipes/simple-markdown.pipe.mjs +27 -0
- package/esm2022/lib/shared/snackbar/snackbar.component.mjs +43 -0
- package/esm2022/lib/shared/snackbar/snackbar.service.mjs +46 -0
- package/esm2022/lib/shared/snackbar/snackbar.utils.mjs +43 -0
- package/esm2022/public-api.mjs +37 -0
- package/fesm2022/aakash58-chatbot.mjs +1114 -867
- package/fesm2022/aakash58-chatbot.mjs.map +1 -1
- package/index.d.ts +3 -377
- package/lib/app/chat/chat-ui-state.service.d.ts +96 -0
- package/lib/app/chat/chat.service.d.ts +88 -0
- package/lib/app/chat/components/chat-button/chat-button.component.d.ts +16 -0
- package/lib/app/chat/components/chat-footer/chat-footer.component.d.ts +5 -0
- package/lib/app/chat/components/chat-header/chat-header.component.d.ts +24 -0
- package/lib/app/chat/components/chat-history-sidebar/chat-history-sidebar.component.d.ts +49 -0
- package/lib/app/chat/components/chat-window/chat-window.component.d.ts +107 -0
- package/lib/app/chat/components/message-input/message-input.component.d.ts +12 -0
- package/lib/app/chat/components/message-list/message-list.component.d.ts +40 -0
- package/lib/app/chat/model/chat-history.model.d.ts +51 -0
- package/lib/app/chat/model/chat-request.model.d.ts +10 -0
- package/lib/app/chat/model/chat-response.model.d.ts +9 -0
- package/lib/app/chat/model/chat-session.model.d.ts +12 -0
- package/lib/app/chat/model/chat-stream-message.model.d.ts +5 -0
- package/lib/app/chat/model/chat-stream-response.model.d.ts +10 -0
- package/lib/app/chat/services/chat-api.service.d.ts +30 -0
- package/lib/app/chat/services/chat-audio.service.d.ts +19 -0
- package/lib/app/chat/services/chat-history.service.d.ts +53 -0
- package/lib/app/login/login-form.component.d.ts +20 -0
- package/lib/app/personalization/personalization-dialog.component.d.ts +53 -0
- package/lib/app/personalization/personalization.service.d.ts +66 -0
- package/lib/app/personalization/sections/account/account-section.component.d.ts +30 -0
- package/lib/app/personalization/sections/preferences/color-picker-dialog.component.d.ts +17 -0
- package/lib/app/personalization/sections/preferences/preferences-section.component.d.ts +27 -0
- package/lib/app/personalization/sections/profile/profile-section.component.d.ts +17 -0
- package/lib/app/personalization/sections/settings/setting-section.component.d.ts +10 -0
- package/lib/app/personalization/sections/terms/terms-section.component.d.ts +5 -0
- package/lib/constant/doohbot-constant.d.ts +12 -0
- package/lib/constant/html-entities.d.ts +8 -0
- package/lib/constant/utf8.d.ts +9 -0
- package/lib/core/app-const.d.ts +11 -0
- package/lib/core/auth/account-api.service.d.ts +20 -0
- package/lib/core/auth/auth.service.d.ts +90 -0
- package/lib/core/auth/models/auth-result.model.d.ts +4 -0
- package/lib/core/auth/models/federated-login-request.model.d.ts +5 -0
- package/lib/core/auth/models/login-request.model.d.ts +6 -0
- package/lib/core/auth/storage.service.d.ts +21 -0
- package/lib/core/directives/draggable/draggable-dialog.directive.d.ts +23 -0
- package/lib/core/directives/fullscreen/fullscreen.directive.d.ts +14 -0
- package/lib/core/directives/resizable/resizable-dialog.directive.d.ts +30 -0
- package/lib/core/environments/environment.d.ts +7 -0
- package/lib/core/environments/environment.prod.d.ts +7 -0
- package/lib/core/helpers/crypto-helper.service.d.ts +12 -0
- package/lib/core/http/http-stream.service.d.ts +18 -0
- package/lib/core/http/http.service.d.ts +20 -0
- package/lib/core/interceptors/auth.interceptor.d.ts +18 -0
- package/lib/core/interceptors/license.interceptor.d.ts +11 -0
- package/lib/core/models/api-config.model.d.ts +58 -0
- package/lib/core/models/api-request.model.d.ts +77 -0
- package/lib/core/models/api-response.model.d.ts +6 -0
- package/lib/core/models/doohbot-config.model.d.ts +81 -0
- package/lib/core/models/license.model.d.ts +23 -0
- package/lib/core/models/message.d.ts +16 -0
- package/lib/core/models/theme-config.model.d.ts +28 -0
- package/lib/core/services/core-config.service.d.ts +23 -0
- package/lib/core/services/license.service.d.ts +33 -0
- package/lib/core/services/markdown.service.d.ts +8 -0
- package/lib/core/services/theme.service.d.ts +40 -0
- package/lib/core/types/auth-mode.type.d.ts +4 -0
- package/lib/core/types/auth-status.type.d.ts +4 -0
- package/lib/core/types/chat-stream.type.d.ts +4 -0
- package/lib/core/types/message-role.type.d.ts +4 -0
- package/lib/core/types/prompt-mode.type.d.ts +4 -0
- package/lib/core/types/snackbar-error.type.d.ts +4 -0
- package/lib/core/types/tenant-resolution-strategy.type.d.ts +4 -0
- package/lib/core/utils/logger.service.d.ts +11 -0
- package/lib/doohbot-input.d.ts +19 -0
- package/lib/doohbot.component.d.ts +108 -0
- package/lib/predefined_messages.d.ts +2 -0
- package/lib/shared/chips/chips.component.d.ts +10 -0
- package/lib/shared/dialog/dialog.component.d.ts +19 -0
- package/lib/shared/dialog/dialog.service.d.ts +29 -0
- package/lib/shared/dialog/dialog.utils.d.ts +41 -0
- package/lib/shared/dropdown-menu/dropdown-menu.component.d.ts +11 -0
- package/lib/shared/input-dialog/input-dialog.component.d.ts +20 -0
- package/lib/shared/menu-item/menu-item.component.d.ts +9 -0
- package/lib/shared/pipes/simple-markdown.pipe.d.ts +10 -0
- package/lib/shared/snackbar/snackbar.component.d.ts +14 -0
- package/lib/shared/snackbar/snackbar.service.d.ts +19 -0
- package/lib/shared/snackbar/snackbar.utils.d.ts +33 -0
- package/package.json +4 -2
- package/public-api.d.ts +11 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import { Injectable, signal, inject, computed } from '@angular/core';
|
|
2
|
+
import { Subject, lastValueFrom } from 'rxjs';
|
|
3
|
+
import { ChatHistoryService } from './services/chat-history.service';
|
|
4
|
+
// Extracted Services
|
|
5
|
+
import { ChatApiService } from './services/chat-api.service';
|
|
6
|
+
import { ChatAudioService } from './services/chat-audio.service';
|
|
7
|
+
import { SnackbarUtils } from '../../shared/snackbar/snackbar.utils';
|
|
8
|
+
import { DOOHBOT_ADVANCED_CONFIG } from '../../core/models/doohbot-config.model';
|
|
9
|
+
import logger from '../../core/utils/logger.service';
|
|
10
|
+
import { AuthService } from './../../core/auth/auth.service';
|
|
11
|
+
import { ChatUIStateService } from './chat-ui-state.service';
|
|
12
|
+
import { PersonalizationService } from '../personalization/personalization.service';
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
export class ChatService {
|
|
15
|
+
getFallbackReply() {
|
|
16
|
+
return "I'm sorry 😔, I didn't understand that.";
|
|
17
|
+
}
|
|
18
|
+
getFallbackError() {
|
|
19
|
+
return 'Something went wrong. Please try again.';
|
|
20
|
+
}
|
|
21
|
+
constructor() {
|
|
22
|
+
// Dependencies
|
|
23
|
+
this.apiService = inject(ChatApiService);
|
|
24
|
+
this.authService = inject(AuthService);
|
|
25
|
+
this.audioService = inject(ChatAudioService);
|
|
26
|
+
this.config = inject(DOOHBOT_ADVANCED_CONFIG, { optional: true });
|
|
27
|
+
this.chatHistoryService = inject(ChatHistoryService);
|
|
28
|
+
this.chatUIStateService = inject(ChatUIStateService);
|
|
29
|
+
this.personalization = inject(PersonalizationService);
|
|
30
|
+
this.chatSessions = this.chatHistoryService.sessions;
|
|
31
|
+
// Public messages signal for current context
|
|
32
|
+
this.messages = signal([]);
|
|
33
|
+
/**
|
|
34
|
+
* Determine if suggestion chips should be shown
|
|
35
|
+
*/
|
|
36
|
+
this.showSuggestionChips = computed(() => {
|
|
37
|
+
const msgs = this.messages();
|
|
38
|
+
if (msgs.length === 0)
|
|
39
|
+
return false;
|
|
40
|
+
const lastBotMsg = [...msgs].reverse().find((m) => m.sender === 'assistant');
|
|
41
|
+
return lastBotMsg?.showSuggestions === true;
|
|
42
|
+
});
|
|
43
|
+
// Active session
|
|
44
|
+
this.activeSession = null;
|
|
45
|
+
// UI state signals (Keep these here as they are relevant to the Chat UI state)
|
|
46
|
+
this.isLoadingApi = signal(false);
|
|
47
|
+
this.apiError = signal(null);
|
|
48
|
+
this.isBotTyping = signal(false);
|
|
49
|
+
this.promptMode = signal('markdown');
|
|
50
|
+
this.isStreaming = signal(true); //! `isStreaming` is set to true by default
|
|
51
|
+
this.messagesStream = [];
|
|
52
|
+
this.currentResponse = '';
|
|
53
|
+
this.cancelSubject = new Subject();
|
|
54
|
+
logger.log('ChatService: Initialized');
|
|
55
|
+
// Initialize prompt mode from config if available
|
|
56
|
+
if (this.config?.promptMode) {
|
|
57
|
+
this.promptMode.set(this.config.promptMode);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//! ==================== STATE MANAGEMENT ====================
|
|
61
|
+
/**
|
|
62
|
+
* Generate a unique session ID
|
|
63
|
+
*/
|
|
64
|
+
generateSessionId() {
|
|
65
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
66
|
+
return `session_${crypto.randomUUID()}`;
|
|
67
|
+
}
|
|
68
|
+
return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create a new chat session
|
|
72
|
+
*/
|
|
73
|
+
createSession(userId) {
|
|
74
|
+
return {
|
|
75
|
+
id: this.generateSessionId(),
|
|
76
|
+
timestamp: new Date(),
|
|
77
|
+
title: 'New Conversation',
|
|
78
|
+
messages: [],
|
|
79
|
+
userId,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Start a new chat session
|
|
84
|
+
*/
|
|
85
|
+
startNewSession() {
|
|
86
|
+
// this.cancelRequest(); //! Cancel any ongoing request before starting new session
|
|
87
|
+
const userId = this.authService.getUserId();
|
|
88
|
+
this.isBotTyping.set(false);
|
|
89
|
+
this.isLoadingApi.set(false);
|
|
90
|
+
this.activeSession = this.createSession(userId);
|
|
91
|
+
this.messages.set([]);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Load an existing session
|
|
95
|
+
*/
|
|
96
|
+
loadSession(session) {
|
|
97
|
+
logger.log('[ChatService] Loading session:', session.id, 'Messages:', session.messages.length);
|
|
98
|
+
this.activeSession = session;
|
|
99
|
+
this.messages.set([...session.messages]);
|
|
100
|
+
logger.log('[ChatService] Messages signal updated. Current count:', this.messages().length);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get active session
|
|
104
|
+
*/
|
|
105
|
+
getActiveSession() {
|
|
106
|
+
return this.activeSession;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Clear messages for current session and start new one
|
|
110
|
+
*/
|
|
111
|
+
clearMessages() {
|
|
112
|
+
this.messages.set([]);
|
|
113
|
+
this.startNewSession();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Add message to current session
|
|
117
|
+
*/
|
|
118
|
+
addMessage(message) {
|
|
119
|
+
const newMessage = { ...message, timestamp: new Date() };
|
|
120
|
+
// Update current messages signal
|
|
121
|
+
this.messages.update((msgs) => [...msgs, newMessage]);
|
|
122
|
+
// Save to active session (Server handles actual storage, UI just adds to local signal for immediate feedback)
|
|
123
|
+
if (message.sender === 'assistant') {
|
|
124
|
+
this.audioService.playBotSound();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Continue a chat session
|
|
129
|
+
*/
|
|
130
|
+
continueSession(sessionId) {
|
|
131
|
+
logger.log(`[ChatService] continuing session: ${sessionId}`);
|
|
132
|
+
this.chatHistoryService.loadSessionMessages(sessionId).subscribe((messages) => {
|
|
133
|
+
const loadedMessages = messages || [];
|
|
134
|
+
const sessionFromList = this.chatSessions().find((s) => s.id === sessionId);
|
|
135
|
+
if (sessionFromList) {
|
|
136
|
+
sessionFromList.messages = loadedMessages;
|
|
137
|
+
this.loadSession(sessionFromList);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const timestamp = loadedMessages.length > 0
|
|
141
|
+
? loadedMessages[loadedMessages.length - 1].timestamp || new Date()
|
|
142
|
+
: new Date();
|
|
143
|
+
const userId = this.authService.getUserId();
|
|
144
|
+
const newSession = {
|
|
145
|
+
id: sessionId,
|
|
146
|
+
timestamp: timestamp,
|
|
147
|
+
title: 'Previous Conversation',
|
|
148
|
+
messages: loadedMessages,
|
|
149
|
+
userId,
|
|
150
|
+
};
|
|
151
|
+
this.loadSession(newSession);
|
|
152
|
+
}
|
|
153
|
+
this.audioService.unlockAudio();
|
|
154
|
+
this.chatUIStateService.openChat();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
//! ==================== MESSAGE PROCESSING ====================
|
|
158
|
+
/**
|
|
159
|
+
* Process a user message: add it, get bot reply, and add bot reply
|
|
160
|
+
*/
|
|
161
|
+
async sendMessage(text, maxLength = 1000) {
|
|
162
|
+
const trimmedText = text.trim();
|
|
163
|
+
if (!trimmedText) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (trimmedText.length > maxLength) {
|
|
167
|
+
SnackbarUtils.error(`Message exceeds maximum length of ${maxLength} characters.`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
//! Cancel any ongoing request before starting a new one
|
|
171
|
+
if (this.isBotTyping()) {
|
|
172
|
+
this.cancelRequest();
|
|
173
|
+
}
|
|
174
|
+
const currentSessionId = this.activeSession?.id;
|
|
175
|
+
this.addMessage({
|
|
176
|
+
sender: 'user',
|
|
177
|
+
text: text,
|
|
178
|
+
completed: true,
|
|
179
|
+
isHistory: false,
|
|
180
|
+
id: Date.now().toString(),
|
|
181
|
+
timestamp: new Date(),
|
|
182
|
+
});
|
|
183
|
+
this.isBotTyping.set(true);
|
|
184
|
+
try {
|
|
185
|
+
const response = await this.getBotReply(text);
|
|
186
|
+
// Check if session has changed while waiting for response
|
|
187
|
+
if (this.activeSession?.id !== currentSessionId) {
|
|
188
|
+
logger.log(`[ChatService] Ignoring response for session: ${currentSessionId} as active session is now: ${this.activeSession?.id}`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const isFallback = response === this.getFallbackReply();
|
|
192
|
+
// Only add completion message if it wasn't handled by streaming (response is not empty string)
|
|
193
|
+
if (response !== '') {
|
|
194
|
+
this.addMessage({
|
|
195
|
+
sender: 'assistant',
|
|
196
|
+
text: response,
|
|
197
|
+
completed: true,
|
|
198
|
+
isHistory: false,
|
|
199
|
+
id: Date.now().toString(),
|
|
200
|
+
showSuggestions: false, //! Don't show suggestions for fallback reply
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
// Only reset typing if we are still in the same session, or if we want to be safe (though resetting false is usually harmless)
|
|
206
|
+
if (this.activeSession?.id === currentSessionId) {
|
|
207
|
+
this.isBotTyping.set(false);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//! ==================== API CALLS ====================
|
|
212
|
+
async getBotReply(userText) {
|
|
213
|
+
logger.log('Requesting bot reply for:', userText);
|
|
214
|
+
try {
|
|
215
|
+
this.isLoadingApi.set(true);
|
|
216
|
+
this.apiError.set(null);
|
|
217
|
+
const request = this.buildChatRequest(userText);
|
|
218
|
+
//! chat endpoints
|
|
219
|
+
if (this.isStreaming()) {
|
|
220
|
+
return await this.stream(request);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
return await this.ask(request);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
SnackbarUtils.error('An error occurred while getting the bot reply.');
|
|
228
|
+
return this.getFallbackError();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Builds a chat request payload with the given user text and optional active session
|
|
233
|
+
* @param {string} userInput - The text provided by the user
|
|
234
|
+
* @returns {ChatRequest} - A chat request payload with the user text and optional active session
|
|
235
|
+
* @memberof ChatService
|
|
236
|
+
*/
|
|
237
|
+
buildChatRequest(userText) {
|
|
238
|
+
const instructions = this.personalization.getFormattedInstructions();
|
|
239
|
+
const finalQuestion = instructions ? `${instructions}\n\n${userText}` : userText;
|
|
240
|
+
const request = {
|
|
241
|
+
question: finalQuestion,
|
|
242
|
+
organization_id: this.authService.getOrganizationId() || '',
|
|
243
|
+
prompt_mode: this.promptMode(),
|
|
244
|
+
custom_instructions: instructions,
|
|
245
|
+
};
|
|
246
|
+
if (this.activeSession && !this.activeSession.id.startsWith('session_')) {
|
|
247
|
+
request.response_id = this.activeSession.id;
|
|
248
|
+
logger.log('>>>> conversation continued:', this.activeSession.id);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
logger.log('>>>> new conversation started');
|
|
252
|
+
}
|
|
253
|
+
return request;
|
|
254
|
+
}
|
|
255
|
+
// ! Ask api endpoint
|
|
256
|
+
async ask(request) {
|
|
257
|
+
logger.log('>>>>Using Standard Chat Endpoint<<<<');
|
|
258
|
+
const responseSubject = new Subject();
|
|
259
|
+
const currentSessionId = this.activeSession?.id;
|
|
260
|
+
this.streamSubscription = this.apiService.sendMessage(request, true).subscribe({
|
|
261
|
+
next: (response) => {
|
|
262
|
+
if (this.activeSession?.id === currentSessionId) {
|
|
263
|
+
this.isLoadingApi.set(false);
|
|
264
|
+
}
|
|
265
|
+
if (response?.success && response.data) {
|
|
266
|
+
if (this.activeSession?.id === currentSessionId) {
|
|
267
|
+
this.mapSessionId(response.data.id);
|
|
268
|
+
}
|
|
269
|
+
responseSubject.next(response.data.content || this.getFallbackError());
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
responseSubject.next(this.getFallbackError());
|
|
273
|
+
}
|
|
274
|
+
responseSubject.complete();
|
|
275
|
+
},
|
|
276
|
+
error: (error) => {
|
|
277
|
+
logger.error('Ask error:', error);
|
|
278
|
+
if (this.activeSession?.id === currentSessionId) {
|
|
279
|
+
this.isLoadingApi.set(false);
|
|
280
|
+
this.isBotTyping.set(false);
|
|
281
|
+
}
|
|
282
|
+
responseSubject.next(this.getFallbackError());
|
|
283
|
+
responseSubject.complete();
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
// Handle manual cancellation
|
|
287
|
+
const cancelSub = this.cancelSubject.subscribe(() => {
|
|
288
|
+
responseSubject.next(''); // Resolve with empty string if cancelled
|
|
289
|
+
responseSubject.complete();
|
|
290
|
+
});
|
|
291
|
+
try {
|
|
292
|
+
return await lastValueFrom(responseSubject);
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
cancelSub.unsubscribe();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// ! Stream api endpoint
|
|
299
|
+
async stream(request) {
|
|
300
|
+
logger.log('>>>>Using Stream Chat Endpoint<<<<');
|
|
301
|
+
this.currentResponse = '';
|
|
302
|
+
this.isBotTyping.set(true);
|
|
303
|
+
const assistantMessage = {
|
|
304
|
+
id: Date.now().toString(),
|
|
305
|
+
sender: 'assistant',
|
|
306
|
+
text: '',
|
|
307
|
+
chunks: [],
|
|
308
|
+
timestamp: new Date(),
|
|
309
|
+
completed: false,
|
|
310
|
+
isHistory: false,
|
|
311
|
+
showSuggestions: false,
|
|
312
|
+
};
|
|
313
|
+
// Add empty bubble after first chunk has been received
|
|
314
|
+
this.addMessage(assistantMessage);
|
|
315
|
+
const streamComplete$ = new Subject();
|
|
316
|
+
let hasStarted = false;
|
|
317
|
+
// Handle manual cancellation for stream
|
|
318
|
+
const cancelSub = this.cancelSubject.subscribe(() => {
|
|
319
|
+
if (!streamComplete$.closed) {
|
|
320
|
+
streamComplete$.next('');
|
|
321
|
+
streamComplete$.complete();
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
this.streamSubscription = this.apiService.sendMessageStream(request).subscribe({
|
|
325
|
+
next: (chunk) => {
|
|
326
|
+
if (!hasStarted) {
|
|
327
|
+
hasStarted = true;
|
|
328
|
+
this.isBotTyping.set(false);
|
|
329
|
+
// replace response_id in message id
|
|
330
|
+
this.messages.update((msgs) => msgs.map((m) => m.id === assistantMessage.id
|
|
331
|
+
? {
|
|
332
|
+
...m,
|
|
333
|
+
...{ id: chunk.id },
|
|
334
|
+
}
|
|
335
|
+
: m));
|
|
336
|
+
assistantMessage.id = chunk.id;
|
|
337
|
+
// Map the session ID to the backend-generated one
|
|
338
|
+
this.mapSessionId(chunk.response_id || chunk.id);
|
|
339
|
+
}
|
|
340
|
+
const text = chunk.content ?? '';
|
|
341
|
+
if (!text)
|
|
342
|
+
return;
|
|
343
|
+
// keep message in sync without regeneration
|
|
344
|
+
this.messages.update((msgs) => msgs.map((m) => m.id === assistantMessage.id
|
|
345
|
+
? {
|
|
346
|
+
...m,
|
|
347
|
+
chunks: [...(m.chunks ?? []), text], // immutable append
|
|
348
|
+
}
|
|
349
|
+
: m));
|
|
350
|
+
// const message = this.messages().find((m) => m.id === assistantMessage.id);
|
|
351
|
+
// logger.log('Appending chunk to assistant message:', message?.chunks);
|
|
352
|
+
},
|
|
353
|
+
complete: () => {
|
|
354
|
+
this.isLoadingApi.set(false);
|
|
355
|
+
// Mark the chunk stream compelted
|
|
356
|
+
this.messages.update((msgs) => msgs.map((m) => (m.id === assistantMessage.id ? { ...m, completed: true } : m)));
|
|
357
|
+
// const message = this.messages().find((m) => m.id === assistantMessage.id);
|
|
358
|
+
// this.currentResponse += message?.chunks?.join('') ?? '';
|
|
359
|
+
// logger.log('Appending chunk to assistant message:', message?.text);
|
|
360
|
+
// logger.log('Appending chunk to assistant message:', message?.chunks);
|
|
361
|
+
streamComplete$.next(this.currentResponse);
|
|
362
|
+
streamComplete$.complete();
|
|
363
|
+
},
|
|
364
|
+
error: (error) => {
|
|
365
|
+
logger.error('Chat error:', error);
|
|
366
|
+
SnackbarUtils.error('An error occurred during reply.');
|
|
367
|
+
this.isLoadingApi.set(false);
|
|
368
|
+
this.isBotTyping.set(false);
|
|
369
|
+
SnackbarUtils.error('An error occurred during reply.');
|
|
370
|
+
if (!hasStarted)
|
|
371
|
+
this.addMessage(assistantMessage);
|
|
372
|
+
if (!assistantMessage.text)
|
|
373
|
+
assistantMessage.text = this.getFallbackError();
|
|
374
|
+
// mark completed, do NOT rebuild content
|
|
375
|
+
this.messages.update((msgs) => msgs.map((m) => m.id === assistantMessage.id
|
|
376
|
+
? {
|
|
377
|
+
...m,
|
|
378
|
+
completed: true,
|
|
379
|
+
isHistory: false,
|
|
380
|
+
text: assistantMessage.text,
|
|
381
|
+
}
|
|
382
|
+
: m));
|
|
383
|
+
streamComplete$.next('');
|
|
384
|
+
streamComplete$.complete();
|
|
385
|
+
// this.finalizeStreamError(assistantMessage, hasStarted, streamComplete$);
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
try {
|
|
389
|
+
await lastValueFrom(streamComplete$);
|
|
390
|
+
}
|
|
391
|
+
finally {
|
|
392
|
+
cancelSub.unsubscribe();
|
|
393
|
+
}
|
|
394
|
+
return '';
|
|
395
|
+
}
|
|
396
|
+
//! -----------------------------------------
|
|
397
|
+
cancelRequest() {
|
|
398
|
+
this.cancelSubject.next();
|
|
399
|
+
// Reset UI states immediately
|
|
400
|
+
this.isLoadingApi.set(false);
|
|
401
|
+
this.isBotTyping.set(false);
|
|
402
|
+
this.currentResponse = '';
|
|
403
|
+
if (this.streamSubscription) {
|
|
404
|
+
logger.log('Cancelling ongoing chat request...');
|
|
405
|
+
this.streamSubscription.unsubscribe();
|
|
406
|
+
this.streamSubscription = undefined;
|
|
407
|
+
// Clean up assistant messages:
|
|
408
|
+
// Remove if completely empty
|
|
409
|
+
// Mark as completed if it has content
|
|
410
|
+
this.messages.update((msgs) => msgs
|
|
411
|
+
.filter((m) => !(m.sender === 'assistant' &&
|
|
412
|
+
!m.completed &&
|
|
413
|
+
!m.text &&
|
|
414
|
+
(!m.chunks || m.chunks.length === 0)))
|
|
415
|
+
.map((m) => (m.sender === 'assistant' && !m.completed ? { ...m, completed: true } : m)));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
//! ==================== AUDIO ====================
|
|
419
|
+
unlockAudio() {
|
|
420
|
+
this.audioService.unlockAudio();
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Map local placeholder session ID to backend-generated ID
|
|
424
|
+
*/
|
|
425
|
+
mapSessionId(responseId) {
|
|
426
|
+
if (!responseId || !this.activeSession || !this.activeSession.id.startsWith('session_')) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const oldId = this.activeSession.id;
|
|
430
|
+
logger.log(`[ChatService] Mapping local session ${oldId} → backend ID ${responseId}`);
|
|
431
|
+
// Update active session subject
|
|
432
|
+
this.activeSession.id = responseId;
|
|
433
|
+
// Trigger history refresh to get the server-generated title
|
|
434
|
+
this.chatHistoryService.invalidateCache();
|
|
435
|
+
}
|
|
436
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
437
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatService, providedIn: 'root' }); }
|
|
438
|
+
}
|
|
439
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatService, decorators: [{
|
|
440
|
+
type: Injectable,
|
|
441
|
+
args: [{
|
|
442
|
+
providedIn: 'root',
|
|
443
|
+
}]
|
|
444
|
+
}], ctorParameters: () => [] });
|
|
445
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9vaGJvdC9zcmMvbGliL2FwcC9jaGF0L2NoYXQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3JFLE9BQU8sRUFBZ0IsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUU1RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVyRSxxQkFBcUI7QUFDckIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUVyRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUdqRixPQUFPLE1BQU0sTUFBTSxpQ0FBaUMsQ0FBQztBQUdyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFN0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDN0QsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNENBQTRDLENBQUM7O0FBS3BGLE1BQU0sT0FBTyxXQUFXO0lBd0N0QixnQkFBZ0I7UUFDZCxPQUFPLHlDQUF5QyxDQUFDO0lBQ25ELENBQUM7SUFFRCxnQkFBZ0I7UUFDZCxPQUFPLHlDQUF5QyxDQUFDO0lBQ25ELENBQUM7SUFFRDtRQS9DQSxlQUFlO1FBQ1AsZUFBVSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNwQyxnQkFBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNsQyxp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OzRGQUVQLFdBQVc7a0JBSHZCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgc2lnbmFsLCBpbmplY3QsIGNvbXB1dGVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiwgU3ViamVjdCwgbGFzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBDaGF0U2Vzc2lvbiB9IGZyb20gJy4vbW9kZWwvY2hhdC1zZXNzaW9uLm1vZGVsJztcclxuaW1wb3J0IHsgQ2hhdEhpc3RvcnlTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9jaGF0LWhpc3Rvcnkuc2VydmljZSc7XHJcblxyXG4vLyBFeHRyYWN0ZWQgU2VydmljZXNcclxuaW1wb3J0IHsgQ2hhdEFwaVNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL2NoYXQtYXBpLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDaGF0QXVkaW9TZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9jaGF0LWF1ZGlvLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTbmFja2JhclV0aWxzIH0gZnJvbSAnLi4vLi4vc2hhcmVkL3NuYWNrYmFyL3NuYWNrYmFyLnV0aWxzJztcclxuaW1wb3J0IHsgQ2hhdEFwaUVycm9yIH0gZnJvbSAnLi4vLi4vY29yZS9tb2RlbHMvYXBpLXJlcXVlc3QubW9kZWwnO1xyXG5pbXBvcnQgeyBET09IQk9UX0FEVkFOQ0VEX0NPTkZJRyB9IGZyb20gJy4uLy4uL2NvcmUvbW9kZWxzL2Rvb2hib3QtY29uZmlnLm1vZGVsJztcclxuaW1wb3J0IHsgTWVzc2FnZSB9IGZyb20gJy4uLy4uL2NvcmUvbW9kZWxzL21lc3NhZ2UnO1xyXG5pbXBvcnQgeyBQcm9tcHRNb2RlIH0gZnJvbSAnLi4vLi4vY29yZS90eXBlcy9wcm9tcHQtbW9kZS50eXBlJztcclxuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi8uLi9jb3JlL3V0aWxzL2xvZ2dlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQ2hhdFJlcXVlc3QgfSBmcm9tICcuL21vZGVsL2NoYXQtcmVxdWVzdC5tb2RlbCc7XHJcbmltcG9ydCB7IENoYXRTdHJlYW1NZXNzYWdlIH0gZnJvbSAnLi9tb2RlbC9jaGF0LXN0cmVhbS1tZXNzYWdlLm1vZGVsJztcclxuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLy4uLy4uL2NvcmUvYXV0aC9hdXRoLnNlcnZpY2UnO1xyXG5cclxuaW1wb3J0IHsgQ2hhdFVJU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi9jaGF0LXVpLXN0YXRlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBQZXJzb25hbGl6YXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vcGVyc29uYWxpemF0aW9uL3BlcnNvbmFsaXphdGlvbi5zZXJ2aWNlJztcclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCcsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDaGF0U2VydmljZSB7XHJcbiAgLy8gRGVwZW5kZW5jaWVzXHJcbiAgcHJpdmF0ZSBhcGlTZXJ2aWNlID0gaW5qZWN0KENoYXRBcGlTZXJ2aWNlKTtcclxuICBwcml2YXRlIGF1dGhTZXJ2aWNlID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcclxuICBwcml2YXRlIGF1ZGlvU2VydmljZSA9IGluamVjdChDaGF0QXVkaW9TZXJ2aWNlKTtcclxuICBwcml2YXRlIGNvbmZpZyA9IGluamVjdChET09IQk9UX0FEVkFOQ0VEX0NPTkZJRywgeyBvcHRpb25hbDogdHJ1ZSB9KTtcclxuICBwcml2YXRlIGNoYXRIaXN0b3J5U2VydmljZSA9IGluamVjdChDaGF0SGlzdG9yeVNlcnZpY2UpO1xyXG4gIHByaXZhdGUgY2hhdFVJU3RhdGVTZXJ2aWNlID0gaW5qZWN0KENoYXRVSVN0YXRlU2VydmljZSk7XHJcbiAgcHJpdmF0ZSBwZXJzb25hbGl6YXRpb24gPSBpbmplY3QoUGVyc29uYWxpemF0aW9uU2VydmljZSk7XHJcbiAgcHJpdmF0ZSBjaGF0U2Vzc2lvbnMgPSB0aGlzLmNoYXRIaXN0b3J5U2VydmljZS5zZXNzaW9ucztcclxuXHJcbiAgLy8gUHVibGljIG1lc3NhZ2VzIHNpZ25hbCBmb3IgY3VycmVudCBjb250ZXh0XHJcbiAgcHVibGljIG1lc3NhZ2VzID0gc2lnbmFsPE1lc3NhZ2VbXT4oW10pO1xyXG5cclxuICAvKipcclxuICAgKiBEZXRlcm1pbmUgaWYgc3VnZ2VzdGlvbiBjaGlwcyBzaG91bGQgYmUgc2hvd25cclxuICAgKi9cclxuICBwdWJsaWMgc2hvd1N1Z2dlc3Rpb25DaGlwcyA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIGNvbnN0IG1zZ3MgPSB0aGlzLm1lc3NhZ2VzKCk7XHJcbiAgICBpZiAobXNncy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcclxuICAgIGNvbnN0IGxhc3RCb3RNc2cgPSBbLi4ubXNnc10ucmV2ZXJzZSgpLmZpbmQoKG0pID0+IG0uc2VuZGVyID09PSAnYXNzaXN0YW50Jyk7XHJcbiAgICByZXR1cm4gbGFzdEJvdE1zZz8uc2hvd1N1Z2dlc3Rpb25zID09PSB0cnVlO1xyXG4gIH0pO1xyXG5cclxuICAvLyBBY3RpdmUgc2Vzc2lvblxyXG4gIHByaXZhdGUgYWN0aXZlU2Vzc2lvbjogQ2hhdFNlc3Npb24gfCBudWxsID0gbnVsbDtcclxuXHJcbiAgLy8gVUkgc3RhdGUgc2lnbmFscyAoS2VlcCB0aGVzZSBoZXJlIGFzIHRoZXkgYXJlIHJlbGV2YW50IHRvIHRoZSBDaGF0IFVJIHN0YXRlKVxyXG4gIHB1YmxpYyBpc0xvYWRpbmdBcGkgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xyXG4gIHB1YmxpYyBhcGlFcnJvciA9IHNpZ25hbDxDaGF0QXBpRXJyb3IgfCBudWxsPihudWxsKTtcclxuICBwdWJsaWMgaXNCb3RUeXBpbmcgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xyXG4gIHB1YmxpYyBwcm9tcHRNb2RlID0gc2lnbmFsPFByb21wdE1vZGU+KCdtYXJrZG93bicpO1xyXG4gIHB1YmxpYyBpc1N0cmVhbWluZyA9IHNpZ25hbDxib29sZWFuPih0cnVlKTsgLy8hIGBpc1N0cmVhbWluZ2AgaXMgc2V0IHRvIHRydWUgYnkgZGVmYXVsdFxyXG5cclxuICBtZXNzYWdlc1N0cmVhbTogQXJyYXk8Q2hhdFN0cmVhbU1lc3NhZ2U+ID0gW107XHJcbiAgY3VycmVudFJlc3BvbnNlID0gJyc7XHJcblxyXG4gIHByaXZhdGUgc3RyZWFtU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xyXG4gIHByaXZhdGUgY2FuY2VsU3ViamVjdCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gIGdldEZhbGxiYWNrUmVwbHkoKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBcIkknbSBzb3JyeSDwn5iULCBJIGRpZG4ndCB1bmRlcnN0YW5kIHRoYXQuXCI7XHJcbiAgfVxyXG5cclxuICBnZXRGYWxsYmFja0Vycm9yKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gJ1NvbWV0aGluZyB3ZW50IHdyb25nLiBQbGVhc2UgdHJ5IGFnYWluLic7XHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICAgIGxvZ2dlci5sb2coJ0NoYXRTZXJ2aWNlOiBJbml0aWFsaXplZCcpO1xyXG5cclxuICAgIC8vIEluaXRpYWxpemUgcHJvbXB0IG1vZGUgZnJvbSBjb25maWcgaWYgYXZhaWxhYmxlXHJcbiAgICBpZiAodGhpcy5jb25maWc/LnByb21wdE1vZGUpIHtcclxuICAgICAgdGhpcy5wcm9tcHRNb2RlLnNldCh0aGlzLmNvbmZpZy5wcm9tcHRNb2RlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vISA9PT09PT09PT09PT09PT09PT09PSBTVEFURSBNQU5BR0VNRU5UID09PT09PT09PT09PT09PT09PT09XHJcblxyXG4gIC8qKlxyXG4gICAqIEdlbmVyYXRlIGEgdW5pcXVlIHNlc3Npb24gSURcclxuICAgKi9cclxuICBwcml2YXRlIGdlbmVyYXRlU2Vzc2lvbklkKCk6IHN0cmluZyB7XHJcbiAgICBpZiAodHlwZW9mIGNyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLnJhbmRvbVVVSUQpIHtcclxuICAgICAgcmV0dXJuIGBzZXNzaW9uXyR7Y3J5cHRvLnJhbmRvbVVVSUQoKX1gO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGBzZXNzaW9uXyR7RGF0ZS5ub3coKX1fJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHJpbmcoMiwgMTUpfWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGUgYSBuZXcgY2hhdCBzZXNzaW9uXHJcbiAgICovXHJcbiAgY3JlYXRlU2Vzc2lvbih1c2VySWQ6IHN0cmluZyk6IENoYXRTZXNzaW9uIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGlkOiB0aGlzLmdlbmVyYXRlU2Vzc2lvbklkKCksXHJcbiAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKSxcclxuICAgICAgdGl0bGU6ICdOZXcgQ29udmVyc2F0aW9uJyxcclxuICAgICAgbWVzc2FnZXM6IFtdLFxyXG4gICAgICB1c2VySWQsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU3RhcnQgYSBuZXcgY2hhdCBzZXNzaW9uXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXJ0TmV3U2Vzc2lvbigpOiB2b2lkIHtcclxuICAgIC8vIHRoaXMuY2FuY2VsUmVxdWVzdCgpOyAvLyEgQ2FuY2VsIGFueSBvbmdvaW5nIHJlcXVlc3QgYmVmb3JlIHN0YXJ0aW5nIG5ldyBzZXNzaW9uXHJcbiAgICBjb25zdCB1c2VySWQgPSB0aGlzLmF1dGhTZXJ2aWNlLmdldFVzZXJJZCgpO1xyXG5cclxuICAgIHRoaXMuaXNCb3RUeXBpbmcuc2V0KGZhbHNlKTtcclxuICAgIHRoaXMuaXNMb2FkaW5nQXBpLnNldChmYWxzZSk7XHJcblxyXG4gICAgdGhpcy5hY3RpdmVTZXNzaW9uID0gdGhpcy5jcmVhdGVTZXNzaW9uKHVzZXJJZCk7XHJcbiAgICB0aGlzLm1lc3NhZ2VzLnNldChbXSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb2FkIGFuIGV4aXN0aW5nIHNlc3Npb25cclxuICAgKi9cclxuICBwdWJsaWMgbG9hZFNlc3Npb24oc2Vzc2lvbjogQ2hhdFNlc3Npb24pOiB2b2lkIHtcclxuICAgIGxvZ2dlci5sb2coJ1tDaGF0U2VydmljZV0gTG9hZGluZyBzZXNzaW9uOicsIHNlc3Npb24uaWQsICdNZXNzYWdlczonLCBzZXNzaW9uLm1lc3NhZ2VzLmxlbmd0aCk7XHJcbiAgICB0aGlzLmFjdGl2ZVNlc3Npb24gPSBzZXNzaW9uO1xyXG4gICAgdGhpcy5tZXNzYWdlcy5zZXQoWy4uLnNlc3Npb24ubWVzc2FnZXNdKTtcclxuICAgIGxvZ2dlci5sb2coJ1tDaGF0U2VydmljZV0gTWVzc2FnZXMgc2lnbmFsIHVwZGF0ZWQuIEN1cnJlbnQgY291bnQ6JywgdGhpcy5tZXNzYWdlcygpLmxlbmd0aCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYWN0aXZlIHNlc3Npb25cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0QWN0aXZlU2Vzc2lvbigpOiBDaGF0U2Vzc2lvbiB8IG51bGwge1xyXG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlU2Vzc2lvbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENsZWFyIG1lc3NhZ2VzIGZvciBjdXJyZW50IHNlc3Npb24gYW5kIHN0YXJ0IG5ldyBvbmVcclxuICAgKi9cclxuICBjbGVhck1lc3NhZ2VzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5tZXNzYWdlcy5zZXQoW10pO1xyXG4gICAgdGhpcy5zdGFydE5ld1Nlc3Npb24oKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZCBtZXNzYWdlIHRvIGN1cnJlbnQgc2Vzc2lvblxyXG4gICAqL1xyXG4gIHB1YmxpYyBhZGRNZXNzYWdlKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkIHtcclxuICAgIGNvbnN0IG5ld01lc3NhZ2UgPSB7IC4uLm1lc3NhZ2UsIHRpbWVzdGFtcDogbmV3IERhdGUoKSB9O1xyXG5cclxuICAgIC8vIFVwZGF0ZSBjdXJyZW50IG1lc3NhZ2VzIHNpZ25hbFxyXG4gICAgdGhpcy5tZXNzYWdlcy51cGRhdGUoKG1zZ3MpID0+IFsuLi5tc2dzLCBuZXdNZXNzYWdlXSk7XHJcblxyXG4gICAgLy8gU2F2ZSB0byBhY3RpdmUgc2Vzc2lvbiAoU2VydmVyIGhhbmRsZXMgYWN0dWFsIHN0b3JhZ2UsIFVJIGp1c3QgYWRkcyB0byBsb2NhbCBzaWduYWwgZm9yIGltbWVkaWF0ZSBmZWVkYmFjaylcclxuICAgIGlmIChtZXNzYWdlLnNlbmRlciA9PT0gJ2Fzc2lzdGFudCcpIHtcclxuICAgICAgdGhpcy5hdWRpb1NlcnZpY2UucGxheUJvdFNvdW5kKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb250aW51ZSBhIGNoYXQgc2Vzc2lvblxyXG4gICAqL1xyXG4gIHB1YmxpYyBjb250aW51ZVNlc3Npb24oc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGxvZ2dlci5sb2coYFtDaGF0U2VydmljZV0gY29udGludWluZyBzZXNzaW9uOiAke3Nlc3Npb25JZH1gKTtcclxuICAgIHRoaXMuY2hhdEhpc3RvcnlTZXJ2aWNlLmxvYWRTZXNzaW9uTWVzc2FnZXMoc2Vzc2lvbklkKS5zdWJzY3JpYmUoKG1lc3NhZ2VzKSA9PiB7XHJcbiAgICAgIGNvbnN0IGxvYWRlZE1lc3NhZ2VzID0gbWVzc2FnZXMgfHwgW107XHJcbiAgICAgIGNvbnN0IHNlc3Npb25Gcm9tTGlzdCA9IHRoaXMuY2hhdFNlc3Npb25zKCkuZmluZCgocykgPT4gcy5pZCA9PT0gc2Vzc2lvbklkKTtcclxuXHJcbiAgICAgIGlmIChzZXNzaW9uRnJvbUxpc3QpIHtcclxuICAgICAgICBzZXNzaW9uRnJvbUxpc3QubWVzc2FnZXMgPSBsb2FkZWRNZXNzYWdlcztcclxuICAgICAgICB0aGlzLmxvYWRTZXNzaW9uKHNlc3Npb25Gcm9tTGlzdCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29uc3QgdGltZXN0YW1wID1cclxuICAgICAgICAgIGxvYWRlZE1lc3NhZ2VzLmxlbmd0aCA+IDBcclxuICAgICAgICAgICAgPyBsb2FkZWRNZXNzYWdlc1tsb2FkZWRNZXNzYWdlcy5sZW5ndGggLSAxXS50aW1lc3RhbXAgfHwgbmV3IERhdGUoKVxyXG4gICAgICAgICAgICA6IG5ldyBEYXRlKCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHVzZXJJZCA9IHRoaXMuYXV0aFNlcnZpY2UuZ2V0VXNlcklkKCk7XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld1Nlc3Npb246IENoYXRTZXNzaW9uID0ge1xyXG4gICAgICAgICAgaWQ6IHNlc3Npb25JZCxcclxuICAgICAgICAgIHRpbWVzdGFtcDogdGltZXN0YW1wLFxyXG4gICAgICAgICAgdGl0bGU6ICdQcmV2aW91cyBDb252ZXJzYXRpb24nLFxyXG4gICAgICAgICAgbWVzc2FnZXM6IGxvYWRlZE1lc3NhZ2VzLFxyXG4gICAgICAgICAgdXNlcklkLFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgdGhpcy5sb2FkU2Vzc2lvbihuZXdTZXNzaW9uKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5hdWRpb1NlcnZpY2UudW5sb2NrQXVkaW8oKTtcclxuICAgICAgdGhpcy5jaGF0VUlTdGF0ZVNlcnZpY2Uub3BlbkNoYXQoKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8hID09PT09PT09PT09PT09PT09PT09IE1FU1NBR0UgUFJPQ0VTU0lORyA9PT09PT09PT09PT09PT09PT09PVxyXG5cclxuICAvKipcclxuICAgKiBQcm9jZXNzIGEgdXNlciBtZXNzYWdlOiBhZGQgaXQsIGdldCBib3QgcmVwbHksIGFuZCBhZGQgYm90IHJlcGx5XHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIHNlbmRNZXNzYWdlKHRleHQ6IHN0cmluZywgbWF4TGVuZ3RoOiBudW1iZXIgPSAxMDAwKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBjb25zdCB0cmltbWVkVGV4dCA9IHRleHQudHJpbSgpO1xyXG4gICAgaWYgKCF0cmltbWVkVGV4dCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRyaW1tZWRUZXh0Lmxlbmd0aCA+IG1heExlbmd0aCkge1xyXG4gICAgICBTbmFja2JhclV0aWxzLmVycm9yKGBNZXNzYWdlIGV4Y2VlZHMgbWF4aW11bSBsZW5ndGggb2YgJHttYXhMZW5ndGh9IGNoYXJhY3RlcnMuYCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyEgQ2FuY2VsIGFueSBvbmdvaW5nIHJlcXVlc3QgYmVmb3JlIHN0YXJ0aW5nIGEgbmV3IG9uZVxyXG4gICAgaWYgKHRoaXMuaXNCb3RUeXBpbmcoKSkge1xyXG4gICAgICB0aGlzLmNhbmNlbFJlcXVlc3QoKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjdXJyZW50U2Vzc2lvbklkID0gdGhpcy5hY3RpdmVTZXNzaW9uPy5pZDtcclxuXHJcbiAgICB0aGlzLmFkZE1lc3NhZ2Uoe1xyXG4gICAgICBzZW5kZXI6ICd1c2VyJyxcclxuICAgICAgdGV4dDogdGV4dCxcclxuICAgICAgY29tcGxldGVkOiB0cnVlLFxyXG4gICAgICBpc0hpc3Rvcnk6IGZhbHNlLFxyXG4gICAgICBpZDogRGF0ZS5ub3coKS50b1N0cmluZygpLFxyXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCksXHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLmlzQm90VHlwaW5nLnNldCh0cnVlKTtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0Qm90UmVwbHkodGV4dCk7XHJcblxyXG4gICAgICAvLyBDaGVjayBpZiBzZXNzaW9uIGhhcyBjaGFuZ2VkIHdoaWxlIHdhaXRpbmcgZm9yIHJlc3BvbnNlXHJcbiAgICAgIGlmICh0aGlzLmFjdGl2ZVNlc3Npb24/LmlkICE9PSBjdXJyZW50U2Vzc2lvbklkKSB7XHJcbiAgICAgICAgbG9nZ2VyLmxvZyhcclxuICAgICAgICAgIGBbQ2hhdFNlcnZpY2VdIElnbm9yaW5nIHJlc3BvbnNlIGZvciBzZXNzaW9uOiAke2N1cnJlbnRTZXNzaW9uSWR9IGFzIGFjdGl2ZSBzZXNzaW9uIGlzIG5vdzogJHt0aGlzLmFjdGl2ZVNlc3Npb24/LmlkfWAsXHJcbiAgICAgICAgKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGlzRmFsbGJhY2sgPSByZXNwb25zZSA9PT0gdGhpcy5nZXRGYWxsYmFja1JlcGx5KCk7XHJcblxyXG4gICAgICAvLyBPbmx5IGFkZCBjb21wbGV0aW9uIG1lc3NhZ2UgaWYgaXQgd2Fzbid0IGhhbmRsZWQgYnkgc3RyZWFtaW5nIChyZXNwb25zZSBpcyBub3QgZW1wdHkgc3RyaW5nKVxyXG4gICAgICBpZiAocmVzcG9uc2UgIT09ICcnKSB7XHJcbiAgICAgICAgdGhpcy5hZGRNZXNzYWdlKHtcclxuICAgICAgICAgIHNlbmRlcjogJ2Fzc2lzdGFudCcsXHJcbiAgICAgICAgICB0ZXh0OiByZXNwb25zZSxcclxuICAgICAgICAgIGNvbXBsZXRlZDogdHJ1ZSxcclxuICAgICAgICAgIGlzSGlzdG9yeTogZmFsc2UsXHJcbiAgICAgICAgICBpZDogRGF0ZS5ub3coKS50b1N0cmluZygpLFxyXG4gICAgICAgICAgc2hvd1N1Z2dlc3Rpb25zOiBmYWxzZSwgLy8hIERvbid0IHNob3cgc3VnZ2VzdGlvbnMgZm9yIGZhbGxiYWNrIHJlcGx5XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIC8vIE9ubHkgcmVzZXQgdHlwaW5nIGlmIHdlIGFyZSBzdGlsbCBpbiB0aGUgc2FtZSBzZXNzaW9uLCBvciBpZiB3ZSB3YW50IHRvIGJlIHNhZmUgKHRob3VnaCByZXNldHRpbmcgZmFsc2UgaXMgdXN1YWxseSBoYXJtbGVzcylcclxuICAgICAgaWYgKHRoaXMuYWN0aXZlU2Vzc2lvbj8uaWQgPT09IGN1cnJlbnRTZXNzaW9uSWQpIHtcclxuICAgICAgICB0aGlzLmlzQm90VHlwaW5nLnNldChmYWxzZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vISA9PT09PT09PT09PT09PT09PT09PSBBUEkgQ0FMTFMgPT09PT09PT09PT09PT09PT09PT1cclxuXHJcbiAgYXN5bmMgZ2V0Qm90UmVwbHkodXNlclRleHQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICBsb2dnZXIubG9nKCdSZXF1ZXN0aW5nIGJvdCByZXBseSBmb3I6JywgdXNlclRleHQpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuaXNMb2FkaW5nQXBpLnNldCh0cnVlKTtcclxuICAgICAgdGhpcy5hcGlFcnJvci5zZXQobnVsbCk7XHJcblxyXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZENoYXRSZXF1ZXN0KHVzZXJUZXh0KTtcclxuXHJcbiAgICAgIC8vISBjaGF0IGVuZHBvaW50c1xyXG4gICAgICBpZiAodGhpcy5pc1N0cmVhbWluZygpKSB7XHJcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuc3RyZWFtKHJlcXVlc3QpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmFzayhyZXF1ZXN0KTtcclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgU25hY2tiYXJVdGlscy5lcnJvcignQW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgZ2V0dGluZyB0aGUgYm90IHJlcGx5LicpO1xyXG4gICAgICByZXR1cm4gdGhpcy5nZXRGYWxsYmFja0Vycm9yKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBCdWlsZHMgYSBjaGF0IHJlcXVlc3QgcGF5bG9hZCB3aXRoIHRoZSBnaXZlbiB1c2VyIHRleHQgYW5kIG9wdGlvbmFsIGFjdGl2ZSBzZXNzaW9uXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJJbnB1dCAtIFRoZSB0ZXh0IHByb3ZpZGVkIGJ5IHRoZSB1c2VyXHJcbiAgICogQHJldHVybnMge0NoYXRSZXF1ZXN0fSAtIEEgY2hhdCByZXF1ZXN0IHBheWxvYWQgd2l0aCB0aGUgdXNlciB0ZXh0IGFuZCBvcHRpb25hbCBhY3RpdmUgc2Vzc2lvblxyXG4gICAqIEBtZW1iZXJvZiBDaGF0U2VydmljZVxyXG4gICAqL1xyXG5cclxuICBwcml2YXRlIGJ1aWxkQ2hhdFJlcXVlc3QodXNlclRleHQ6IHN0cmluZyk6IENoYXRSZXF1ZXN0IHtcclxuICAgIGNvbnN0IGluc3RydWN0aW9ucyA9IHRoaXMucGVyc29uYWxpemF0aW9uLmdldEZvcm1hdHRlZEluc3RydWN0aW9ucygpO1xyXG4gICAgY29uc3QgZmluYWxRdWVzdGlvbiA9IGluc3RydWN0aW9ucyA/IGAke2luc3RydWN0aW9uc31cXG5cXG4ke3VzZXJUZXh0fWAgOiB1c2VyVGV4dDtcclxuXHJcbiAgICBjb25zdCByZXF1ZXN0OiBDaGF0UmVxdWVzdCA9IHtcclxuICAgICAgcXVlc3Rpb246IGZpbmFsUXVlc3Rpb24sXHJcbiAgICAgIG9yZ2FuaXphdGlvbl9pZDogdGhpcy5hdXRoU2VydmljZS5nZXRPcmdhbml6YXRpb25JZCgpIHx8ICcnLFxyXG4gICAgICBwcm9tcHRfbW9kZTogdGhpcy5wcm9tcHRNb2RlKCksXHJcbiAgICAgIGN1c3RvbV9pbnN0cnVjdGlvbnM6IGluc3RydWN0aW9ucyxcclxuICAgIH07XHJcblxyXG4gICAgaWYgKHRoaXMuYWN0aXZlU2Vzc2lvbiAmJiAhdGhpcy5hY3RpdmVTZXNzaW9uLmlkLnN0YXJ0c1dpdGgoJ3Nlc3Npb25fJykpIHtcclxuICAgICAgcmVxdWVzdC5yZXNwb25zZV9pZCA9IHRoaXMuYWN0aXZlU2Vzc2lvbi5pZDtcclxuICAgICAgbG9nZ2VyLmxvZygnPj4+PiBjb252ZXJzYXRpb24gY29udGludWVkOicsIHRoaXMuYWN0aXZlU2Vzc2lvbi5pZCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsb2dnZXIubG9nKCc+Pj4+IG5ldyBjb252ZXJzYXRpb24gc3RhcnRlZCcpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZXF1ZXN0O1xyXG4gIH1cclxuXHJcbiAgLy8gISBBc2sgYXBpIGVuZHBvaW50XHJcbiAgcHJpdmF0ZSBhc3luYyBhc2socmVxdWVzdDogQ2hhdFJlcXVlc3QpOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgbG9nZ2VyLmxvZygnPj4+PlVzaW5nIFN0YW5kYXJkIENoYXQgRW5kcG9pbnQ8PDw8Jyk7XHJcblxyXG4gICAgY29uc3QgcmVzcG9uc2VTdWJqZWN0ID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG5cclxuICAgIGNvbnN0IGN1cnJlbnRTZXNzaW9uSWQgPSB0aGlzLmFjdGl2ZVNlc3Npb24/LmlkO1xyXG5cclxuICAgIHRoaXMuc3RyZWFtU3Vic2NyaXB0aW9uID0gdGhpcy5hcGlTZXJ2aWNlLnNlbmRNZXNzYWdlKHJlcXVlc3QsIHRydWUpLnN1YnNjcmliZSh7XHJcbiAgICAgIG5leHQ6IChyZXNwb25zZSkgPT4ge1xyXG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZVNlc3Npb24/LmlkID09PSBjdXJyZW50U2Vzc2lvbklkKSB7XHJcbiAgICAgICAgICB0aGlzLmlzTG9hZGluZ0FwaS5zZXQoZmFsc2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocmVzcG9uc2U/LnN1Y2Nlc3MgJiYgcmVzcG9uc2UuZGF0YSkge1xyXG4gICAgICAgICAgaWYgKHRoaXMuYWN0aXZlU2Vzc2lvbj8uaWQgPT09IGN1cnJlbnRTZXNzaW9uSWQpIHtcclxuICAgICAgICAgICAgdGhpcy5tYXBTZXNzaW9uSWQocmVzcG9uc2UuZGF0YS5pZCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICByZXNwb25zZVN1YmplY3QubmV4dChyZXNwb25zZS5kYXRhLmNvbnRlbnQgfHwgdGhpcy5nZXRGYWxsYmFja0Vycm9yKCkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICByZXNwb25zZVN1YmplY3QubmV4dCh0aGlzLmdldEZhbGxiYWNrRXJyb3IoKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlc3BvbnNlU3ViamVjdC5jb21wbGV0ZSgpO1xyXG4gICAgICB9LFxyXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB7XHJcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdBc2sgZXJyb3I6JywgZXJyb3IpO1xyXG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZVNlc3Npb24/LmlkID09PSBjdXJyZW50U2Vzc2lvbklkKSB7XHJcbiAgICAgICAgICB0aGlzLmlzTG9hZGluZ0FwaS5zZXQoZmFsc2UpO1xyXG4gICAgICAgICAgdGhpcy5pc0JvdFR5cGluZy5zZXQoZmFsc2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXNwb25zZVN1YmplY3QubmV4dCh0aGlzLmdldEZhbGxiYWNrRXJyb3IoKSk7XHJcbiAgICAgICAgcmVzcG9uc2VTdWJqZWN0LmNvbXBsZXRlKCk7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBIYW5kbGUgbWFudWFsIGNhbmNlbGxhdGlvblxyXG4gICAgY29uc3QgY2FuY2VsU3ViID0gdGhpcy5jYW5jZWxTdWJqZWN0LnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgIHJlc3BvbnNlU3ViamVjdC5uZXh0KCcnKTsgLy8gUmVzb2x2ZSB3aXRoIGVtcHR5IHN0cmluZyBpZiBjYW5jZWxsZWRcclxuICAgICAgcmVzcG9uc2VTdWJqZWN0LmNvbXBsZXRlKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICByZXR1cm4gYXdhaXQgbGFzdFZhbHVlRnJvbShyZXNwb25zZVN1YmplY3QpO1xyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgY2FuY2VsU3ViLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyAhIFN0cmVhbSBhcGkgZW5kcG9pbnRcclxuICBwcml2YXRlIGFzeW5jIHN0cmVhbShyZXF1ZXN0OiBDaGF0UmVxdWVzdCk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICBsb2dnZXIubG9nKCc+Pj4+VXNpbmcgU3RyZWFtIENoYXQgRW5kcG9pbnQ8PDw8Jyk7XHJcblxyXG4gICAgdGhpcy5jdXJyZW50UmVzcG9uc2UgPSAnJztcclxuICAgIHRoaXMuaXNCb3RUeXBpbmcuc2V0KHRydWUpO1xyXG5cclxuICAgIGNvbnN0IGFzc2lzdGFudE1lc3NhZ2U6IE1lc3NhZ2UgPSB7XHJcbiAgICAgIGlkOiBEYXRlLm5vdygpLnRvU3RyaW5nKCksXHJcbiAgICAgIHNlbmRlcjogJ2Fzc2lzdGFudCcsXHJcbiAgICAgIHRleHQ6ICcnLFxyXG4gICAgICBjaHVua3M6IFtdLFxyXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCksXHJcbiAgICAgIGNvbXBsZXRlZDogZmFsc2UsXHJcbiAgICAgIGlzSGlzdG9yeTogZmFsc2UsXHJcbiAgICAgIHNob3dTdWdnZXN0aW9uczogZmFsc2UsXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZCBlbXB0eSBidWJibGUgYWZ0ZXIgZmlyc3QgY2h1bmsgaGFzIGJlZW4gcmVjZWl2ZWRcclxuICAgIHRoaXMuYWRkTWVzc2FnZShhc3Npc3RhbnRNZXNzYWdlKTtcclxuXHJcbiAgICBjb25zdCBzdHJlYW1Db21wbGV0ZSQgPSBuZXcgU3ViamVjdDxzdHJpbmc+KCk7XHJcbiAgICBsZXQgaGFzU3RhcnRlZCA9IGZhbHNlO1xyXG5cclxuICAgIC8vIEhhbmRsZSBtYW51YWwgY2FuY2VsbGF0aW9uIGZvciBzdHJlYW1cclxuICAgIGNvbnN0IGNhbmNlbFN1YiA9IHRoaXMuY2FuY2VsU3ViamVjdC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICBpZiAoIXN0cmVhbUNvbXBsZXRlJC5jbG9zZWQpIHtcclxuICAgICAgICBzdHJlYW1Db21wbGV0ZSQubmV4dCgnJyk7XHJcbiAgICAgICAgc3RyZWFtQ29tcGxldGUkLmNvbXBsZXRlKCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuc3RyZWFtU3Vic2NyaXB0aW9uID0gdGhpcy5hcGlTZXJ2aWNlLnNlbmRNZXNzYWdlU3RyZWFtKHJlcXVlc3QpLnN1YnNjcmliZSh7XHJcbiAgICAgIG5leHQ6IChjaHVuaykgPT4ge1xyXG4gICAgICAgIGlmICghaGFzU3RhcnRlZCkge1xyXG4gICAgICAgICAgaGFzU3RhcnRlZCA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLmlzQm90VHlwaW5nLnNldChmYWxzZSk7XHJcblxyXG4gICAgICAgICAgLy8gcmVwbGFjZSByZXNwb25zZV9pZCBpbiBtZXNzYWdlIGlkXHJcbiAgICAgICAgICB0aGlzLm1lc3NhZ2VzLnVwZGF0ZSgobXNncykgPT5cclxuICAgICAgICAgICAgbXNncy5tYXAoKG0pID0+XHJcbiAgICAgICAgICAgICAgbS5pZCA9PT0gYXNzaXN0YW50TWVzc2FnZS5pZFxyXG4gICAgICAgICAgICAgICAgPyB7XHJcbiAgICAgICAgICAgICAgICAgIC4uLm0sXHJcbiAgICAgICAgICAgICAgICAgIC4uLnsgaWQ6IGNodW5rLmlkIH0sXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICA6IG0sXHJcbiAgICAgICAgICAgICksXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIGFzc2lzdGFudE1lc3NhZ2UuaWQgPSBjaHVuay5pZDtcclxuXHJcbiAgICAgICAgICAvLyBNYXAgdGhlIHNlc3Npb24gSUQgdG8gdGhlIGJhY2tlbmQtZ2VuZXJhdGVkIG9uZVxyXG4gICAgICAgICAgdGhpcy5tYXBTZXNzaW9uSWQoY2h1bmsucmVzcG9uc2VfaWQgfHwgY2h1bmsuaWQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgdGV4dCA9IGNodW5rLmNvbnRlbnQgPz8gJyc7XHJcbiAgICAgICAgaWYgKCF0ZXh0KSByZXR1cm47XHJcblxyXG4gICAgICAgIC8vIGtlZXAgbWVzc2FnZSBpbiBzeW5jIHdpdGhvdXQgcmVnZW5lcmF0aW9uXHJcbiAgICAgICAgdGhpcy5tZXNzYWdlcy51cGRhdGUoKG1zZ3MpID0+XHJcbiAgICAgICAgICBtc2dzLm1hcCgobSkgPT5cclxuICAgICAgICAgICAgbS5pZCA9PT0gYXNzaXN0YW50TWVzc2FnZS5pZFxyXG4gICAgICAgICAgICAgID8ge1xyXG4gICAgICAgICAgICAgICAgLi4ubSxcclxuICAgICAgICAgICAgICAgIGNodW5rczogWy4uLihtLmNodW5rcyA/PyBbXSksIHRleHRdLCAvLyBpbW11dGFibGUgYXBwZW5kXHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDogbSxcclxuICAgICAgICAgICksXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgLy8gY29uc3QgbWVzc2FnZSA9IHRoaXMubWVzc2FnZXMoKS5maW5kKChtKSA9PiBtLmlkID09PSBhc3Npc3RhbnRNZXNzYWdlLmlkKTtcclxuICAgICAgICAvLyBsb2dnZXIubG9nKCdBcHBlbmRpbmcgY2h1bmsgdG8gYXNzaXN0YW50IG1lc3NhZ2U6JywgbWVzc2FnZT8uY2h1bmtzKTtcclxuICAgICAgfSxcclxuICAgICAgY29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICB0aGlzLmlzTG9hZGluZ0FwaS5zZXQoZmFsc2UpO1xyXG5cclxuICAgICAgICAvLyBNYXJrIHRoZSBjaHVuayBzdHJlYW0gY29tcGVsdGVkXHJcbiAgICAgICAgdGhpcy5tZXNzYWdlcy51cGRhdGUoKG1zZ3MpID0+XHJcbiAgICAgICAgICBtc2dzLm1hcCgobSkgPT4gKG0uaWQgPT09IGFzc2lzdGFudE1lc3NhZ2UuaWQgPyB7IC4uLm0sIGNvbXBsZXRlZDogdHJ1ZSB9IDogbSkpLFxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIC8vIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLm1lc3NhZ2VzKCkuZmluZCgobSkgPT4gbS5pZCA9PT0gYXNzaXN0YW50TWVzc2FnZS5pZCk7XHJcbiAgICAgICAgLy8gdGhpcy5jdXJyZW50UmVzcG9uc2UgKz0gbWVzc2FnZT8uY2h1bmtzPy5qb2luKCcnKSA/PyAnJztcclxuXHJcbiAgICAgICAgLy8gbG9nZ2VyLmxvZygnQXBwZW5kaW5nIGNodW5rIHRvIGFzc2lzdGFudCBtZXNzYWdlOicsIG1lc3NhZ2U/LnRleHQpO1xyXG4gICAgICAgIC8vIGxvZ2dlci5sb2coJ0FwcGVuZGluZyBjaHVuayB0byBhc3Npc3RhbnQgbWVzc2FnZTonLCBtZXNzYWdlPy5jaHVua3MpO1xyXG5cclxuICAgICAgICBzdHJlYW1Db21wbGV0ZSQubmV4dCh0aGlzLmN1cnJlbnRSZXNwb25zZSk7XHJcbiAgICAgICAgc3RyZWFtQ29tcGxldGUkLmNvbXBsZXRlKCk7XHJcbiAgICAgIH0sXHJcbiAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICBsb2dnZXIuZXJyb3IoJ0NoYXQgZXJyb3I6JywgZXJyb3IpO1xyXG4gICAgICAgIFNuYWNrYmFyVXRpbHMuZXJyb3IoJ0FuIGVycm9yIG9jY3VycmVkIGR1cmluZyByZXBseS4nKTtcclxuXHJcbiAgICAgICAgdGhpcy5pc0xvYWRpbmdBcGkuc2V0KGZhbHNlKTtcclxuICAgICAgICB0aGlzLmlzQm90VHlwaW5nLnNldChmYWxzZSk7XHJcbiAgICAgICAgU25hY2tiYXJVdGlscy5lcnJvcignQW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIHJlcGx5LicpO1xyXG5cclxuICAgICAgICBpZiAoIWhhc1N0YXJ0ZWQpIHRoaXMuYWRkTWVzc2FnZShhc3Npc3RhbnRNZXNzYWdlKTtcclxuICAgICAgICBpZiAoIWFzc2lzdGFudE1lc3NhZ2UudGV4dCkgYXNzaXN0YW50TWVzc2FnZS50ZXh0ID0gdGhpcy5nZXRGYWxsYmFja0Vycm9yKCk7XHJcblxyXG4gICAgICAgIC8vIG1hcmsgY29tcGxldGVkLCBkbyBOT1QgcmVidWlsZCBjb250ZW50XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlcy51cGRhdGUoKG1zZ3MpID0+XHJcbiAgICAgICAgICBtc2dzLm1hcCgobSkgPT5cclxuICAgICAgICAgICAgbS5pZCA9PT0gYXNzaXN0YW50TWVzc2FnZS5pZFxyXG4gICAgICAgICAgICAgID8ge1xyXG4gICAgICAgICAgICAgICAgLi4ubSxcclxuICAgICAgICAgICAgICAgIGNvbXBsZXRlZDogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGlzSGlzdG9yeTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB0ZXh0OiBhc3Npc3RhbnRNZXNzYWdlLnRleHQsXHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDogbSxcclxuICAgICAgICAgICksXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgc3RyZWFtQ29tcGxldGUkLm5leHQoJycpO1xyXG4gICAgICAgIHN0cmVhbUNvbXBsZXRlJC5jb21wbGV0ZSgpO1xyXG4gICAgICAgIC8vIHRoaXMuZmluYWxpemVTdHJlYW1FcnJvcihhc3Npc3RhbnRNZXNzYWdlLCBoYXNTdGFydGVkLCBzdHJlYW1Db21wbGV0ZSQpO1xyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgYXdhaXQgbGFzdFZhbHVlRnJvbShzdHJlYW1Db21wbGV0ZSQpO1xyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgY2FuY2VsU3ViLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gJyc7XHJcbiAgfVxyXG5cclxuICAvLyEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgY2FuY2VsUmVxdWVzdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2FuY2VsU3ViamVjdC5uZXh0KCk7XHJcblxyXG4gICAgLy8gUmVzZXQgVUkgc3RhdGVzIGltbWVkaWF0ZWx5XHJcbiAgICB0aGlzLmlzTG9hZGluZ0FwaS5zZXQoZmFsc2UpO1xyXG4gICAgdGhpcy5pc0JvdFR5cGluZy5zZXQoZmFsc2UpO1xyXG4gICAgdGhpcy5jdXJyZW50UmVzcG9uc2UgPSAnJztcclxuXHJcbiAgICBpZiAodGhpcy5zdHJlYW1TdWJzY3JpcHRpb24pIHtcclxuICAgICAgbG9nZ2VyLmxvZygnQ2FuY2VsbGluZyBvbmdvaW5nIGNoYXQgcmVxdWVzdC4uLicpO1xyXG4gICAgICB0aGlzLnN0cmVhbVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xyXG4gICAgICB0aGlzLnN0cmVhbVN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgIC8vIENsZWFuIHVwIGFzc2lzdGFudCBtZXNzYWdlczpcclxuICAgICAgLy8gUmVtb3ZlIGlmIGNvbXBsZXRlbHkgZW1wdHlcclxuICAgICAgLy8gTWFyayBhcyBjb21wbGV0ZWQgaWYgaXQgaGFzIGNvbnRlbnRcclxuICAgICAgdGhpcy5tZXNzYWdlcy51cGRhdGUoKG1zZ3MpID0+XHJcbiAgICAgICAgbXNnc1xyXG4gICAgICAgICAgLmZpbHRlcihcclxuICAgICAgICAgICAgKG0pID0+XHJcbiAgICAgICAgICAgICAgIShcclxuICAgICAgICAgICAgICAgIG0uc2VuZGVyID09PSAnYXNzaXN0YW50JyAmJlxyXG4gICAgICAgICAgICAgICAgIW0uY29tcGxldGVkICYmXHJcbiAgICAgICAgICAgICAgICAhbS50ZXh0ICYmXHJcbiAgICAgICAgICAgICAgICAoIW0uY2h1bmtzIHx8IG0uY2h1bmtzLmxlbmd0aCA9PT0gMClcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgKVxyXG4gICAgICAgICAgLm1hcCgobSkgPT4gKG0uc2VuZGVyID09PSAnYXNzaXN0YW50JyAmJiAhbS5jb21wbGV0ZWQgPyB7IC4uLm0sIGNvbXBsZXRlZDogdHJ1ZSB9IDogbSkpLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8hID09PT09PT09PT09PT09PT09PT09IEFVRElPID09PT09PT09PT09PT09PT09PT09XHJcblxyXG4gIHB1YmxpYyB1bmxvY2tBdWRpbygpOiB2b2lkIHtcclxuICAgIHRoaXMuYXVkaW9TZXJ2aWNlLnVubG9ja0F1ZGlvKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNYXAgbG9jYWwgcGxhY2Vob2xkZXIgc2Vzc2lvbiBJRCB0byBiYWNrZW5kLWdlbmVyYXRlZCBJRFxyXG4gICAqL1xyXG4gIHByaXZhdGUgbWFwU2Vzc2lvbklkKHJlc3BvbnNlSWQ/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICghcmVzcG9uc2VJZCB8fCAhdGhpcy5hY3RpdmVTZXNzaW9uIHx8ICF0aGlzLmFjdGl2ZVNlc3Npb24uaWQuc3RhcnRzV2l0aCgnc2Vzc2lvbl8nKSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3Qgb2xkSWQgPSB0aGlzLmFjdGl2ZVNlc3Npb24uaWQ7XHJcbiAgICBsb2dnZXIubG9nKGBbQ2hhdFNlcnZpY2VdIE1hcHBpbmcgbG9jYWwgc2Vzc2lvbiAke29sZElkfSDihpIgYmFja2VuZCBJRCAke3Jlc3BvbnNlSWR9YCk7XHJcblxyXG4gICAgLy8gVXBkYXRlIGFjdGl2ZSBzZXNzaW9uIHN1YmplY3RcclxuICAgIHRoaXMuYWN0aXZlU2Vzc2lvbi5pZCA9IHJlc3BvbnNlSWQ7XHJcblxyXG4gICAgLy8gVHJpZ2dlciBoaXN0b3J5IHJlZnJlc2ggdG8gZ2V0IHRoZSBzZXJ2ZXItZ2VuZXJhdGVkIHRpdGxlXHJcbiAgICB0aGlzLmNoYXRIaXN0b3J5U2VydmljZS5pbnZhbGlkYXRlQ2FjaGUoKTtcclxuICB9XHJcbn1cclxuIl19
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/common";
|
|
6
|
+
export class ChatButtonComponent {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.buttonStyle = 'fab';
|
|
9
|
+
this.isChatOpen = false;
|
|
10
|
+
this.unreadCount = 0;
|
|
11
|
+
this.appTitle = 'Chat';
|
|
12
|
+
this.appLogoUrl = '';
|
|
13
|
+
this.appTextLogoUrl = '';
|
|
14
|
+
this.toggle = new EventEmitter();
|
|
15
|
+
}
|
|
16
|
+
get isSidebar() {
|
|
17
|
+
return this.buttonStyle.startsWith('sidebar');
|
|
18
|
+
}
|
|
19
|
+
get sidebarPosition() {
|
|
20
|
+
if (!this.isSidebar)
|
|
21
|
+
return 'center';
|
|
22
|
+
if (this.buttonStyle === 'sidebar')
|
|
23
|
+
return 'center';
|
|
24
|
+
return this.buttonStyle.split('-')[1];
|
|
25
|
+
}
|
|
26
|
+
onToggle() {
|
|
27
|
+
this.toggle.emit();
|
|
28
|
+
}
|
|
29
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
30
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: ChatButtonComponent, isStandalone: true, selector: "app-chat-button", inputs: { buttonStyle: "buttonStyle", isChatOpen: "isChatOpen", unreadCount: "unreadCount", appTitle: "appTitle", appLogoUrl: "appLogoUrl", appTextLogoUrl: "appTextLogoUrl" }, outputs: { toggle: "toggle" }, ngImport: i0, template: "<!-- fab -->\r\n@if (buttonStyle === 'fab' && !isChatOpen) {\r\n <button class=\"chat-fab\" (click)=\"onToggle()\">\r\n <!-- <mat-icon>{{ chatIcon }}</mat-icon> -->\r\n <img style=\"width: 30px; height: 30px\" [src]=\"appLogoUrl\" />\r\n <!-- <div class=\"chat-logo\"></div> -->\r\n @if (unreadCount > 0) {\r\n <span class=\"alert-badge\">\r\n {{ unreadCount > 9 ? '9+' : unreadCount }}\r\n </span>\r\n }\r\n </button>\r\n}\r\n\r\n<!-- sidebar button -->\r\n@if (isSidebar && !isChatOpen) {\r\n <button class=\"chat-sidebar\" (click)=\"onToggle()\" [ngClass]=\"sidebarPosition\">\r\n <!-- <h2 style=\"transform: rotate(-90deg); font-size: 16px\">{{ appTitle }}</h2> -->\r\n <img style=\"transform: rotate(-90deg); width: 100px; height: 45px\" [src]=\"appTextLogoUrl\" />\r\n\r\n @if (unreadCount > 0) {\r\n <span class=\"alert-badge\">\r\n {{ unreadCount > 9 ? '9+' : unreadCount }}\r\n </span>\r\n }\r\n </button>\r\n}\r\n", styles: [".chat-sidebar{position:fixed;right:0;width:40px;height:120px;border-radius:16px 0 0 16px;background:var(--background-color);color:var(--white);border:none;box-shadow:var(--border-shadow-color);display:flex;justify-content:center;align-items:center;cursor:pointer;z-index:1000}.chat-sidebar.disabled{background:transparent;border-radius:0}.chat-sidebar h2{margin:0;font-size:12px;transform:rotate(-90deg);white-space:nowrap}.chat-sidebar .alert-badge{position:absolute;bottom:15px;right:30px;width:18px;height:18px;border-radius:50%;background:var(--red);color:var(--white);font-size:10px;display:flex;align-items:center;justify-content:center}.chat-sidebar.center{top:50%;transform:translateY(-50%)}.chat-sidebar.top{top:calc(50% - 45vh);transform:none}.chat-sidebar.bottom{top:calc(50% + 30vh);transform:none}.chat-fab{position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;background:var(--background-color);color:var(--white);box-shadow:0 6px 16px rgba(var(--black-rgb),.2);border:none;cursor:pointer;z-index:1000;display:flex;align-items:center;justify-content:center}.chat-fab svg,.chat-fab mat-icon{width:24px;height:24px}.chat-fab:hover{transform:scale(1.1)}.alert-badge{position:absolute;top:-4px;right:-4px;background:var(--red);color:var(--white);border-radius:50%;min-width:18px;height:18px;font-size:11px;display:flex;align-items:center;justify-content:center;font-weight:700;line-height:1}.chat-logo{width:45px;height:45px;mask:url(/assets/logo.svg) no-repeat center;-webkit-mask-size:contain;mask-size:contain;background-color:var(--mat-sys-on-primary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatIconModule }] }); }
|
|
31
|
+
}
|
|
32
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatButtonComponent, decorators: [{
|
|
33
|
+
type: Component,
|
|
34
|
+
args: [{ selector: 'app-chat-button', standalone: true, imports: [CommonModule, MatIconModule], template: "<!-- fab -->\r\n@if (buttonStyle === 'fab' && !isChatOpen) {\r\n <button class=\"chat-fab\" (click)=\"onToggle()\">\r\n <!-- <mat-icon>{{ chatIcon }}</mat-icon> -->\r\n <img style=\"width: 30px; height: 30px\" [src]=\"appLogoUrl\" />\r\n <!-- <div class=\"chat-logo\"></div> -->\r\n @if (unreadCount > 0) {\r\n <span class=\"alert-badge\">\r\n {{ unreadCount > 9 ? '9+' : unreadCount }}\r\n </span>\r\n }\r\n </button>\r\n}\r\n\r\n<!-- sidebar button -->\r\n@if (isSidebar && !isChatOpen) {\r\n <button class=\"chat-sidebar\" (click)=\"onToggle()\" [ngClass]=\"sidebarPosition\">\r\n <!-- <h2 style=\"transform: rotate(-90deg); font-size: 16px\">{{ appTitle }}</h2> -->\r\n <img style=\"transform: rotate(-90deg); width: 100px; height: 45px\" [src]=\"appTextLogoUrl\" />\r\n\r\n @if (unreadCount > 0) {\r\n <span class=\"alert-badge\">\r\n {{ unreadCount > 9 ? '9+' : unreadCount }}\r\n </span>\r\n }\r\n </button>\r\n}\r\n", styles: [".chat-sidebar{position:fixed;right:0;width:40px;height:120px;border-radius:16px 0 0 16px;background:var(--background-color);color:var(--white);border:none;box-shadow:var(--border-shadow-color);display:flex;justify-content:center;align-items:center;cursor:pointer;z-index:1000}.chat-sidebar.disabled{background:transparent;border-radius:0}.chat-sidebar h2{margin:0;font-size:12px;transform:rotate(-90deg);white-space:nowrap}.chat-sidebar .alert-badge{position:absolute;bottom:15px;right:30px;width:18px;height:18px;border-radius:50%;background:var(--red);color:var(--white);font-size:10px;display:flex;align-items:center;justify-content:center}.chat-sidebar.center{top:50%;transform:translateY(-50%)}.chat-sidebar.top{top:calc(50% - 45vh);transform:none}.chat-sidebar.bottom{top:calc(50% + 30vh);transform:none}.chat-fab{position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;background:var(--background-color);color:var(--white);box-shadow:0 6px 16px rgba(var(--black-rgb),.2);border:none;cursor:pointer;z-index:1000;display:flex;align-items:center;justify-content:center}.chat-fab svg,.chat-fab mat-icon{width:24px;height:24px}.chat-fab:hover{transform:scale(1.1)}.alert-badge{position:absolute;top:-4px;right:-4px;background:var(--red);color:var(--white);border-radius:50%;min-width:18px;height:18px;font-size:11px;display:flex;align-items:center;justify-content:center;font-weight:700;line-height:1}.chat-logo{width:45px;height:45px;mask:url(/assets/logo.svg) no-repeat center;-webkit-mask-size:contain;mask-size:contain;background-color:var(--mat-sys-on-primary)}\n"] }]
|
|
35
|
+
}], propDecorators: { buttonStyle: [{
|
|
36
|
+
type: Input
|
|
37
|
+
}], isChatOpen: [{
|
|
38
|
+
type: Input
|
|
39
|
+
}], unreadCount: [{
|
|
40
|
+
type: Input
|
|
41
|
+
}], appTitle: [{
|
|
42
|
+
type: Input
|
|
43
|
+
}], appLogoUrl: [{
|
|
44
|
+
type: Input
|
|
45
|
+
}], appTextLogoUrl: [{
|
|
46
|
+
type: Input
|
|
47
|
+
}], toggle: [{
|
|
48
|
+
type: Output
|
|
49
|
+
}] } });
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC1idXR0b24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9vaGJvdC9zcmMvbGliL2FwcC9jaGF0L2NvbXBvbmVudHMvY2hhdC1idXR0b24vY2hhdC1idXR0b24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9vaGJvdC9zcmMvbGliL2FwcC9jaGF0L2NvbXBvbmVudHMvY2hhdC1idXR0b24vY2hhdC1idXR0b24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDOzs7QUFTdkQsTUFBTSxPQUFPLG1CQUFtQjtJQVBoQztRQVFXLGdCQUFXLEdBQXlELEtBQUssQ0FBQztRQUMxRSxlQUFVLEdBQVksS0FBSyxDQUFDO1FBQzVCLGdCQUFXLEdBQVcsQ0FBQyxDQUFDO1FBQ3hCLGFBQVEsR0FBVyxNQUFNLENBQUM7UUFDMUIsZUFBVSxHQUFXLEVBQUUsQ0FBQztRQUN4QixtQkFBYyxHQUFXLEVBQUUsQ0FBQztRQUUzQixXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztLQWU3QztJQWJDLElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVELElBQUksZUFBZTtRQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVM7WUFBRSxPQUFPLFFBQVEsQ0FBQztRQUNyQyxJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssU0FBUztZQUFFLE9BQU8sUUFBUSxDQUFDO1FBQ3BELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFnQyxDQUFDO0lBQ3ZFLENBQUM7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNyQixDQUFDOytHQXRCVSxtQkFBbUI7bUdBQW5CLG1CQUFtQiwwUkNYaEMsODlCQTJCQSxrbkREcEJZLFlBQVksNEhBQUUsYUFBYTs7NEZBSTFCLG1CQUFtQjtrQkFQL0IsU0FBUzsrQkFDRSxpQkFBaUIsY0FDZixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDOzhCQUs3QixXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFFSSxNQUFNO3NCQUFmLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2FwcC1jaGF0LWJ1dHRvbicsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBNYXRJY29uTW9kdWxlXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vY2hhdC1idXR0b24uY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2NoYXQtYnV0dG9uLmNvbXBvbmVudC5zY3NzJ10sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDaGF0QnV0dG9uQ29tcG9uZW50IHtcclxuICBASW5wdXQoKSBidXR0b25TdHlsZTogJ2ZhYicgfCAnc2lkZWJhcicgfCAnc2lkZWJhci10b3AnIHwgJ3NpZGViYXItYm90dG9tJyA9ICdmYWInO1xyXG4gIEBJbnB1dCgpIGlzQ2hhdE9wZW46IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSB1bnJlYWRDb3VudDogbnVtYmVyID0gMDtcclxuICBASW5wdXQoKSBhcHBUaXRsZTogc3RyaW5nID0gJ0NoYXQnO1xyXG4gIEBJbnB1dCgpIGFwcExvZ29Vcmw6IHN0cmluZyA9ICcnO1xyXG4gIEBJbnB1dCgpIGFwcFRleHRMb2dvVXJsOiBzdHJpbmcgPSAnJztcclxuXHJcbiAgQE91dHB1dCgpIHRvZ2dsZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgZ2V0IGlzU2lkZWJhcigpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmJ1dHRvblN0eWxlLnN0YXJ0c1dpdGgoJ3NpZGViYXInKTtcclxuICB9XHJcblxyXG4gIGdldCBzaWRlYmFyUG9zaXRpb24oKTogJ3RvcCcgfCAnY2VudGVyJyB8ICdib3R0b20nIHtcclxuICAgIGlmICghdGhpcy5pc1NpZGViYXIpIHJldHVybiAnY2VudGVyJztcclxuICAgIGlmICh0aGlzLmJ1dHRvblN0eWxlID09PSAnc2lkZWJhcicpIHJldHVybiAnY2VudGVyJztcclxuICAgIHJldHVybiB0aGlzLmJ1dHRvblN0eWxlLnNwbGl0KCctJylbMV0gYXMgJ3RvcCcgfCAnY2VudGVyJyB8ICdib3R0b20nO1xyXG4gIH1cclxuXHJcbiAgb25Ub2dnbGUoKSB7XHJcbiAgICB0aGlzLnRvZ2dsZS5lbWl0KCk7XHJcbiAgfVxyXG59XHJcbiIsIjwhLS0gZmFiIC0tPlxyXG5AaWYgKGJ1dHRvblN0eWxlID09PSAnZmFiJyAmJiAhaXNDaGF0T3Blbikge1xyXG4gIDxidXR0b24gY2xhc3M9XCJjaGF0LWZhYlwiIChjbGljayk9XCJvblRvZ2dsZSgpXCI+XHJcbiAgICA8IS0tIDxtYXQtaWNvbj57eyBjaGF0SWNvbiB9fTwvbWF0LWljb24+IC0tPlxyXG4gICAgPGltZyBzdHlsZT1cIndpZHRoOiAzMHB4OyBoZWlnaHQ6IDMwcHhcIiBbc3JjXT1cImFwcExvZ29VcmxcIiAvPlxyXG4gICAgPCEtLSA8ZGl2IGNsYXNzPVwiY2hhdC1sb2dvXCI+PC9kaXY+IC0tPlxyXG4gICAgQGlmICh1bnJlYWRDb3VudCA+IDApIHtcclxuICAgICAgPHNwYW4gY2xhc3M9XCJhbGVydC1iYWRnZVwiPlxyXG4gICAgICAgIHt7IHVucmVhZENvdW50ID4gOSA/ICc5KycgOiB1bnJlYWRDb3VudCB9fVxyXG4gICAgICA8L3NwYW4+XHJcbiAgICB9XHJcbiAgPC9idXR0b24+XHJcbn1cclxuXHJcbjwhLS0gc2lkZWJhciBidXR0b24gLS0+XHJcbkBpZiAoaXNTaWRlYmFyICYmICFpc0NoYXRPcGVuKSB7XHJcbiAgPGJ1dHRvbiBjbGFzcz1cImNoYXQtc2lkZWJhclwiIChjbGljayk9XCJvblRvZ2dsZSgpXCIgW25nQ2xhc3NdPVwic2lkZWJhclBvc2l0aW9uXCI+XHJcbiAgICA8IS0tIDxoMiBzdHlsZT1cInRyYW5zZm9ybTogcm90YXRlKC05MGRlZyk7IGZvbnQtc2l6ZTogMTZweFwiPnt7IGFwcFRpdGxlIH19PC9oMj4gLS0+XHJcbiAgICA8aW1nIHN0eWxlPVwidHJhbnNmb3JtOiByb3RhdGUoLTkwZGVnKTsgd2lkdGg6IDEwMHB4OyBoZWlnaHQ6IDQ1cHhcIiBbc3JjXT1cImFwcFRleHRMb2dvVXJsXCIgLz5cclxuXHJcbiAgICBAaWYgKHVucmVhZENvdW50ID4gMCkge1xyXG4gICAgICA8c3BhbiBjbGFzcz1cImFsZXJ0LWJhZGdlXCI+XHJcbiAgICAgICAge3sgdW5yZWFkQ291bnQgPiA5ID8gJzkrJyA6IHVucmVhZENvdW50IH19XHJcbiAgICAgIDwvc3Bhbj5cclxuICAgIH1cclxuICA8L2J1dHRvbj5cclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export class ChatFooterComponent {
|
|
5
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ChatFooterComponent, isStandalone: true, selector: "app-chat-footer", ngImport: i0, template: "<div class=\"terms-conditions\">\r\n <!-- Terms and conditions relocated to Personalization Hub -->\r\n</div>", styles: [".terms-conditions{padding:10px 15px;text-align:center;font-size:.8rem;background-color:var(--background-color);border-top:1px solid var(--background-color);border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.terms-conditions a{color:var(--secondary-text-color);text-decoration:none;transition:color .2s ease}.terms-conditions a:hover{color:var(--primary-color);text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7
|
+
}
|
|
8
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChatFooterComponent, decorators: [{
|
|
9
|
+
type: Component,
|
|
10
|
+
args: [{ selector: 'app-chat-footer', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"terms-conditions\">\r\n <!-- Terms and conditions relocated to Personalization Hub -->\r\n</div>", styles: [".terms-conditions{padding:10px 15px;text-align:center;font-size:.8rem;background-color:var(--background-color);border-top:1px solid var(--background-color);border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.terms-conditions a{color:var(--secondary-text-color);text-decoration:none;transition:color .2s ease}.terms-conditions a:hover{color:var(--primary-color);text-decoration:underline}\n"] }]
|
|
11
|
+
}] });
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC1mb290ZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9vaGJvdC9zcmMvbGliL2FwcC9jaGF0L2NvbXBvbmVudHMvY2hhdC1mb290ZXIvY2hhdC1mb290ZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9vaGJvdC9zcmMvbGliL2FwcC9jaGF0L2NvbXBvbmVudHMvY2hhdC1mb290ZXIvY2hhdC1mb290ZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7O0FBVS9DLE1BQU0sT0FBTyxtQkFBbUI7K0dBQW5CLG1CQUFtQjttR0FBbkIsbUJBQW1CLDJFQ1hoQyxrSEFFTSxnZERJTSxZQUFZOzs0RkFLWCxtQkFBbUI7a0JBUi9CLFNBQVM7K0JBQ0UsaUJBQWlCLGNBQ2YsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDLG1CQUdOLHVCQUF1QixDQUFDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2FwcC1jaGF0LWZvb3RlcicsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vY2hhdC1mb290ZXIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2NoYXQtZm9vdGVyLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDaGF0Rm9vdGVyQ29tcG9uZW50IHt9XHJcbiIsIjxkaXYgY2xhc3M9XCJ0ZXJtcy1jb25kaXRpb25zXCI+XHJcbiAgICA8IS0tIFRlcm1zIGFuZCBjb25kaXRpb25zIHJlbG9jYXRlZCB0byBQZXJzb25hbGl6YXRpb24gSHViIC0tPlxyXG48L2Rpdj4iXX0=
|