@product7/product7-js 0.3.4 → 0.3.6
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/product7-js.js +159 -241
- package/dist/product7-js.js.map +1 -1
- package/dist/product7-js.min.js +1 -1
- package/dist/product7-js.min.js.map +1 -1
- package/package.json +1 -1
- package/src/api/services/FeedbackService.js +7 -0
- package/src/api/services/MessengerService.js +42 -0
- package/src/api/services/SurveyService.js +6 -0
- package/src/core/APIService.js +58 -211
- package/src/core/BaseAPIService.js +14 -0
- package/src/core/Product7.js +1 -1
- package/src/widgets/MessengerWidget.js +3 -1
package/dist/product7-js.js
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
];
|
|
56
56
|
|
|
57
|
-
const MOCK_CONVERSATIONS
|
|
57
|
+
const MOCK_CONVERSATIONS = [
|
|
58
58
|
{
|
|
59
59
|
id: 'conv_1',
|
|
60
60
|
subject: 'Question about pricing',
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
];
|
|
87
87
|
|
|
88
|
-
const MOCK_MESSAGES
|
|
88
|
+
const MOCK_MESSAGES = {
|
|
89
89
|
conv_1: [
|
|
90
90
|
{
|
|
91
91
|
id: 'msg_1',
|
|
@@ -443,12 +443,19 @@
|
|
|
443
443
|
};
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
+
const contact = this.api.getContactIdentity();
|
|
447
|
+
|
|
446
448
|
const payload = {
|
|
447
449
|
board:
|
|
448
450
|
feedbackData.board_id || feedbackData.board || feedbackData.boardName,
|
|
449
451
|
title: feedbackData.title,
|
|
450
452
|
content: feedbackData.content,
|
|
451
453
|
attachments: feedbackData.attachments || [],
|
|
454
|
+
...(contact?.contactId && {
|
|
455
|
+
contact_id: contact.contactId,
|
|
456
|
+
contact_email: contact.contactEmail,
|
|
457
|
+
contact_name: contact.contactName,
|
|
458
|
+
}),
|
|
452
459
|
};
|
|
453
460
|
|
|
454
461
|
return this.api._handleAuthRetry(async () => {
|
|
@@ -549,6 +556,10 @@
|
|
|
549
556
|
agents_online: true,
|
|
550
557
|
online_count: 2,
|
|
551
558
|
response_time: 'Usually replies within a few minutes',
|
|
559
|
+
available_agents: [
|
|
560
|
+
{ full_name: 'Sarah', picture: '' },
|
|
561
|
+
{ full_name: 'Tom', picture: '' },
|
|
562
|
+
],
|
|
552
563
|
},
|
|
553
564
|
};
|
|
554
565
|
}
|
|
@@ -566,8 +577,8 @@
|
|
|
566
577
|
await delay$1(300);
|
|
567
578
|
return {
|
|
568
579
|
status: true,
|
|
569
|
-
data: MOCK_CONVERSATIONS
|
|
570
|
-
meta: { total: MOCK_CONVERSATIONS
|
|
580
|
+
data: MOCK_CONVERSATIONS,
|
|
581
|
+
meta: { total: MOCK_CONVERSATIONS.length, page: 1, limit: 20 },
|
|
571
582
|
};
|
|
572
583
|
}
|
|
573
584
|
|
|
@@ -586,10 +597,10 @@
|
|
|
586
597
|
|
|
587
598
|
if (this.api.mock) {
|
|
588
599
|
await delay$1(200);
|
|
589
|
-
const conv = MOCK_CONVERSATIONS
|
|
600
|
+
const conv = MOCK_CONVERSATIONS.find((c) => c.id === conversationId);
|
|
590
601
|
return {
|
|
591
602
|
status: true,
|
|
592
|
-
data: { ...conv, messages: MOCK_MESSAGES
|
|
603
|
+
data: { ...conv, messages: MOCK_MESSAGES[conversationId] || [] },
|
|
593
604
|
};
|
|
594
605
|
}
|
|
595
606
|
|
|
@@ -623,8 +634,8 @@
|
|
|
623
634
|
},
|
|
624
635
|
],
|
|
625
636
|
};
|
|
626
|
-
MOCK_CONVERSATIONS
|
|
627
|
-
MOCK_MESSAGES
|
|
637
|
+
MOCK_CONVERSATIONS.unshift(newConv);
|
|
638
|
+
MOCK_MESSAGES[newConv.id] = newConv.messages;
|
|
628
639
|
return { status: true, data: newConv };
|
|
629
640
|
}
|
|
630
641
|
|
|
@@ -654,10 +665,10 @@
|
|
|
654
665
|
created_at: new Date().toISOString(),
|
|
655
666
|
attachments: data.attachments || [],
|
|
656
667
|
};
|
|
657
|
-
if (!MOCK_MESSAGES
|
|
658
|
-
MOCK_MESSAGES
|
|
668
|
+
if (!MOCK_MESSAGES[conversationId]) {
|
|
669
|
+
MOCK_MESSAGES[conversationId] = [];
|
|
659
670
|
}
|
|
660
|
-
MOCK_MESSAGES
|
|
671
|
+
MOCK_MESSAGES[conversationId].push(newMessage);
|
|
661
672
|
return { status: true, data: newMessage };
|
|
662
673
|
}
|
|
663
674
|
|
|
@@ -681,7 +692,7 @@
|
|
|
681
692
|
await this.api._ensureSession();
|
|
682
693
|
|
|
683
694
|
if (this.api.mock) {
|
|
684
|
-
const count = MOCK_CONVERSATIONS
|
|
695
|
+
const count = MOCK_CONVERSATIONS.reduce(
|
|
685
696
|
(sum, c) => sum + (c.unread || 0),
|
|
686
697
|
0
|
|
687
698
|
);
|
|
@@ -720,7 +731,7 @@
|
|
|
720
731
|
await delay$1(200);
|
|
721
732
|
return {
|
|
722
733
|
status: true,
|
|
723
|
-
data: MOCK_MESSAGES
|
|
734
|
+
data: MOCK_MESSAGES[conversationId] || [],
|
|
724
735
|
meta: { total: 0, page: 1, limit: 50 },
|
|
725
736
|
};
|
|
726
737
|
}
|
|
@@ -736,10 +747,48 @@
|
|
|
736
747
|
});
|
|
737
748
|
}
|
|
738
749
|
|
|
750
|
+
async uploadFile(base64Data, filename) {
|
|
751
|
+
await this.api._ensureSession();
|
|
752
|
+
|
|
753
|
+
if (this.api.mock) {
|
|
754
|
+
await delay$1(300);
|
|
755
|
+
return { status: true, url: `https://mock-cdn.example.com/${filename}` };
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
return this.api._makeRequest('/widget/messenger/upload', {
|
|
759
|
+
method: 'POST',
|
|
760
|
+
headers: {
|
|
761
|
+
'Content-Type': 'application/json',
|
|
762
|
+
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
763
|
+
},
|
|
764
|
+
body: JSON.stringify({ file: base64Data, filename }),
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
|
|
739
768
|
async identifyContact(data) {
|
|
740
769
|
return this.api.identify(data);
|
|
741
770
|
}
|
|
742
771
|
|
|
772
|
+
async submitRating(conversationId, data) {
|
|
773
|
+
await this.api._ensureSession();
|
|
774
|
+
|
|
775
|
+
if (this.api.mock) {
|
|
776
|
+
return { status: true, data: { rated: true } };
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return this.api._makeRequest(
|
|
780
|
+
`/widget/messenger/conversations/${conversationId}/rating`,
|
|
781
|
+
{
|
|
782
|
+
method: 'POST',
|
|
783
|
+
headers: {
|
|
784
|
+
'Content-Type': 'application/json',
|
|
785
|
+
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
786
|
+
},
|
|
787
|
+
body: JSON.stringify(data),
|
|
788
|
+
}
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
|
|
743
792
|
async sendTypingIndicator(conversationId, isTyping) {
|
|
744
793
|
await this.api._ensureSession();
|
|
745
794
|
|
|
@@ -773,7 +822,7 @@
|
|
|
773
822
|
}
|
|
774
823
|
}
|
|
775
824
|
|
|
776
|
-
|
|
825
|
+
class APIError extends Error {
|
|
777
826
|
constructor(status, message, response) {
|
|
778
827
|
super(message);
|
|
779
828
|
this.name = 'APIError';
|
|
@@ -796,7 +845,7 @@
|
|
|
796
845
|
isServerError() {
|
|
797
846
|
return this.status >= 500 && this.status < 600;
|
|
798
847
|
}
|
|
799
|
-
}
|
|
848
|
+
}
|
|
800
849
|
|
|
801
850
|
class WidgetError extends Error {
|
|
802
851
|
constructor(message, widgetType, widgetId) {
|
|
@@ -894,7 +943,7 @@
|
|
|
894
943
|
}
|
|
895
944
|
|
|
896
945
|
async submitSurveyResponse(surveyId, responseData) {
|
|
897
|
-
if (!surveyId) throw new APIError
|
|
946
|
+
if (!surveyId) throw new APIError(400, 'Survey ID is required');
|
|
898
947
|
|
|
899
948
|
await this.api._ensureSession();
|
|
900
949
|
|
|
@@ -912,6 +961,7 @@
|
|
|
912
961
|
}
|
|
913
962
|
|
|
914
963
|
const respondent = this._getRespondentContext(responseData);
|
|
964
|
+
const contact = this.api.getContactIdentity?.() || null;
|
|
915
965
|
|
|
916
966
|
const payload = {
|
|
917
967
|
rating: responseData.rating,
|
|
@@ -921,6 +971,11 @@
|
|
|
921
971
|
respondent_id: respondent.respondent_id,
|
|
922
972
|
}),
|
|
923
973
|
...(respondent.email && { email: respondent.email }),
|
|
974
|
+
...(contact?.contactId && {
|
|
975
|
+
contact_id: contact.contactId,
|
|
976
|
+
contact_email: contact.contactEmail,
|
|
977
|
+
contact_name: contact.contactName,
|
|
978
|
+
}),
|
|
924
979
|
};
|
|
925
980
|
|
|
926
981
|
return this.api._handleAuthRetry(async () => {
|
|
@@ -939,7 +994,7 @@
|
|
|
939
994
|
}
|
|
940
995
|
|
|
941
996
|
async dismissSurvey(surveyId) {
|
|
942
|
-
if (!surveyId) throw new APIError
|
|
997
|
+
if (!surveyId) throw new APIError(400, 'Survey ID is required');
|
|
943
998
|
|
|
944
999
|
await this.api._ensureSession();
|
|
945
1000
|
|
|
@@ -1025,7 +1080,7 @@
|
|
|
1025
1080
|
}
|
|
1026
1081
|
|
|
1027
1082
|
if (!this.workspace) {
|
|
1028
|
-
throw new APIError
|
|
1083
|
+
throw new APIError(400, 'Missing workspace for initialization');
|
|
1029
1084
|
}
|
|
1030
1085
|
|
|
1031
1086
|
if (this.mock) {
|
|
@@ -1081,7 +1136,7 @@
|
|
|
1081
1136
|
configVersion: initData.configVersion,
|
|
1082
1137
|
};
|
|
1083
1138
|
} catch (error) {
|
|
1084
|
-
throw new APIError
|
|
1139
|
+
throw new APIError(
|
|
1085
1140
|
error.status || 500,
|
|
1086
1141
|
`Failed to initialize widget: ${error.message}`,
|
|
1087
1142
|
error.response
|
|
@@ -1099,11 +1154,11 @@
|
|
|
1099
1154
|
const expiresIn = Number(payload.expires_in ?? payload.expiresIn);
|
|
1100
1155
|
|
|
1101
1156
|
if (!sessionToken) {
|
|
1102
|
-
throw new APIError
|
|
1157
|
+
throw new APIError(500, 'Invalid init response: missing session_token');
|
|
1103
1158
|
}
|
|
1104
1159
|
|
|
1105
1160
|
if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
|
|
1106
|
-
throw new APIError
|
|
1161
|
+
throw new APIError(500, 'Invalid init response: missing expires_in');
|
|
1107
1162
|
}
|
|
1108
1163
|
|
|
1109
1164
|
return {
|
|
@@ -1124,7 +1179,7 @@
|
|
|
1124
1179
|
await this.init();
|
|
1125
1180
|
}
|
|
1126
1181
|
if (!this.sessionToken) {
|
|
1127
|
-
throw new APIError
|
|
1182
|
+
throw new APIError(401, 'No valid session token available');
|
|
1128
1183
|
}
|
|
1129
1184
|
}
|
|
1130
1185
|
|
|
@@ -1149,7 +1204,7 @@
|
|
|
1149
1204
|
}
|
|
1150
1205
|
|
|
1151
1206
|
if (!this.metadata) {
|
|
1152
|
-
throw new APIError
|
|
1207
|
+
throw new APIError(400, 'Missing user context for identify');
|
|
1153
1208
|
}
|
|
1154
1209
|
|
|
1155
1210
|
await this._ensureSession();
|
|
@@ -1206,8 +1261,12 @@
|
|
|
1206
1261
|
this.sessionToken = null;
|
|
1207
1262
|
this.sessionExpiry = null;
|
|
1208
1263
|
this.identitySyncedToken = null;
|
|
1264
|
+
this.contactId = null;
|
|
1265
|
+
this.contactEmail = null;
|
|
1266
|
+
this.contactName = null;
|
|
1209
1267
|
this._removeData('product7_session');
|
|
1210
1268
|
this._removeData('product7_metadata');
|
|
1269
|
+
this._removeData('product7_contact');
|
|
1211
1270
|
}
|
|
1212
1271
|
|
|
1213
1272
|
_storeSession() {
|
|
@@ -1231,6 +1290,15 @@
|
|
|
1231
1290
|
if (!stored) return false;
|
|
1232
1291
|
|
|
1233
1292
|
const sessionData = JSON.parse(stored);
|
|
1293
|
+
|
|
1294
|
+
// Invalidate mock tokens when not in mock mode (and vice versa)
|
|
1295
|
+
const isMockToken =
|
|
1296
|
+
sessionData.token && sessionData.token.startsWith('mock_');
|
|
1297
|
+
if (isMockToken !== this.mock) {
|
|
1298
|
+
localStorage.removeItem('product7_session');
|
|
1299
|
+
return false;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1234
1302
|
if (
|
|
1235
1303
|
this.workspace &&
|
|
1236
1304
|
sessionData.workspace &&
|
|
@@ -1239,6 +1307,7 @@
|
|
|
1239
1307
|
localStorage.removeItem('product7_session');
|
|
1240
1308
|
return false;
|
|
1241
1309
|
}
|
|
1310
|
+
|
|
1242
1311
|
this.sessionToken = sessionData.token;
|
|
1243
1312
|
this.sessionExpiry = new Date(sessionData.expiry);
|
|
1244
1313
|
|
|
@@ -1304,7 +1373,7 @@
|
|
|
1304
1373
|
errorMessage = (await response.text()) || errorMessage;
|
|
1305
1374
|
}
|
|
1306
1375
|
|
|
1307
|
-
throw new APIError
|
|
1376
|
+
throw new APIError(response.status, errorMessage, responseData);
|
|
1308
1377
|
}
|
|
1309
1378
|
|
|
1310
1379
|
const contentType = response.headers.get('content-type');
|
|
@@ -1314,8 +1383,8 @@
|
|
|
1314
1383
|
|
|
1315
1384
|
return await response.text();
|
|
1316
1385
|
} catch (error) {
|
|
1317
|
-
if (error instanceof APIError
|
|
1318
|
-
throw new APIError
|
|
1386
|
+
if (error instanceof APIError) throw error;
|
|
1387
|
+
throw new APIError(0, error.message, null);
|
|
1319
1388
|
}
|
|
1320
1389
|
}
|
|
1321
1390
|
|
|
@@ -1400,29 +1469,7 @@
|
|
|
1400
1469
|
}
|
|
1401
1470
|
|
|
1402
1471
|
async checkAgentsOnline() {
|
|
1403
|
-
|
|
1404
|
-
await this.init();
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
if (this.mock) {
|
|
1408
|
-
return {
|
|
1409
|
-
status: true,
|
|
1410
|
-
data: {
|
|
1411
|
-
agents_online: true,
|
|
1412
|
-
online_count: 2,
|
|
1413
|
-
response_time: 'Usually replies within a few minutes',
|
|
1414
|
-
available_agents: [
|
|
1415
|
-
{ full_name: 'Sarah', picture: '' },
|
|
1416
|
-
{ full_name: 'Tom', picture: '' },
|
|
1417
|
-
],
|
|
1418
|
-
},
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
return this._makeRequest('/widget/messenger/agents/online', {
|
|
1423
|
-
method: 'GET',
|
|
1424
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
1425
|
-
});
|
|
1472
|
+
return this.messenger.checkAgentsOnline();
|
|
1426
1473
|
}
|
|
1427
1474
|
|
|
1428
1475
|
async getConversations(options) {
|
|
@@ -1438,137 +1485,15 @@
|
|
|
1438
1485
|
}
|
|
1439
1486
|
|
|
1440
1487
|
async startConversation(data) {
|
|
1441
|
-
|
|
1442
|
-
console.log(
|
|
1443
|
-
'[APIService] startConversation: session invalid, calling init...'
|
|
1444
|
-
);
|
|
1445
|
-
try {
|
|
1446
|
-
await this.init();
|
|
1447
|
-
console.log(
|
|
1448
|
-
'[APIService] startConversation: init result, token:',
|
|
1449
|
-
this.sessionToken ? 'set' : 'null'
|
|
1450
|
-
);
|
|
1451
|
-
} catch (initError) {
|
|
1452
|
-
console.error(
|
|
1453
|
-
'[APIService] startConversation: init failed:',
|
|
1454
|
-
initError.message
|
|
1455
|
-
);
|
|
1456
|
-
throw initError;
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
if (!this.sessionToken) {
|
|
1461
|
-
console.error(
|
|
1462
|
-
'[APIService] startConversation: no session token after init'
|
|
1463
|
-
);
|
|
1464
|
-
throw new APIError(401, 'No valid session token available');
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
console.log(
|
|
1468
|
-
'[APIService] startConversation: sending to',
|
|
1469
|
-
`${this.baseURL}/widget/messenger/conversations`,
|
|
1470
|
-
'mock:',
|
|
1471
|
-
this.mock
|
|
1472
|
-
);
|
|
1473
|
-
|
|
1474
|
-
if (this.mock) {
|
|
1475
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1476
|
-
const newConv = {
|
|
1477
|
-
id: 'conv_' + Date.now(),
|
|
1478
|
-
subject: data.subject || 'New conversation',
|
|
1479
|
-
status: 'open',
|
|
1480
|
-
last_message_at: new Date().toISOString(),
|
|
1481
|
-
created_at: new Date().toISOString(),
|
|
1482
|
-
messages: [
|
|
1483
|
-
{
|
|
1484
|
-
id: 'msg_' + Date.now(),
|
|
1485
|
-
content: data.message,
|
|
1486
|
-
sender_type: 'customer',
|
|
1487
|
-
created_at: new Date().toISOString(),
|
|
1488
|
-
},
|
|
1489
|
-
],
|
|
1490
|
-
};
|
|
1491
|
-
MOCK_CONVERSATIONS.unshift(newConv);
|
|
1492
|
-
MOCK_MESSAGES[newConv.id] = newConv.messages;
|
|
1493
|
-
return { status: true, data: newConv };
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
return this._makeRequest('/widget/messenger/conversations', {
|
|
1497
|
-
method: 'POST',
|
|
1498
|
-
headers: {
|
|
1499
|
-
'Content-Type': 'application/json',
|
|
1500
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
1501
|
-
},
|
|
1502
|
-
body: JSON.stringify({
|
|
1503
|
-
message: data.message,
|
|
1504
|
-
subject: data.subject || '',
|
|
1505
|
-
}),
|
|
1506
|
-
});
|
|
1488
|
+
return this.messenger.startConversation(data);
|
|
1507
1489
|
}
|
|
1508
1490
|
|
|
1509
1491
|
async sendMessage(conversationId, data) {
|
|
1510
|
-
|
|
1511
|
-
await this.init();
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
if (this.mock) {
|
|
1515
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1516
|
-
const newMessage = {
|
|
1517
|
-
id: 'msg_' + Date.now(),
|
|
1518
|
-
content: data.content,
|
|
1519
|
-
attachments: data.attachments || [],
|
|
1520
|
-
sender_type: 'customer',
|
|
1521
|
-
created_at: new Date().toISOString(),
|
|
1522
|
-
};
|
|
1523
|
-
if (!MOCK_MESSAGES[conversationId]) {
|
|
1524
|
-
MOCK_MESSAGES[conversationId] = [];
|
|
1525
|
-
}
|
|
1526
|
-
MOCK_MESSAGES[conversationId].push(newMessage);
|
|
1527
|
-
return { status: true, data: newMessage };
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
const payload = { content: data.content };
|
|
1531
|
-
if (data.attachments && data.attachments.length > 0) {
|
|
1532
|
-
payload.attachments = data.attachments;
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
return this._makeRequest(
|
|
1536
|
-
`/widget/messenger/conversations/${conversationId}/messages`,
|
|
1537
|
-
{
|
|
1538
|
-
method: 'POST',
|
|
1539
|
-
headers: {
|
|
1540
|
-
'Content-Type': 'application/json',
|
|
1541
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
1542
|
-
},
|
|
1543
|
-
body: JSON.stringify(payload),
|
|
1544
|
-
}
|
|
1545
|
-
);
|
|
1492
|
+
return this.messenger.sendMessage(conversationId, data);
|
|
1546
1493
|
}
|
|
1547
1494
|
|
|
1548
|
-
/**
|
|
1549
|
-
* Upload a file to CDN via widget endpoint
|
|
1550
|
-
* @param {string} base64Data - Base64 encoded file data (with or without data URI prefix)
|
|
1551
|
-
* @param {string} filename - Original filename
|
|
1552
|
-
* @returns {Promise<Object>} Response with url
|
|
1553
|
-
*/
|
|
1554
1495
|
async uploadFile(base64Data, filename) {
|
|
1555
|
-
|
|
1556
|
-
await this.init();
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
if (this.mock) {
|
|
1560
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1561
|
-
return { status: true, url: `https://mock-cdn.example.com/${filename}` };
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
|
-
return this._makeRequest('/widget/messenger/upload', {
|
|
1565
|
-
method: 'POST',
|
|
1566
|
-
headers: {
|
|
1567
|
-
'Content-Type': 'application/json',
|
|
1568
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
1569
|
-
},
|
|
1570
|
-
body: JSON.stringify({ file: base64Data, filename }),
|
|
1571
|
-
});
|
|
1496
|
+
return this.messenger.uploadFile(base64Data, filename);
|
|
1572
1497
|
}
|
|
1573
1498
|
|
|
1574
1499
|
async sendTypingIndicator(conversationId, isTyping) {
|
|
@@ -1592,7 +1517,7 @@
|
|
|
1592
1517
|
|
|
1593
1518
|
if (this.mock) {
|
|
1594
1519
|
await new Promise((r) => setTimeout(r, 300));
|
|
1595
|
-
|
|
1520
|
+
const mockResponse = {
|
|
1596
1521
|
status: true,
|
|
1597
1522
|
data: {
|
|
1598
1523
|
contact_id: 'mock_contact_' + Date.now(),
|
|
@@ -1601,9 +1526,11 @@
|
|
|
1601
1526
|
is_new: true,
|
|
1602
1527
|
},
|
|
1603
1528
|
};
|
|
1529
|
+
this._storeContactIdentity(mockResponse.data, metadata);
|
|
1530
|
+
return mockResponse;
|
|
1604
1531
|
}
|
|
1605
1532
|
|
|
1606
|
-
|
|
1533
|
+
const response = await this._makeRequest('/widget/messenger/identify', {
|
|
1607
1534
|
method: 'POST',
|
|
1608
1535
|
headers: {
|
|
1609
1536
|
'Content-Type': 'application/json',
|
|
@@ -1619,83 +1546,72 @@
|
|
|
1619
1546
|
metadata: metadata.custom_fields || {},
|
|
1620
1547
|
}),
|
|
1621
1548
|
});
|
|
1622
|
-
}
|
|
1623
1549
|
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
async getHelpCollections(options) {
|
|
1629
|
-
return this.help.getHelpCollections(options);
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
async searchHelpArticles(query, options) {
|
|
1633
|
-
return this.help.searchHelpArticles(query, options);
|
|
1634
|
-
}
|
|
1550
|
+
if (response?.status && response?.data) {
|
|
1551
|
+
this._storeContactIdentity(response.data, metadata);
|
|
1552
|
+
}
|
|
1635
1553
|
|
|
1636
|
-
|
|
1637
|
-
return this.changelog.getChangelogs(options);
|
|
1554
|
+
return response;
|
|
1638
1555
|
}
|
|
1639
1556
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1557
|
+
_storeContactIdentity(data, metadata = {}) {
|
|
1558
|
+
this.contactId = data.contact_id || null;
|
|
1559
|
+
this.contactEmail = data.email || metadata.email || null;
|
|
1560
|
+
this.contactName = data.name || metadata.name || null;
|
|
1642
1561
|
|
|
1643
1562
|
try {
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
return false;
|
|
1655
|
-
}
|
|
1656
|
-
|
|
1657
|
-
this.sessionToken = sessionData.token;
|
|
1658
|
-
this.sessionExpiry = new Date(sessionData.expiry);
|
|
1659
|
-
|
|
1660
|
-
return this.isSessionValid();
|
|
1661
|
-
} catch (error) {
|
|
1662
|
-
return false;
|
|
1563
|
+
localStorage.setItem(
|
|
1564
|
+
'product7_contact',
|
|
1565
|
+
JSON.stringify({
|
|
1566
|
+
contactId: this.contactId,
|
|
1567
|
+
contactEmail: this.contactEmail,
|
|
1568
|
+
contactName: this.contactName,
|
|
1569
|
+
})
|
|
1570
|
+
);
|
|
1571
|
+
} catch (e) {
|
|
1572
|
+
/* silent */
|
|
1663
1573
|
}
|
|
1664
1574
|
}
|
|
1665
1575
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1576
|
+
getContactIdentity() {
|
|
1577
|
+
if (this.contactId) {
|
|
1578
|
+
return {
|
|
1579
|
+
contactId: this.contactId,
|
|
1580
|
+
contactEmail: this.contactEmail,
|
|
1581
|
+
contactName: this.contactName,
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1668
1584
|
|
|
1669
1585
|
try {
|
|
1670
|
-
const
|
|
1586
|
+
const stored = localStorage.getItem('product7_contact');
|
|
1587
|
+
if (stored) {
|
|
1588
|
+
const parsed = JSON.parse(stored);
|
|
1589
|
+
this.contactId = parsed.contactId;
|
|
1590
|
+
this.contactEmail = parsed.contactEmail;
|
|
1591
|
+
this.contactName = parsed.contactName;
|
|
1592
|
+
return parsed;
|
|
1593
|
+
}
|
|
1594
|
+
} catch (e) {
|
|
1595
|
+
/* silent */
|
|
1596
|
+
}
|
|
1671
1597
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
let responseData = null;
|
|
1598
|
+
return null;
|
|
1599
|
+
}
|
|
1675
1600
|
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
responseData.message || responseData.error || errorMessage;
|
|
1680
|
-
} catch (e) {
|
|
1681
|
-
errorMessage = (await response.text()) || errorMessage;
|
|
1682
|
-
}
|
|
1601
|
+
async identifyContact(data) {
|
|
1602
|
+
return this.identify(data);
|
|
1603
|
+
}
|
|
1683
1604
|
|
|
1684
|
-
|
|
1685
|
-
|
|
1605
|
+
async getHelpCollections(options) {
|
|
1606
|
+
return this.help.getHelpCollections(options);
|
|
1607
|
+
}
|
|
1686
1608
|
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
}
|
|
1609
|
+
async searchHelpArticles(query, options) {
|
|
1610
|
+
return this.help.searchHelpArticles(query, options);
|
|
1611
|
+
}
|
|
1691
1612
|
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
if (error instanceof APIError) {
|
|
1695
|
-
throw error;
|
|
1696
|
-
}
|
|
1697
|
-
throw new APIError(0, error.message, null);
|
|
1698
|
-
}
|
|
1613
|
+
async getChangelogs(options) {
|
|
1614
|
+
return this.changelog.getChangelogs(options);
|
|
1699
1615
|
}
|
|
1700
1616
|
}
|
|
1701
1617
|
|
|
@@ -11411,6 +11327,7 @@
|
|
|
11411
11327
|
initialView: options.initialView || 'home',
|
|
11412
11328
|
previewData: options.previewData || null,
|
|
11413
11329
|
featuredContent: options.featuredContent || null,
|
|
11330
|
+
feedbackBoardName: options.feedbackBoardName || null,
|
|
11414
11331
|
feedbackUrl: options.feedbackUrl || null,
|
|
11415
11332
|
changelogUrl: options.changelogUrl || null,
|
|
11416
11333
|
helpUrl: options.helpUrl || null,
|
|
@@ -11462,7 +11379,8 @@
|
|
|
11462
11379
|
const widget = this.sdk.createWidget('button', {
|
|
11463
11380
|
trigger: false,
|
|
11464
11381
|
displayMode: 'modal',
|
|
11465
|
-
boardName:
|
|
11382
|
+
boardName:
|
|
11383
|
+
this.messengerOptions.feedbackBoardName || this.sdk.config.boardName,
|
|
11466
11384
|
primaryColor: this.messengerOptions.primaryColor,
|
|
11467
11385
|
theme: this.messengerOptions.theme,
|
|
11468
11386
|
});
|
|
@@ -14768,7 +14686,7 @@
|
|
|
14768
14686
|
metadata: null,
|
|
14769
14687
|
position: 'right',
|
|
14770
14688
|
theme: 'light',
|
|
14771
|
-
boardName: '
|
|
14689
|
+
boardName: 'feature-requests',
|
|
14772
14690
|
autoShow: true,
|
|
14773
14691
|
debug: false,
|
|
14774
14692
|
mock: false,
|
|
@@ -15716,7 +15634,7 @@
|
|
|
15716
15634
|
EventBus,
|
|
15717
15635
|
APIService,
|
|
15718
15636
|
SDKError,
|
|
15719
|
-
APIError
|
|
15637
|
+
APIError,
|
|
15720
15638
|
WidgetError,
|
|
15721
15639
|
ConfigError,
|
|
15722
15640
|
ValidationError,
|
|
@@ -15735,7 +15653,7 @@
|
|
|
15735
15653
|
}
|
|
15736
15654
|
}
|
|
15737
15655
|
|
|
15738
|
-
exports.APIError = APIError
|
|
15656
|
+
exports.APIError = APIError;
|
|
15739
15657
|
exports.APIService = APIService;
|
|
15740
15658
|
exports.BaseWidget = BaseWidget;
|
|
15741
15659
|
exports.ButtonWidget = ButtonWidget;
|