@product7/product7-js 0.6.7 → 0.6.9
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 +301 -12
- 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/core/APIService.js +4 -0
- package/src/styles/liveChat-components.js +159 -0
- package/src/styles/liveChat-core.js +4 -0
- package/src/utils/getIpInfo.js +17 -0
- package/src/widgets/LiveChatWidget.js +2 -0
- package/src/widgets/liveChat/components/LiveChatPanel.js +3 -2
- package/src/widgets/liveChat/views/FeedbackFormView.js +104 -0
- package/src/widgets/liveChat/views/HomeView.js +8 -10
package/dist/product7-js.js
CHANGED
|
@@ -1458,6 +1458,24 @@
|
|
|
1458
1458
|
}
|
|
1459
1459
|
}
|
|
1460
1460
|
|
|
1461
|
+
let _cached = null;
|
|
1462
|
+
|
|
1463
|
+
async function getIpInfo() {
|
|
1464
|
+
if (_cached) return _cached;
|
|
1465
|
+
|
|
1466
|
+
try {
|
|
1467
|
+
const res = await fetch('http://ip-api.com/json');
|
|
1468
|
+
if (!res.ok) return null;
|
|
1469
|
+
const data = await res.json();
|
|
1470
|
+
if (data.status === 'success') {
|
|
1471
|
+
_cached = data;
|
|
1472
|
+
}
|
|
1473
|
+
return _cached;
|
|
1474
|
+
} catch {
|
|
1475
|
+
return null;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1461
1479
|
class APIService extends BaseAPIService {
|
|
1462
1480
|
constructor(config = {}) {
|
|
1463
1481
|
super(config);
|
|
@@ -1561,6 +1579,9 @@
|
|
|
1561
1579
|
if (metadata.attributes) payload.attributes = metadata.attributes;
|
|
1562
1580
|
if (metadata.company) payload.company = metadata.company;
|
|
1563
1581
|
|
|
1582
|
+
const ipInfo = await getIpInfo();
|
|
1583
|
+
if (ipInfo) payload.ip_info = ipInfo;
|
|
1584
|
+
|
|
1564
1585
|
const response = await this._makeRequest('/widget/identify', {
|
|
1565
1586
|
method: 'POST',
|
|
1566
1587
|
headers: {
|
|
@@ -4282,10 +4303,173 @@
|
|
|
4282
4303
|
opacity: 0.7;
|
|
4283
4304
|
cursor: not-allowed;
|
|
4284
4305
|
}
|
|
4306
|
+
|
|
4307
|
+
/* ========================================
|
|
4308
|
+
FEEDBACK FORM VIEW
|
|
4309
|
+
======================================== */
|
|
4310
|
+
|
|
4311
|
+
.liveChat-feedback-view {
|
|
4312
|
+
display: flex;
|
|
4313
|
+
flex-direction: column;
|
|
4314
|
+
height: 100%;
|
|
4315
|
+
overflow: hidden;
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
.liveChat-feedback-header {
|
|
4319
|
+
display: flex;
|
|
4320
|
+
align-items: center;
|
|
4321
|
+
gap: var(--spacing-3);
|
|
4322
|
+
padding: var(--spacing-4) var(--spacing-4);
|
|
4323
|
+
border-bottom: 1px solid var(--border-color);
|
|
4324
|
+
flex-shrink: 0;
|
|
4325
|
+
}
|
|
4326
|
+
|
|
4327
|
+
.liveChat-feedback-title {
|
|
4328
|
+
font-size: var(--font-size-base);
|
|
4329
|
+
font-weight: var(--font-weight-semibold);
|
|
4330
|
+
color: var(--text-primary);
|
|
4331
|
+
}
|
|
4332
|
+
|
|
4333
|
+
.liveChat-feedback-body {
|
|
4334
|
+
display: flex;
|
|
4335
|
+
flex-direction: column;
|
|
4336
|
+
gap: var(--spacing-4);
|
|
4337
|
+
padding: var(--spacing-5) var(--spacing-4);
|
|
4338
|
+
flex: 1;
|
|
4339
|
+
overflow-y: auto;
|
|
4340
|
+
}
|
|
4341
|
+
|
|
4342
|
+
.liveChat-feedback-prompt {
|
|
4343
|
+
margin: 0;
|
|
4344
|
+
font-size: var(--font-size-sm);
|
|
4345
|
+
color: var(--text-secondary);
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
|
|
4349
|
+
.liveChat-feedback-input {
|
|
4350
|
+
width: 100%;
|
|
4351
|
+
border: 1px solid var(--border-color);
|
|
4352
|
+
border-radius: var(--radius-md);
|
|
4353
|
+
padding: var(--spacing-3);
|
|
4354
|
+
font-size: var(--font-size-sm);
|
|
4355
|
+
font-family: inherit;
|
|
4356
|
+
color: var(--text-primary);
|
|
4357
|
+
background: var(--msg-bg);
|
|
4358
|
+
box-sizing: border-box;
|
|
4359
|
+
transition: border-color var(--transition-fast);
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
.liveChat-feedback-input::placeholder {
|
|
4363
|
+
color: var(--msg-text-secondary);
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
.liveChat-feedback-input:focus {
|
|
4367
|
+
outline: none;
|
|
4368
|
+
border-color: var(--color-primary);
|
|
4369
|
+
}
|
|
4370
|
+
|
|
4371
|
+
.liveChat-feedback-textarea {
|
|
4372
|
+
width: 100%;
|
|
4373
|
+
resize: none;
|
|
4374
|
+
border: 1px solid var(--border-color);
|
|
4375
|
+
border-radius: var(--radius-md);
|
|
4376
|
+
padding: var(--spacing-3);
|
|
4377
|
+
font-size: var(--font-size-sm);
|
|
4378
|
+
font-family: inherit;
|
|
4379
|
+
color: var(--text-primary);
|
|
4380
|
+
background: var(--msg-bg);
|
|
4381
|
+
box-sizing: border-box;
|
|
4382
|
+
transition: border-color var(--transition-fast);
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4385
|
+
.liveChat-feedback-textarea::placeholder {
|
|
4386
|
+
color: var(--msg-text-secondary);
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
.liveChat-feedback-textarea:focus {
|
|
4390
|
+
outline: none;
|
|
4391
|
+
border-color: var(--color-primary);
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
.liveChat-feedback-submit {
|
|
4395
|
+
display: flex;
|
|
4396
|
+
align-items: center;
|
|
4397
|
+
justify-content: center;
|
|
4398
|
+
padding: var(--spacing-3);
|
|
4399
|
+
border-radius: var(--radius-md);
|
|
4400
|
+
font-size: var(--font-size-sm);
|
|
4401
|
+
font-weight: var(--font-weight-medium);
|
|
4402
|
+
font-family: inherit;
|
|
4403
|
+
cursor: pointer;
|
|
4404
|
+
border: none;
|
|
4405
|
+
background: var(--color-primary);
|
|
4406
|
+
color: #ffffff;
|
|
4407
|
+
transition: all var(--transition-fast);
|
|
4408
|
+
}
|
|
4409
|
+
|
|
4410
|
+
.liveChat-feedback-submit:hover:not(:disabled) {
|
|
4411
|
+
background: var(--color-primary-hover);
|
|
4412
|
+
}
|
|
4413
|
+
|
|
4414
|
+
.liveChat-feedback-submit:disabled {
|
|
4415
|
+
opacity: 0.5;
|
|
4416
|
+
cursor: not-allowed;
|
|
4417
|
+
}
|
|
4418
|
+
|
|
4419
|
+
.liveChat-feedback-thankyou {
|
|
4420
|
+
display: flex;
|
|
4421
|
+
flex-direction: column;
|
|
4422
|
+
align-items: center;
|
|
4423
|
+
justify-content: center;
|
|
4424
|
+
flex: 1;
|
|
4425
|
+
padding: var(--spacing-6) var(--spacing-4);
|
|
4426
|
+
text-align: center;
|
|
4427
|
+
gap: var(--spacing-3);
|
|
4428
|
+
}
|
|
4429
|
+
|
|
4430
|
+
.liveChat-feedback-thankyou-emoji {
|
|
4431
|
+
font-size: 48px;
|
|
4432
|
+
line-height: 1;
|
|
4433
|
+
}
|
|
4434
|
+
|
|
4435
|
+
.liveChat-feedback-thankyou h3 {
|
|
4436
|
+
margin: 0;
|
|
4437
|
+
font-size: var(--font-size-lg);
|
|
4438
|
+
font-weight: var(--font-weight-semibold);
|
|
4439
|
+
color: var(--text-primary);
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
.liveChat-feedback-thankyou p {
|
|
4443
|
+
margin: 0;
|
|
4444
|
+
font-size: var(--font-size-sm);
|
|
4445
|
+
color: var(--text-secondary);
|
|
4446
|
+
}
|
|
4447
|
+
|
|
4448
|
+
.liveChat-feedback-done-btn {
|
|
4449
|
+
margin-top: var(--spacing-2);
|
|
4450
|
+
padding: var(--spacing-2) var(--spacing-5);
|
|
4451
|
+
border-radius: var(--radius-md);
|
|
4452
|
+
font-size: var(--font-size-sm);
|
|
4453
|
+
font-weight: var(--font-weight-medium);
|
|
4454
|
+
font-family: inherit;
|
|
4455
|
+
cursor: pointer;
|
|
4456
|
+
border: 1px solid var(--border-color);
|
|
4457
|
+
background: transparent;
|
|
4458
|
+
color: var(--text-primary);
|
|
4459
|
+
transition: all var(--transition-fast);
|
|
4460
|
+
}
|
|
4461
|
+
|
|
4462
|
+
.liveChat-feedback-done-btn:hover {
|
|
4463
|
+
background: var(--bg-secondary);
|
|
4464
|
+
}
|
|
4285
4465
|
`;
|
|
4286
4466
|
|
|
4287
4467
|
const liveChatCoreStyles = `
|
|
4288
4468
|
|
|
4469
|
+
.liveChat-widget * {
|
|
4470
|
+
font-weight: 500;
|
|
4471
|
+
}
|
|
4472
|
+
|
|
4289
4473
|
.liveChat-launcher {
|
|
4290
4474
|
position: fixed;
|
|
4291
4475
|
z-index: var(--z-modal);
|
|
@@ -9490,11 +9674,12 @@
|
|
|
9490
9674
|
</div>`;
|
|
9491
9675
|
}
|
|
9492
9676
|
|
|
9493
|
-
// Hide nav in chat and
|
|
9677
|
+
// Hide nav in chat, prechat and feedback views
|
|
9494
9678
|
if (navContainer) {
|
|
9495
9679
|
const hideNav =
|
|
9496
9680
|
this.state.currentView === 'chat' ||
|
|
9497
|
-
this.state.currentView === 'prechat'
|
|
9681
|
+
this.state.currentView === 'prechat' ||
|
|
9682
|
+
this.state.currentView === 'feedback';
|
|
9498
9683
|
navContainer.style.display = hideNav ? 'none' : '';
|
|
9499
9684
|
}
|
|
9500
9685
|
}
|
|
@@ -11232,8 +11417,11 @@
|
|
|
11232
11417
|
const sendIcon = `<iconify-icon icon="ph:paper-plane-right" width="20" height="20" style="flex-shrink: 0;"></iconify-icon>`;
|
|
11233
11418
|
const caretIcon = `<iconify-icon icon="ph:caret-right" width="20" height="20" style="flex-shrink: 0;"></iconify-icon>`;
|
|
11234
11419
|
|
|
11235
|
-
const
|
|
11236
|
-
|
|
11420
|
+
const isUnavailable = this.state.businessHoursState === 'offline' || this.state.businessHoursState === 'away';
|
|
11421
|
+
const buttonLabel = isUnavailable ? 'Leave us a message' : this.state.startButtonText;
|
|
11422
|
+
const buttonSubtext = isUnavailable
|
|
11423
|
+
? "We'll get back to you when we're back"
|
|
11424
|
+
: (this.state.responseTime || 'We typically reply within a few minutes');
|
|
11237
11425
|
|
|
11238
11426
|
const recentCardHtml = openConversation
|
|
11239
11427
|
? this._renderRecentMessageCard(openConversation)
|
|
@@ -11243,8 +11431,8 @@
|
|
|
11243
11431
|
${recentCardHtml}
|
|
11244
11432
|
<button class="liveChat-home-message-btn">
|
|
11245
11433
|
<div class="liveChat-home-continue-info">
|
|
11246
|
-
<span class="liveChat-home-continue-label">${
|
|
11247
|
-
<span class="liveChat-home-message-subtext">${
|
|
11434
|
+
<span class="liveChat-home-continue-label">${buttonLabel}</span>
|
|
11435
|
+
<span class="liveChat-home-message-subtext">${buttonSubtext}</span>
|
|
11248
11436
|
</div>
|
|
11249
11437
|
${sendIcon}
|
|
11250
11438
|
</button>
|
|
@@ -11408,12 +11596,7 @@
|
|
|
11408
11596
|
const feedbackBtn = this.element.querySelector('.liveChat-feedback-btn');
|
|
11409
11597
|
if (feedbackBtn) {
|
|
11410
11598
|
feedbackBtn.addEventListener('click', () => {
|
|
11411
|
-
|
|
11412
|
-
this.state.setOpen(false);
|
|
11413
|
-
this.options.onFeedbackClick();
|
|
11414
|
-
} else if (this.state.urls?.feedback) {
|
|
11415
|
-
window.open(this.state.urls.feedback, '_blank');
|
|
11416
|
-
}
|
|
11599
|
+
this.state.setView('feedback');
|
|
11417
11600
|
});
|
|
11418
11601
|
}
|
|
11419
11602
|
|
|
@@ -11467,6 +11650,111 @@
|
|
|
11467
11650
|
}
|
|
11468
11651
|
}
|
|
11469
11652
|
|
|
11653
|
+
class FeedbackFormView {
|
|
11654
|
+
constructor(state, options = {}) {
|
|
11655
|
+
this.state = state;
|
|
11656
|
+
this.options = options;
|
|
11657
|
+
this.element = null;
|
|
11658
|
+
this._isSubmitting = false;
|
|
11659
|
+
this._selectedRating = null;
|
|
11660
|
+
}
|
|
11661
|
+
|
|
11662
|
+
render() {
|
|
11663
|
+
this.element = document.createElement('div');
|
|
11664
|
+
this.element.className = 'liveChat-view liveChat-feedback-view';
|
|
11665
|
+
this._renderForm();
|
|
11666
|
+
return this.element;
|
|
11667
|
+
}
|
|
11668
|
+
|
|
11669
|
+
_renderForm() {
|
|
11670
|
+
this.element.innerHTML = `
|
|
11671
|
+
<div class="liveChat-feedback-header">
|
|
11672
|
+
<button class="sdk-btn-icon liveChat-feedback-back-btn">
|
|
11673
|
+
<iconify-icon icon="ph:arrow-left" width="20" height="20"></iconify-icon>
|
|
11674
|
+
</button>
|
|
11675
|
+
<span class="liveChat-feedback-title">Leave us feedback</span>
|
|
11676
|
+
</div>
|
|
11677
|
+
<div class="liveChat-feedback-body">
|
|
11678
|
+
<p class="liveChat-feedback-prompt">Share your thoughts with us. We read every message.</p>
|
|
11679
|
+
<input
|
|
11680
|
+
type="text"
|
|
11681
|
+
class="liveChat-feedback-input"
|
|
11682
|
+
placeholder="Title"
|
|
11683
|
+
/>
|
|
11684
|
+
<textarea
|
|
11685
|
+
class="liveChat-feedback-textarea"
|
|
11686
|
+
placeholder="Your feedback..."
|
|
11687
|
+
rows="5"
|
|
11688
|
+
></textarea>
|
|
11689
|
+
<button class="liveChat-feedback-submit">Send feedback</button>
|
|
11690
|
+
</div>
|
|
11691
|
+
`;
|
|
11692
|
+
this._attachEvents();
|
|
11693
|
+
}
|
|
11694
|
+
|
|
11695
|
+
_renderThankYou() {
|
|
11696
|
+
this.element.innerHTML = `
|
|
11697
|
+
<div class="liveChat-feedback-header">
|
|
11698
|
+
<button class="sdk-btn-icon liveChat-feedback-back-btn">
|
|
11699
|
+
<iconify-icon icon="ph:arrow-left" width="20" height="20"></iconify-icon>
|
|
11700
|
+
</button>
|
|
11701
|
+
<span class="liveChat-feedback-title">Leave us feedback</span>
|
|
11702
|
+
</div>
|
|
11703
|
+
<div class="liveChat-feedback-thankyou">
|
|
11704
|
+
<span class="liveChat-feedback-thankyou-emoji">🙏</span>
|
|
11705
|
+
<h3>Thanks for your feedback!</h3>
|
|
11706
|
+
<p>We appreciate you taking the time to share your thoughts.</p>
|
|
11707
|
+
<button class="liveChat-feedback-done-btn">Done</button>
|
|
11708
|
+
</div>
|
|
11709
|
+
`;
|
|
11710
|
+
this.element.querySelector('.liveChat-feedback-back-btn').addEventListener('click', () => {
|
|
11711
|
+
this.state.setView('home');
|
|
11712
|
+
});
|
|
11713
|
+
this.element.querySelector('.liveChat-feedback-done-btn').addEventListener('click', () => {
|
|
11714
|
+
this.state.setView('home');
|
|
11715
|
+
});
|
|
11716
|
+
}
|
|
11717
|
+
|
|
11718
|
+
_attachEvents() {
|
|
11719
|
+
this.element.querySelector('.liveChat-feedback-back-btn').addEventListener('click', () => {
|
|
11720
|
+
this.state.setView('home');
|
|
11721
|
+
});
|
|
11722
|
+
|
|
11723
|
+
const submitBtn = this.element.querySelector('.liveChat-feedback-submit');
|
|
11724
|
+
submitBtn.addEventListener('click', async () => {
|
|
11725
|
+
if (this._isSubmitting) return;
|
|
11726
|
+
const title = this.element.querySelector('.liveChat-feedback-input').value.trim();
|
|
11727
|
+
const message = this.element.querySelector('.liveChat-feedback-textarea').value.trim();
|
|
11728
|
+
await this._submit(title, message);
|
|
11729
|
+
});
|
|
11730
|
+
}
|
|
11731
|
+
|
|
11732
|
+
async _submit(title, message) {
|
|
11733
|
+
this._isSubmitting = true;
|
|
11734
|
+
const submitBtn = this.element.querySelector('.liveChat-feedback-submit');
|
|
11735
|
+
if (submitBtn) {
|
|
11736
|
+
submitBtn.disabled = true;
|
|
11737
|
+
submitBtn.textContent = 'Sending...';
|
|
11738
|
+
}
|
|
11739
|
+
|
|
11740
|
+
try {
|
|
11741
|
+
if (this.options.onSubmitFeedback) {
|
|
11742
|
+
await this.options.onSubmitFeedback({ title, message });
|
|
11743
|
+
}
|
|
11744
|
+
} catch (e) {
|
|
11745
|
+
console.warn('[FeedbackFormView] Submit error:', e);
|
|
11746
|
+
}
|
|
11747
|
+
|
|
11748
|
+
this._renderThankYou();
|
|
11749
|
+
}
|
|
11750
|
+
|
|
11751
|
+
destroy() {
|
|
11752
|
+
if (this.element && this.element.parentNode) {
|
|
11753
|
+
this.element.parentNode.removeChild(this.element);
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11756
|
+
}
|
|
11757
|
+
|
|
11470
11758
|
class PreChatFormView {
|
|
11471
11759
|
constructor(state, options = {}) {
|
|
11472
11760
|
this.state = state;
|
|
@@ -11785,6 +12073,7 @@
|
|
|
11785
12073
|
this.panel.registerView('messages', ConversationsView);
|
|
11786
12074
|
this.panel.registerView('chat', ChatView);
|
|
11787
12075
|
this.panel.registerView('prechat', PreChatFormView);
|
|
12076
|
+
this.panel.registerView('feedback', FeedbackFormView);
|
|
11788
12077
|
this.panel.registerView('help', HelpView);
|
|
11789
12078
|
this.panel.registerView('changelog', ChangelogView);
|
|
11790
12079
|
|