@product7/feedback-sdk 1.3.1 → 1.3.3
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/dist/feedback-sdk.js +114 -189
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/widgets/MessengerWidget.js +116 -189
package/dist/feedback-sdk.js
CHANGED
|
@@ -5736,10 +5736,6 @@
|
|
|
5736
5736
|
}
|
|
5737
5737
|
}
|
|
5738
5738
|
|
|
5739
|
-
/**
|
|
5740
|
-
* MessengerWidget - Full-featured Messenger/Chat widget
|
|
5741
|
-
*/
|
|
5742
|
-
|
|
5743
5739
|
class MessengerWidget extends BaseWidget {
|
|
5744
5740
|
constructor(options) {
|
|
5745
5741
|
super({ ...options, type: 'messenger' });
|
|
@@ -5755,13 +5751,11 @@
|
|
|
5755
5751
|
logoUrl: options.logoUrl || 'https://product7.io/p7logo.svg',
|
|
5756
5752
|
featuredContent: options.featuredContent || null,
|
|
5757
5753
|
primaryColor: options.primaryColor || '#1c1c1e',
|
|
5758
|
-
// Callbacks
|
|
5759
5754
|
onSendMessage: options.onSendMessage || null,
|
|
5760
5755
|
onArticleClick: options.onArticleClick || null,
|
|
5761
5756
|
onChangelogClick: options.onChangelogClick || null,
|
|
5762
5757
|
};
|
|
5763
5758
|
|
|
5764
|
-
// Create state
|
|
5765
5759
|
this.messengerState = new MessengerState({
|
|
5766
5760
|
teamName: this.messengerOptions.teamName,
|
|
5767
5761
|
teamAvatars: this.messengerOptions.teamAvatars,
|
|
@@ -5776,7 +5770,6 @@
|
|
|
5776
5770
|
this.wsService = null;
|
|
5777
5771
|
this._wsUnsubscribers = [];
|
|
5778
5772
|
|
|
5779
|
-
// Bind methods
|
|
5780
5773
|
this._handleOpenChange = this._handleOpenChange.bind(this);
|
|
5781
5774
|
this._handleWebSocketMessage = this._handleWebSocketMessage.bind(this);
|
|
5782
5775
|
this._handleTypingStarted = this._handleTypingStarted.bind(this);
|
|
@@ -5785,42 +5778,34 @@
|
|
|
5785
5778
|
}
|
|
5786
5779
|
|
|
5787
5780
|
_render() {
|
|
5788
|
-
// Create container
|
|
5789
5781
|
const container = document.createElement('div');
|
|
5790
5782
|
container.className = `messenger-widget theme-${this.messengerOptions.theme}`;
|
|
5791
5783
|
container.style.zIndex = '999999';
|
|
5792
5784
|
|
|
5793
|
-
// Create launcher
|
|
5794
5785
|
this.launcher = new MessengerLauncher(this.messengerState, {
|
|
5795
5786
|
position: this.messengerOptions.position,
|
|
5796
5787
|
primaryColor: this.messengerOptions.primaryColor,
|
|
5797
5788
|
});
|
|
5798
5789
|
container.appendChild(this.launcher.render());
|
|
5799
5790
|
|
|
5800
|
-
// Create panel with all callbacks
|
|
5801
5791
|
this.panel = new MessengerPanel(this.messengerState, {
|
|
5802
5792
|
position: this.messengerOptions.position,
|
|
5803
5793
|
theme: this.messengerOptions.theme,
|
|
5804
5794
|
primaryColor: this.messengerOptions.primaryColor,
|
|
5805
5795
|
logoUrl: this.messengerOptions.logoUrl,
|
|
5806
5796
|
featuredContent: this.messengerOptions.featuredContent,
|
|
5807
|
-
// Chat callbacks
|
|
5808
5797
|
onSendMessage:
|
|
5809
5798
|
this.messengerOptions.onSendMessage ||
|
|
5810
5799
|
this._handleSendMessage.bind(this),
|
|
5811
5800
|
onStartConversation: this._handleStartConversation.bind(this),
|
|
5812
5801
|
onTyping: this.sendTypingIndicator.bind(this),
|
|
5813
|
-
// Conversation list callbacks
|
|
5814
5802
|
onSelectConversation: this._handleSelectConversation.bind(this),
|
|
5815
5803
|
onStartNewConversation: this._handleNewConversationClick.bind(this),
|
|
5816
|
-
// Pre-chat form callbacks
|
|
5817
5804
|
onIdentifyContact: this._handleIdentifyContact.bind(this),
|
|
5818
|
-
// Article/changelog callbacks
|
|
5819
5805
|
onArticleClick: this.messengerOptions.onArticleClick,
|
|
5820
5806
|
onChangelogClick: this.messengerOptions.onChangelogClick,
|
|
5821
5807
|
});
|
|
5822
5808
|
|
|
5823
|
-
// Register views
|
|
5824
5809
|
this.panel.registerView('home', HomeView);
|
|
5825
5810
|
this.panel.registerView('messages', ConversationsView);
|
|
5826
5811
|
this.panel.registerView('chat', ChatView);
|
|
@@ -5835,13 +5820,15 @@
|
|
|
5835
5820
|
}
|
|
5836
5821
|
|
|
5837
5822
|
_attachEvents() {
|
|
5838
|
-
// Subscribe to state changes
|
|
5839
5823
|
this._stateUnsubscribe = this.messengerState.subscribe((type, data) => {
|
|
5840
5824
|
if (type === 'openChange') {
|
|
5841
5825
|
this._handleOpenChange(data.isOpen);
|
|
5842
5826
|
}
|
|
5843
5827
|
if (type === 'conversationChange') {
|
|
5844
|
-
this._handleActiveConversationChange(
|
|
5828
|
+
this._handleActiveConversationChange(
|
|
5829
|
+
data.conversationId,
|
|
5830
|
+
data.previousConversationId
|
|
5831
|
+
);
|
|
5845
5832
|
}
|
|
5846
5833
|
});
|
|
5847
5834
|
}
|
|
@@ -5857,50 +5844,74 @@
|
|
|
5857
5844
|
}
|
|
5858
5845
|
}
|
|
5859
5846
|
|
|
5860
|
-
/**
|
|
5861
|
-
* Subscribe/unsubscribe to conversation WebSocket channel
|
|
5862
|
-
*/
|
|
5863
5847
|
_handleActiveConversationChange(conversationId, previousConversationId) {
|
|
5864
5848
|
if (previousConversationId && this.wsService) {
|
|
5865
|
-
this.wsService.send('conversation:unsubscribe', {
|
|
5849
|
+
this.wsService.send('conversation:unsubscribe', {
|
|
5850
|
+
conversation_id: previousConversationId,
|
|
5851
|
+
});
|
|
5866
5852
|
}
|
|
5867
5853
|
if (conversationId && this.wsService) {
|
|
5868
|
-
this.wsService.send('conversation:subscribe', {
|
|
5854
|
+
this.wsService.send('conversation:subscribe', {
|
|
5855
|
+
conversation_id: conversationId,
|
|
5856
|
+
});
|
|
5869
5857
|
}
|
|
5870
5858
|
}
|
|
5871
5859
|
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
async _handleStartConversation(messageContent, pendingAttachments) {
|
|
5877
|
-
try {
|
|
5878
|
-
// Check for existing open conversation first
|
|
5879
|
-
const openConversation = this.messengerState.conversations.find(
|
|
5880
|
-
(c) => c.status === 'open'
|
|
5881
|
-
);
|
|
5860
|
+
async _handleStartConversation(messageContent, pendingAttachments) {
|
|
5861
|
+
try {
|
|
5862
|
+
const userContext = this.messengerState.userContext;
|
|
5863
|
+
const isAuthenticated = userContext?.email && userContext?.name;
|
|
5882
5864
|
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
await this.
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
);
|
|
5891
|
-
|
|
5865
|
+
// If user is authenticated, silently identify them first
|
|
5866
|
+
if (isAuthenticated) {
|
|
5867
|
+
try {
|
|
5868
|
+
await this.apiService.identifyContact({
|
|
5869
|
+
name: userContext.name,
|
|
5870
|
+
email: userContext.email,
|
|
5871
|
+
});
|
|
5872
|
+
console.log('[MessengerWidget] User auto-identified for conversation');
|
|
5873
|
+
} catch (error) {
|
|
5874
|
+
// If identification fails with a non-critical error, continue anyway
|
|
5875
|
+
if (error?.code !== 'ALREADY_IDENTIFIED') {
|
|
5876
|
+
console.warn('[MessengerWidget] Auto-identification failed:', error);
|
|
5877
|
+
}
|
|
5892
5878
|
}
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5879
|
+
} else {
|
|
5880
|
+
// Unauthenticated user - show pre-chat form
|
|
5881
|
+
this.messengerState.pendingMessage = {
|
|
5882
|
+
content: messageContent,
|
|
5883
|
+
attachments: pendingAttachments,
|
|
5884
|
+
};
|
|
5885
|
+
this.messengerState.setView('prechat');
|
|
5897
5886
|
return null;
|
|
5898
5887
|
}
|
|
5888
|
+
|
|
5889
|
+
// Check for existing open conversation
|
|
5890
|
+
const openConversation = this.messengerState.conversations.find(
|
|
5891
|
+
(c) => c.status === 'open'
|
|
5892
|
+
);
|
|
5893
|
+
|
|
5894
|
+
if (openConversation) {
|
|
5895
|
+
this.messengerState.setActiveConversation(openConversation.id);
|
|
5896
|
+
await this._handleSendMessage(
|
|
5897
|
+
openConversation.id,
|
|
5898
|
+
{ content: messageContent },
|
|
5899
|
+
pendingAttachments
|
|
5900
|
+
);
|
|
5901
|
+
return openConversation;
|
|
5902
|
+
}
|
|
5903
|
+
|
|
5904
|
+
return await this.startNewConversation(
|
|
5905
|
+
messageContent,
|
|
5906
|
+
'',
|
|
5907
|
+
pendingAttachments
|
|
5908
|
+
);
|
|
5909
|
+
} catch (error) {
|
|
5910
|
+
console.error('[MessengerWidget] Failed to start conversation:', error);
|
|
5911
|
+
return null;
|
|
5899
5912
|
}
|
|
5913
|
+
}
|
|
5900
5914
|
|
|
5901
|
-
/**
|
|
5902
|
-
* Handle selecting a conversation from the list
|
|
5903
|
-
*/
|
|
5904
5915
|
async _handleSelectConversation(conversationId) {
|
|
5905
5916
|
try {
|
|
5906
5917
|
await this.fetchMessages(conversationId);
|
|
@@ -5909,34 +5920,23 @@
|
|
|
5909
5920
|
}
|
|
5910
5921
|
}
|
|
5911
5922
|
|
|
5912
|
-
/**
|
|
5913
|
-
* Handle clicking "new conversation" button
|
|
5914
|
-
* Reuses the most recent open conversation if one exists
|
|
5915
|
-
*/
|
|
5916
5923
|
_handleNewConversationClick() {
|
|
5917
|
-
// Check for an existing open conversation to reuse
|
|
5918
5924
|
const openConversation = this.messengerState.conversations.find(
|
|
5919
5925
|
(c) => c.status === 'open'
|
|
5920
5926
|
);
|
|
5921
5927
|
|
|
5922
5928
|
if (openConversation) {
|
|
5923
|
-
// Reuse existing open conversation
|
|
5924
5929
|
this.messengerState.setActiveConversation(openConversation.id);
|
|
5925
5930
|
this.messengerState.setView('chat');
|
|
5926
5931
|
this._handleSelectConversation(openConversation.id);
|
|
5927
5932
|
} else {
|
|
5928
|
-
// No open conversation — start a new one
|
|
5929
5933
|
this.messengerState.setActiveConversation(null);
|
|
5930
5934
|
this.messengerState.setView('chat');
|
|
5931
5935
|
}
|
|
5932
5936
|
}
|
|
5933
5937
|
|
|
5934
|
-
/**
|
|
5935
|
-
* Handle identifying contact from pre-chat form
|
|
5936
|
-
*/
|
|
5937
5938
|
async _handleIdentifyContact(contactData) {
|
|
5938
5939
|
try {
|
|
5939
|
-
// Call API to identify/update contact
|
|
5940
5940
|
const response = await this.apiService.identifyContact({
|
|
5941
5941
|
name: contactData.name,
|
|
5942
5942
|
email: contactData.email,
|
|
@@ -5945,12 +5945,24 @@
|
|
|
5945
5945
|
if (response.status) {
|
|
5946
5946
|
console.log('[MessengerWidget] Contact identified:', contactData.email);
|
|
5947
5947
|
|
|
5948
|
-
// Update local user context
|
|
5949
5948
|
if (!this.messengerState.userContext) {
|
|
5950
5949
|
this.messengerState.userContext = {};
|
|
5951
5950
|
}
|
|
5952
5951
|
this.messengerState.userContext.name = contactData.name;
|
|
5953
5952
|
this.messengerState.userContext.email = contactData.email;
|
|
5953
|
+
|
|
5954
|
+
const pendingMessage = this.messengerState.pendingMessage;
|
|
5955
|
+
if (pendingMessage) {
|
|
5956
|
+
this.messengerState.pendingMessage = null;
|
|
5957
|
+
|
|
5958
|
+
await this.startNewConversation(
|
|
5959
|
+
pendingMessage.content,
|
|
5960
|
+
'',
|
|
5961
|
+
pendingMessage.attachments
|
|
5962
|
+
);
|
|
5963
|
+
} else {
|
|
5964
|
+
this.messengerState.setView('chat');
|
|
5965
|
+
}
|
|
5954
5966
|
}
|
|
5955
5967
|
|
|
5956
5968
|
return response;
|
|
@@ -5986,14 +5998,17 @@
|
|
|
5986
5998
|
name: att.file.name,
|
|
5987
5999
|
});
|
|
5988
6000
|
} catch (err) {
|
|
5989
|
-
console.error(
|
|
6001
|
+
console.error(
|
|
6002
|
+
'[MessengerWidget] Skipping failed attachment upload:',
|
|
6003
|
+
att.file.name,
|
|
6004
|
+
err
|
|
6005
|
+
);
|
|
5990
6006
|
}
|
|
5991
6007
|
}
|
|
5992
6008
|
return uploaded;
|
|
5993
6009
|
}
|
|
5994
6010
|
|
|
5995
6011
|
async _handleSendMessage(conversationId, message, pendingAttachments) {
|
|
5996
|
-
// Emit event for external listeners
|
|
5997
6012
|
this.sdk.eventBus.emit('messenger:messageSent', {
|
|
5998
6013
|
widget: this,
|
|
5999
6014
|
conversationId,
|
|
@@ -6001,22 +6016,18 @@
|
|
|
6001
6016
|
});
|
|
6002
6017
|
|
|
6003
6018
|
try {
|
|
6004
|
-
|
|
6005
|
-
|
|
6019
|
+
const uploadedAttachments =
|
|
6020
|
+
await this._uploadPendingAttachments(pendingAttachments);
|
|
6006
6021
|
|
|
6007
|
-
// Send message through API
|
|
6008
6022
|
const response = await this.apiService.sendMessage(conversationId, {
|
|
6009
6023
|
content: message.content,
|
|
6010
6024
|
attachments: uploadedAttachments,
|
|
6011
6025
|
});
|
|
6012
6026
|
|
|
6013
6027
|
if (response.status && response.data) {
|
|
6014
|
-
// Update the message ID with server-assigned ID
|
|
6015
|
-
// Message is already added to state optimistically in ChatView
|
|
6016
6028
|
console.log('[MessengerWidget] Message sent:', response.data.id);
|
|
6017
6029
|
}
|
|
6018
6030
|
|
|
6019
|
-
// In mock mode, simulate an agent response after a delay
|
|
6020
6031
|
if (this.apiService?.mock) {
|
|
6021
6032
|
setTimeout(() => {
|
|
6022
6033
|
const mockResponse = {
|
|
@@ -6034,29 +6045,24 @@
|
|
|
6034
6045
|
}
|
|
6035
6046
|
} catch (error) {
|
|
6036
6047
|
console.error('[MessengerWidget] Failed to send message:', error);
|
|
6037
|
-
// Could add error handling UI here
|
|
6038
6048
|
}
|
|
6039
6049
|
}
|
|
6040
6050
|
|
|
6041
|
-
/**
|
|
6042
|
-
* Handle incoming WebSocket message
|
|
6043
|
-
*/
|
|
6044
6051
|
_handleWebSocketMessage(data) {
|
|
6045
6052
|
const { conversation_id, message } = data;
|
|
6046
6053
|
|
|
6047
|
-
// Parse attachments from server message
|
|
6048
6054
|
let attachments = [];
|
|
6049
6055
|
if (message.attachments) {
|
|
6050
6056
|
try {
|
|
6051
|
-
attachments =
|
|
6052
|
-
|
|
6053
|
-
|
|
6057
|
+
attachments =
|
|
6058
|
+
typeof message.attachments === 'string'
|
|
6059
|
+
? JSON.parse(message.attachments)
|
|
6060
|
+
: message.attachments;
|
|
6054
6061
|
} catch (e) {
|
|
6055
|
-
// ignore
|
|
6062
|
+
// ignore
|
|
6056
6063
|
}
|
|
6057
6064
|
}
|
|
6058
6065
|
|
|
6059
|
-
// Transform message to local format
|
|
6060
6066
|
const localMessage = {
|
|
6061
6067
|
id: message.id,
|
|
6062
6068
|
content: message.content,
|
|
@@ -6069,10 +6075,8 @@
|
|
|
6069
6075
|
},
|
|
6070
6076
|
};
|
|
6071
6077
|
|
|
6072
|
-
// Add message to state
|
|
6073
6078
|
this.messengerState.addMessage(conversation_id, localMessage);
|
|
6074
6079
|
|
|
6075
|
-
// Update unread count if panel is closed or viewing different conversation
|
|
6076
6080
|
if (
|
|
6077
6081
|
!this.messengerState.isOpen ||
|
|
6078
6082
|
this.messengerState.activeConversationId !== conversation_id
|
|
@@ -6081,9 +6085,6 @@
|
|
|
6081
6085
|
}
|
|
6082
6086
|
}
|
|
6083
6087
|
|
|
6084
|
-
/**
|
|
6085
|
-
* Handle typing started event
|
|
6086
|
-
*/
|
|
6087
6088
|
_handleTypingStarted(data) {
|
|
6088
6089
|
if (data.is_agent) {
|
|
6089
6090
|
this.messengerState._notify('typingStarted', {
|
|
@@ -6093,31 +6094,20 @@
|
|
|
6093
6094
|
}
|
|
6094
6095
|
}
|
|
6095
6096
|
|
|
6096
|
-
/**
|
|
6097
|
-
* Handle typing stopped event
|
|
6098
|
-
*/
|
|
6099
6097
|
_handleTypingStopped(data) {
|
|
6100
6098
|
this.messengerState._notify('typingStopped', {
|
|
6101
6099
|
conversationId: data.conversation_id,
|
|
6102
6100
|
});
|
|
6103
6101
|
}
|
|
6104
6102
|
|
|
6105
|
-
/**
|
|
6106
|
-
* Handle conversation closed event
|
|
6107
|
-
*/
|
|
6108
6103
|
_handleConversationClosed(data) {
|
|
6109
6104
|
const conversationId =
|
|
6110
|
-
data?.conversation_id ||
|
|
6111
|
-
data?.id ||
|
|
6112
|
-
data?.conversation?.id;
|
|
6105
|
+
data?.conversation_id || data?.id || data?.conversation?.id;
|
|
6113
6106
|
if (!conversationId) return;
|
|
6114
6107
|
|
|
6115
6108
|
this.messengerState.updateConversation(conversationId, { status: 'closed' });
|
|
6116
6109
|
}
|
|
6117
6110
|
|
|
6118
|
-
/**
|
|
6119
|
-
* Update unread count from API
|
|
6120
|
-
*/
|
|
6121
6111
|
async _updateUnreadCount() {
|
|
6122
6112
|
try {
|
|
6123
6113
|
const response = await this.apiService.getUnreadCount();
|
|
@@ -6132,9 +6122,6 @@
|
|
|
6132
6122
|
}
|
|
6133
6123
|
}
|
|
6134
6124
|
|
|
6135
|
-
/**
|
|
6136
|
-
* Initialize WebSocket connection
|
|
6137
|
-
*/
|
|
6138
6125
|
_initWebSocket() {
|
|
6139
6126
|
if (this.wsService) {
|
|
6140
6127
|
this.wsService.disconnect();
|
|
@@ -6147,7 +6134,6 @@
|
|
|
6147
6134
|
mock: this.apiService.mock,
|
|
6148
6135
|
});
|
|
6149
6136
|
|
|
6150
|
-
// Subscribe to WebSocket events
|
|
6151
6137
|
this._wsUnsubscribers.push(
|
|
6152
6138
|
this.wsService.on('message', this._handleWebSocketMessage)
|
|
6153
6139
|
);
|
|
@@ -6163,7 +6149,6 @@
|
|
|
6163
6149
|
this._wsUnsubscribers.push(
|
|
6164
6150
|
this.wsService.on('connected', () => {
|
|
6165
6151
|
console.log('[MessengerWidget] WebSocket connected');
|
|
6166
|
-
// Re-subscribe to active conversation on reconnect
|
|
6167
6152
|
if (this.messengerState.activeConversationId) {
|
|
6168
6153
|
this.wsService.send('conversation:subscribe', {
|
|
6169
6154
|
conversation_id: this.messengerState.activeConversationId,
|
|
@@ -6177,34 +6162,21 @@
|
|
|
6177
6162
|
})
|
|
6178
6163
|
);
|
|
6179
6164
|
|
|
6180
|
-
// Connect
|
|
6181
6165
|
this.wsService.connect();
|
|
6182
6166
|
}
|
|
6183
6167
|
|
|
6184
|
-
/**
|
|
6185
|
-
* Open the messenger panel
|
|
6186
|
-
*/
|
|
6187
6168
|
open() {
|
|
6188
6169
|
this.messengerState.setOpen(true);
|
|
6189
6170
|
}
|
|
6190
6171
|
|
|
6191
|
-
/**
|
|
6192
|
-
* Close the messenger panel
|
|
6193
|
-
*/
|
|
6194
6172
|
close() {
|
|
6195
6173
|
this.messengerState.setOpen(false);
|
|
6196
6174
|
}
|
|
6197
6175
|
|
|
6198
|
-
/**
|
|
6199
|
-
* Toggle the messenger panel
|
|
6200
|
-
*/
|
|
6201
6176
|
toggle() {
|
|
6202
6177
|
this.messengerState.setOpen(!this.messengerState.isOpen);
|
|
6203
6178
|
}
|
|
6204
6179
|
|
|
6205
|
-
/**
|
|
6206
|
-
* Navigate to a specific view
|
|
6207
|
-
*/
|
|
6208
6180
|
navigateTo(view) {
|
|
6209
6181
|
this.messengerState.setView(view);
|
|
6210
6182
|
if (!this.messengerState.isOpen) {
|
|
@@ -6212,52 +6184,31 @@
|
|
|
6212
6184
|
}
|
|
6213
6185
|
}
|
|
6214
6186
|
|
|
6215
|
-
/**
|
|
6216
|
-
* Set conversations
|
|
6217
|
-
*/
|
|
6218
6187
|
setConversations(conversations) {
|
|
6219
6188
|
this.messengerState.setConversations(conversations);
|
|
6220
6189
|
}
|
|
6221
6190
|
|
|
6222
|
-
/**
|
|
6223
|
-
* Add a message to a conversation
|
|
6224
|
-
*/
|
|
6225
6191
|
addMessage(conversationId, message) {
|
|
6226
6192
|
this.messengerState.addMessage(conversationId, message);
|
|
6227
6193
|
}
|
|
6228
6194
|
|
|
6229
|
-
/**
|
|
6230
|
-
* Set help articles
|
|
6231
|
-
*/
|
|
6232
6195
|
setHelpArticles(articles) {
|
|
6233
6196
|
this.messengerState.setHelpArticles(articles);
|
|
6234
6197
|
}
|
|
6235
6198
|
|
|
6236
|
-
/**
|
|
6237
|
-
* Set home changelog items
|
|
6238
|
-
*/
|
|
6239
6199
|
setHomeChangelogItems(items) {
|
|
6240
6200
|
this.messengerState.setHomeChangelogItems(items);
|
|
6241
6201
|
}
|
|
6242
6202
|
|
|
6243
|
-
/**
|
|
6244
|
-
* Set changelog items
|
|
6245
|
-
*/
|
|
6246
6203
|
setChangelogItems(items) {
|
|
6247
6204
|
this.messengerState.setChangelogItems(items);
|
|
6248
6205
|
}
|
|
6249
6206
|
|
|
6250
|
-
/**
|
|
6251
|
-
* Update unread count (for external updates)
|
|
6252
|
-
*/
|
|
6253
6207
|
setUnreadCount(count) {
|
|
6254
6208
|
this.messengerState.unreadCount = count;
|
|
6255
6209
|
this.messengerState._notify('unreadCountChange', { count });
|
|
6256
6210
|
}
|
|
6257
6211
|
|
|
6258
|
-
/**
|
|
6259
|
-
* Get current state
|
|
6260
|
-
*/
|
|
6261
6212
|
getState() {
|
|
6262
6213
|
return {
|
|
6263
6214
|
isOpen: this.messengerState.isOpen,
|
|
@@ -6267,11 +6218,7 @@
|
|
|
6267
6218
|
};
|
|
6268
6219
|
}
|
|
6269
6220
|
|
|
6270
|
-
/**
|
|
6271
|
-
* Load initial data (mock or API)
|
|
6272
|
-
*/
|
|
6273
6221
|
async loadInitialData() {
|
|
6274
|
-
// Load conversations
|
|
6275
6222
|
try {
|
|
6276
6223
|
const conversations = await this._fetchConversations();
|
|
6277
6224
|
this.messengerState.setConversations(conversations);
|
|
@@ -6279,7 +6226,6 @@
|
|
|
6279
6226
|
console.error('[MessengerWidget] Failed to load conversations:', error);
|
|
6280
6227
|
}
|
|
6281
6228
|
|
|
6282
|
-
// Load help articles if enabled
|
|
6283
6229
|
if (this.messengerOptions.enableHelp) {
|
|
6284
6230
|
try {
|
|
6285
6231
|
const articles = await this._fetchHelpArticles();
|
|
@@ -6289,7 +6235,6 @@
|
|
|
6289
6235
|
}
|
|
6290
6236
|
}
|
|
6291
6237
|
|
|
6292
|
-
// Load changelog if enabled
|
|
6293
6238
|
if (this.messengerOptions.enableChangelog) {
|
|
6294
6239
|
try {
|
|
6295
6240
|
const { homeItems, changelogItems } = await this._fetchChangelog();
|
|
@@ -6305,7 +6250,6 @@
|
|
|
6305
6250
|
try {
|
|
6306
6251
|
const response = await this.apiService.getConversations();
|
|
6307
6252
|
if (response.status && response.data) {
|
|
6308
|
-
// Transform API response to local format
|
|
6309
6253
|
return response.data.map((conv) => ({
|
|
6310
6254
|
id: conv.id,
|
|
6311
6255
|
title:
|
|
@@ -6336,7 +6280,6 @@
|
|
|
6336
6280
|
try {
|
|
6337
6281
|
const response = await this.apiService.getHelpCollections();
|
|
6338
6282
|
if (response.status && response.data) {
|
|
6339
|
-
// Transform API response to local format
|
|
6340
6283
|
return response.data.map((collection) => ({
|
|
6341
6284
|
id: collection.id,
|
|
6342
6285
|
title: collection.title || collection.name,
|
|
@@ -6354,9 +6297,6 @@
|
|
|
6354
6297
|
}
|
|
6355
6298
|
}
|
|
6356
6299
|
|
|
6357
|
-
/**
|
|
6358
|
-
* Fetch messages for a conversation
|
|
6359
|
-
*/
|
|
6360
6300
|
async fetchMessages(conversationId) {
|
|
6361
6301
|
try {
|
|
6362
6302
|
const response = await this.apiService.getConversation(conversationId);
|
|
@@ -6365,11 +6305,12 @@
|
|
|
6365
6305
|
let attachments;
|
|
6366
6306
|
if (msg.attachments) {
|
|
6367
6307
|
try {
|
|
6368
|
-
attachments =
|
|
6369
|
-
|
|
6370
|
-
|
|
6308
|
+
attachments =
|
|
6309
|
+
typeof msg.attachments === 'string'
|
|
6310
|
+
? JSON.parse(msg.attachments)
|
|
6311
|
+
: msg.attachments;
|
|
6371
6312
|
} catch (e) {
|
|
6372
|
-
// ignore
|
|
6313
|
+
// ignore
|
|
6373
6314
|
}
|
|
6374
6315
|
}
|
|
6375
6316
|
return {
|
|
@@ -6377,16 +6318,18 @@
|
|
|
6377
6318
|
content: msg.content,
|
|
6378
6319
|
isOwn: msg.sender_type === 'customer',
|
|
6379
6320
|
timestamp: msg.created_at,
|
|
6380
|
-
attachments:
|
|
6321
|
+
attachments:
|
|
6322
|
+
attachments && attachments.length > 0 ? attachments : undefined,
|
|
6381
6323
|
sender: {
|
|
6382
|
-
name:
|
|
6324
|
+
name:
|
|
6325
|
+
msg.sender_name ||
|
|
6326
|
+
(msg.sender_type === 'customer' ? 'You' : 'Support'),
|
|
6383
6327
|
avatarUrl: msg.sender_avatar || null,
|
|
6384
6328
|
},
|
|
6385
6329
|
};
|
|
6386
6330
|
});
|
|
6387
6331
|
this.messengerState.setMessages(conversationId, messages);
|
|
6388
6332
|
|
|
6389
|
-
// Mark as read
|
|
6390
6333
|
await this.apiService.markConversationAsRead(conversationId);
|
|
6391
6334
|
this.messengerState.markAsRead(conversationId);
|
|
6392
6335
|
|
|
@@ -6399,19 +6342,18 @@
|
|
|
6399
6342
|
}
|
|
6400
6343
|
}
|
|
6401
6344
|
|
|
6402
|
-
/**
|
|
6403
|
-
* Start a new conversation
|
|
6404
|
-
*/
|
|
6405
6345
|
async startNewConversation(message, subject = '', pendingAttachments = []) {
|
|
6406
6346
|
try {
|
|
6407
|
-
|
|
6408
|
-
|
|
6347
|
+
const uploadedAttachments =
|
|
6348
|
+
await this._uploadPendingAttachments(pendingAttachments);
|
|
6409
6349
|
|
|
6410
6350
|
console.log('[MessengerWidget] Starting conversation...', {
|
|
6411
6351
|
message,
|
|
6412
6352
|
attachmentCount: uploadedAttachments.length,
|
|
6413
6353
|
hasSession: this.apiService.isSessionValid(),
|
|
6414
|
-
sessionToken: this.apiService.sessionToken
|
|
6354
|
+
sessionToken: this.apiService.sessionToken
|
|
6355
|
+
? this.apiService.sessionToken.substring(0, 10) + '...'
|
|
6356
|
+
: null,
|
|
6415
6357
|
baseURL: this.apiService.baseURL,
|
|
6416
6358
|
mock: this.apiService.mock,
|
|
6417
6359
|
});
|
|
@@ -6436,10 +6378,8 @@
|
|
|
6436
6378
|
status: 'open',
|
|
6437
6379
|
};
|
|
6438
6380
|
|
|
6439
|
-
// Add to state
|
|
6440
6381
|
this.messengerState.addConversation(newConversation);
|
|
6441
6382
|
|
|
6442
|
-
// Set initial message in messages cache
|
|
6443
6383
|
this.messengerState.setMessages(conv.id, [
|
|
6444
6384
|
{
|
|
6445
6385
|
id: 'msg_' + Date.now(),
|
|
@@ -6449,7 +6389,6 @@
|
|
|
6449
6389
|
},
|
|
6450
6390
|
]);
|
|
6451
6391
|
|
|
6452
|
-
// Navigate to chat
|
|
6453
6392
|
this.messengerState.setActiveConversation(conv.id);
|
|
6454
6393
|
this.messengerState.setView('chat');
|
|
6455
6394
|
|
|
@@ -6462,20 +6401,14 @@
|
|
|
6462
6401
|
}
|
|
6463
6402
|
}
|
|
6464
6403
|
|
|
6465
|
-
/**
|
|
6466
|
-
* Send typing indicator
|
|
6467
|
-
*/
|
|
6468
6404
|
async sendTypingIndicator(conversationId, isTyping) {
|
|
6469
6405
|
try {
|
|
6470
6406
|
await this.apiService.sendTypingIndicator(conversationId, isTyping);
|
|
6471
6407
|
} catch (error) {
|
|
6472
|
-
//
|
|
6408
|
+
// Silent fail
|
|
6473
6409
|
}
|
|
6474
6410
|
}
|
|
6475
6411
|
|
|
6476
|
-
/**
|
|
6477
|
-
* Check agent availability
|
|
6478
|
-
*/
|
|
6479
6412
|
async checkAgentAvailability() {
|
|
6480
6413
|
try {
|
|
6481
6414
|
const response = await this.apiService.checkAgentsOnline();
|
|
@@ -6484,9 +6417,10 @@
|
|
|
6484
6417
|
this.messengerState.onlineCount = response.data.online_count || 0;
|
|
6485
6418
|
this.messengerState.responseTime = response.data.response_time || '';
|
|
6486
6419
|
|
|
6487
|
-
// Update team avatars from online agents
|
|
6488
6420
|
if (response.data.available_agents) {
|
|
6489
|
-
this.messengerState.setTeamAvatarsFromAgents(
|
|
6421
|
+
this.messengerState.setTeamAvatarsFromAgents(
|
|
6422
|
+
response.data.available_agents
|
|
6423
|
+
);
|
|
6490
6424
|
}
|
|
6491
6425
|
|
|
6492
6426
|
this.messengerState._notify('availabilityUpdate', response.data);
|
|
@@ -6578,11 +6512,9 @@
|
|
|
6578
6512
|
};
|
|
6579
6513
|
}
|
|
6580
6514
|
|
|
6581
|
-
// Fetch changelogs from API
|
|
6582
6515
|
const response = await this.apiService.getChangelogs({ limit: 20 });
|
|
6583
6516
|
const changelogs = response.data || [];
|
|
6584
6517
|
|
|
6585
|
-
// Map API response to expected format
|
|
6586
6518
|
const mappedItems = changelogs.map((item) => ({
|
|
6587
6519
|
id: item.id,
|
|
6588
6520
|
title: item.title,
|
|
@@ -6600,39 +6532,32 @@
|
|
|
6600
6532
|
};
|
|
6601
6533
|
}
|
|
6602
6534
|
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
this.loadInitialData();
|
|
6535
|
+
async onMount() {
|
|
6536
|
+
this.loadInitialData();
|
|
6606
6537
|
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
}
|
|
6538
|
+
if (this.apiService?.sessionToken) {
|
|
6539
|
+
this._initWebSocket();
|
|
6540
|
+
}
|
|
6611
6541
|
|
|
6612
|
-
|
|
6613
|
-
this.checkAgentAvailability();
|
|
6542
|
+
this.checkAgentAvailability();
|
|
6614
6543
|
|
|
6615
|
-
|
|
6616
|
-
this.
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
}
|
|
6544
|
+
this._availabilityInterval = setInterval(() => {
|
|
6545
|
+
this.checkAgentAvailability();
|
|
6546
|
+
}, 60000);
|
|
6547
|
+
}
|
|
6620
6548
|
|
|
6621
6549
|
onDestroy() {
|
|
6622
6550
|
if (this._stateUnsubscribe) {
|
|
6623
6551
|
this._stateUnsubscribe();
|
|
6624
6552
|
}
|
|
6625
6553
|
|
|
6626
|
-
// Clean up WebSocket
|
|
6627
6554
|
if (this.wsService) {
|
|
6628
6555
|
this.wsService.disconnect();
|
|
6629
6556
|
}
|
|
6630
6557
|
|
|
6631
|
-
// Clean up WebSocket event listeners
|
|
6632
6558
|
this._wsUnsubscribers.forEach((unsub) => unsub());
|
|
6633
6559
|
this._wsUnsubscribers = [];
|
|
6634
6560
|
|
|
6635
|
-
// Clean up availability interval
|
|
6636
6561
|
if (this._availabilityInterval) {
|
|
6637
6562
|
clearInterval(this._availabilityInterval);
|
|
6638
6563
|
}
|