@pendo/agent 2.332.0 → 2.332.1
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/dom.esm.js +23 -3
- package/dist/pendo.module.js +1205 -1097
- package/dist/pendo.module.min.js +109 -4
- package/dist/servers.json +7 -7
- package/package.json +1 -1
package/dist/pendo.module.js
CHANGED
|
@@ -648,7 +648,27 @@ function getPendoConfigValue(key) {
|
|
|
648
648
|
return config[key];
|
|
649
649
|
}
|
|
650
650
|
|
|
651
|
-
|
|
651
|
+
// Resolve the global object without relying on a bare `window` identifier.
|
|
652
|
+
// `window` is only a bound global in a normal browser realm; when the agent is
|
|
653
|
+
// loaded via the npm `loadAsModule` path (or inside a Web Worker) the module is
|
|
654
|
+
// evaluated in a realm where `window` is undeclared, so referencing it bare
|
|
655
|
+
// throws a ReferenceError at module-load. `globalThis` resolves in every realm.
|
|
656
|
+
function getGlobalScope() {
|
|
657
|
+
if (typeof globalThis !== 'undefined') {
|
|
658
|
+
return globalThis;
|
|
659
|
+
}
|
|
660
|
+
if (typeof self !== 'undefined') {
|
|
661
|
+
return self;
|
|
662
|
+
}
|
|
663
|
+
if (typeof window !== 'undefined') {
|
|
664
|
+
return window;
|
|
665
|
+
}
|
|
666
|
+
return {};
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
var globalScope = getGlobalScope();
|
|
670
|
+
|
|
671
|
+
var setTimeout = safeBind(globalScope.setTimeout, globalScope);
|
|
652
672
|
|
|
653
673
|
function safeBind(fn, scope) {
|
|
654
674
|
if (typeof fn.bind === 'function') {
|
|
@@ -671,7 +691,7 @@ setTimeout = (function(global) {
|
|
|
671
691
|
}
|
|
672
692
|
|
|
673
693
|
return getZoneSafeMethod('setTimeout');
|
|
674
|
-
})(
|
|
694
|
+
})(globalScope);
|
|
675
695
|
|
|
676
696
|
var setTimeout$1 = setTimeout;
|
|
677
697
|
|
|
@@ -4008,8 +4028,8 @@ let SERVER = '';
|
|
|
4008
4028
|
let ASSET_HOST = '';
|
|
4009
4029
|
let ASSET_PATH = '';
|
|
4010
4030
|
let DESIGNER_SERVER = '';
|
|
4011
|
-
let VERSION = '2.332.
|
|
4012
|
-
let PACKAGE_VERSION = '2.332.
|
|
4031
|
+
let VERSION = '2.332.1_';
|
|
4032
|
+
let PACKAGE_VERSION = '2.332.1';
|
|
4013
4033
|
let LOADER = 'xhr';
|
|
4014
4034
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
4015
4035
|
/**
|
|
@@ -41163,12 +41183,12 @@ function TextCapture() {
|
|
|
41163
41183
|
return {
|
|
41164
41184
|
name: 'TextCapture',
|
|
41165
41185
|
initialize: init,
|
|
41166
|
-
teardown
|
|
41167
|
-
isEnabled
|
|
41168
|
-
isTextCapturable
|
|
41169
|
-
hasWhitelist
|
|
41186
|
+
teardown,
|
|
41187
|
+
isEnabled,
|
|
41188
|
+
isTextCapturable,
|
|
41189
|
+
hasWhitelist,
|
|
41170
41190
|
serializer: textSerializer,
|
|
41171
|
-
guideActivity
|
|
41191
|
+
guideActivity
|
|
41172
41192
|
};
|
|
41173
41193
|
// technically not idempotent but might actually be right. not sure.
|
|
41174
41194
|
function init(pendo, PluginAPI) {
|
|
@@ -41207,30 +41227,30 @@ function TextCapture() {
|
|
|
41207
41227
|
function guideActivity(pendo, event) {
|
|
41208
41228
|
if (!isEnabled())
|
|
41209
41229
|
return;
|
|
41210
|
-
|
|
41211
|
-
|
|
41230
|
+
const { _ } = pendo;
|
|
41231
|
+
const eventData = event.data[0];
|
|
41212
41232
|
if (eventData && eventData.type === 'guideActivity') {
|
|
41213
|
-
|
|
41233
|
+
const shownSteps = _.reduce(pendo.getActiveGuides({ channel: '*' }), (shown, guide) => {
|
|
41214
41234
|
if (guide.isShown()) {
|
|
41215
|
-
return shown.concat(_.filter(guide.steps,
|
|
41235
|
+
return shown.concat(_.filter(guide.steps, (step) => step.isShown()));
|
|
41216
41236
|
}
|
|
41217
41237
|
return shown;
|
|
41218
41238
|
}, []);
|
|
41219
41239
|
if (!shownSteps.length)
|
|
41220
41240
|
return;
|
|
41221
|
-
|
|
41222
|
-
|
|
41223
|
-
_.find(shownSteps,
|
|
41241
|
+
const findDomBlockInDomJson = pendo.BuildingBlocks.BuildingBlockGuides.findDomBlockInDomJson;
|
|
41242
|
+
let elementJson;
|
|
41243
|
+
_.find(shownSteps, (step) => {
|
|
41224
41244
|
if (!step.domJson)
|
|
41225
41245
|
return false;
|
|
41226
|
-
|
|
41246
|
+
elementJson = findDomBlockInDomJson(step.domJson, function (domJson) {
|
|
41227
41247
|
return domJson.props && domJson.props.id && domJson.props.id === eventData.props.ui_element_id;
|
|
41228
41248
|
});
|
|
41229
|
-
return
|
|
41249
|
+
return elementJson;
|
|
41230
41250
|
});
|
|
41231
|
-
if (!
|
|
41251
|
+
if (!elementJson)
|
|
41232
41252
|
return;
|
|
41233
|
-
eventData.props.ui_element_text =
|
|
41253
|
+
eventData.props.ui_element_text = elementJson.content;
|
|
41234
41254
|
}
|
|
41235
41255
|
}
|
|
41236
41256
|
function isEnabled() {
|
|
@@ -41308,20 +41328,20 @@ function getZoneSafeMethod(_, method, target) {
|
|
|
41308
41328
|
}
|
|
41309
41329
|
|
|
41310
41330
|
// Does not support submit and go to
|
|
41311
|
-
|
|
41312
|
-
|
|
41331
|
+
const goToRegex = new RegExp(guideMarkdownUtil.goToString);
|
|
41332
|
+
const PollBranching = {
|
|
41313
41333
|
name: 'PollBranching',
|
|
41314
|
-
script
|
|
41315
|
-
|
|
41316
|
-
|
|
41334
|
+
script(step, guide, pendo) {
|
|
41335
|
+
let isAdvanceIntercepted = false;
|
|
41336
|
+
const branchingQuestions = initialBranchingSetup(step, pendo);
|
|
41317
41337
|
if (branchingQuestions) {
|
|
41318
41338
|
// If there are too many branching questions saved, exit and run the guide normally.
|
|
41319
41339
|
if (pendo._.size(branchingQuestions) > 1)
|
|
41320
41340
|
return;
|
|
41321
|
-
this.on('beforeAdvance',
|
|
41322
|
-
|
|
41323
|
-
|
|
41324
|
-
|
|
41341
|
+
this.on('beforeAdvance', (evt) => {
|
|
41342
|
+
const noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
|
|
41343
|
+
const responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
|
|
41344
|
+
let noGotoLabel;
|
|
41325
41345
|
if (responseLabel) {
|
|
41326
41346
|
noGotoLabel = pendo._.isNull(responseLabel.getAttribute('goToStep'));
|
|
41327
41347
|
}
|
|
@@ -41332,58 +41352,58 @@ var PollBranching = {
|
|
|
41332
41352
|
});
|
|
41333
41353
|
}
|
|
41334
41354
|
},
|
|
41335
|
-
test
|
|
41355
|
+
test(step, guide, pendo) {
|
|
41336
41356
|
var _a;
|
|
41337
|
-
|
|
41357
|
+
let branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41338
41358
|
return !pendo._.isUndefined(branchingQuestions) && pendo._.size(branchingQuestions);
|
|
41339
41359
|
},
|
|
41340
|
-
designerListener
|
|
41341
|
-
|
|
41342
|
-
|
|
41360
|
+
designerListener(pendo) {
|
|
41361
|
+
const target = pendo.dom.getBody();
|
|
41362
|
+
const config = {
|
|
41343
41363
|
attributeFilter: ['data-layout'],
|
|
41344
41364
|
attributes: true,
|
|
41345
41365
|
childList: true,
|
|
41346
41366
|
characterData: true,
|
|
41347
41367
|
subtree: true
|
|
41348
41368
|
};
|
|
41349
|
-
|
|
41350
|
-
|
|
41369
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41370
|
+
const observer = new MutationObserver(applyBranchingIndicators);
|
|
41351
41371
|
observer.observe(target, config);
|
|
41352
41372
|
function applyBranchingIndicators(mutations) {
|
|
41353
41373
|
pendo._.each(mutations, function (mutation) {
|
|
41354
41374
|
var _a;
|
|
41355
|
-
|
|
41375
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
|
|
41356
41376
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41357
41377
|
if (mutation.addedNodes[0].querySelector('._pendo-multi-choice-poll-select-border')) {
|
|
41358
41378
|
if (pendo._.size(pendo.dom('._pendo-multi-choice-poll-question:contains("{branching/}")'))) {
|
|
41359
41379
|
pendo
|
|
41360
41380
|
.dom('._pendo-multi-choice-poll-question:contains("{branching/}")')
|
|
41361
|
-
.each(
|
|
41362
|
-
pendo._.each(pendo.dom(
|
|
41381
|
+
.each((question, index) => {
|
|
41382
|
+
pendo._.each(pendo.dom(`#${question.id} *`), (element) => {
|
|
41363
41383
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41364
41384
|
});
|
|
41365
41385
|
pendo
|
|
41366
|
-
.dom(
|
|
41386
|
+
.dom(`#${question.id} p`)
|
|
41367
41387
|
.css({ display: 'inline-block !important' })
|
|
41368
41388
|
.append(branchingIcon('#999', '20px'))
|
|
41369
41389
|
.attr({ title: 'Custom Branching Added' });
|
|
41370
|
-
|
|
41371
|
-
if (pendo.dom(
|
|
41390
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41391
|
+
if (pendo.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]) {
|
|
41372
41392
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41373
41393
|
pendo
|
|
41374
|
-
.dom(
|
|
41394
|
+
.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]
|
|
41375
41395
|
.textContent.trim();
|
|
41376
41396
|
}
|
|
41377
|
-
|
|
41397
|
+
let pollLabels = pendo.dom(`label[for*=${dataPendoPollId}]`);
|
|
41378
41398
|
if (pendo._.size(pollLabels)) {
|
|
41379
|
-
pendo._.forEach(pollLabels,
|
|
41399
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41380
41400
|
if (goToRegex.test(label.textContent)) {
|
|
41381
|
-
|
|
41401
|
+
let labelTitle = goToRegex.exec(label.textContent)[2];
|
|
41382
41402
|
guideMarkdownUtil.removeMarkdownSyntax(label, goToRegex, '', pendo);
|
|
41383
41403
|
pendo
|
|
41384
41404
|
.dom(label)
|
|
41385
41405
|
.append(branchingIcon('#999', '14px'))
|
|
41386
|
-
.attr({ title:
|
|
41406
|
+
.attr({ title: `Branching to step ${labelTitle}` });
|
|
41387
41407
|
}
|
|
41388
41408
|
});
|
|
41389
41409
|
}
|
|
@@ -41391,9 +41411,9 @@ var PollBranching = {
|
|
|
41391
41411
|
pendo
|
|
41392
41412
|
.dom(question)
|
|
41393
41413
|
.append(branchingErrorHTML(question.dataset.pendoPollId));
|
|
41394
|
-
pendo.dom(
|
|
41414
|
+
pendo.dom(`#${question.id} #pendo-ps-branching-svg`).remove();
|
|
41395
41415
|
pendo
|
|
41396
|
-
.dom(
|
|
41416
|
+
.dom(`#${question.id} p`)
|
|
41397
41417
|
.css({ display: 'inline-block !important' })
|
|
41398
41418
|
.append(branchingIcon('red', '20px'))
|
|
41399
41419
|
.attr({ title: 'Unsupported Branching configuration' });
|
|
@@ -41405,31 +41425,49 @@ var PollBranching = {
|
|
|
41405
41425
|
});
|
|
41406
41426
|
}
|
|
41407
41427
|
function branchingErrorHTML(dataPendoPollId) {
|
|
41408
|
-
return
|
|
41428
|
+
return `<div style="text-align:lrft; font-size: 14px; color: red;
|
|
41429
|
+
font-style: italic; margin-top: 0px;" class="branching-wrapper"
|
|
41430
|
+
name="${dataPendoPollId}">
|
|
41431
|
+
* Branching Error: Multiple branching polls not supported</div>`;
|
|
41409
41432
|
}
|
|
41410
41433
|
function branchingIcon(color, size) {
|
|
41411
|
-
return
|
|
41434
|
+
return `<svg id="pendo-ps-branching-svg" viewBox="0 0 24 24" fill="none"
|
|
41435
|
+
style="margin-left: 5px;
|
|
41436
|
+
height:${size}; width:${size}; display:inline; vertical-align:middle;" xmlns="http://www.w3.org/2000/svg">
|
|
41437
|
+
<g stroke-width="0"></g>
|
|
41438
|
+
<g stroke-linecap="round" stroke-linejoin="round"></g>
|
|
41439
|
+
<g> <circle cx="4" cy="7" r="2" stroke="${color}"
|
|
41440
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41441
|
+
<circle cx="20" cy="7" r="2" stroke="${color}"
|
|
41442
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41443
|
+
<circle cx="20" cy="17" r="2" stroke="${color}" stroke-width="2"
|
|
41444
|
+
stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41445
|
+
<path d="M18 7H6" stroke="${color}" stroke-width="2"
|
|
41446
|
+
stroke-linecap="round" stroke-linejoin="round"></path>
|
|
41447
|
+
<path d="M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18"
|
|
41448
|
+
stroke="${color}" stroke-width="2" stroke-linecap="round"
|
|
41449
|
+
stroke-linejoin="round"></path> </g></svg>`;
|
|
41412
41450
|
}
|
|
41413
41451
|
}
|
|
41414
41452
|
};
|
|
41415
41453
|
function initialBranchingSetup(step, pendo) {
|
|
41416
|
-
|
|
41417
|
-
pendo._.forEach(questions,
|
|
41418
|
-
|
|
41419
|
-
pendo._.each(step.guideElement.find(
|
|
41454
|
+
const questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41455
|
+
pendo._.forEach(questions, (question) => {
|
|
41456
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41457
|
+
pendo._.each(step.guideElement.find(`#${question.id} *`), (element) => {
|
|
41420
41458
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41421
41459
|
});
|
|
41422
|
-
|
|
41423
|
-
pendo._.forEach(pollLabels,
|
|
41460
|
+
let pollLabels = step.guideElement.find(`label[for*=${dataPendoPollId}]`);
|
|
41461
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41424
41462
|
if (pendo._.isNull(goToRegex.exec(label.textContent))) {
|
|
41425
41463
|
return;
|
|
41426
41464
|
}
|
|
41427
|
-
|
|
41428
|
-
|
|
41465
|
+
let gotoSubstring = goToRegex.exec(label.textContent)[1];
|
|
41466
|
+
let gotoIndex = goToRegex.exec(label.textContent)[2];
|
|
41429
41467
|
label.setAttribute('goToStep', gotoIndex);
|
|
41430
41468
|
guideMarkdownUtil.removeMarkdownSyntax(label, gotoSubstring, '', pendo);
|
|
41431
41469
|
});
|
|
41432
|
-
|
|
41470
|
+
let pollChoiceContainer = step.guideElement.find(`[data-pendo-poll-id=${dataPendoPollId}]._pendo-multi-choice-poll-select-border`);
|
|
41433
41471
|
if (pollChoiceContainer && pollChoiceContainer.length) {
|
|
41434
41472
|
pollChoiceContainer[0].setAttribute('branching', '');
|
|
41435
41473
|
}
|
|
@@ -41438,15 +41476,15 @@ function initialBranchingSetup(step, pendo) {
|
|
|
41438
41476
|
}
|
|
41439
41477
|
function branchingGoToStep(event, step, guide, pendo) {
|
|
41440
41478
|
var _a;
|
|
41441
|
-
|
|
41442
|
-
|
|
41443
|
-
|
|
41444
|
-
|
|
41479
|
+
let checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
41480
|
+
let checkedPollLabel = step.guideElement.find(`label[for="${checkedPollInputId}"]`)[0];
|
|
41481
|
+
let checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
|
|
41482
|
+
let pollStepIndex = checkedPollLabelStepIndex - 1;
|
|
41445
41483
|
if (pollStepIndex < 0)
|
|
41446
41484
|
return;
|
|
41447
|
-
|
|
41485
|
+
const destinationObject = {
|
|
41448
41486
|
destinationStepId: guide.steps[pollStepIndex].id,
|
|
41449
|
-
step
|
|
41487
|
+
step
|
|
41450
41488
|
};
|
|
41451
41489
|
pendo.goToStep(destinationObject);
|
|
41452
41490
|
event.cancel = true;
|
|
@@ -41467,10 +41505,10 @@ function encodeMetadataForUrl(value, urlBeforePlaceholder) {
|
|
|
41467
41505
|
return window.encodeURI(str);
|
|
41468
41506
|
}
|
|
41469
41507
|
|
|
41470
|
-
|
|
41508
|
+
const MetadataSubstitution = {
|
|
41471
41509
|
name: 'MetadataSubstitution',
|
|
41472
|
-
script
|
|
41473
|
-
|
|
41510
|
+
script(step, guide, pendo) {
|
|
41511
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41474
41512
|
if (step.domJson) {
|
|
41475
41513
|
findSubstitutableUrlsInJson(step.domJson, placeholderData, pendo);
|
|
41476
41514
|
}
|
|
@@ -41478,22 +41516,22 @@ var MetadataSubstitution = {
|
|
|
41478
41516
|
pendo._.each(placeholderData, function (placeholder) {
|
|
41479
41517
|
processPlaceholder(placeholder, pendo);
|
|
41480
41518
|
});
|
|
41481
|
-
|
|
41482
|
-
|
|
41483
|
-
updateGuideContainer(containerId,
|
|
41519
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41520
|
+
const context = step.guideElement;
|
|
41521
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41484
41522
|
}
|
|
41485
41523
|
},
|
|
41486
|
-
designerListener
|
|
41487
|
-
|
|
41524
|
+
designerListener(pendo) {
|
|
41525
|
+
const target = pendo.dom.getBody();
|
|
41488
41526
|
if (pendo.designerv2) {
|
|
41489
41527
|
pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
|
|
41490
41528
|
var _a;
|
|
41491
41529
|
if (!document.querySelector(guideMarkdownUtil.containerSelector))
|
|
41492
41530
|
return;
|
|
41493
|
-
|
|
41531
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41494
41532
|
if (!step)
|
|
41495
41533
|
return;
|
|
41496
|
-
|
|
41534
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41497
41535
|
if (step.buildingBlocks) {
|
|
41498
41536
|
findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
|
|
41499
41537
|
}
|
|
@@ -41503,32 +41541,32 @@ var MetadataSubstitution = {
|
|
|
41503
41541
|
return;
|
|
41504
41542
|
processPlaceholder(placeholder, pendo);
|
|
41505
41543
|
});
|
|
41506
|
-
|
|
41507
|
-
|
|
41508
|
-
updateGuideContainer(containerId,
|
|
41544
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41545
|
+
const context = step.guideElement;
|
|
41546
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41509
41547
|
}
|
|
41510
41548
|
};
|
|
41511
41549
|
}
|
|
41512
|
-
|
|
41550
|
+
const config = {
|
|
41513
41551
|
attributeFilter: ['data-layout'],
|
|
41514
41552
|
attributes: true,
|
|
41515
41553
|
childList: true,
|
|
41516
41554
|
characterData: true,
|
|
41517
41555
|
subtree: true
|
|
41518
41556
|
};
|
|
41519
|
-
|
|
41520
|
-
|
|
41557
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41558
|
+
const observer = new MutationObserver(applySubstitutionIndicators);
|
|
41521
41559
|
observer.observe(target, config);
|
|
41522
41560
|
function applySubstitutionIndicators(mutations) {
|
|
41523
41561
|
pendo._.each(mutations, function (mutation) {
|
|
41524
41562
|
var _a;
|
|
41525
41563
|
if (mutation.addedNodes.length) {
|
|
41526
41564
|
if (document.querySelector(guideMarkdownUtil.containerSelector)) {
|
|
41527
|
-
|
|
41528
|
-
|
|
41565
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41566
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41529
41567
|
if (!step)
|
|
41530
41568
|
return;
|
|
41531
|
-
|
|
41569
|
+
const pendoBlocks = step.buildingBlocks;
|
|
41532
41570
|
if (!pendo._.isUndefined(pendoBlocks)) {
|
|
41533
41571
|
findSubstitutableUrlsInJson(pendoBlocks, placeholderData, pendo);
|
|
41534
41572
|
}
|
|
@@ -41538,9 +41576,9 @@ var MetadataSubstitution = {
|
|
|
41538
41576
|
return;
|
|
41539
41577
|
processPlaceholder(placeholder, pendo);
|
|
41540
41578
|
});
|
|
41541
|
-
|
|
41542
|
-
|
|
41543
|
-
updateGuideContainer(containerId,
|
|
41579
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41580
|
+
const context = step.guideElement;
|
|
41581
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41544
41582
|
}
|
|
41545
41583
|
}
|
|
41546
41584
|
}
|
|
@@ -41549,18 +41587,18 @@ var MetadataSubstitution = {
|
|
|
41549
41587
|
}
|
|
41550
41588
|
};
|
|
41551
41589
|
function processPlaceholder(placeholder, pendo) {
|
|
41552
|
-
|
|
41553
|
-
|
|
41554
|
-
|
|
41590
|
+
let match;
|
|
41591
|
+
const { data, target } = placeholder;
|
|
41592
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41555
41593
|
while ((match = matchPlaceholder(placeholder, subRegex))) {
|
|
41556
|
-
|
|
41557
|
-
|
|
41594
|
+
const usedArrayPath = Array.isArray(match) && match.length >= 2;
|
|
41595
|
+
const currentStr = target === 'textContent'
|
|
41558
41596
|
? data[target]
|
|
41559
41597
|
: decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
|
|
41560
|
-
|
|
41598
|
+
const matched = usedArrayPath ? match : subRegex.exec(currentStr);
|
|
41561
41599
|
if (!matched)
|
|
41562
41600
|
continue;
|
|
41563
|
-
|
|
41601
|
+
const mdValue = getSubstituteValue(matched, pendo);
|
|
41564
41602
|
substituteMetadataByTarget(data, target, mdValue, matched);
|
|
41565
41603
|
}
|
|
41566
41604
|
}
|
|
@@ -41569,50 +41607,50 @@ function matchPlaceholder(placeholder, regex) {
|
|
|
41569
41607
|
return placeholder.data[placeholder.target].match(regex);
|
|
41570
41608
|
}
|
|
41571
41609
|
else {
|
|
41572
|
-
|
|
41610
|
+
const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
|
|
41573
41611
|
? (placeholder.data.getAttribute(placeholder.target) || '')
|
|
41574
41612
|
: placeholder.data[placeholder.target];
|
|
41575
41613
|
return decodeURI(raw).match(regex);
|
|
41576
41614
|
}
|
|
41577
41615
|
}
|
|
41578
41616
|
function getMetadataValueCaseInsensitive(metadata, type, property) {
|
|
41579
|
-
|
|
41617
|
+
const kind = metadata && metadata[type];
|
|
41580
41618
|
if (!kind || typeof kind !== 'object')
|
|
41581
41619
|
return undefined;
|
|
41582
|
-
|
|
41620
|
+
const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
|
|
41583
41621
|
if (direct !== undefined) {
|
|
41584
41622
|
return direct;
|
|
41585
41623
|
}
|
|
41586
|
-
|
|
41587
|
-
|
|
41588
|
-
|
|
41624
|
+
const propLower = property.toLowerCase();
|
|
41625
|
+
const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
|
|
41626
|
+
const value = key !== undefined ? kind[key] : undefined;
|
|
41589
41627
|
return value;
|
|
41590
41628
|
}
|
|
41591
41629
|
function getSubstituteValue(match, pendo) {
|
|
41592
41630
|
if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
|
|
41593
41631
|
return;
|
|
41594
41632
|
}
|
|
41595
|
-
|
|
41596
|
-
|
|
41597
|
-
|
|
41633
|
+
let type = match[1];
|
|
41634
|
+
let property = match[2];
|
|
41635
|
+
let defaultValue = match[3];
|
|
41598
41636
|
if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
|
|
41599
41637
|
return;
|
|
41600
41638
|
}
|
|
41601
|
-
|
|
41602
|
-
|
|
41639
|
+
const metadata = pendo.getSerializedMetadata();
|
|
41640
|
+
let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
|
|
41603
41641
|
if (mdValue === undefined || mdValue === null)
|
|
41604
41642
|
mdValue = defaultValue || '';
|
|
41605
41643
|
return mdValue;
|
|
41606
41644
|
}
|
|
41607
41645
|
function substituteMetadataByTarget(data, target, mdValue, matched) {
|
|
41608
|
-
|
|
41609
|
-
|
|
41646
|
+
const isElement = data && typeof data.getAttribute === 'function';
|
|
41647
|
+
const current = (target === 'href' || target === 'value') && isElement
|
|
41610
41648
|
? (data.getAttribute(target) || '')
|
|
41611
41649
|
: data[target];
|
|
41612
41650
|
if (target === 'href' || target === 'value') {
|
|
41613
|
-
|
|
41614
|
-
|
|
41615
|
-
|
|
41651
|
+
const decodedUrl = decodeURI(current);
|
|
41652
|
+
const urlBeforePlaceholder = decodedUrl.slice(0, decodedUrl.indexOf(matched[0]));
|
|
41653
|
+
const safeValue = encodeMetadataForUrl(mdValue, urlBeforePlaceholder);
|
|
41616
41654
|
data[target] = decodedUrl.replace(matched[0], safeValue);
|
|
41617
41655
|
}
|
|
41618
41656
|
else {
|
|
@@ -41626,9 +41664,8 @@ function updateGuideContainer(containerId, context, pendo) {
|
|
|
41626
41664
|
pendo.flexElement(pendo.dom(guideMarkdownUtil.containerSelector));
|
|
41627
41665
|
pendo.BuildingBlocks.BuildingBlockGuides.recalculateGuideHeight(containerId, context);
|
|
41628
41666
|
}
|
|
41629
|
-
function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
41630
|
-
|
|
41631
|
-
var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41667
|
+
function findSubstitutableUrlsInJson(originalData, placeholderData = [], pendo) {
|
|
41668
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41632
41669
|
if ((originalData.name === 'url' || originalData.name === 'href') && originalData.value) {
|
|
41633
41670
|
if (subRegex.test(originalData.value)) {
|
|
41634
41671
|
placeholderData.push({
|
|
@@ -41638,37 +41675,37 @@ function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
|
41638
41675
|
}
|
|
41639
41676
|
}
|
|
41640
41677
|
if (originalData.properties && originalData.id === 'href_link_block') {
|
|
41641
|
-
pendo._.each(originalData.properties,
|
|
41678
|
+
pendo._.each(originalData.properties, (prop) => {
|
|
41642
41679
|
findSubstitutableUrlsInJson(prop, placeholderData, pendo);
|
|
41643
41680
|
});
|
|
41644
41681
|
}
|
|
41645
41682
|
if (originalData.views) {
|
|
41646
|
-
pendo._.each(originalData.views,
|
|
41683
|
+
pendo._.each(originalData.views, (view) => {
|
|
41647
41684
|
findSubstitutableUrlsInJson(view, placeholderData, pendo);
|
|
41648
41685
|
});
|
|
41649
41686
|
}
|
|
41650
41687
|
if (originalData.parameters) {
|
|
41651
|
-
pendo._.each(originalData.parameters,
|
|
41688
|
+
pendo._.each(originalData.parameters, (param) => {
|
|
41652
41689
|
findSubstitutableUrlsInJson(param, placeholderData, pendo);
|
|
41653
41690
|
});
|
|
41654
41691
|
}
|
|
41655
41692
|
if (originalData.actions) {
|
|
41656
|
-
pendo._.each(originalData.actions,
|
|
41693
|
+
pendo._.each(originalData.actions, (action) => {
|
|
41657
41694
|
findSubstitutableUrlsInJson(action, placeholderData, pendo);
|
|
41658
41695
|
});
|
|
41659
41696
|
}
|
|
41660
41697
|
if (originalData.children) {
|
|
41661
|
-
pendo._.each(originalData.children,
|
|
41698
|
+
pendo._.each(originalData.children, (child) => {
|
|
41662
41699
|
findSubstitutableUrlsInJson(child, placeholderData, pendo);
|
|
41663
41700
|
});
|
|
41664
41701
|
}
|
|
41665
41702
|
return placeholderData;
|
|
41666
41703
|
}
|
|
41667
41704
|
function findSubstitutableElements(pendo) {
|
|
41668
|
-
|
|
41705
|
+
let elements = pendo.dom(`${guideMarkdownUtil.containerSelector} *:not(.pendo-inline-ui)`);
|
|
41669
41706
|
return pendo._.chain(elements)
|
|
41670
41707
|
.filter(function (placeholder) {
|
|
41671
|
-
|
|
41708
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41672
41709
|
if (placeholder.localName === 'a') {
|
|
41673
41710
|
return subRegex.test(decodeURI(placeholder.href)) || subRegex.test(placeholder.textContent);
|
|
41674
41711
|
}
|
|
@@ -41724,25 +41761,51 @@ function findSubstitutableElements(pendo) {
|
|
|
41724
41761
|
.value();
|
|
41725
41762
|
}
|
|
41726
41763
|
function substitutionIcon(color, size) {
|
|
41727
|
-
return (
|
|
41728
|
-
|
|
41729
|
-
|
|
41730
|
-
|
|
41731
|
-
|
|
41732
|
-
|
|
41764
|
+
return (`<div title="Metadata Substitution added">
|
|
41765
|
+
<svg id="pendo-ps-substitution-icon" viewBox="0 0 24 24"
|
|
41766
|
+
preserveAspectRatio="xMidYMid meet"
|
|
41767
|
+
height=${size} width=${size} title="Metadata Substitution"
|
|
41768
|
+
style="bottom:5px; right:10px; position: absolute;"
|
|
41769
|
+
fill="none" xmlns="http://www.w3.org/2000/svg" stroke="${color}"
|
|
41770
|
+
transform="matrix(1, 0, 0, 1, 0, 0)rotate(0)">
|
|
41771
|
+
<g stroke-width="0"></g>
|
|
41772
|
+
<g stroke-linecap="round" stroke-linejoin="round"
|
|
41773
|
+
stroke="${color}" stroke-width="0.528"></g>
|
|
41774
|
+
<g><path fill-rule="evenodd" clip-rule="evenodd"
|
|
41775
|
+
d="M5 5.5C4.17157 5.5 3.5 6.17157 3.5 7V10C3.5 10.8284
|
|
41776
|
+
4.17157 11.5 5 11.5H8C8.82843 11.5 9.5 10.8284 9.5
|
|
41777
|
+
10V9H17V11C17 11.2761 17.2239 11.5 17.5 11.5C17.7761
|
|
41778
|
+
11.5 18 11.2761 18 11V8.5C18 8.22386 17.7761 8 17.5
|
|
41779
|
+
8H9.5V7C9.5 6.17157 8.82843 5.5 8 5.5H5ZM8.5 7C8.5
|
|
41780
|
+
6.72386 8.27614 6.5 8 6.5H5C4.72386 6.5 4.5 6.72386
|
|
41781
|
+
4.5 7V10C4.5 10.2761 4.72386 10.5 5 10.5H8C8.27614
|
|
41782
|
+
10.5 8.5 10.2761 8.5 10V7Z" fill="${color}"></path>
|
|
41783
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
41784
|
+
d="M7 13C7 12.7239 6.77614 12.5 6.5 12.5C6.22386 12.5
|
|
41785
|
+
6 12.7239 6 13V15.5C6 15.7761 6.22386 16 6.5
|
|
41786
|
+
16H14.5V17C14.5 17.8284 15.1716 18.5 16 18.5H19C19.8284
|
|
41787
|
+
18.5 20.5 17.8284 20.5 17V14C20.5 13.1716 19.8284 12.5
|
|
41788
|
+
19 12.5H16C15.1716 12.5 14.5 13.1716 14.5
|
|
41789
|
+
14V15H7V13ZM15.5 17C15.5 17.2761 15.7239 17.5 16
|
|
41790
|
+
17.5H19C19.2761 17.5 19.5 17.2761 19.5 17V14C19.5
|
|
41791
|
+
13.7239 19.2761 13.5 19 13.5H16C15.7239 13.5 15.5
|
|
41792
|
+
13.7239 15.5 14V17Z" fill="${color}"></path> </g></svg></div>`);
|
|
41793
|
+
}
|
|
41794
|
+
|
|
41795
|
+
const requiredElement = '<span class="_pendo-required-indicator" style="color:red; font-style:italic;" title="Question is required"> *</span>';
|
|
41796
|
+
const requiredSyntax = '{required/}';
|
|
41797
|
+
const RequiredQuestions = {
|
|
41733
41798
|
name: 'RequiredQuestions',
|
|
41734
|
-
script
|
|
41799
|
+
script(step, guide, pendo) {
|
|
41735
41800
|
var _a;
|
|
41736
|
-
|
|
41737
|
-
|
|
41738
|
-
|
|
41739
|
-
});
|
|
41740
|
-
var requiredQuestions = processRequiredQuestions();
|
|
41801
|
+
let requiredPollIds = [];
|
|
41802
|
+
let submitButtons = (_a = guideMarkdownUtil.lookupGuideButtons(step.domJson)) === null || _a === void 0 ? void 0 : _a.filter(button => button.actions.find(action => action.action === 'submitPoll' || action.action === 'submitPollAndGoToStep'));
|
|
41803
|
+
const requiredQuestions = processRequiredQuestions();
|
|
41741
41804
|
if (requiredQuestions) {
|
|
41742
|
-
pendo._.forEach(requiredQuestions,
|
|
41805
|
+
pendo._.forEach(requiredQuestions, (question) => {
|
|
41743
41806
|
if (question.classList.contains('_pendo-open-text-poll-question')) {
|
|
41744
|
-
|
|
41745
|
-
step.attachEvent(step.guideElement.find(
|
|
41807
|
+
let pollId = question.dataset.pendoPollId;
|
|
41808
|
+
step.attachEvent(step.guideElement.find(`[data-pendo-poll-id=${pollId}]._pendo-open-text-poll-input`)[0], 'input', function () {
|
|
41746
41809
|
evaluateRequiredQuestions(requiredQuestions);
|
|
41747
41810
|
});
|
|
41748
41811
|
}
|
|
@@ -41754,13 +41817,11 @@ var RequiredQuestions = {
|
|
|
41754
41817
|
});
|
|
41755
41818
|
}
|
|
41756
41819
|
function getEligibleQuestions() {
|
|
41757
|
-
|
|
41758
|
-
|
|
41759
|
-
|
|
41760
|
-
|
|
41761
|
-
|
|
41762
|
-
var allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
41763
|
-
return pendo._.reduce(allQuestions, function (eligibleQuestions, question) {
|
|
41820
|
+
const pollQuestions = pendo._.toArray(step.guideElement.find(`[class*=-poll-question]:contains(${requiredSyntax})`));
|
|
41821
|
+
const surveyMatches = pendo._.toArray(step.guideElement.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`));
|
|
41822
|
+
const surveyQuestions = pendo._.filter(surveyMatches, (candidate) => !pendo._.some(surveyMatches, (other) => other !== candidate && candidate.contains(other)));
|
|
41823
|
+
const allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
41824
|
+
return pendo._.reduce(allQuestions, (eligibleQuestions, question) => {
|
|
41764
41825
|
if (question.classList.contains('_pendo-yes-no-poll-question'))
|
|
41765
41826
|
return eligibleQuestions;
|
|
41766
41827
|
eligibleQuestions.push(question);
|
|
@@ -41768,24 +41829,22 @@ var RequiredQuestions = {
|
|
|
41768
41829
|
}, []);
|
|
41769
41830
|
}
|
|
41770
41831
|
function ownsRequiredText(element) {
|
|
41771
|
-
return pendo._.some(element.childNodes,
|
|
41772
|
-
return node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1;
|
|
41773
|
-
});
|
|
41832
|
+
return pendo._.some(element.childNodes, (node) => node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1);
|
|
41774
41833
|
}
|
|
41775
41834
|
function processRequiredQuestions() {
|
|
41776
|
-
|
|
41835
|
+
let questions = getEligibleQuestions();
|
|
41777
41836
|
if (questions) {
|
|
41778
|
-
pendo._.forEach(questions,
|
|
41779
|
-
|
|
41837
|
+
pendo._.forEach(questions, question => {
|
|
41838
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41780
41839
|
requiredPollIds.push(dataPendoPollId);
|
|
41781
|
-
|
|
41782
|
-
|
|
41783
|
-
pendo._.each(candidates,
|
|
41840
|
+
const candidates = step.guideElement.find(`#${question.id} *, #${question.id}`);
|
|
41841
|
+
const textHost = pendo._.find(candidates, ownsRequiredText) || question;
|
|
41842
|
+
pendo._.each(candidates, (element) => {
|
|
41784
41843
|
guideMarkdownUtil.removeMarkdownSyntax(element, requiredSyntax, '', pendo);
|
|
41785
41844
|
});
|
|
41786
|
-
|
|
41845
|
+
const textHostEl = pendo.dom(textHost);
|
|
41787
41846
|
if (textHostEl.find('._pendo-required-indicator').length === 0) {
|
|
41788
|
-
|
|
41847
|
+
const questionParagraph = textHostEl.find('p');
|
|
41789
41848
|
if (questionParagraph && questionParagraph.length) {
|
|
41790
41849
|
pendo.dom(questionParagraph[0]).append(requiredElement);
|
|
41791
41850
|
}
|
|
@@ -41796,7 +41855,15 @@ var RequiredQuestions = {
|
|
|
41796
41855
|
});
|
|
41797
41856
|
}
|
|
41798
41857
|
if (pendo._.size(requiredPollIds)) {
|
|
41799
|
-
|
|
41858
|
+
const disabledButtonStyles = `<style type=text/css
|
|
41859
|
+
id=_pendo-guide-required-disabled>
|
|
41860
|
+
._pendo-button:disabled, ._pendo-buttons[disabled] {
|
|
41861
|
+
border: 1px solid #999999 !important;
|
|
41862
|
+
background-color: #cccccc !important;
|
|
41863
|
+
color: #666666 !important;
|
|
41864
|
+
pointer-events: none !important;
|
|
41865
|
+
}
|
|
41866
|
+
</style>`;
|
|
41800
41867
|
if (pendo.dom('#_pendo-guide-required-disabled').length === 0) {
|
|
41801
41868
|
pendo.dom('head').append(disabledButtonStyles);
|
|
41802
41869
|
}
|
|
@@ -41807,11 +41874,15 @@ var RequiredQuestions = {
|
|
|
41807
41874
|
function evaluateRequiredQuestions(questions) {
|
|
41808
41875
|
if (questions.length === 0)
|
|
41809
41876
|
return;
|
|
41810
|
-
|
|
41811
|
-
|
|
41812
|
-
responses = responses.concat(pendo._.map(questions,
|
|
41813
|
-
|
|
41814
|
-
|
|
41877
|
+
let allRequiredComplete = true;
|
|
41878
|
+
let responses = [];
|
|
41879
|
+
responses = responses.concat(pendo._.map(questions, (question) => {
|
|
41880
|
+
let pollId = question.getAttribute('data-pendo-poll-id');
|
|
41881
|
+
let input = step.guideElement.find(`
|
|
41882
|
+
[data-pendo-poll-id=${pollId}] textarea,
|
|
41883
|
+
[data-pendo-poll-id=${pollId}] input:text,
|
|
41884
|
+
[data-pendo-poll-id=${pollId}] select,
|
|
41885
|
+
[data-pendo-poll-id=${pollId}] input:radio:checked`);
|
|
41815
41886
|
if (input && input.length && input[0].value) {
|
|
41816
41887
|
return input[0].value;
|
|
41817
41888
|
}
|
|
@@ -41828,50 +41899,50 @@ var RequiredQuestions = {
|
|
|
41828
41899
|
}
|
|
41829
41900
|
function disableEligibleButtons(buttons) {
|
|
41830
41901
|
pendo._.each(buttons, function (button) {
|
|
41831
|
-
if (step.guideElement.find(
|
|
41832
|
-
step.guideElement.find(
|
|
41833
|
-
step.guideElement.find(
|
|
41902
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
41903
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = true;
|
|
41904
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = 'Please complete all required questions.';
|
|
41834
41905
|
}
|
|
41835
41906
|
});
|
|
41836
41907
|
}
|
|
41837
41908
|
function enableEligibleButtons(buttons) {
|
|
41838
41909
|
pendo._.each(buttons, function (button) {
|
|
41839
|
-
if (step.guideElement.find(
|
|
41840
|
-
step.guideElement.find(
|
|
41841
|
-
step.guideElement.find(
|
|
41910
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
41911
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = false;
|
|
41912
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = '';
|
|
41842
41913
|
}
|
|
41843
41914
|
});
|
|
41844
41915
|
}
|
|
41845
41916
|
},
|
|
41846
|
-
test
|
|
41917
|
+
test(step, guide, pendo) {
|
|
41847
41918
|
var _a, _b;
|
|
41848
|
-
|
|
41849
|
-
|
|
41919
|
+
const pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(`[class*=-poll-question]:contains(${requiredSyntax})`);
|
|
41920
|
+
const surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`);
|
|
41850
41921
|
return (!pendo._.isUndefined(pollQuestions) && pendo._.size(pollQuestions)) ||
|
|
41851
41922
|
(!pendo._.isUndefined(surveyQuestions) && pendo._.size(surveyQuestions));
|
|
41852
41923
|
},
|
|
41853
|
-
designerListener
|
|
41854
|
-
|
|
41855
|
-
|
|
41856
|
-
|
|
41924
|
+
designerListener(pendo) {
|
|
41925
|
+
const requiredQuestions = [];
|
|
41926
|
+
const target = pendo.dom.getBody();
|
|
41927
|
+
const config = {
|
|
41857
41928
|
attributeFilter: ['data-layout'],
|
|
41858
41929
|
attributes: true,
|
|
41859
41930
|
childList: true,
|
|
41860
41931
|
characterData: true,
|
|
41861
41932
|
subtree: true
|
|
41862
41933
|
};
|
|
41863
|
-
|
|
41864
|
-
|
|
41934
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41935
|
+
const observer = new MutationObserver(applyRequiredIndicators);
|
|
41865
41936
|
observer.observe(target, config);
|
|
41866
41937
|
function applyRequiredIndicators(mutations) {
|
|
41867
41938
|
pendo._.each(mutations, function (mutation) {
|
|
41868
41939
|
var _a;
|
|
41869
|
-
|
|
41940
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
41870
41941
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41871
|
-
|
|
41942
|
+
let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
|
|
41872
41943
|
if (eligiblePolls) {
|
|
41873
41944
|
pendo._.each(eligiblePolls, function (poll) {
|
|
41874
|
-
|
|
41945
|
+
let dataPendoPollId;
|
|
41875
41946
|
if (poll.classList.contains('_pendo-open-text-poll-wrapper') ||
|
|
41876
41947
|
poll.classList.contains('_pendo-number-scale-poll-wrapper')) {
|
|
41877
41948
|
dataPendoPollId = poll.getAttribute('name');
|
|
@@ -41879,31 +41950,31 @@ var RequiredQuestions = {
|
|
|
41879
41950
|
else {
|
|
41880
41951
|
dataPendoPollId = poll.getAttribute('data-pendo-poll-id');
|
|
41881
41952
|
}
|
|
41882
|
-
|
|
41883
|
-
|
|
41884
|
-
pendo.dom(
|
|
41953
|
+
let questionText;
|
|
41954
|
+
const questionElement = pendo.dom(`[class*="-poll-question"][data-pendo-poll-id=${dataPendoPollId}]`)[0] ||
|
|
41955
|
+
pendo.dom(`.bb-text[data-pendo-poll-id=${dataPendoPollId}]`)[0];
|
|
41885
41956
|
if (questionElement) {
|
|
41886
41957
|
questionText = questionElement.textContent;
|
|
41887
41958
|
}
|
|
41888
|
-
|
|
41959
|
+
const requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
|
|
41889
41960
|
if (requiredSyntaxIndex > -1) {
|
|
41890
|
-
pendo._.each(pendo.dom(
|
|
41891
|
-
pendo._.each(pendo.dom(
|
|
41961
|
+
pendo._.each(pendo.dom(`[data-pendo-poll-id=${dataPendoPollId}]:not(.pendo-radio)`), (element) => {
|
|
41962
|
+
pendo._.each(pendo.dom(`#${element.id} *:not(".pendo-radio"), #${element.id}:not(".pendo-radio")`), (item) => {
|
|
41892
41963
|
guideMarkdownUtil.removeMarkdownSyntax(item, requiredSyntax, '', pendo);
|
|
41893
41964
|
});
|
|
41894
41965
|
});
|
|
41895
|
-
|
|
41896
|
-
|
|
41897
|
-
|
|
41898
|
-
|
|
41899
|
-
pendo._.each(pendo.dom(
|
|
41900
|
-
pendo._.each(el.childNodes,
|
|
41966
|
+
const pollTextSelector = `.bb-text[data-pendo-poll-id=${dataPendoPollId}]`;
|
|
41967
|
+
const pollParagraphSelector = `${pollTextSelector} p`;
|
|
41968
|
+
const pollListItemSelector = `${pollTextSelector} li`;
|
|
41969
|
+
const pollIndicatorSelector = `${pollTextSelector} ._pendo-required-indicator`;
|
|
41970
|
+
pendo._.each(pendo.dom(`${pollParagraphSelector}, ${pollListItemSelector}`), (el) => {
|
|
41971
|
+
pendo._.each(el.childNodes, (node) => {
|
|
41901
41972
|
if (node.nodeType === 3 && node.nodeValue.indexOf(requiredSyntax) !== -1) {
|
|
41902
41973
|
node.nodeValue = node.nodeValue.split(requiredSyntax).join('');
|
|
41903
41974
|
}
|
|
41904
41975
|
});
|
|
41905
41976
|
});
|
|
41906
|
-
|
|
41977
|
+
const hasIndicator = pendo.dom(pollIndicatorSelector).length !== 0;
|
|
41907
41978
|
if (!hasIndicator) {
|
|
41908
41979
|
if (pendo.dom(pollParagraphSelector).length !== 0 || pendo.dom(pollListItemSelector).length !== 0) {
|
|
41909
41980
|
pendo.dom(pollParagraphSelector).append(requiredElement);
|
|
@@ -41914,7 +41985,7 @@ var RequiredQuestions = {
|
|
|
41914
41985
|
}
|
|
41915
41986
|
}
|
|
41916
41987
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
41917
|
-
|
|
41988
|
+
let questionIndex = requiredQuestions.indexOf(dataPendoPollId);
|
|
41918
41989
|
if (questionIndex !== -1) {
|
|
41919
41990
|
requiredQuestions.splice(questionIndex, 1);
|
|
41920
41991
|
}
|
|
@@ -41925,7 +41996,7 @@ var RequiredQuestions = {
|
|
|
41925
41996
|
}
|
|
41926
41997
|
else {
|
|
41927
41998
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
41928
|
-
|
|
41999
|
+
let index = requiredQuestions.indexOf(dataPendoPollId);
|
|
41929
42000
|
if (index !== -1) {
|
|
41930
42001
|
requiredQuestions.splice(index, 1);
|
|
41931
42002
|
}
|
|
@@ -41939,54 +42010,54 @@ var RequiredQuestions = {
|
|
|
41939
42010
|
}
|
|
41940
42011
|
};
|
|
41941
42012
|
|
|
41942
|
-
|
|
41943
|
-
|
|
41944
|
-
script
|
|
41945
|
-
|
|
41946
|
-
|
|
41947
|
-
|
|
41948
|
-
|
|
41949
|
-
|
|
42013
|
+
const skipStepRegex = new RegExp(guideMarkdownUtil.skipStepString);
|
|
42014
|
+
const SkipToEligibleStep = {
|
|
42015
|
+
script(step, guide, pendo) {
|
|
42016
|
+
let isAdvanceIntercepted = false;
|
|
42017
|
+
let isPreviousIntercepted = false;
|
|
42018
|
+
let guideContainer = step.guideElement.find(guideMarkdownUtil.containerSelector);
|
|
42019
|
+
let guideContainerAriaLabel = guideContainer.attr('aria-label');
|
|
42020
|
+
let stepNumberOrAuto = skipStepRegex.exec(guideContainerAriaLabel)[1];
|
|
41950
42021
|
if (guideContainer) {
|
|
41951
42022
|
guideContainer.attr({ 'aria-label': guideContainer.attr('aria-label').replace(skipStepRegex, '') });
|
|
41952
42023
|
}
|
|
41953
|
-
this.on('beforeAdvance',
|
|
42024
|
+
this.on('beforeAdvance', (evt) => {
|
|
41954
42025
|
if (guide.getPositionOfStep(step) === guide.steps.length || pendo._.isUndefined(stepNumberOrAuto))
|
|
41955
42026
|
return; // exit on the last step of a guide or when we don't have an argument
|
|
41956
|
-
|
|
42027
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'next');
|
|
41957
42028
|
if (!isAdvanceIntercepted && stepNumberOrAuto) {
|
|
41958
42029
|
isAdvanceIntercepted = true;
|
|
41959
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
42030
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
41960
42031
|
evt.cancel = true;
|
|
41961
42032
|
}
|
|
41962
42033
|
});
|
|
41963
|
-
this.on('beforePrevious',
|
|
42034
|
+
this.on('beforePrevious', (evt) => {
|
|
41964
42035
|
if (pendo._.isUndefined(stepNumberOrAuto))
|
|
41965
42036
|
return;
|
|
41966
|
-
|
|
42037
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'previous');
|
|
41967
42038
|
if (!isPreviousIntercepted && stepNumberOrAuto) {
|
|
41968
42039
|
isPreviousIntercepted = true;
|
|
41969
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
42040
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
41970
42041
|
evt.cancel = true;
|
|
41971
42042
|
}
|
|
41972
42043
|
});
|
|
41973
42044
|
function findEligibleSkipStep(stepNumber, direction) {
|
|
41974
42045
|
// Find the next eligible step by using getPosition of step (1 based)
|
|
41975
42046
|
// getPosition - 2 gives the previous step
|
|
41976
|
-
|
|
41977
|
-
|
|
42047
|
+
let skipForwardStep = findStepOnPage(guide.getPositionOfStep(step), 'next', stepNumber);
|
|
42048
|
+
let skipPreviousStep = findStepOnPage(guide.getPositionOfStep(step) - 2, 'previous', stepNumber);
|
|
41978
42049
|
if (skipForwardStep && direction == 'next') {
|
|
41979
|
-
pendo.goToStep({ destinationStepId: skipForwardStep, step
|
|
42050
|
+
pendo.goToStep({ destinationStepId: skipForwardStep, step });
|
|
41980
42051
|
}
|
|
41981
42052
|
if (skipPreviousStep && direction == 'previous') {
|
|
41982
|
-
pendo.goToStep({ destinationStepId: skipPreviousStep, step
|
|
42053
|
+
pendo.goToStep({ destinationStepId: skipPreviousStep, step });
|
|
41983
42054
|
}
|
|
41984
42055
|
return direction === 'next' ? skipForwardStep : skipPreviousStep;
|
|
41985
42056
|
}
|
|
41986
42057
|
function findStepOnPage(stepIndex, direction, stepNumber) {
|
|
41987
42058
|
if (pendo._.isNaN(stepIndex))
|
|
41988
42059
|
return;
|
|
41989
|
-
|
|
42060
|
+
let $step = guide.steps[stepIndex];
|
|
41990
42061
|
if ($step && !$step.canShow()) {
|
|
41991
42062
|
if (stepNumber !== 'auto') {
|
|
41992
42063
|
return guide.steps[stepNumber - 1];
|
|
@@ -42003,34 +42074,34 @@ var SkipToEligibleStep = {
|
|
|
42003
42074
|
}
|
|
42004
42075
|
}
|
|
42005
42076
|
},
|
|
42006
|
-
test
|
|
42077
|
+
test(step, guide, pendo) {
|
|
42007
42078
|
var _a;
|
|
42008
|
-
|
|
42079
|
+
const guideContainerAriaLabel = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(guideMarkdownUtil.containerSelector).attr('aria-label');
|
|
42009
42080
|
return pendo._.isString(guideContainerAriaLabel) && guideContainerAriaLabel.indexOf('{skipStep') !== -1;
|
|
42010
42081
|
},
|
|
42011
|
-
designerListener
|
|
42012
|
-
|
|
42013
|
-
|
|
42082
|
+
designerListener(pendo) {
|
|
42083
|
+
const target = pendo.dom.getBody();
|
|
42084
|
+
const config = {
|
|
42014
42085
|
attributeFilter: ['data-layout'],
|
|
42015
42086
|
attributes: true,
|
|
42016
42087
|
childList: true,
|
|
42017
42088
|
characterData: true,
|
|
42018
42089
|
subtree: true
|
|
42019
42090
|
};
|
|
42020
|
-
|
|
42021
|
-
|
|
42091
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42092
|
+
const observer = new MutationObserver(applySkipStepIndicator);
|
|
42022
42093
|
observer.observe(target, config);
|
|
42023
42094
|
// create an observer instance
|
|
42024
42095
|
function applySkipStepIndicator(mutations) {
|
|
42025
42096
|
pendo._.each(mutations, function (mutation) {
|
|
42026
42097
|
var _a, _b;
|
|
42027
|
-
|
|
42098
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
42028
42099
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
42029
|
-
|
|
42030
|
-
|
|
42100
|
+
let guideContainer = mutation.addedNodes[0].querySelectorAll(guideMarkdownUtil.containerSelector);
|
|
42101
|
+
let guideContainerAriaLabel = (_b = guideContainer[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label');
|
|
42031
42102
|
if (guideContainerAriaLabel) {
|
|
42032
42103
|
if (guideContainerAriaLabel.match(skipStepRegex)) {
|
|
42033
|
-
|
|
42104
|
+
let fullSkipStepString = guideContainerAriaLabel.match(skipStepRegex)[0];
|
|
42034
42105
|
guideContainerAriaLabel.replace(fullSkipStepString, '');
|
|
42035
42106
|
if (!pendo.dom('#_pendoSkipIcon').length) {
|
|
42036
42107
|
pendo.dom(guideMarkdownUtil.containerSelector).append(skipIcon('#999', '30px').trim());
|
|
@@ -42041,30 +42112,48 @@ var SkipToEligibleStep = {
|
|
|
42041
42112
|
});
|
|
42042
42113
|
}
|
|
42043
42114
|
function skipIcon(color, size) {
|
|
42044
|
-
return (
|
|
42115
|
+
return (`<div title="Skip step added"><svg id="_pendoSkipIcon" version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
42116
|
+
width="${size}" height="${size}" viewBox="0 0 512.000000 512.000000"
|
|
42117
|
+
preserveAspectRatio="xMidYMid meet" style="bottom:5px; right:10px; position: absolute;">
|
|
42118
|
+
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
|
|
42119
|
+
fill="${color}" stroke="none">
|
|
42120
|
+
<path d="M2185 4469 c-363 -38 -739 -186 -1034 -407 -95 -71 -273 -243 -357
|
|
42121
|
+
-343 -205 -246 -364 -577 -429 -897 -25 -121 -45 -288 -45 -373 l0 -49 160 0
|
|
42122
|
+
160 0 0 48 c0 26 5 88 10 137 68 593 417 1103 940 1374 1100 570 2418 -137
|
|
42123
|
+
2560 -1374 5 -49 10 -111 10 -137 l0 -47 -155 -3 -155 -3 235 -235 235 -236
|
|
42124
|
+
235 236 235 235 -155 3 -155 3 0 48 c0 27 -5 95 -10 152 -100 989 -878 1767
|
|
42125
|
+
-1869 1868 -117 12 -298 12 -416 0z"/>
|
|
42126
|
+
<path d="M320 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42127
|
+
<path d="M960 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42128
|
+
<path d="M1600 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42129
|
+
<path d="M2240 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42130
|
+
<path d="M2880 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42131
|
+
<path d="M3840 1440 l0 -160 480 0 480 0 0 160 0 160 -480 0 -480 0 0 -160z"/>
|
|
42132
|
+
</g></svg></div>
|
|
42133
|
+
`);
|
|
42045
42134
|
}
|
|
42046
42135
|
}
|
|
42047
42136
|
};
|
|
42048
42137
|
|
|
42049
42138
|
function GuideMarkdown() {
|
|
42050
|
-
|
|
42051
|
-
|
|
42052
|
-
|
|
42139
|
+
let guideMarkdown;
|
|
42140
|
+
let pluginApi;
|
|
42141
|
+
let globalPendo;
|
|
42053
42142
|
return {
|
|
42054
42143
|
name: 'GuideMarkdown',
|
|
42055
42144
|
initialize: init,
|
|
42056
|
-
teardown
|
|
42145
|
+
teardown
|
|
42057
42146
|
};
|
|
42058
42147
|
function init(pendo, PluginAPI) {
|
|
42059
42148
|
globalPendo = pendo;
|
|
42060
42149
|
pluginApi = PluginAPI;
|
|
42061
|
-
|
|
42062
|
-
|
|
42150
|
+
const configReader = PluginAPI.ConfigReader;
|
|
42151
|
+
const GUIDEMARKDOWN_CONFIG = 'guideMarkdown';
|
|
42063
42152
|
configReader.addOption(GUIDEMARKDOWN_CONFIG, [
|
|
42064
42153
|
configReader.sources.SNIPPET_SRC,
|
|
42065
42154
|
configReader.sources.PENDO_CONFIG_SRC
|
|
42066
42155
|
], false);
|
|
42067
|
-
|
|
42156
|
+
const markdownScriptsEnabled = configReader.get(GUIDEMARKDOWN_CONFIG);
|
|
42068
42157
|
if (!markdownScriptsEnabled)
|
|
42069
42158
|
return;
|
|
42070
42159
|
guideMarkdown = [PollBranching, MetadataSubstitution, RequiredQuestions, SkipToEligibleStep];
|
|
@@ -42093,7 +42182,27 @@ function GuideMarkdown() {
|
|
|
42093
42182
|
}
|
|
42094
42183
|
}
|
|
42095
42184
|
|
|
42096
|
-
|
|
42185
|
+
// Resolve the global object without relying on a bare `window` identifier.
|
|
42186
|
+
// `window` is only a bound global in a normal browser realm; when the agent is
|
|
42187
|
+
// loaded via the npm `loadAsModule` path (or inside a Web Worker) the module is
|
|
42188
|
+
// evaluated in a realm where `window` is undeclared, so referencing it bare
|
|
42189
|
+
// throws a ReferenceError at module-load. `globalThis` resolves in every realm.
|
|
42190
|
+
function getGlobalScope() {
|
|
42191
|
+
if (typeof globalThis !== 'undefined') {
|
|
42192
|
+
return globalThis;
|
|
42193
|
+
}
|
|
42194
|
+
if (typeof self !== 'undefined') {
|
|
42195
|
+
return self;
|
|
42196
|
+
}
|
|
42197
|
+
if (typeof window !== 'undefined') {
|
|
42198
|
+
return window;
|
|
42199
|
+
}
|
|
42200
|
+
return {};
|
|
42201
|
+
}
|
|
42202
|
+
|
|
42203
|
+
var globalScope = getGlobalScope();
|
|
42204
|
+
|
|
42205
|
+
var setTimeout = safeBind(globalScope.setTimeout, globalScope);
|
|
42097
42206
|
|
|
42098
42207
|
function safeBind(fn, scope) {
|
|
42099
42208
|
if (typeof fn.bind === 'function') {
|
|
@@ -42116,7 +42225,7 @@ setTimeout = (function(global) {
|
|
|
42116
42225
|
}
|
|
42117
42226
|
|
|
42118
42227
|
return getZoneSafeMethod('setTimeout');
|
|
42119
|
-
})(
|
|
42228
|
+
})(globalScope);
|
|
42120
42229
|
|
|
42121
42230
|
var setTimeout$1 = setTimeout;
|
|
42122
42231
|
|
|
@@ -42993,22 +43102,22 @@ const startListening = (
|
|
|
42993
43102
|
};
|
|
42994
43103
|
|
|
42995
43104
|
function VocPortal() {
|
|
42996
|
-
|
|
42997
|
-
|
|
43105
|
+
let pendoGlobal;
|
|
43106
|
+
let pluginAPI;
|
|
42998
43107
|
return {
|
|
42999
43108
|
name: 'VocPortal',
|
|
43000
|
-
initialize
|
|
43001
|
-
routeHandlerLookup
|
|
43002
|
-
queryMessageHandler
|
|
43003
|
-
resizeMessageHandler
|
|
43004
|
-
teardown
|
|
43109
|
+
initialize,
|
|
43110
|
+
routeHandlerLookup,
|
|
43111
|
+
queryMessageHandler,
|
|
43112
|
+
resizeMessageHandler,
|
|
43113
|
+
teardown
|
|
43005
43114
|
};
|
|
43006
43115
|
function initialize(pendo, PluginAPI) {
|
|
43007
43116
|
pendoGlobal = pendo;
|
|
43008
43117
|
pluginAPI = PluginAPI;
|
|
43009
|
-
|
|
43118
|
+
const { frameId } = PluginAPI.EventTracer.addTracerIds({});
|
|
43010
43119
|
this.removeResizeEvent = pendoGlobal.attachEvent(window, 'resize', resizePortalIframe);
|
|
43011
|
-
startListening('VocPortal', frameId, routeHandlerLookup,
|
|
43120
|
+
startListening('VocPortal', frameId, routeHandlerLookup, () => '*');
|
|
43012
43121
|
}
|
|
43013
43122
|
function routeHandlerLookup(path) {
|
|
43014
43123
|
switch (path) {
|
|
@@ -43021,14 +43130,14 @@ function VocPortal() {
|
|
|
43021
43130
|
}
|
|
43022
43131
|
}
|
|
43023
43132
|
function resizePortalIframe() {
|
|
43024
|
-
|
|
43025
|
-
|
|
43133
|
+
const vocPortalRcContainer = document.getElementById('pendo-resource-center-container');
|
|
43134
|
+
const vocPortalRcDOM = pendoGlobal.dom(vocPortalRcContainer);
|
|
43026
43135
|
pluginAPI.sizeElements(vocPortalRcDOM);
|
|
43027
43136
|
}
|
|
43028
43137
|
function queryMessageHandler(_, responseHandler) {
|
|
43029
|
-
|
|
43030
|
-
|
|
43031
|
-
|
|
43138
|
+
const metadata = pendoGlobal.getSerializedMetadata();
|
|
43139
|
+
const sandBoxMode = !!pendoGlobal.designer || pluginAPI.store.getters['preview/isInPreviewMode']();
|
|
43140
|
+
const response = {
|
|
43032
43141
|
apiKey: pendoGlobal.apiKey,
|
|
43033
43142
|
url: pendoGlobal.url.externalizeURL(),
|
|
43034
43143
|
visitor: metadata.visitor,
|
|
@@ -43042,19 +43151,26 @@ function VocPortal() {
|
|
|
43042
43151
|
}
|
|
43043
43152
|
function resizeMessageHandler(msg) {
|
|
43044
43153
|
try {
|
|
43045
|
-
|
|
43046
|
-
|
|
43154
|
+
const { 'value': widthValue, 'unit': widthUnit, 'isImportant': widthIsImportant } = msg.data.width;
|
|
43155
|
+
const { 'value': heightValue, 'unit': heightUnit, 'isImportant': heightIsImportant } = msg.data.height;
|
|
43047
43156
|
if (typeof widthValue !== 'number' || typeof heightValue !== 'number') {
|
|
43048
43157
|
return;
|
|
43049
43158
|
}
|
|
43050
|
-
|
|
43159
|
+
const validUnits = ['px', '%', 'vh', 'vw'];
|
|
43051
43160
|
if (!pendoGlobal._.contains(validUnits, widthUnit) || !pendoGlobal._.contains(validUnits, heightUnit)) {
|
|
43052
43161
|
return;
|
|
43053
43162
|
}
|
|
43054
|
-
|
|
43055
|
-
|
|
43056
|
-
|
|
43057
|
-
pluginAPI.util.addInlineStyles('pendo-voc-portal-styles',
|
|
43163
|
+
const width = `${widthValue}${widthUnit}${widthIsImportant ? ' !important' : ''}`;
|
|
43164
|
+
const height = `${heightValue}${heightUnit}${heightIsImportant ? ' !important' : ''}`;
|
|
43165
|
+
const container = document.getElementById('pendo-resource-center-container');
|
|
43166
|
+
pluginAPI.util.addInlineStyles('pendo-voc-portal-styles', `#pendo-resource-center-container:has(iframe[src*="portal"][src*="mode=rc"]) {
|
|
43167
|
+
width: ${width};
|
|
43168
|
+
height: ${height};
|
|
43169
|
+
._pendo-step-container-size {
|
|
43170
|
+
width: ${width};
|
|
43171
|
+
height: ${height};
|
|
43172
|
+
}
|
|
43173
|
+
}`, container);
|
|
43058
43174
|
resizePortalIframe();
|
|
43059
43175
|
clampContainerToViewport(container);
|
|
43060
43176
|
}
|
|
@@ -43065,10 +43181,10 @@ function VocPortal() {
|
|
|
43065
43181
|
function clampContainerToViewport(container) {
|
|
43066
43182
|
if (!container)
|
|
43067
43183
|
return;
|
|
43068
|
-
|
|
43069
|
-
|
|
43184
|
+
const leftPadding = 10;
|
|
43185
|
+
const rect = container.getBoundingClientRect();
|
|
43070
43186
|
if (rect.left < leftPadding) {
|
|
43071
|
-
container.style.transform =
|
|
43187
|
+
container.style.transform = `translateX(${leftPadding - rect.left}px)`;
|
|
43072
43188
|
}
|
|
43073
43189
|
else {
|
|
43074
43190
|
container.style.transform = '';
|
|
@@ -43096,8 +43212,8 @@ function Feedback() {
|
|
|
43096
43212
|
var widgetLoaded = false;
|
|
43097
43213
|
var feedbackAllowedProductId = '';
|
|
43098
43214
|
var initialized = false;
|
|
43099
|
-
|
|
43100
|
-
|
|
43215
|
+
const PING_COOKIE = 'feedback_ping_sent';
|
|
43216
|
+
const PING_COOKIE_EXPIRATION = 1000 * 60 * 60;
|
|
43101
43217
|
var overflowMediaQuery = '@media only screen and (max-device-width:1112px){#feedback-widget{overflow-y:scroll}}';
|
|
43102
43218
|
var slideIn = '@-webkit-keyframes pendoFeedbackSlideIn{from{opacity:0;transform:translate(145px,0) rotate(270deg) translateY(-50%)}to{opacity:1;transform:translate(50%,0) rotate(270deg) translateY(-50%)}}@keyframes pendoFeedbackSlideIn{from{opacity:0;transform:translate(145px,0) rotate(270deg) translateY(-50%)}to{opacity:1;transform:translate(50%,0) rotate(270deg) translateY(-50%)}}';
|
|
43103
43219
|
var slideInLeft = '@-webkit-keyframes pendoFeedbackSlideIn-left{from{opacity:0;transform:rotate(270deg) translateX(-55%) translateY(-55%)}to{opacity:1;transform:rotate(270deg) translateX(-55%) translateY(0)}}@keyframes pendoFeedbackSlideIn-left{from{opacity:0;transform:rotate(270deg) translateX(-55%) translateY(-55%)}to{opacity:1;transform:rotate(270deg) translateX(-55%) translateY(0)}}';
|
|
@@ -43117,28 +43233,28 @@ function Feedback() {
|
|
|
43117
43233
|
feedbackStyles: 'pendo-feedback-styles',
|
|
43118
43234
|
feedbackFrameStyles: 'pendo-feedback-visible-buttons-styles'
|
|
43119
43235
|
};
|
|
43120
|
-
|
|
43121
|
-
|
|
43236
|
+
let globalPendo;
|
|
43237
|
+
let pluginApi;
|
|
43122
43238
|
return {
|
|
43123
43239
|
name: 'Feedback',
|
|
43124
|
-
initialize
|
|
43125
|
-
teardown
|
|
43126
|
-
validate
|
|
43240
|
+
initialize,
|
|
43241
|
+
teardown,
|
|
43242
|
+
validate
|
|
43127
43243
|
};
|
|
43128
43244
|
function initialize(pendo, PluginAPI) {
|
|
43129
43245
|
globalPendo = pendo;
|
|
43130
43246
|
pluginApi = PluginAPI;
|
|
43131
43247
|
var publicFeedback = {
|
|
43132
|
-
ping
|
|
43133
|
-
init
|
|
43248
|
+
ping,
|
|
43249
|
+
init,
|
|
43134
43250
|
initialized: getInitialized,
|
|
43135
|
-
loginAndRedirect
|
|
43136
|
-
openFeedback
|
|
43137
|
-
initializeFeedbackOnce
|
|
43138
|
-
isFeedbackLoaded
|
|
43139
|
-
convertPendoToFeedbackOptions
|
|
43251
|
+
loginAndRedirect,
|
|
43252
|
+
openFeedback,
|
|
43253
|
+
initializeFeedbackOnce,
|
|
43254
|
+
isFeedbackLoaded,
|
|
43255
|
+
convertPendoToFeedbackOptions,
|
|
43140
43256
|
isUnsupportedIE: pendo._.partial(isUnsupportedIE, PluginAPI),
|
|
43141
|
-
removeFeedbackWidget
|
|
43257
|
+
removeFeedbackWidget
|
|
43142
43258
|
};
|
|
43143
43259
|
pendo.feedback = publicFeedback;
|
|
43144
43260
|
pendo.getFeedbackSettings = getFeedbackSettings;
|
|
@@ -43169,7 +43285,7 @@ function Feedback() {
|
|
|
43169
43285
|
localStorageOnly: true
|
|
43170
43286
|
});
|
|
43171
43287
|
return {
|
|
43172
|
-
validate
|
|
43288
|
+
validate
|
|
43173
43289
|
};
|
|
43174
43290
|
}
|
|
43175
43291
|
function teardown() {
|
|
@@ -43189,18 +43305,18 @@ function Feedback() {
|
|
|
43189
43305
|
return result;
|
|
43190
43306
|
}
|
|
43191
43307
|
function pingOrInitialize() {
|
|
43192
|
-
|
|
43308
|
+
const options = getPendoOptions();
|
|
43193
43309
|
if (initialized) {
|
|
43194
|
-
|
|
43310
|
+
const feedbackOptions = convertPendoToFeedbackOptions(options);
|
|
43195
43311
|
ping(feedbackOptions);
|
|
43196
43312
|
}
|
|
43197
43313
|
else if (shouldInitializeFeedback() && !globalPendo._.isEmpty(options)) {
|
|
43198
|
-
|
|
43199
|
-
init(options, settings)
|
|
43314
|
+
const settings = pluginApi.ConfigReader.get('feedbackSettings');
|
|
43315
|
+
init(options, settings).catch(globalPendo._.noop);
|
|
43200
43316
|
}
|
|
43201
43317
|
}
|
|
43202
43318
|
function handleIdentityChange(event) {
|
|
43203
|
-
|
|
43319
|
+
const visitorId = globalPendo._.get(event, 'data.0.visitor_id') || globalPendo._.get(event, 'data.0.options.visitor.id');
|
|
43204
43320
|
if (globalPendo.isAnonymousVisitor(visitorId)) {
|
|
43205
43321
|
removeFeedbackWidget();
|
|
43206
43322
|
return;
|
|
@@ -43270,9 +43386,9 @@ function Feedback() {
|
|
|
43270
43386
|
if (toSend.data && toSend.data !== '{}' && toSend.data !== 'null') {
|
|
43271
43387
|
return globalPendo.ajax
|
|
43272
43388
|
.postJSON(getFullUrl('/widget/pendo_ping'), toSend)
|
|
43273
|
-
.then(
|
|
43389
|
+
.then((response) => {
|
|
43274
43390
|
onWidgetPingResponse(response);
|
|
43275
|
-
})
|
|
43391
|
+
}).catch(() => { onPingFailure(); });
|
|
43276
43392
|
}
|
|
43277
43393
|
}
|
|
43278
43394
|
return pluginApi.q.resolve();
|
|
@@ -43406,10 +43522,10 @@ function Feedback() {
|
|
|
43406
43522
|
return globalPendo.ajax.postJSON(getFullUrl('/analytics'), toSend);
|
|
43407
43523
|
}
|
|
43408
43524
|
function addOverlay() {
|
|
43409
|
-
|
|
43525
|
+
const widget = globalPendo.dom(`#${elemIds.feedbackWidget}`);
|
|
43410
43526
|
if (!widget)
|
|
43411
43527
|
return;
|
|
43412
|
-
|
|
43528
|
+
const overlayStyles = {
|
|
43413
43529
|
'position': 'fixed',
|
|
43414
43530
|
'top': '0',
|
|
43415
43531
|
'right': '0',
|
|
@@ -43421,7 +43537,7 @@ function Feedback() {
|
|
|
43421
43537
|
'animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both',
|
|
43422
43538
|
'-webkit-animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both'
|
|
43423
43539
|
};
|
|
43424
|
-
|
|
43540
|
+
const overlayElement = globalPendo.dom(document.createElement('div'));
|
|
43425
43541
|
overlayElement.attr('id', 'feedback-overlay');
|
|
43426
43542
|
overlayElement.css(overlayStyles);
|
|
43427
43543
|
overlayElement.appendTo(widget.getParent());
|
|
@@ -43526,22 +43642,22 @@ function Feedback() {
|
|
|
43526
43642
|
}
|
|
43527
43643
|
}
|
|
43528
43644
|
function buildOuterTriggerDiv(positionInfo) {
|
|
43529
|
-
|
|
43530
|
-
|
|
43531
|
-
|
|
43645
|
+
const horizontalStyles = getHorizontalPositionStyles(positionInfo);
|
|
43646
|
+
const verticalStyles = getVerticalPositionStyles(positionInfo);
|
|
43647
|
+
const styles = globalPendo._.extend({
|
|
43532
43648
|
'position': 'fixed',
|
|
43533
43649
|
'height': '43px',
|
|
43534
43650
|
'opacity': '1 !important',
|
|
43535
43651
|
'z-index': '9001'
|
|
43536
43652
|
}, horizontalStyles, verticalStyles);
|
|
43537
|
-
|
|
43653
|
+
const outerTrigger = globalPendo.dom(document.createElement('div'));
|
|
43538
43654
|
outerTrigger.attr('id', elemIds.feedbackTrigger);
|
|
43539
43655
|
outerTrigger.css(styles);
|
|
43540
43656
|
outerTrigger.attr('data-turbolinks-permanent', '');
|
|
43541
43657
|
return outerTrigger;
|
|
43542
43658
|
}
|
|
43543
43659
|
function buildNotification() {
|
|
43544
|
-
|
|
43660
|
+
const styles = {
|
|
43545
43661
|
'background-color': '#D85039',
|
|
43546
43662
|
'color': '#fff',
|
|
43547
43663
|
'border-radius': '50%',
|
|
@@ -43558,20 +43674,20 @@ function Feedback() {
|
|
|
43558
43674
|
'animation-delay': '1s',
|
|
43559
43675
|
'animation-iteration-count': '1'
|
|
43560
43676
|
};
|
|
43561
|
-
|
|
43677
|
+
const notification = globalPendo.dom(document.createElement('span'));
|
|
43562
43678
|
notification.attr('id', 'feedback-trigger-notification');
|
|
43563
43679
|
notification.css(styles);
|
|
43564
43680
|
return notification;
|
|
43565
43681
|
}
|
|
43566
43682
|
function buildTriggerButton(settings, positionInfo) {
|
|
43567
|
-
|
|
43683
|
+
let borderRadius;
|
|
43568
43684
|
if (positionInfo.horizontalPosition === 'left') {
|
|
43569
43685
|
borderRadius = '0 0 5px 5px';
|
|
43570
43686
|
}
|
|
43571
43687
|
else {
|
|
43572
43688
|
borderRadius = '3px 3px 0 0';
|
|
43573
43689
|
}
|
|
43574
|
-
|
|
43690
|
+
const styles = {
|
|
43575
43691
|
'border': 'none',
|
|
43576
43692
|
'padding': '11px 18px 14px 18px',
|
|
43577
43693
|
'background-color': settings.triggerColor,
|
|
@@ -43582,21 +43698,32 @@ function Feedback() {
|
|
|
43582
43698
|
'cursor': 'pointer',
|
|
43583
43699
|
'text-align': 'left'
|
|
43584
43700
|
};
|
|
43585
|
-
|
|
43701
|
+
const triggerButton = globalPendo.dom(document.createElement('button'));
|
|
43586
43702
|
triggerButton.attr('id', elemIds.feedbackTriggerButton);
|
|
43587
43703
|
triggerButton.css(styles);
|
|
43588
43704
|
triggerButton.text(settings.triggerText);
|
|
43589
43705
|
return triggerButton;
|
|
43590
43706
|
}
|
|
43591
43707
|
function addTriggerPseudoStyles() {
|
|
43592
|
-
|
|
43708
|
+
const pseudoStyles = `
|
|
43709
|
+
#feedback-trigger button:hover {
|
|
43710
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
43711
|
+
outline: none !important;
|
|
43712
|
+
background: #3e566f !important;
|
|
43713
|
+
}
|
|
43714
|
+
#feedback-trigger button:focus {
|
|
43715
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
43716
|
+
outline: none !important;
|
|
43717
|
+
background: #3e566f !important;
|
|
43718
|
+
}
|
|
43719
|
+
`;
|
|
43593
43720
|
pluginApi.util.addInlineStyles('pendo-feedback-trigger-styles', pseudoStyles);
|
|
43594
43721
|
}
|
|
43595
43722
|
function createTrigger(settings, positionInfo) {
|
|
43596
43723
|
addTriggerPseudoStyles();
|
|
43597
|
-
|
|
43598
|
-
|
|
43599
|
-
|
|
43724
|
+
const triggerElement = buildOuterTriggerDiv(positionInfo);
|
|
43725
|
+
const notificationElement = buildNotification();
|
|
43726
|
+
const triggerButtonElement = buildTriggerButton(settings, positionInfo);
|
|
43600
43727
|
triggerElement.append(notificationElement);
|
|
43601
43728
|
triggerElement.append(triggerButtonElement);
|
|
43602
43729
|
triggerElement.appendTo(globalPendo.dom.getBody());
|
|
@@ -43620,7 +43747,7 @@ function Feedback() {
|
|
|
43620
43747
|
iframeWrapper.css(getWidgetOriginalStyles());
|
|
43621
43748
|
iframeWrapper.attr('id', elemIds.feedbackWidget);
|
|
43622
43749
|
iframeWrapper.attr('data-turbolinks-permanent', 'true');
|
|
43623
|
-
iframeWrapper.addClass(
|
|
43750
|
+
iframeWrapper.addClass(`buttonIs-${horizontalPosition}`);
|
|
43624
43751
|
return iframeWrapper;
|
|
43625
43752
|
}
|
|
43626
43753
|
function buildIframeContainer() {
|
|
@@ -43637,13 +43764,22 @@ function Feedback() {
|
|
|
43637
43764
|
return iframeContainer;
|
|
43638
43765
|
}
|
|
43639
43766
|
function addWidgetVisibleButtonStyles(buttonStylePosition) {
|
|
43640
|
-
|
|
43641
|
-
|
|
43767
|
+
let side = buttonStylePosition === 'left' ? 'left' : 'right'; // just in case something was not left or right for some reason
|
|
43768
|
+
const styles = `
|
|
43769
|
+
.buttonIs-${side}.visible {
|
|
43770
|
+
${side}: 0 !important;
|
|
43771
|
+
width: 470px !important;
|
|
43772
|
+
animation-direction: alternate-reverse !important;
|
|
43773
|
+
animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
43774
|
+
-webkit-animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
43775
|
+
z-index: 9002 !important;
|
|
43776
|
+
}
|
|
43777
|
+
`;
|
|
43642
43778
|
pluginApi.util.addInlineStyles(elemIds.feedbackFrameStyles, styles);
|
|
43643
43779
|
}
|
|
43644
43780
|
function initialiseWidgetFrame(horizontalPosition) {
|
|
43645
43781
|
addWidgetVisibleButtonStyles(horizontalPosition);
|
|
43646
|
-
|
|
43782
|
+
const iframeElement = buildIframeWrapper(horizontalPosition);
|
|
43647
43783
|
iframeElement.append(buildIframeContainer());
|
|
43648
43784
|
iframeElement.appendTo(globalPendo.dom.getBody());
|
|
43649
43785
|
subscribeToIframeMessages();
|
|
@@ -43667,7 +43803,7 @@ function Feedback() {
|
|
|
43667
43803
|
return widgetLoaded;
|
|
43668
43804
|
}
|
|
43669
43805
|
function getPendoOptions() {
|
|
43670
|
-
|
|
43806
|
+
let options = pluginApi.ConfigReader.getLocalConfig();
|
|
43671
43807
|
if (!globalPendo._.isObject(options))
|
|
43672
43808
|
options = {};
|
|
43673
43809
|
if (!globalPendo._.isObject(options.visitor))
|
|
@@ -43695,7 +43831,7 @@ function Feedback() {
|
|
|
43695
43831
|
return true;
|
|
43696
43832
|
}
|
|
43697
43833
|
function getQueryParam(url, paramName) {
|
|
43698
|
-
|
|
43834
|
+
const results = new RegExp('[?&]' + paramName + '=([^&#]*)').exec(url);
|
|
43699
43835
|
if (results == null) {
|
|
43700
43836
|
return null;
|
|
43701
43837
|
}
|
|
@@ -43712,13 +43848,13 @@ function Feedback() {
|
|
|
43712
43848
|
return pluginApi.q.reject();
|
|
43713
43849
|
if (!canInitFeedback(pendoOptions))
|
|
43714
43850
|
return pluginApi.q.reject();
|
|
43715
|
-
|
|
43851
|
+
const feedbackOptions = convertPendoToFeedbackOptions(pendoOptions);
|
|
43716
43852
|
try {
|
|
43717
|
-
|
|
43718
|
-
if (
|
|
43853
|
+
const fdbkDst = getQueryParam(globalPendo.url.get(), 'fdbkDst');
|
|
43854
|
+
if (fdbkDst && fdbkDst.startsWith('case')) {
|
|
43719
43855
|
initialized = true;
|
|
43720
43856
|
getFeedbackLoginUrl().then(function (loginUrl) {
|
|
43721
|
-
|
|
43857
|
+
const destinationUrl = loginUrl + '&fdbkDst=' + fdbkDst;
|
|
43722
43858
|
window.location.href = destinationUrl;
|
|
43723
43859
|
});
|
|
43724
43860
|
return;
|
|
@@ -43767,7 +43903,7 @@ function Feedback() {
|
|
|
43767
43903
|
function convertPendoToFeedbackOptions(options) {
|
|
43768
43904
|
var jwtOptions = pluginApi.agent.getJwtInfoCopy();
|
|
43769
43905
|
if (globalPendo._.isEmpty(jwtOptions)) {
|
|
43770
|
-
|
|
43906
|
+
const feedbackOptions = {};
|
|
43771
43907
|
feedbackOptions.user = globalPendo._.pick(options.visitor, 'id', 'full_name', 'firstName', 'lastName', 'email', 'tags', 'custom_allowed_products');
|
|
43772
43908
|
globalPendo._.extend(feedbackOptions.user, { allowed_products: [{ id: feedbackAllowedProductId }] });
|
|
43773
43909
|
feedbackOptions.account = globalPendo._.pick(options.account, 'id', 'name', 'monthly_value', 'is_paying', 'tags');
|
|
@@ -49302,72 +49438,6 @@ var n;
|
|
|
49302
49438
|
}(n || (n = {}));
|
|
49303
49439
|
return record; }
|
|
49304
49440
|
|
|
49305
|
-
var __assign = function() {
|
|
49306
|
-
__assign = Object.assign || function __assign(t) {
|
|
49307
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
49308
|
-
s = arguments[i];
|
|
49309
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
49310
|
-
}
|
|
49311
|
-
return t;
|
|
49312
|
-
};
|
|
49313
|
-
return __assign.apply(this, arguments);
|
|
49314
|
-
};
|
|
49315
|
-
|
|
49316
|
-
function __rest(s, e) {
|
|
49317
|
-
var t = {};
|
|
49318
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
49319
|
-
t[p] = s[p];
|
|
49320
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
49321
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
49322
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
49323
|
-
t[p[i]] = s[p[i]];
|
|
49324
|
-
}
|
|
49325
|
-
return t;
|
|
49326
|
-
}
|
|
49327
|
-
|
|
49328
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
49329
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
49330
|
-
return new (P || (P = Promise$2))(function (resolve, reject) {
|
|
49331
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
49332
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
49333
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
49334
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
49335
|
-
});
|
|
49336
|
-
}
|
|
49337
|
-
|
|
49338
|
-
function __generator(thisArg, body) {
|
|
49339
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
49340
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
49341
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49342
|
-
function step(op) {
|
|
49343
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
49344
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
49345
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
49346
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
49347
|
-
switch (op[0]) {
|
|
49348
|
-
case 0: case 1: t = op; break;
|
|
49349
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
49350
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
49351
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
49352
|
-
default:
|
|
49353
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
49354
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
49355
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
49356
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
49357
|
-
if (t[2]) _.ops.pop();
|
|
49358
|
-
_.trys.pop(); continue;
|
|
49359
|
-
}
|
|
49360
|
-
op = body.call(thisArg, _);
|
|
49361
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49362
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
49363
|
-
}
|
|
49364
|
-
}
|
|
49365
|
-
|
|
49366
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
49367
|
-
var e = new Error(message);
|
|
49368
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
49369
|
-
};
|
|
49370
|
-
|
|
49371
49441
|
var SessionRecorderBuffer = /** @class */ (function () {
|
|
49372
49442
|
function SessionRecorderBuffer(interval, maxCount) {
|
|
49373
49443
|
if (maxCount === void 0) { maxCount = Infinity; }
|
|
@@ -49423,6 +49493,61 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49423
49493
|
return SessionRecorderBuffer;
|
|
49424
49494
|
}());
|
|
49425
49495
|
|
|
49496
|
+
function __rest(s, e) {
|
|
49497
|
+
var t = {};
|
|
49498
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
49499
|
+
t[p] = s[p];
|
|
49500
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
49501
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
49502
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
49503
|
+
t[p[i]] = s[p[i]];
|
|
49504
|
+
}
|
|
49505
|
+
return t;
|
|
49506
|
+
}
|
|
49507
|
+
|
|
49508
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
49509
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
49510
|
+
return new (P || (P = Promise$2))(function (resolve, reject) {
|
|
49511
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
49512
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
49513
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
49514
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
49515
|
+
});
|
|
49516
|
+
}
|
|
49517
|
+
|
|
49518
|
+
function __generator(thisArg, body) {
|
|
49519
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
49520
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
49521
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49522
|
+
function step(op) {
|
|
49523
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
49524
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
49525
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
49526
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
49527
|
+
switch (op[0]) {
|
|
49528
|
+
case 0: case 1: t = op; break;
|
|
49529
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
49530
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
49531
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
49532
|
+
default:
|
|
49533
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
49534
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
49535
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
49536
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
49537
|
+
if (t[2]) _.ops.pop();
|
|
49538
|
+
_.trys.pop(); continue;
|
|
49539
|
+
}
|
|
49540
|
+
op = body.call(thisArg, _);
|
|
49541
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49542
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
49543
|
+
}
|
|
49544
|
+
}
|
|
49545
|
+
|
|
49546
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
49547
|
+
var e = new Error(message);
|
|
49548
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
49549
|
+
};
|
|
49550
|
+
|
|
49426
49551
|
var RECORDING_CONFIG_WORKERURL$1 = 'recording.workerUrl';
|
|
49427
49552
|
var MAX_SIZE = 2000000;
|
|
49428
49553
|
var RESOURCE_CACHING$1 = 'resourceCaching';
|
|
@@ -49659,33 +49784,33 @@ function maskText(options, text, element) {
|
|
|
49659
49784
|
return text;
|
|
49660
49785
|
}
|
|
49661
49786
|
|
|
49662
|
-
|
|
49663
|
-
|
|
49664
|
-
|
|
49665
|
-
|
|
49666
|
-
|
|
49667
|
-
|
|
49668
|
-
|
|
49669
|
-
|
|
49670
|
-
|
|
49671
|
-
|
|
49672
|
-
|
|
49673
|
-
|
|
49674
|
-
|
|
49675
|
-
|
|
49676
|
-
|
|
49677
|
-
|
|
49678
|
-
|
|
49679
|
-
|
|
49680
|
-
|
|
49787
|
+
const RECORDING_CONFIG = 'recording';
|
|
49788
|
+
const RECORDING_CONFIG_ENABLED = 'recording.enabled';
|
|
49789
|
+
const RECORDING_CONFIG_AUTO_START = 'recording.autoStart';
|
|
49790
|
+
const RECORDING_CONFIG_WORKERURL = 'recording.workerUrl';
|
|
49791
|
+
const RECORDING_CONFIG_ON_RECORDING_START = 'recording.onRecordingStart';
|
|
49792
|
+
const RECORDING_CONFIG_ON_RECORDING_STOP = 'recording.onRecordingStop';
|
|
49793
|
+
const RECORDING_CONFIG_WORKER_OVERRIDE = 'recording.workerOverride';
|
|
49794
|
+
const RECORDING_CONFIG_TREAT_IFRAME_AS_ROOT = 'recording.treatIframeAsRoot';
|
|
49795
|
+
const RECORDING_CONFIG_DISABLE_UNLOAD = 'recording.disableUnload';
|
|
49796
|
+
const RESOURCE_CACHING = 'resourceCaching';
|
|
49797
|
+
const ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000;
|
|
49798
|
+
const ONE_MINUTE_IN_MILLISECONDS = 60 * 1000;
|
|
49799
|
+
const THIRTY_MINUTES = 1000 * 60 * 30;
|
|
49800
|
+
const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
|
|
49801
|
+
const SESSION_RECORDING_ID = 'pendo_srId';
|
|
49802
|
+
const SESSION_RECORDING_LAST_USER_INTERACTION_EVENT = 'pendo_srLastUserInteractionEvent';
|
|
49803
|
+
const SEND_INTERVAL = 5000;
|
|
49804
|
+
const MAX_SEND_COUNT = 20000;
|
|
49805
|
+
const EVENT_TYPES = {
|
|
49681
49806
|
INCREMENTAL_SOURCE_MUTATION: 0,
|
|
49682
49807
|
FULL_SNAPSHOT: 2,
|
|
49683
49808
|
INCREMENTAL_SNAPSHOT: 3,
|
|
49684
49809
|
META: 4,
|
|
49685
49810
|
INCREMENTAL_SOURCE_INPUT: 5
|
|
49686
49811
|
};
|
|
49687
|
-
|
|
49688
|
-
|
|
49812
|
+
class SessionRecorder {
|
|
49813
|
+
constructor(rrwebRecord, WorkerClass) {
|
|
49689
49814
|
this.name = 'Replay';
|
|
49690
49815
|
this.record = rrwebRecord;
|
|
49691
49816
|
this.WorkerClass = WorkerClass;
|
|
@@ -49693,8 +49818,8 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49693
49818
|
this.eventsSinceLastKeyFrame = 0;
|
|
49694
49819
|
this.currentRecordingSize = 0;
|
|
49695
49820
|
}
|
|
49696
|
-
|
|
49697
|
-
|
|
49821
|
+
addConfigOptions() {
|
|
49822
|
+
const cf = this.api.ConfigReader;
|
|
49698
49823
|
cf.addOption(RECORDING_CONFIG, [cf.sources.PENDO_CONFIG_SRC], {});
|
|
49699
49824
|
/**
|
|
49700
49825
|
* Determines if replay will immediately begin collecting data. If false, you can resume collecting
|
|
@@ -49780,12 +49905,12 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49780
49905
|
*/
|
|
49781
49906
|
cf.addOption(RECORDING_CONFIG_TREAT_IFRAME_AS_ROOT, [cf.sources.SNIPPET_SRC], undefined);
|
|
49782
49907
|
cf.addOption(RESOURCE_CACHING, [cf.sources.PENDO_CONFIG_SRC], undefined);
|
|
49783
|
-
}
|
|
49784
|
-
|
|
49908
|
+
}
|
|
49909
|
+
initialize(pendo, PluginAPI) {
|
|
49785
49910
|
this.pendo = pendo;
|
|
49786
49911
|
this.api = PluginAPI;
|
|
49787
|
-
|
|
49788
|
-
|
|
49912
|
+
const bind = this.pendo._.bind;
|
|
49913
|
+
const configReader = this.api.ConfigReader;
|
|
49789
49914
|
this.buffer = new SessionRecorderBuffer(SEND_INTERVAL, MAX_SEND_COUNT);
|
|
49790
49915
|
this.buffer.onRateLimit = bind(this.rateLimitExceeded, this);
|
|
49791
49916
|
this.transport = new Transport(this.WorkerClass, this.pendo, this.api);
|
|
@@ -49803,8 +49928,8 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49803
49928
|
? configReader.get(RECORDING_CONFIG_ON_RECORDING_START) : function () { };
|
|
49804
49929
|
this.onRecordingStop = this.pendo._.isFunction(configReader.get(RECORDING_CONFIG_ON_RECORDING_STOP))
|
|
49805
49930
|
? configReader.get(RECORDING_CONFIG_ON_RECORDING_STOP) : function () { };
|
|
49806
|
-
|
|
49807
|
-
|
|
49931
|
+
let isSessionReplayEnabled = false;
|
|
49932
|
+
const snippetOverrideValue = configReader.get(RECORDING_CONFIG_ENABLED);
|
|
49808
49933
|
// The snippet config value should take precedence over whatever value the backend returns,
|
|
49809
49934
|
// but ONLY for replay being enabled - all other values should be taken from the backend
|
|
49810
49935
|
if (this.pendo._.isBoolean(snippetOverrideValue)) {
|
|
@@ -49823,7 +49948,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49823
49948
|
this.api.log.info('Session Replay is disabled because excludeNonGuideAnalytics is enabled');
|
|
49824
49949
|
return;
|
|
49825
49950
|
}
|
|
49826
|
-
|
|
49951
|
+
const sessionIdKey = this.sessionIdKey = `${SESSION_RECORDING_ID}.${this.pendo.apiKey}`;
|
|
49827
49952
|
this.pendo.recording = {
|
|
49828
49953
|
start: bind(this.start, this),
|
|
49829
49954
|
stop: bind(this.stop, this)
|
|
@@ -49839,10 +49964,10 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49839
49964
|
this.api.attachEvent(this.api.Events, 'tabIdChanged:self', bind(this.handleTabIdChange, this))
|
|
49840
49965
|
];
|
|
49841
49966
|
// APP-153357 Zone.js could bypass filterCrossWindowMessages (don't use attachEvent)
|
|
49842
|
-
|
|
49843
|
-
|
|
49967
|
+
const channel = this.api.frames.getChannel();
|
|
49968
|
+
const frameMessageHandler = bind(this._frameMessage, this);
|
|
49844
49969
|
channel.addEventListener('message', frameMessageHandler);
|
|
49845
|
-
this.subscriptions.push(
|
|
49970
|
+
this.subscriptions.push(() => {
|
|
49846
49971
|
channel.removeEventListener('message', frameMessageHandler);
|
|
49847
49972
|
});
|
|
49848
49973
|
if (this.api.store.getters['frames/isReady']()) {
|
|
@@ -49870,8 +49995,8 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49870
49995
|
* @label SESSION_RECORDING_LAST_USER_INTERACTION_EVENT
|
|
49871
49996
|
*/
|
|
49872
49997
|
this.api.agentStorage.registry.addSession(SESSION_RECORDING_LAST_USER_INTERACTION_EVENT);
|
|
49873
|
-
}
|
|
49874
|
-
|
|
49998
|
+
}
|
|
49999
|
+
teardown() {
|
|
49875
50000
|
delete this.pendo.recording;
|
|
49876
50001
|
delete this.allowStart;
|
|
49877
50002
|
this.pendo._.each(this.subscriptions, function (unsubscribe) {
|
|
@@ -49881,36 +50006,35 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49881
50006
|
this.subscriptions.length = 0;
|
|
49882
50007
|
this.stop();
|
|
49883
50008
|
this.transport.stop();
|
|
49884
|
-
}
|
|
49885
|
-
|
|
50009
|
+
}
|
|
50010
|
+
ready() {
|
|
49886
50011
|
if (this.api.ConfigReader.get(RECORDING_CONFIG_AUTO_START) !== false) {
|
|
49887
50012
|
this.start();
|
|
49888
50013
|
}
|
|
49889
|
-
}
|
|
49890
|
-
|
|
49891
|
-
var _this = this;
|
|
50014
|
+
}
|
|
50015
|
+
addPageLifecycleListeners() {
|
|
49892
50016
|
// It's important these event listeners use the capture phase, so making it explicit.
|
|
49893
|
-
|
|
49894
|
-
this.pendo._.each(['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'],
|
|
49895
|
-
|
|
50017
|
+
const useCapture = true;
|
|
50018
|
+
this.pendo._.each(['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'], (type) => {
|
|
50019
|
+
this.pageLifecycleListeners.push(this.api.attachEventInternal(window, type, this.pendo._.bind(this.checkPageLifecycleState, this), useCapture));
|
|
49896
50020
|
});
|
|
49897
|
-
}
|
|
49898
|
-
|
|
50021
|
+
}
|
|
50022
|
+
removePageLifecycleListeners() {
|
|
49899
50023
|
this.pendo._.each(this.pageLifecycleListeners, function (teardownFn) {
|
|
49900
50024
|
teardownFn();
|
|
49901
50025
|
});
|
|
49902
50026
|
this.pageLifecycleListeners = [];
|
|
49903
|
-
}
|
|
49904
|
-
|
|
49905
|
-
|
|
50027
|
+
}
|
|
50028
|
+
checkPageLifecycleState() {
|
|
50029
|
+
const state = this.getPageLifecycleState();
|
|
49906
50030
|
if (state === 'active' || state === 'passive') {
|
|
49907
50031
|
if (!this.isRecording() && this.allowStart) {
|
|
49908
50032
|
this.removePageLifecycleListeners();
|
|
49909
50033
|
this.ready();
|
|
49910
50034
|
}
|
|
49911
50035
|
}
|
|
49912
|
-
}
|
|
49913
|
-
|
|
50036
|
+
}
|
|
50037
|
+
getPageLifecycleState() {
|
|
49914
50038
|
if (document.visibilityState === 'hidden') {
|
|
49915
50039
|
return 'hidden';
|
|
49916
50040
|
}
|
|
@@ -49918,9 +50042,8 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49918
50042
|
return 'active';
|
|
49919
50043
|
}
|
|
49920
50044
|
return 'passive';
|
|
49921
|
-
}
|
|
49922
|
-
|
|
49923
|
-
var _this = this;
|
|
50045
|
+
}
|
|
50046
|
+
changeIdentity(identifyEvent) {
|
|
49924
50047
|
if (!this.allowStart)
|
|
49925
50048
|
return;
|
|
49926
50049
|
clearTimeout(this._changeIdentityTimer);
|
|
@@ -49935,56 +50058,55 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49935
50058
|
}
|
|
49936
50059
|
this.visitorId = identifyEvent.data[0].visitor_id;
|
|
49937
50060
|
this.accountId = identifyEvent.data[0].account_id;
|
|
49938
|
-
this._changeIdentityTimer = setTimeout$1(
|
|
49939
|
-
|
|
50061
|
+
this._changeIdentityTimer = setTimeout$1(() => {
|
|
50062
|
+
this._start();
|
|
49940
50063
|
}, 500);
|
|
49941
|
-
}
|
|
49942
|
-
|
|
49943
|
-
|
|
50064
|
+
}
|
|
50065
|
+
changeMetadata(metadataEvent) {
|
|
50066
|
+
const { hashChanged, options } = metadataEvent.data[0];
|
|
49944
50067
|
if (this.allowStart && hashChanged) {
|
|
49945
50068
|
clearTimeout(this._changeIdentityTimer);
|
|
49946
50069
|
this.visitorId = options.visitor.id;
|
|
49947
50070
|
this.accountId = options.account.id;
|
|
49948
50071
|
return this.checkVisitorEligibility();
|
|
49949
50072
|
}
|
|
49950
|
-
}
|
|
49951
|
-
|
|
49952
|
-
var _this = this;
|
|
50073
|
+
}
|
|
50074
|
+
checkVisitorEligibility(continuationCallback) {
|
|
49953
50075
|
if (!this.isRecording() && this.pendo._.isNull(this.visitorId) && this.pendo._.isNull(this.accountId))
|
|
49954
50076
|
return;
|
|
49955
50077
|
this.isCheckingVisitorEligibility = true;
|
|
49956
|
-
return this.fetchVisitorConfig().then(
|
|
49957
|
-
if ((!visitorConfig || !visitorConfig.enable) &&
|
|
49958
|
-
|
|
50078
|
+
return this.fetchVisitorConfig().then(visitorConfig => {
|
|
50079
|
+
if ((!visitorConfig || !visitorConfig.enable) && this.isRecording()) {
|
|
50080
|
+
this.stop();
|
|
49959
50081
|
}
|
|
49960
|
-
if (visitorConfig && visitorConfig.enable &&
|
|
50082
|
+
if (visitorConfig && visitorConfig.enable && this.isRecording()) {
|
|
49961
50083
|
if (continuationCallback) {
|
|
49962
|
-
continuationCallback.call(
|
|
50084
|
+
continuationCallback.call(this);
|
|
49963
50085
|
}
|
|
49964
|
-
|
|
50086
|
+
this.api.Events.trigger('recording:unpaused');
|
|
49965
50087
|
}
|
|
49966
|
-
if (visitorConfig && visitorConfig.enable && !
|
|
49967
|
-
|
|
50088
|
+
if (visitorConfig && visitorConfig.enable && !this.isRecording()) {
|
|
50089
|
+
this._startRecordingForVisitor(visitorConfig);
|
|
49968
50090
|
}
|
|
49969
|
-
|
|
49970
|
-
})
|
|
49971
|
-
|
|
49972
|
-
|
|
49973
|
-
|
|
50091
|
+
this.isCheckingVisitorEligibility = false;
|
|
50092
|
+
}).catch((e) => {
|
|
50093
|
+
this.isCheckingVisitorEligibility = false;
|
|
50094
|
+
this.api.log.critical('Failed to re-fetch recording config', { error: e });
|
|
50095
|
+
this.logStopReason('VISITOR_CONFIG_ERROR');
|
|
49974
50096
|
});
|
|
49975
|
-
}
|
|
49976
|
-
|
|
50097
|
+
}
|
|
50098
|
+
snapshot() {
|
|
49977
50099
|
if (!this.isRecording())
|
|
49978
50100
|
return;
|
|
49979
50101
|
this.send();
|
|
49980
50102
|
this.record.takeFullSnapshot();
|
|
49981
|
-
}
|
|
49982
|
-
|
|
50103
|
+
}
|
|
50104
|
+
isRecording() {
|
|
49983
50105
|
return this.interval != null;
|
|
49984
|
-
}
|
|
49985
|
-
|
|
49986
|
-
|
|
49987
|
-
|
|
50106
|
+
}
|
|
50107
|
+
recordingConfig(visitorConfig) {
|
|
50108
|
+
const recordingOptions = this.pendo._.extend({}, this.config.options, visitorConfig);
|
|
50109
|
+
const maskOptions = {
|
|
49988
50110
|
maskAllText: recordingOptions.privateByDefault != null ? recordingOptions.privateByDefault : true,
|
|
49989
50111
|
maskTextSelector: ['.pendo-sr-mask'].concat(recordingOptions.maskedSelectors || []).join(','),
|
|
49990
50112
|
unmaskTextSelector: ['.pendo-sr-unmask'].concat(recordingOptions.unmaskedSelectors || []).join(','),
|
|
@@ -49999,9 +50121,9 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
49999
50121
|
password: true,
|
|
50000
50122
|
tel: true
|
|
50001
50123
|
});
|
|
50002
|
-
|
|
50003
|
-
|
|
50004
|
-
|
|
50124
|
+
const blockedSelectors = ['.pendo-ignore', '.pendo-sr-ignore'].concat(recordingOptions.blockedSelectors || []);
|
|
50125
|
+
const hiddenSelectors = ['.pendo-sr-hide'].concat(recordingOptions.hiddenSelectors || []);
|
|
50126
|
+
const config = {
|
|
50005
50127
|
maskInputFn: this.pendo._.partial(maskInput, maskOptions),
|
|
50006
50128
|
maskTextFn: this.pendo._.partial(maskText, maskOptions),
|
|
50007
50129
|
maskTextSelector: '*',
|
|
@@ -50015,7 +50137,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50015
50137
|
emitFromIframe: !!this.api.ConfigReader.get(RECORDING_CONFIG_TREAT_IFRAME_AS_ROOT)
|
|
50016
50138
|
};
|
|
50017
50139
|
return config;
|
|
50018
|
-
}
|
|
50140
|
+
}
|
|
50019
50141
|
/**
|
|
50020
50142
|
* Used to start collecting replay data.
|
|
50021
50143
|
*
|
|
@@ -50026,71 +50148,67 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50026
50148
|
* @example
|
|
50027
50149
|
* pendo.recording.start()
|
|
50028
50150
|
*/
|
|
50029
|
-
|
|
50151
|
+
start() {
|
|
50030
50152
|
this._restartPtm = this.api.analytics.ptm().pause();
|
|
50031
50153
|
this.allowStart = true;
|
|
50032
50154
|
this.visitorId = this.pendo.get_visitor_id();
|
|
50033
50155
|
this.accountId = this.pendo.get_account_id();
|
|
50034
50156
|
this._start();
|
|
50035
|
-
}
|
|
50036
|
-
|
|
50157
|
+
}
|
|
50158
|
+
_markEvents(events) {
|
|
50037
50159
|
if (!this.recordingId || !this.isRecording())
|
|
50038
50160
|
return;
|
|
50039
|
-
for (var
|
|
50040
|
-
var e = events_1[_i];
|
|
50161
|
+
for (var e of events) {
|
|
50041
50162
|
if ((e.visitor_id === this.visitorId || e.visitorId === this.visitorId) && e.type !== 'identify') {
|
|
50042
50163
|
e.recordingId = this.recordingId;
|
|
50043
50164
|
e.recordingSessionId = this.sessionId(this.recordingId);
|
|
50044
50165
|
}
|
|
50045
50166
|
}
|
|
50046
|
-
}
|
|
50047
|
-
|
|
50167
|
+
}
|
|
50168
|
+
restartPtm() {
|
|
50048
50169
|
if (this.pendo._.isFunction(this._restartPtm)) {
|
|
50049
50170
|
this._markEvents(this.pendo.buffers.events);
|
|
50050
|
-
for (var
|
|
50051
|
-
var silo = _a[_i];
|
|
50171
|
+
for (var silo of this.pendo.buffers.silos) {
|
|
50052
50172
|
this._markEvents(silo);
|
|
50053
50173
|
}
|
|
50054
50174
|
this._restartPtm();
|
|
50055
50175
|
this._restartPtm = null;
|
|
50056
50176
|
}
|
|
50057
|
-
}
|
|
50058
|
-
|
|
50059
|
-
var _this = this;
|
|
50177
|
+
}
|
|
50178
|
+
_start() {
|
|
50060
50179
|
if (this.isRecording())
|
|
50061
50180
|
return;
|
|
50062
50181
|
if (!this.pendo.isSendingEvents())
|
|
50063
50182
|
return;
|
|
50064
50183
|
if (!this.allowStart)
|
|
50065
50184
|
return;
|
|
50066
|
-
return this.fetchVisitorConfig().then(
|
|
50067
|
-
if (!
|
|
50185
|
+
return this.fetchVisitorConfig().then(visitorConfig => {
|
|
50186
|
+
if (!this.allowStart)
|
|
50068
50187
|
return;
|
|
50069
50188
|
if (!visitorConfig || !visitorConfig.enable) {
|
|
50070
|
-
|
|
50071
|
-
|
|
50189
|
+
this.restartPtm();
|
|
50190
|
+
this.logStopReason('VISITOR_DISABLED');
|
|
50072
50191
|
return;
|
|
50073
50192
|
}
|
|
50074
|
-
|
|
50075
|
-
})
|
|
50076
|
-
|
|
50193
|
+
this._startRecordingForVisitor(visitorConfig);
|
|
50194
|
+
}).catch((e) => {
|
|
50195
|
+
this.restartPtm();
|
|
50077
50196
|
if (e && /Failed to fetch/.test(e.toString())) {
|
|
50078
50197
|
return;
|
|
50079
50198
|
}
|
|
50080
|
-
|
|
50199
|
+
this.api.log.critical('Failed to fetch recording config', {
|
|
50081
50200
|
error: e,
|
|
50082
|
-
visitorId:
|
|
50083
|
-
accountId:
|
|
50084
|
-
url:
|
|
50201
|
+
visitorId: this.visitorId,
|
|
50202
|
+
accountId: this.accountId,
|
|
50203
|
+
url: this.pendo.url.get()
|
|
50085
50204
|
});
|
|
50086
|
-
|
|
50205
|
+
this.logStopReason('VISITOR_CONFIG_ERROR');
|
|
50087
50206
|
});
|
|
50088
|
-
}
|
|
50089
|
-
|
|
50090
|
-
var _this = this;
|
|
50207
|
+
}
|
|
50208
|
+
_startRecordingForVisitor(visitorConfig) {
|
|
50091
50209
|
this.api.Events.trigger('recording:unpaused');
|
|
50092
50210
|
this.transport.start(this.config);
|
|
50093
|
-
|
|
50211
|
+
const disableFallback = this.pendo._.get(this.config, 'disableFallback', true);
|
|
50094
50212
|
if (disableFallback && !this.transport.worker) {
|
|
50095
50213
|
this.restartPtm();
|
|
50096
50214
|
this.pendo.log('Worker failed to start and main thread fallback is disabled. Recording prevented from starting.');
|
|
@@ -50102,9 +50220,9 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50102
50220
|
this.visitorConfig = visitorConfig;
|
|
50103
50221
|
this.clearOldSessionId();
|
|
50104
50222
|
this.sendQueue.start();
|
|
50105
|
-
this.interval = setInterval(
|
|
50106
|
-
if (!
|
|
50107
|
-
|
|
50223
|
+
this.interval = setInterval(() => {
|
|
50224
|
+
if (!this.sendQueue.failed()) {
|
|
50225
|
+
this.send();
|
|
50108
50226
|
}
|
|
50109
50227
|
}, SEND_INTERVAL);
|
|
50110
50228
|
var config = this.recordingConfig(visitorConfig);
|
|
@@ -50119,8 +50237,8 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50119
50237
|
this.restartPtm();
|
|
50120
50238
|
this.logStopReason('RECORDING_ERROR');
|
|
50121
50239
|
}
|
|
50122
|
-
}
|
|
50123
|
-
|
|
50240
|
+
}
|
|
50241
|
+
_sendIds() {
|
|
50124
50242
|
if (window != window.top)
|
|
50125
50243
|
return;
|
|
50126
50244
|
this.api.frames.getChannel().postMessage({
|
|
@@ -50129,16 +50247,16 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50129
50247
|
_sessionId: this._sessionId,
|
|
50130
50248
|
topId: this.api.store.state.frames.topId
|
|
50131
50249
|
});
|
|
50132
|
-
}
|
|
50133
|
-
|
|
50250
|
+
}
|
|
50251
|
+
_refreshIds() {
|
|
50134
50252
|
if (window == window.top)
|
|
50135
50253
|
return;
|
|
50136
50254
|
this.api.frames.getChannel().postMessage({
|
|
50137
50255
|
type: 'pendo:sr:refresh'
|
|
50138
50256
|
});
|
|
50139
|
-
}
|
|
50140
|
-
|
|
50141
|
-
|
|
50257
|
+
}
|
|
50258
|
+
_frameMessage(e) {
|
|
50259
|
+
const message = e.data;
|
|
50142
50260
|
if (message.type === 'pendo:sr:id') {
|
|
50143
50261
|
// When useBroadcastChannel is true, code in filterCrossWindowMessages restricts messages to frames in the
|
|
50144
50262
|
// current browser window/tab. Due to a race condition in clone-detection, you can have two tabs that
|
|
@@ -50154,18 +50272,17 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50154
50272
|
else if (message.type === 'pendo:sr:refresh' && window == window.top) {
|
|
50155
50273
|
this._sendIds();
|
|
50156
50274
|
}
|
|
50157
|
-
}
|
|
50158
|
-
|
|
50275
|
+
}
|
|
50276
|
+
clearSessionId() {
|
|
50159
50277
|
delete this._sessionId;
|
|
50160
50278
|
this.api.sessionStorage.removeItem(SESSION_RECORDING_ID);
|
|
50161
50279
|
this.api.sessionStorage.removeItem(this.sessionIdKey);
|
|
50162
|
-
}
|
|
50163
|
-
|
|
50164
|
-
if (defaultId === void 0) { defaultId = this.pendo.randomString(16); }
|
|
50280
|
+
}
|
|
50281
|
+
sessionId(defaultId = this.pendo.randomString(16)) {
|
|
50165
50282
|
if (!this._sessionId) {
|
|
50166
|
-
|
|
50283
|
+
let currentSessionId = this.api.sessionStorage.getItem(this.sessionIdKey);
|
|
50167
50284
|
if (!currentSessionId) {
|
|
50168
|
-
|
|
50285
|
+
let legacySessionId = this.api.sessionStorage.getItem(SESSION_RECORDING_ID);
|
|
50169
50286
|
if (legacySessionId) {
|
|
50170
50287
|
currentSessionId = legacySessionId;
|
|
50171
50288
|
this.api.sessionStorage.removeItem(SESSION_RECORDING_ID);
|
|
@@ -50178,41 +50295,41 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50178
50295
|
this._sessionId = currentSessionId;
|
|
50179
50296
|
}
|
|
50180
50297
|
return this._sessionId;
|
|
50181
|
-
}
|
|
50182
|
-
|
|
50183
|
-
|
|
50298
|
+
}
|
|
50299
|
+
clearOldSessionId() {
|
|
50300
|
+
let lastUserInteractionEventInfo = this.getLastUserInteractionEventInformation();
|
|
50184
50301
|
if (lastUserInteractionEventInfo) {
|
|
50185
|
-
|
|
50186
|
-
|
|
50187
|
-
|
|
50302
|
+
const lastEmitTime = lastUserInteractionEventInfo.timestamp;
|
|
50303
|
+
const sameVisitor = lastUserInteractionEventInfo.visitorId === this.visitorId && lastUserInteractionEventInfo.accountId === this.accountId;
|
|
50304
|
+
const withinInactivityLimit = lastEmitTime > Date.now() - this.pendo._.get(this.visitorConfig, 'inactivityDuration', THIRTY_MINUTES);
|
|
50188
50305
|
if (sameVisitor && withinInactivityLimit)
|
|
50189
50306
|
return;
|
|
50190
50307
|
}
|
|
50191
50308
|
this.clearSessionInfo();
|
|
50192
50309
|
this.isNewSession = true;
|
|
50193
|
-
}
|
|
50194
|
-
|
|
50310
|
+
}
|
|
50311
|
+
clearSessionInfo() {
|
|
50195
50312
|
this.currentRecordingSize = 0;
|
|
50196
50313
|
this.clearSessionId();
|
|
50197
50314
|
this.clearLastUserInteractionEventInformation();
|
|
50198
|
-
}
|
|
50199
|
-
|
|
50315
|
+
}
|
|
50316
|
+
isUserInteraction(event) {
|
|
50200
50317
|
if (event.type !== EVENT_TYPES.INCREMENTAL_SNAPSHOT) {
|
|
50201
50318
|
return false;
|
|
50202
50319
|
}
|
|
50203
50320
|
return event.data.source > EVENT_TYPES.INCREMENTAL_SOURCE_MUTATION && event.data.source <= EVENT_TYPES.INCREMENTAL_SOURCE_INPUT;
|
|
50204
|
-
}
|
|
50205
|
-
|
|
50321
|
+
}
|
|
50322
|
+
storeLastUserInteractionEventInformation(event, visitorId, accountId, skipUserInteractionCheck) {
|
|
50206
50323
|
if (this.isUserInteraction(event) || skipUserInteractionCheck) {
|
|
50207
|
-
this.lastUserInteractionEventInfo = { timestamp: event.timestamp, visitorId
|
|
50324
|
+
this.lastUserInteractionEventInfo = { timestamp: event.timestamp, visitorId, accountId };
|
|
50208
50325
|
this.api.sessionStorage.setItem(SESSION_RECORDING_LAST_USER_INTERACTION_EVENT, JSON.stringify(this.lastUserInteractionEventInfo));
|
|
50209
50326
|
}
|
|
50210
|
-
}
|
|
50211
|
-
|
|
50327
|
+
}
|
|
50328
|
+
clearLastUserInteractionEventInformation() {
|
|
50212
50329
|
delete this.lastUserInteractionEventInfo;
|
|
50213
50330
|
this.api.sessionStorage.removeItem(SESSION_RECORDING_LAST_USER_INTERACTION_EVENT);
|
|
50214
|
-
}
|
|
50215
|
-
|
|
50331
|
+
}
|
|
50332
|
+
getLastUserInteractionEventInformation() {
|
|
50216
50333
|
if (this.lastUserInteractionEventInfo)
|
|
50217
50334
|
return this.lastUserInteractionEventInfo;
|
|
50218
50335
|
try {
|
|
@@ -50222,7 +50339,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50222
50339
|
catch (e) { // nothing here yet or failed to be written; don't need to log
|
|
50223
50340
|
return null;
|
|
50224
50341
|
}
|
|
50225
|
-
}
|
|
50342
|
+
}
|
|
50226
50343
|
/**
|
|
50227
50344
|
* Handle new rrweb events coming in. This will also make sure that we are properly sending a "keyframe"
|
|
50228
50345
|
* as the BE expects it. A "keyframe" should consist of only the events needed to start a recording. This includes
|
|
@@ -50233,19 +50350,19 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50233
50350
|
* @param event.type The enum type of the specific event (e.g. meta, full snapshot, incremental snapshot)
|
|
50234
50351
|
* @param event.data The specific data to describe the event, this is different depending on what the type is
|
|
50235
50352
|
*/
|
|
50236
|
-
|
|
50237
|
-
|
|
50238
|
-
|
|
50239
|
-
|
|
50240
|
-
|
|
50241
|
-
|
|
50353
|
+
emit(event) {
|
|
50354
|
+
const isMeta = event.type === EVENT_TYPES.META;
|
|
50355
|
+
const isSnapshot = event.type === EVENT_TYPES.FULL_SNAPSHOT;
|
|
50356
|
+
const prevLastEmitTime = this.pendo._.get(this.getLastUserInteractionEventInformation(), 'timestamp');
|
|
50357
|
+
const inactivityDuration = this.pendo._.get(this.visitorConfig, 'inactivityDuration', THIRTY_MINUTES);
|
|
50358
|
+
let skipUserInteractionCheck = false;
|
|
50242
50359
|
if (event.timestamp && event.timestamp.getTime) {
|
|
50243
50360
|
event.timestamp = event.timestamp.getTime();
|
|
50244
50361
|
}
|
|
50245
50362
|
if (!event.timestamp) {
|
|
50246
50363
|
event.timestamp = (new Date()).getTime();
|
|
50247
50364
|
}
|
|
50248
|
-
|
|
50365
|
+
const withinInactivityLimit = prevLastEmitTime && event.timestamp - prevLastEmitTime <= inactivityDuration;
|
|
50249
50366
|
// If we don't have a last emit time and a META event is emitted, store the META event as the last user interaction
|
|
50250
50367
|
// event. This most commonly happens when a replay is first started and establishes a baseline timestamp to
|
|
50251
50368
|
// to compare inactivity against. For subsequent META events that are part of the same replay, we should have
|
|
@@ -50268,7 +50385,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50268
50385
|
this.logStopReason('INACTIVE_HIDDEN_TAB');
|
|
50269
50386
|
}
|
|
50270
50387
|
if (!this.isCheckingVisitorEligibility) {
|
|
50271
|
-
|
|
50388
|
+
const continuationCallback = function () {
|
|
50272
50389
|
this.send();
|
|
50273
50390
|
this.clearSessionInfo();
|
|
50274
50391
|
this.snapshot();
|
|
@@ -50304,13 +50421,13 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50304
50421
|
}
|
|
50305
50422
|
else if (!isMeta) {
|
|
50306
50423
|
this.eventsSinceLastKeyFrame += 1;
|
|
50307
|
-
|
|
50308
|
-
|
|
50309
|
-
|
|
50310
|
-
|
|
50311
|
-
|
|
50424
|
+
const timeSinceLastKeyFrame = event.timestamp - this.lastKeyFrameTime;
|
|
50425
|
+
const exceeds24Hours = timeSinceLastKeyFrame >= ONE_DAY_IN_MILLISECONDS;
|
|
50426
|
+
const exceedsTimeFreq = timeSinceLastKeyFrame >= this.pendo._.get(this.visitorConfig, 'keyframeTimeFrequency', 30645047); // Defaults determined by BE originally, shouldn't really ever be used
|
|
50427
|
+
const exceedsEventFreq = this.eventsSinceLastKeyFrame >= this.pendo._.get(this.visitorConfig, 'keyframeEventFrequency', 4548); // Defaults determined by BE originally, shouldn't really ever be used
|
|
50428
|
+
const exceedsRecordingSizeLimit = this.currentRecordingSize >= this.pendo._.get(this.visitorConfig, 'recordingSizeLimit', ONE_HUNDRED_MB_IN_BYTES);
|
|
50312
50429
|
if (exceeds24Hours || (exceedsTimeFreq && exceedsEventFreq) || exceedsRecordingSizeLimit) {
|
|
50313
|
-
|
|
50430
|
+
const continuationCallback = function () {
|
|
50314
50431
|
this.currentRecordingSize = 0;
|
|
50315
50432
|
this.snapshot();
|
|
50316
50433
|
};
|
|
@@ -50322,18 +50439,18 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50322
50439
|
}
|
|
50323
50440
|
}
|
|
50324
50441
|
}
|
|
50325
|
-
}
|
|
50326
|
-
|
|
50442
|
+
}
|
|
50443
|
+
updateCurrentRecordingSize(recordingPayloadSize) {
|
|
50327
50444
|
this.currentRecordingSize += recordingPayloadSize;
|
|
50328
|
-
}
|
|
50329
|
-
|
|
50445
|
+
}
|
|
50446
|
+
onWorkerMessage(messageData) {
|
|
50330
50447
|
switch (messageData.type) {
|
|
50331
50448
|
case 'workerDied': {
|
|
50332
50449
|
this.logStopReason('WORKER_DIED');
|
|
50333
50450
|
break;
|
|
50334
50451
|
}
|
|
50335
50452
|
case 'recordingPayloadSize': {
|
|
50336
|
-
|
|
50453
|
+
const { recordingPayloadSize, exceedsPayloadSizeLimit } = messageData;
|
|
50337
50454
|
if (!recordingPayloadSize)
|
|
50338
50455
|
return;
|
|
50339
50456
|
// stop recording if recording payload exceeds allowed payload size
|
|
@@ -50346,7 +50463,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50346
50463
|
break;
|
|
50347
50464
|
}
|
|
50348
50465
|
case 'hostedResources': {
|
|
50349
|
-
|
|
50466
|
+
const { hostedResourcesEvent } = messageData;
|
|
50350
50467
|
if (!hostedResourcesEvent)
|
|
50351
50468
|
return;
|
|
50352
50469
|
this.sendHostedResources(hostedResourcesEvent);
|
|
@@ -50357,12 +50474,12 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50357
50474
|
break;
|
|
50358
50475
|
}
|
|
50359
50476
|
case 'missingData': {
|
|
50360
|
-
this.logStopReason(
|
|
50477
|
+
this.logStopReason(`MISSING_${messageData.missingData}`);
|
|
50361
50478
|
break;
|
|
50362
50479
|
}
|
|
50363
50480
|
}
|
|
50364
|
-
}
|
|
50365
|
-
|
|
50481
|
+
}
|
|
50482
|
+
addRecordingId(event) {
|
|
50366
50483
|
if (!this.isRecording())
|
|
50367
50484
|
return;
|
|
50368
50485
|
if (!this.recordingId || !event || !event.data || !event.data.length)
|
|
@@ -50381,7 +50498,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50381
50498
|
return;
|
|
50382
50499
|
}
|
|
50383
50500
|
this._markEvents([capturedEvent]);
|
|
50384
|
-
}
|
|
50501
|
+
}
|
|
50385
50502
|
/**
|
|
50386
50503
|
* Used to stop collecting replay data.
|
|
50387
50504
|
*
|
|
@@ -50392,7 +50509,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50392
50509
|
* @example
|
|
50393
50510
|
* pendo.recording.stop()
|
|
50394
50511
|
*/
|
|
50395
|
-
|
|
50512
|
+
stop() {
|
|
50396
50513
|
if (this._stop) {
|
|
50397
50514
|
this._stop();
|
|
50398
50515
|
}
|
|
@@ -50410,33 +50527,32 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50410
50527
|
this.accountId = null;
|
|
50411
50528
|
this.clearSessionInfo();
|
|
50412
50529
|
this.onRecordingStop();
|
|
50413
|
-
}
|
|
50414
|
-
|
|
50530
|
+
}
|
|
50531
|
+
handleHidden() {
|
|
50415
50532
|
this.send({ hidden: true });
|
|
50416
|
-
}
|
|
50417
|
-
|
|
50533
|
+
}
|
|
50534
|
+
handleUnload() {
|
|
50418
50535
|
if (this.api.ConfigReader.get(RECORDING_CONFIG_DISABLE_UNLOAD))
|
|
50419
50536
|
return;
|
|
50420
50537
|
this.send({ unload: true });
|
|
50421
|
-
}
|
|
50422
|
-
|
|
50538
|
+
}
|
|
50539
|
+
buildRequestUrl(baseUrl, queryObj) {
|
|
50423
50540
|
var authedQueryObj = this.pendo._.extend({}, this.api.agent.getJwtInfoCopy(), queryObj);
|
|
50424
50541
|
var queryString = this.pendo._.map(authedQueryObj, function (value, key) {
|
|
50425
|
-
return
|
|
50542
|
+
return `${key}=${value}`;
|
|
50426
50543
|
}).join('&');
|
|
50427
|
-
return queryString.length ?
|
|
50428
|
-
}
|
|
50429
|
-
|
|
50544
|
+
return queryString.length ? `${baseUrl}?${queryString}` : baseUrl;
|
|
50545
|
+
}
|
|
50546
|
+
sendFailure(reason) {
|
|
50430
50547
|
this.stop();
|
|
50431
50548
|
this.logStopReason(reason);
|
|
50432
|
-
}
|
|
50433
|
-
|
|
50549
|
+
}
|
|
50550
|
+
rateLimitExceeded() {
|
|
50434
50551
|
this.send(); // sends first chunk of 20k
|
|
50435
50552
|
this.stop(); // sends 2nd chunk of 20k, rest is ignored
|
|
50436
50553
|
this.logStopReason('DATA_OVERLOAD');
|
|
50437
|
-
}
|
|
50438
|
-
|
|
50439
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.keyframe, keyframe = _d === void 0 ? false : _d, _e = _b.hidden, hidden = _e === void 0 ? false : _e;
|
|
50554
|
+
}
|
|
50555
|
+
send({ unload = false, keyframe = false, hidden = false } = {}) {
|
|
50440
50556
|
if (!this.isRecording())
|
|
50441
50557
|
return;
|
|
50442
50558
|
if (!this.buffer)
|
|
@@ -50466,7 +50582,7 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50466
50582
|
}
|
|
50467
50583
|
// Used to add promoted metadata onto the recording event
|
|
50468
50584
|
this.api.Events.eventCaptured.trigger(payload);
|
|
50469
|
-
|
|
50585
|
+
const params = {
|
|
50470
50586
|
v: this.pendo.VERSION,
|
|
50471
50587
|
recordingId: this.recordingId
|
|
50472
50588
|
};
|
|
@@ -50477,11 +50593,11 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50477
50593
|
params.ns = 1;
|
|
50478
50594
|
this.isNewSession = false;
|
|
50479
50595
|
}
|
|
50480
|
-
var url = this.buildRequestUrl(
|
|
50596
|
+
var url = this.buildRequestUrl(`${this.pendo.HOST}/data/rec/${this.pendo.apiKey}`, params);
|
|
50481
50597
|
payload = this.buffer.pack(payload, this.pendo._);
|
|
50482
50598
|
if (unload || hidden) {
|
|
50483
50599
|
try {
|
|
50484
|
-
this.sendQueue.drain([{ url
|
|
50600
|
+
this.sendQueue.drain([{ url, payload }], unload);
|
|
50485
50601
|
}
|
|
50486
50602
|
catch (e) {
|
|
50487
50603
|
if (e.reason) {
|
|
@@ -50493,30 +50609,29 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50493
50609
|
}
|
|
50494
50610
|
}
|
|
50495
50611
|
else {
|
|
50496
|
-
this.sendQueue.push({ url
|
|
50612
|
+
this.sendQueue.push({ url, payload });
|
|
50497
50613
|
}
|
|
50498
50614
|
if (!this.buffer.isEmpty()) {
|
|
50499
|
-
this.send({ unload
|
|
50615
|
+
this.send({ unload });
|
|
50500
50616
|
}
|
|
50501
|
-
}
|
|
50502
|
-
|
|
50503
|
-
|
|
50617
|
+
}
|
|
50618
|
+
fetchVisitorConfig() {
|
|
50619
|
+
const jzb = this.pendo.compress({
|
|
50504
50620
|
url: this.pendo.url.get(),
|
|
50505
50621
|
metadata: this.pendo.getSerializedMetadata(),
|
|
50506
50622
|
visitorId: this.visitorId,
|
|
50507
50623
|
accountId: this.accountId
|
|
50508
50624
|
});
|
|
50509
|
-
|
|
50510
|
-
jzb
|
|
50625
|
+
const url = this.buildRequestUrl(`${this.pendo.HOST}/data/recordingconf/${this.pendo.apiKey}`, {
|
|
50626
|
+
jzb,
|
|
50511
50627
|
ct: (new Date().getTime()),
|
|
50512
50628
|
v: this.pendo.VERSION
|
|
50513
50629
|
});
|
|
50514
50630
|
return fetch(url, {
|
|
50515
50631
|
method: 'GET'
|
|
50516
|
-
}).then(
|
|
50517
|
-
}
|
|
50518
|
-
|
|
50519
|
-
var _this = this;
|
|
50632
|
+
}).then(response => response.json());
|
|
50633
|
+
}
|
|
50634
|
+
logStopReason(reason, error) {
|
|
50520
50635
|
var tracer = this.api.EventTracer.addTracerIds({});
|
|
50521
50636
|
var payload = this.pendo._.extend({
|
|
50522
50637
|
type: 'recording',
|
|
@@ -50532,53 +50647,51 @@ var SessionRecorder = /** @class */ (function () {
|
|
|
50532
50647
|
recordingPayload: [],
|
|
50533
50648
|
sequence: 0,
|
|
50534
50649
|
recordingPayloadCount: 0,
|
|
50535
|
-
props:
|
|
50650
|
+
props: Object.assign({ reason }, (error && { error: error instanceof Error ? error === null || error === void 0 ? void 0 : error.message : error }))
|
|
50536
50651
|
}, tracer);
|
|
50537
50652
|
var jzb = this.pendo.compress(payload);
|
|
50538
|
-
var url = this.buildRequestUrl(
|
|
50539
|
-
jzb
|
|
50653
|
+
var url = this.buildRequestUrl(`${this.pendo.HOST}/data/rec/${this.pendo.apiKey}`, {
|
|
50654
|
+
jzb,
|
|
50540
50655
|
ct: (new Date().getTime()),
|
|
50541
50656
|
v: this.pendo.VERSION,
|
|
50542
50657
|
recordingId: payload.recordingId
|
|
50543
50658
|
});
|
|
50544
50659
|
var body = this.pendo.compress(payload, 'binary');
|
|
50545
50660
|
return this.transport.post(url, {
|
|
50546
|
-
body
|
|
50661
|
+
body,
|
|
50547
50662
|
keepalive: true
|
|
50548
|
-
})
|
|
50549
|
-
|
|
50663
|
+
}).catch((e) => {
|
|
50664
|
+
this.api.log.critical('Failed to send reason for stopping recording', { error: e });
|
|
50550
50665
|
});
|
|
50551
|
-
}
|
|
50552
|
-
|
|
50553
|
-
var _this = this;
|
|
50666
|
+
}
|
|
50667
|
+
sendHostedResources(event) {
|
|
50554
50668
|
var tracer = this.api.EventTracer.addTracerIds({});
|
|
50555
|
-
var payload = this.pendo._.extend(
|
|
50556
|
-
var url = this.buildRequestUrl(
|
|
50669
|
+
var payload = this.pendo._.extend(Object.assign(Object.assign({}, event), { browserTime: new Date().getTime() }), tracer);
|
|
50670
|
+
var url = this.buildRequestUrl(`${this.pendo.HOST}/data/rec/${this.pendo.apiKey}`, {
|
|
50557
50671
|
ct: (new Date().getTime()),
|
|
50558
50672
|
v: this.pendo.VERSION,
|
|
50559
50673
|
recordingId: payload.recordingId
|
|
50560
50674
|
});
|
|
50561
50675
|
var body = this.pendo.compress(payload, 'binary');
|
|
50562
50676
|
return this.transport.post(url, {
|
|
50563
|
-
body
|
|
50677
|
+
body,
|
|
50564
50678
|
keepalive: true
|
|
50565
|
-
})
|
|
50566
|
-
|
|
50679
|
+
}).catch((e) => {
|
|
50680
|
+
this.api.log.critical('Failed to send hosted resources for recording event', { error: e });
|
|
50567
50681
|
});
|
|
50568
|
-
}
|
|
50682
|
+
}
|
|
50569
50683
|
/**
|
|
50570
50684
|
* This should fire when an event is triggered in clearClonedStorage. Under normal circumstances, the event will be
|
|
50571
50685
|
* triggered before recording begins in the cloned tab. On the off chance tabId changes again though, create a new
|
|
50572
50686
|
* replay. We want to avoid scenarios where a single recordingId is associated with multiple tabIds. This can happen if
|
|
50573
50687
|
* clone detection runs in a duplicated tab before it runs in the original tab.
|
|
50574
50688
|
*/
|
|
50575
|
-
|
|
50689
|
+
handleTabIdChange() {
|
|
50576
50690
|
this.send();
|
|
50577
50691
|
this.clearSessionInfo();
|
|
50578
50692
|
this.snapshot();
|
|
50579
|
-
}
|
|
50580
|
-
|
|
50581
|
-
}());
|
|
50693
|
+
}
|
|
50694
|
+
}
|
|
50582
50695
|
|
|
50583
50696
|
function wrapMethodWithCatch(method) {
|
|
50584
50697
|
return function () {
|
|
@@ -50599,8 +50712,7 @@ function errorLogger(recorder) {
|
|
|
50599
50712
|
return recorder;
|
|
50600
50713
|
if (!recorder.constructor || !recorder.constructor.prototype)
|
|
50601
50714
|
return recorder;
|
|
50602
|
-
for (
|
|
50603
|
-
var methodName = _a[_i];
|
|
50715
|
+
for (let methodName of Object.getOwnPropertyNames(recorder.constructor.prototype)) {
|
|
50604
50716
|
if (methodName === 'constructor')
|
|
50605
50717
|
continue;
|
|
50606
50718
|
recorder[methodName] = wrapMethodWithCatch(recorder[methodName]);
|
|
@@ -50642,7 +50754,27 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
50642
50754
|
((function (exports) {
|
|
50643
50755
|
'__worker_loader_strict__';
|
|
50644
50756
|
|
|
50645
|
-
|
|
50757
|
+
// Resolve the global object without relying on a bare `window` identifier.
|
|
50758
|
+
// `window` is only a bound global in a normal browser realm; when the agent is
|
|
50759
|
+
// loaded via the npm `loadAsModule` path (or inside a Web Worker) the module is
|
|
50760
|
+
// evaluated in a realm where `window` is undeclared, so referencing it bare
|
|
50761
|
+
// throws a ReferenceError at module-load. `globalThis` resolves in every realm.
|
|
50762
|
+
function getGlobalScope() {
|
|
50763
|
+
if (typeof globalThis !== 'undefined') {
|
|
50764
|
+
return globalThis;
|
|
50765
|
+
}
|
|
50766
|
+
if (typeof self !== 'undefined') {
|
|
50767
|
+
return self;
|
|
50768
|
+
}
|
|
50769
|
+
if (typeof window !== 'undefined') {
|
|
50770
|
+
return window;
|
|
50771
|
+
}
|
|
50772
|
+
return {};
|
|
50773
|
+
}
|
|
50774
|
+
|
|
50775
|
+
var globalScope = getGlobalScope();
|
|
50776
|
+
|
|
50777
|
+
var setTimeout = safeBind(globalScope.setTimeout, globalScope);
|
|
50646
50778
|
|
|
50647
50779
|
function safeBind(fn, scope) {
|
|
50648
50780
|
if (typeof fn.bind === 'function') {
|
|
@@ -50665,7 +50797,7 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
50665
50797
|
}
|
|
50666
50798
|
|
|
50667
50799
|
return getZoneSafeMethod('setTimeout');
|
|
50668
|
-
})(
|
|
50800
|
+
})(globalScope);
|
|
50669
50801
|
|
|
50670
50802
|
var setTimeout$1 = setTimeout;
|
|
50671
50803
|
|
|
@@ -51545,7 +51677,7 @@ function includes(str, substring) {
|
|
|
51545
51677
|
function getResourceType(blockedURI, directive) {
|
|
51546
51678
|
if (!directive || typeof directive !== 'string')
|
|
51547
51679
|
return 'resource';
|
|
51548
|
-
|
|
51680
|
+
const d = directive.toLowerCase();
|
|
51549
51681
|
if (blockedURI === 'inline') {
|
|
51550
51682
|
if (includes(d, 'script-src-attr')) {
|
|
51551
51683
|
return 'inline event handler';
|
|
@@ -51604,12 +51736,11 @@ function getResourceType(blockedURI, directive) {
|
|
|
51604
51736
|
function getDirective(policy, directiveName) {
|
|
51605
51737
|
if (!policy || !directiveName)
|
|
51606
51738
|
return '';
|
|
51607
|
-
|
|
51608
|
-
for (
|
|
51609
|
-
|
|
51610
|
-
|
|
51611
|
-
|
|
51612
|
-
if (lower === needle || lower.startsWith("".concat(needle, " "))) {
|
|
51739
|
+
const needle = directiveName.toLowerCase();
|
|
51740
|
+
for (const directive of policy.split(';')) {
|
|
51741
|
+
const trimmed = directive.trim();
|
|
51742
|
+
const lower = trimmed.toLowerCase();
|
|
51743
|
+
if (lower === needle || lower.startsWith(`${needle} `)) {
|
|
51613
51744
|
return trimmed;
|
|
51614
51745
|
}
|
|
51615
51746
|
}
|
|
@@ -51631,7 +51762,7 @@ function getDirective(policy, directiveName) {
|
|
|
51631
51762
|
function getArticle(phrase) {
|
|
51632
51763
|
if (!phrase || typeof phrase !== 'string')
|
|
51633
51764
|
return 'A';
|
|
51634
|
-
|
|
51765
|
+
const c = phrase.trim().charAt(0).toLowerCase();
|
|
51635
51766
|
return includes('aeiou', c) ? 'An' : 'A';
|
|
51636
51767
|
}
|
|
51637
51768
|
/**
|
|
@@ -51674,47 +51805,46 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
|
|
|
51674
51805
|
return 'Content Security Policy: Unknown violation occurred.';
|
|
51675
51806
|
}
|
|
51676
51807
|
try {
|
|
51677
|
-
|
|
51808
|
+
const reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
|
|
51678
51809
|
// special case for frame-ancestors since it doesn't fit our template at all
|
|
51679
51810
|
if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
|
|
51680
|
-
return
|
|
51811
|
+
return `Content Security Policy${reportOnlyText}: The display of ${blockedURI} in a frame was blocked because an ancestor violates your site's frame-ancestors policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
51681
51812
|
}
|
|
51682
|
-
|
|
51683
|
-
|
|
51684
|
-
|
|
51685
|
-
|
|
51686
|
-
|
|
51687
|
-
|
|
51688
|
-
return
|
|
51813
|
+
const resourceType = getResourceType(blockedURI, directive);
|
|
51814
|
+
const article = getArticle(resourceType);
|
|
51815
|
+
const source = formatBlockedUri(blockedURI);
|
|
51816
|
+
const directiveValue = getDirective(originalPolicy, directive);
|
|
51817
|
+
const policyDisplay = directiveValue || directive;
|
|
51818
|
+
const resourceDescription = `${article} ${resourceType}${source ? ` from ${source}` : ''}`;
|
|
51819
|
+
return `Content Security Policy${reportOnlyText}: ${resourceDescription} was blocked by your site's \`${policyDisplay}\` policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
51689
51820
|
}
|
|
51690
51821
|
catch (error) {
|
|
51691
|
-
return
|
|
51822
|
+
return `Content Security Policy: Error formatting violation message: ${error.message}`;
|
|
51692
51823
|
}
|
|
51693
51824
|
}
|
|
51694
51825
|
|
|
51695
|
-
|
|
51696
|
-
|
|
51826
|
+
const MAX_LENGTH = 1000;
|
|
51827
|
+
const PII_PATTERN = {
|
|
51697
51828
|
ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
51698
51829
|
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
51699
51830
|
creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
|
|
51700
51831
|
httpsUrls: /https:\/\/[^\s]+/g,
|
|
51701
51832
|
email: /[\w._+-]+@[\w.-]+\.\w+/g
|
|
51702
51833
|
};
|
|
51703
|
-
|
|
51704
|
-
|
|
51705
|
-
|
|
51706
|
-
|
|
51707
|
-
|
|
51834
|
+
const PII_REPLACEMENT = '*'.repeat(10);
|
|
51835
|
+
const JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
|
|
51836
|
+
const UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
|
|
51837
|
+
const joinedKeys = JSON_PII_KEYS.join('|');
|
|
51838
|
+
const keyPattern = `"([^"]*(?:${joinedKeys})[^"]*)"`;
|
|
51708
51839
|
// only scrub strings, numbers, and booleans
|
|
51709
|
-
|
|
51840
|
+
const acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
|
|
51710
51841
|
/**
|
|
51711
51842
|
* Truncates a string to the max length
|
|
51712
51843
|
* @access private
|
|
51713
51844
|
* @param {String} string
|
|
51714
51845
|
* @returns {String}
|
|
51715
51846
|
*/
|
|
51716
|
-
function truncate(string, includeEllipsis) {
|
|
51717
|
-
if (includeEllipsis === void 0) { includeEllipsis = false; }
|
|
51847
|
+
function truncate(string, includeEllipsis = false) {
|
|
51718
51848
|
if (string.length <= MAX_LENGTH)
|
|
51719
51849
|
return string;
|
|
51720
51850
|
if (includeEllipsis) {
|
|
@@ -51731,7 +51861,7 @@ function truncate(string, includeEllipsis) {
|
|
|
51731
51861
|
* @returns {String}
|
|
51732
51862
|
*/
|
|
51733
51863
|
function generateLogKey(methodName, message, stackTrace) {
|
|
51734
|
-
return
|
|
51864
|
+
return `${methodName}|${message}|${stackTrace}`;
|
|
51735
51865
|
}
|
|
51736
51866
|
/**
|
|
51737
51867
|
* Checks if a string has 2 or more digits, a https URL, or an email address
|
|
@@ -51748,13 +51878,12 @@ function mightContainPII(string) {
|
|
|
51748
51878
|
* @param {String} string
|
|
51749
51879
|
* @returns {String}
|
|
51750
51880
|
*/
|
|
51751
|
-
function scrubPII(
|
|
51752
|
-
var string = _a.string, _ = _a._;
|
|
51881
|
+
function scrubPII({ string, _ }) {
|
|
51753
51882
|
if (!string || typeof string !== 'string')
|
|
51754
51883
|
return string;
|
|
51755
51884
|
if (!mightContainPII(string))
|
|
51756
51885
|
return string;
|
|
51757
|
-
return _.reduce(_.values(PII_PATTERN),
|
|
51886
|
+
return _.reduce(_.values(PII_PATTERN), (str, pattern) => str.replace(pattern, PII_REPLACEMENT), string);
|
|
51758
51887
|
}
|
|
51759
51888
|
/**
|
|
51760
51889
|
* Scrub PII from a stringified JSON object
|
|
@@ -51763,14 +51892,12 @@ function scrubPII(_a) {
|
|
|
51763
51892
|
* @returns {String}
|
|
51764
51893
|
*/
|
|
51765
51894
|
function scrubJsonPII(string) {
|
|
51766
|
-
|
|
51895
|
+
const fullScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*[\\{\\[]`, 'i');
|
|
51767
51896
|
if (fullScrubRegex.test(string)) {
|
|
51768
51897
|
return UNABLE_TO_DISPLAY_BODY;
|
|
51769
51898
|
}
|
|
51770
|
-
|
|
51771
|
-
return string.replace(keyValueScrubRegex,
|
|
51772
|
-
return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
|
|
51773
|
-
});
|
|
51899
|
+
const keyValueScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*${acceptedValues}`, 'gi');
|
|
51900
|
+
return string.replace(keyValueScrubRegex, (match, key) => `"${key}":"${PII_REPLACEMENT}"`);
|
|
51774
51901
|
}
|
|
51775
51902
|
/**
|
|
51776
51903
|
* Checks if a string is a JSON object
|
|
@@ -51782,7 +51909,7 @@ function scrubJsonPII(string) {
|
|
|
51782
51909
|
function mightContainJson(string, contentType) {
|
|
51783
51910
|
if (!string || typeof string !== 'string')
|
|
51784
51911
|
return false;
|
|
51785
|
-
|
|
51912
|
+
const firstChar = string.charAt(0);
|
|
51786
51913
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
51787
51914
|
return true;
|
|
51788
51915
|
}
|
|
@@ -51795,20 +51922,19 @@ function mightContainJson(string, contentType) {
|
|
|
51795
51922
|
* @param {String} contentType
|
|
51796
51923
|
* @returns {String}
|
|
51797
51924
|
*/
|
|
51798
|
-
function maskSensitiveFields(
|
|
51799
|
-
var string = _a.string, contentType = _a.contentType, _ = _a._;
|
|
51925
|
+
function maskSensitiveFields({ string, contentType, _ }) {
|
|
51800
51926
|
if (!string || typeof string !== 'string')
|
|
51801
51927
|
return string;
|
|
51802
51928
|
if (mightContainJson(string, contentType)) {
|
|
51803
51929
|
string = scrubJsonPII(string);
|
|
51804
51930
|
}
|
|
51805
51931
|
if (mightContainPII(string)) {
|
|
51806
|
-
string = scrubPII({ string
|
|
51932
|
+
string = scrubPII({ string, _ });
|
|
51807
51933
|
}
|
|
51808
51934
|
return string;
|
|
51809
51935
|
}
|
|
51810
51936
|
|
|
51811
|
-
|
|
51937
|
+
const DEV_LOG_TYPE = 'devlog';
|
|
51812
51938
|
function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
51813
51939
|
return {
|
|
51814
51940
|
browser_time: pluginAPI.util.getNow(),
|
|
@@ -51819,12 +51945,12 @@ function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
|
51819
51945
|
};
|
|
51820
51946
|
}
|
|
51821
51947
|
|
|
51822
|
-
|
|
51823
|
-
|
|
51824
|
-
|
|
51825
|
-
|
|
51826
|
-
|
|
51827
|
-
|
|
51948
|
+
const TOKEN_MAX_SIZE = 100;
|
|
51949
|
+
const TOKEN_REFILL_RATE = 10;
|
|
51950
|
+
const TOKEN_REFRESH_INTERVAL = 1000;
|
|
51951
|
+
const MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
|
|
51952
|
+
class DevlogBuffer {
|
|
51953
|
+
constructor(pendo, pluginAPI) {
|
|
51828
51954
|
this.pendo = pendo;
|
|
51829
51955
|
this.pluginAPI = pluginAPI;
|
|
51830
51956
|
this.events = [];
|
|
@@ -51835,36 +51961,36 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
51835
51961
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
51836
51962
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
51837
51963
|
}
|
|
51838
|
-
|
|
51964
|
+
isEmpty() {
|
|
51839
51965
|
return this.events.length === 0 && this.payloads.length === 0;
|
|
51840
|
-
}
|
|
51841
|
-
|
|
51842
|
-
|
|
51966
|
+
}
|
|
51967
|
+
refillTokens() {
|
|
51968
|
+
const now = this.pluginAPI.util.getNow();
|
|
51843
51969
|
if (now >= this.nextRefillTime) {
|
|
51844
|
-
|
|
51845
|
-
|
|
51846
|
-
|
|
51970
|
+
const timeSinceLastRefill = now - this.lastRefillTime;
|
|
51971
|
+
const secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
|
|
51972
|
+
const tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
|
|
51847
51973
|
this.tokens = Math.min(this.tokens + tokensToRefill, TOKEN_MAX_SIZE);
|
|
51848
51974
|
this.lastRefillTime = now;
|
|
51849
51975
|
this.nextRefillTime = now + TOKEN_REFRESH_INTERVAL;
|
|
51850
51976
|
}
|
|
51851
|
-
}
|
|
51852
|
-
|
|
51977
|
+
}
|
|
51978
|
+
clear() {
|
|
51853
51979
|
this.events = [];
|
|
51854
51980
|
this.lastEvent = null;
|
|
51855
51981
|
this.uncompressedSize = 0;
|
|
51856
|
-
}
|
|
51857
|
-
|
|
51982
|
+
}
|
|
51983
|
+
hasTokenAvailable() {
|
|
51858
51984
|
this.refillTokens();
|
|
51859
51985
|
return this.tokens > 0;
|
|
51860
|
-
}
|
|
51861
|
-
|
|
51986
|
+
}
|
|
51987
|
+
estimateEventSize(event) {
|
|
51862
51988
|
return JSON.stringify(event).length;
|
|
51863
|
-
}
|
|
51864
|
-
|
|
51989
|
+
}
|
|
51990
|
+
push(event) {
|
|
51865
51991
|
if (!this.hasTokenAvailable())
|
|
51866
51992
|
return false;
|
|
51867
|
-
|
|
51993
|
+
const eventSize = this.estimateEventSize(event);
|
|
51868
51994
|
if (this.uncompressedSize + eventSize > MAX_UNCOMPRESSED_SIZE) {
|
|
51869
51995
|
this.compressCurrentChunk();
|
|
51870
51996
|
}
|
|
@@ -51873,55 +51999,54 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
51873
51999
|
this.events.push(event);
|
|
51874
52000
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
51875
52001
|
return true;
|
|
51876
|
-
}
|
|
51877
|
-
|
|
52002
|
+
}
|
|
52003
|
+
compressCurrentChunk() {
|
|
51878
52004
|
if (this.events.length === 0)
|
|
51879
52005
|
return;
|
|
51880
|
-
|
|
52006
|
+
const jzb = this.pendo.compress(this.events);
|
|
51881
52007
|
this.payloads.push(jzb);
|
|
51882
52008
|
this.clear();
|
|
51883
|
-
}
|
|
51884
|
-
|
|
51885
|
-
|
|
52009
|
+
}
|
|
52010
|
+
generateUrl() {
|
|
52011
|
+
const queryParams = {
|
|
51886
52012
|
v: this.pendo.VERSION,
|
|
51887
52013
|
ct: this.pluginAPI.util.getNow()
|
|
51888
52014
|
};
|
|
51889
52015
|
return this.pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, this.pendo.apiKey, queryParams);
|
|
51890
|
-
}
|
|
51891
|
-
|
|
52016
|
+
}
|
|
52017
|
+
pack() {
|
|
51892
52018
|
if (this.isEmpty())
|
|
51893
52019
|
return;
|
|
51894
|
-
|
|
52020
|
+
const url = this.generateUrl();
|
|
51895
52021
|
this.compressCurrentChunk();
|
|
51896
|
-
|
|
51897
|
-
jzb
|
|
51898
|
-
url
|
|
51899
|
-
})
|
|
52022
|
+
const payloads = this.pendo._.map(this.payloads, (jzb) => ({
|
|
52023
|
+
jzb,
|
|
52024
|
+
url
|
|
52025
|
+
}));
|
|
51900
52026
|
this.payloads = [];
|
|
51901
52027
|
return payloads;
|
|
51902
|
-
}
|
|
51903
|
-
|
|
51904
|
-
}());
|
|
52028
|
+
}
|
|
52029
|
+
}
|
|
51905
52030
|
|
|
51906
|
-
|
|
51907
|
-
|
|
52031
|
+
class DevlogTransport {
|
|
52032
|
+
constructor(globalPendo, pluginAPI) {
|
|
51908
52033
|
this.pendo = globalPendo;
|
|
51909
52034
|
this.pluginAPI = pluginAPI;
|
|
51910
52035
|
}
|
|
51911
|
-
|
|
51912
|
-
|
|
52036
|
+
buildGetUrl(baseUrl, jzb) {
|
|
52037
|
+
const params = {};
|
|
51913
52038
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
51914
52039
|
this.pluginAPI.agent.addAccountIdParams(params, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
51915
52040
|
}
|
|
51916
|
-
|
|
52041
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
51917
52042
|
if (!this.pendo._.isEmpty(jwtOptions)) {
|
|
51918
52043
|
this.pendo._.extend(params, jwtOptions);
|
|
51919
52044
|
}
|
|
51920
52045
|
params.jzb = jzb;
|
|
51921
|
-
|
|
51922
|
-
return
|
|
51923
|
-
}
|
|
51924
|
-
|
|
52046
|
+
const queryString = this.pendo._.map(params, (value, key) => `${key}=${value}`).join('&');
|
|
52047
|
+
return `${baseUrl}${baseUrl.indexOf('?') !== -1 ? '&' : '?'}${queryString}`;
|
|
52048
|
+
}
|
|
52049
|
+
get(url, options) {
|
|
51925
52050
|
options.method = 'GET';
|
|
51926
52051
|
if (this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
51927
52052
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
@@ -51929,90 +52054,86 @@ var DevlogTransport = /** @class */ (function () {
|
|
|
51929
52054
|
else {
|
|
51930
52055
|
return this.pendo.ajax.get(url);
|
|
51931
52056
|
}
|
|
51932
|
-
}
|
|
51933
|
-
|
|
51934
|
-
|
|
51935
|
-
var getUrl = this.buildGetUrl(url, jzb);
|
|
52057
|
+
}
|
|
52058
|
+
sendRequestWithGet({ url, jzb }) {
|
|
52059
|
+
const getUrl = this.buildGetUrl(url, jzb);
|
|
51936
52060
|
return this.get(getUrl, {
|
|
51937
52061
|
headers: {
|
|
51938
52062
|
'Content-Type': 'application/octet-stream'
|
|
51939
52063
|
}
|
|
51940
52064
|
});
|
|
51941
|
-
}
|
|
51942
|
-
|
|
52065
|
+
}
|
|
52066
|
+
post(url, options) {
|
|
51943
52067
|
options.method = 'POST';
|
|
51944
52068
|
if (options.keepalive && this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
51945
52069
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
51946
52070
|
}
|
|
51947
52071
|
else if (options.keepalive && this.pluginAPI.transmit.sendBeacon.supported()) {
|
|
51948
|
-
|
|
52072
|
+
const result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
|
|
51949
52073
|
return result ? Promise$2.resolve() : Promise$2.reject(new Error('sendBeacon failed to send devlog data'));
|
|
51950
52074
|
}
|
|
51951
52075
|
else {
|
|
51952
52076
|
return this.pendo.ajax.post(url, options.body);
|
|
51953
52077
|
}
|
|
51954
|
-
}
|
|
51955
|
-
|
|
51956
|
-
|
|
51957
|
-
|
|
51958
|
-
var bodyPayload = {
|
|
52078
|
+
}
|
|
52079
|
+
sendRequestWithPost({ url, jzb }, isUnload) {
|
|
52080
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
52081
|
+
const bodyPayload = {
|
|
51959
52082
|
events: jzb,
|
|
51960
52083
|
browser_time: this.pluginAPI.util.getNow()
|
|
51961
52084
|
};
|
|
51962
52085
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
51963
52086
|
this.pluginAPI.agent.addAccountIdParams(bodyPayload, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
51964
52087
|
}
|
|
51965
|
-
|
|
52088
|
+
const body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
|
|
51966
52089
|
return this.post(url, {
|
|
51967
|
-
body
|
|
52090
|
+
body,
|
|
51968
52091
|
headers: {
|
|
51969
52092
|
'Content-Type': 'application/json'
|
|
51970
52093
|
},
|
|
51971
52094
|
keepalive: isUnload
|
|
51972
52095
|
});
|
|
51973
|
-
}
|
|
51974
|
-
|
|
51975
|
-
|
|
51976
|
-
var compressedLength = jzb.length;
|
|
52096
|
+
}
|
|
52097
|
+
sendRequest({ url, jzb }, isUnload) {
|
|
52098
|
+
const compressedLength = jzb.length;
|
|
51977
52099
|
if (compressedLength <= this.pluginAPI.constants.ENCODED_EVENT_MAX_LENGTH && !this.pluginAPI.ConfigReader.get('sendEventsWithPostOnly')) {
|
|
51978
|
-
return this.sendRequestWithGet({ url
|
|
52100
|
+
return this.sendRequestWithGet({ url, jzb });
|
|
51979
52101
|
}
|
|
51980
|
-
return this.sendRequestWithPost({ url
|
|
51981
|
-
}
|
|
51982
|
-
|
|
51983
|
-
}());
|
|
52102
|
+
return this.sendRequestWithPost({ url, jzb }, isUnload);
|
|
52103
|
+
}
|
|
52104
|
+
}
|
|
51984
52105
|
|
|
51985
52106
|
function ConsoleCapture() {
|
|
51986
|
-
|
|
51987
|
-
|
|
51988
|
-
|
|
51989
|
-
|
|
51990
|
-
|
|
51991
|
-
|
|
51992
|
-
|
|
51993
|
-
|
|
51994
|
-
|
|
51995
|
-
|
|
51996
|
-
|
|
51997
|
-
|
|
52107
|
+
let pluginAPI;
|
|
52108
|
+
let _;
|
|
52109
|
+
let globalPendo;
|
|
52110
|
+
let buffer;
|
|
52111
|
+
let sendQueue;
|
|
52112
|
+
let sendInterval;
|
|
52113
|
+
let transport;
|
|
52114
|
+
let isPtmPaused;
|
|
52115
|
+
let isCapturingConsoleLogs = false;
|
|
52116
|
+
const CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
|
|
52117
|
+
const CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
|
|
52118
|
+
const DEV_LOG_SUB_TYPE = 'console';
|
|
51998
52119
|
// deduplicate logs
|
|
51999
|
-
|
|
52120
|
+
let lastLogKey = '';
|
|
52000
52121
|
return {
|
|
52001
52122
|
name: 'ConsoleCapture',
|
|
52002
|
-
initialize
|
|
52003
|
-
teardown
|
|
52004
|
-
addIntercepts
|
|
52005
|
-
createConsoleEvent
|
|
52006
|
-
captureStackTrace
|
|
52007
|
-
send
|
|
52008
|
-
setCaptureState
|
|
52009
|
-
recordingStarted
|
|
52010
|
-
recordingStopped
|
|
52011
|
-
onAppHidden
|
|
52012
|
-
onAppUnloaded
|
|
52013
|
-
onPtmPaused
|
|
52014
|
-
onPtmUnpaused
|
|
52015
|
-
securityPolicyViolationFn
|
|
52123
|
+
initialize,
|
|
52124
|
+
teardown,
|
|
52125
|
+
addIntercepts,
|
|
52126
|
+
createConsoleEvent,
|
|
52127
|
+
captureStackTrace,
|
|
52128
|
+
send,
|
|
52129
|
+
setCaptureState,
|
|
52130
|
+
recordingStarted,
|
|
52131
|
+
recordingStopped,
|
|
52132
|
+
onAppHidden,
|
|
52133
|
+
onAppUnloaded,
|
|
52134
|
+
onPtmPaused,
|
|
52135
|
+
onPtmUnpaused,
|
|
52136
|
+
securityPolicyViolationFn,
|
|
52016
52137
|
get isCapturingConsoleLogs() {
|
|
52017
52138
|
return isCapturingConsoleLogs;
|
|
52018
52139
|
},
|
|
@@ -52029,16 +52150,16 @@ function ConsoleCapture() {
|
|
|
52029
52150
|
function initialize(pendo, PluginAPI) {
|
|
52030
52151
|
_ = pendo._;
|
|
52031
52152
|
pluginAPI = PluginAPI;
|
|
52032
|
-
|
|
52153
|
+
const { ConfigReader } = pluginAPI;
|
|
52033
52154
|
ConfigReader.addOption(CAPTURE_CONSOLE_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
|
|
52034
|
-
|
|
52155
|
+
const captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
|
|
52035
52156
|
if (!captureConsoleEnabled)
|
|
52036
52157
|
return;
|
|
52037
52158
|
globalPendo = pendo;
|
|
52038
52159
|
buffer = new DevlogBuffer(pendo, pluginAPI);
|
|
52039
52160
|
transport = new DevlogTransport(pendo, pluginAPI);
|
|
52040
52161
|
sendQueue = new pluginAPI.SendQueue(transport.sendRequest.bind(transport));
|
|
52041
|
-
sendInterval = setInterval(
|
|
52162
|
+
sendInterval = setInterval(() => {
|
|
52042
52163
|
if (!sendQueue.failed()) {
|
|
52043
52164
|
send();
|
|
52044
52165
|
}
|
|
@@ -52064,19 +52185,17 @@ function ConsoleCapture() {
|
|
|
52064
52185
|
function onPtmUnpaused() {
|
|
52065
52186
|
isPtmPaused = false;
|
|
52066
52187
|
if (!buffer.isEmpty()) {
|
|
52067
|
-
for (
|
|
52068
|
-
|
|
52069
|
-
pluginAPI.Events.eventCaptured.trigger(event_1);
|
|
52188
|
+
for (const event of buffer.events) {
|
|
52189
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
52070
52190
|
}
|
|
52071
52191
|
send();
|
|
52072
52192
|
}
|
|
52073
52193
|
}
|
|
52074
|
-
function setCaptureState(
|
|
52075
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
|
|
52194
|
+
function setCaptureState({ shouldCapture = false, reason = '' } = {}) {
|
|
52076
52195
|
if (shouldCapture === isCapturingConsoleLogs)
|
|
52077
52196
|
return;
|
|
52078
52197
|
isCapturingConsoleLogs = shouldCapture;
|
|
52079
|
-
pluginAPI.log.info(
|
|
52198
|
+
pluginAPI.log.info(`[ConsoleCapture] Console log capture ${shouldCapture ? 'started' : 'stopped'}${reason ? `: ${reason}` : ''}`);
|
|
52080
52199
|
}
|
|
52081
52200
|
function recordingStarted() {
|
|
52082
52201
|
setCaptureState({ shouldCapture: true, reason: 'recording started' });
|
|
@@ -52096,12 +52215,12 @@ function ConsoleCapture() {
|
|
|
52096
52215
|
}
|
|
52097
52216
|
function addIntercepts() {
|
|
52098
52217
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52099
|
-
|
|
52218
|
+
const originalMethod = console[methodName];
|
|
52100
52219
|
if (!originalMethod)
|
|
52101
52220
|
return;
|
|
52102
52221
|
console[methodName] = _.wrap(originalMethod, function (originalFn) {
|
|
52103
52222
|
// slice 1 to omit originalFn
|
|
52104
|
-
|
|
52223
|
+
const args = _.toArray(arguments).slice(1);
|
|
52105
52224
|
originalFn.apply(console, args);
|
|
52106
52225
|
createConsoleEvent(args, methodName);
|
|
52107
52226
|
});
|
|
@@ -52113,10 +52232,10 @@ function ConsoleCapture() {
|
|
|
52113
52232
|
function securityPolicyViolationFn(evt) {
|
|
52114
52233
|
if (!evt || typeof evt !== 'object')
|
|
52115
52234
|
return;
|
|
52116
|
-
|
|
52117
|
-
|
|
52118
|
-
|
|
52119
|
-
|
|
52235
|
+
const { blockedURI, violatedDirective, effectiveDirective, disposition, originalPolicy } = evt;
|
|
52236
|
+
const directive = violatedDirective || effectiveDirective;
|
|
52237
|
+
const isReportOnly = disposition === 'report';
|
|
52238
|
+
const message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
|
|
52120
52239
|
if (isReportOnly) {
|
|
52121
52240
|
createConsoleEvent([message], 'warn', { skipStackTrace: true, skipScrubPII: true });
|
|
52122
52241
|
}
|
|
@@ -52124,13 +52243,12 @@ function ConsoleCapture() {
|
|
|
52124
52243
|
createConsoleEvent([message], 'error', { skipStackTrace: true, skipScrubPII: true });
|
|
52125
52244
|
}
|
|
52126
52245
|
}
|
|
52127
|
-
function createConsoleEvent(args, methodName,
|
|
52128
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.skipStackTrace, skipStackTrace = _c === void 0 ? false : _c, _d = _b.skipScrubPII, skipScrubPII = _d === void 0 ? false : _d;
|
|
52246
|
+
function createConsoleEvent(args, methodName, { skipStackTrace = false, skipScrubPII = false } = {}) {
|
|
52129
52247
|
if (!isCapturingConsoleLogs || !args || args.length === 0 || !_.contains(CONSOLE_METHODS, methodName))
|
|
52130
52248
|
return;
|
|
52131
52249
|
// stringify args
|
|
52132
|
-
|
|
52133
|
-
|
|
52250
|
+
let message = _.compact(_.map(args, arg => {
|
|
52251
|
+
let stringifiedArg;
|
|
52134
52252
|
try {
|
|
52135
52253
|
stringifiedArg = stringify(arg);
|
|
52136
52254
|
}
|
|
@@ -52142,22 +52260,22 @@ function ConsoleCapture() {
|
|
|
52142
52260
|
if (!message)
|
|
52143
52261
|
return;
|
|
52144
52262
|
// capture stack trace
|
|
52145
|
-
|
|
52263
|
+
let stackTrace = '';
|
|
52146
52264
|
if (!skipStackTrace) {
|
|
52147
|
-
|
|
52265
|
+
const maxStackFrames = methodName === 'error' ? 4 : 1;
|
|
52148
52266
|
stackTrace = captureStackTrace(maxStackFrames);
|
|
52149
52267
|
}
|
|
52150
52268
|
// truncate message and stack trace
|
|
52151
52269
|
message = truncate(message);
|
|
52152
52270
|
stackTrace = truncate(stackTrace);
|
|
52153
52271
|
// de-duplicate log
|
|
52154
|
-
|
|
52272
|
+
const logKey = generateLogKey(methodName, message, stackTrace);
|
|
52155
52273
|
if (isExistingDuplicateLog(logKey)) {
|
|
52156
52274
|
buffer.lastEvent.devLogCount++;
|
|
52157
52275
|
return;
|
|
52158
52276
|
}
|
|
52159
|
-
|
|
52160
|
-
|
|
52277
|
+
const devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
|
|
52278
|
+
const consoleEvent = Object.assign(Object.assign({}, devLogEnvelope), { subType: DEV_LOG_SUB_TYPE, devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: skipScrubPII ? message : scrubPII({ string: message, _ }), devLogTrace: stackTrace, devLogCount: 1 });
|
|
52161
52279
|
if (!buffer.hasTokenAvailable())
|
|
52162
52280
|
return consoleEvent;
|
|
52163
52281
|
if (!isPtmPaused) {
|
|
@@ -52169,8 +52287,8 @@ function ConsoleCapture() {
|
|
|
52169
52287
|
}
|
|
52170
52288
|
function captureStackTrace(maxStackFrames) {
|
|
52171
52289
|
try {
|
|
52172
|
-
|
|
52173
|
-
return _.map(stackFrames,
|
|
52290
|
+
const stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
|
|
52291
|
+
return _.map(stackFrames, frame => frame.toString()).join('\n');
|
|
52174
52292
|
}
|
|
52175
52293
|
catch (error) {
|
|
52176
52294
|
return '';
|
|
@@ -52182,22 +52300,21 @@ function ConsoleCapture() {
|
|
|
52182
52300
|
function updateLastLog(logKey) {
|
|
52183
52301
|
lastLogKey = logKey;
|
|
52184
52302
|
}
|
|
52185
|
-
function send(
|
|
52186
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
|
|
52303
|
+
function send({ unload = false, hidden = false } = {}) {
|
|
52187
52304
|
if (!buffer || buffer.isEmpty())
|
|
52188
52305
|
return;
|
|
52189
52306
|
if (!globalPendo.isSendingEvents()) {
|
|
52190
52307
|
buffer.clear();
|
|
52191
52308
|
return;
|
|
52192
52309
|
}
|
|
52193
|
-
|
|
52310
|
+
const payloads = buffer.pack();
|
|
52194
52311
|
if (!payloads || payloads.length === 0)
|
|
52195
52312
|
return;
|
|
52196
52313
|
if (unload || hidden) {
|
|
52197
52314
|
sendQueue.drain(payloads, unload);
|
|
52198
52315
|
}
|
|
52199
52316
|
else {
|
|
52200
|
-
sendQueue.push
|
|
52317
|
+
sendQueue.push(...payloads);
|
|
52201
52318
|
}
|
|
52202
52319
|
}
|
|
52203
52320
|
function teardown() {
|
|
@@ -52221,7 +52338,7 @@ function ConsoleCapture() {
|
|
|
52221
52338
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52222
52339
|
if (!console[methodName])
|
|
52223
52340
|
return _.noop;
|
|
52224
|
-
|
|
52341
|
+
const unwrap = console[methodName]._pendoUnwrap;
|
|
52225
52342
|
if (_.isFunction(unwrap)) {
|
|
52226
52343
|
unwrap();
|
|
52227
52344
|
}
|
|
@@ -52230,59 +52347,59 @@ function ConsoleCapture() {
|
|
|
52230
52347
|
}
|
|
52231
52348
|
|
|
52232
52349
|
function NetworkCapture() {
|
|
52233
|
-
|
|
52234
|
-
|
|
52235
|
-
|
|
52236
|
-
|
|
52237
|
-
|
|
52238
|
-
|
|
52239
|
-
|
|
52240
|
-
|
|
52241
|
-
|
|
52242
|
-
|
|
52243
|
-
|
|
52244
|
-
|
|
52245
|
-
|
|
52246
|
-
|
|
52247
|
-
|
|
52248
|
-
|
|
52249
|
-
|
|
52250
|
-
|
|
52251
|
-
|
|
52252
|
-
|
|
52253
|
-
|
|
52254
|
-
|
|
52350
|
+
let pluginAPI;
|
|
52351
|
+
let globalPendo;
|
|
52352
|
+
let requestMap = {};
|
|
52353
|
+
let buffer;
|
|
52354
|
+
let sendQueue;
|
|
52355
|
+
let sendInterval;
|
|
52356
|
+
let transport;
|
|
52357
|
+
let isPtmPaused;
|
|
52358
|
+
let requestBodyCb;
|
|
52359
|
+
let responseBodyCb;
|
|
52360
|
+
let pendoDevlogBaseUrl;
|
|
52361
|
+
let isCapturingNetworkLogs = false;
|
|
52362
|
+
let excludeRequestUrls = [];
|
|
52363
|
+
const CAPTURE_NETWORK_CONFIG = 'captureNetworkRequests';
|
|
52364
|
+
const NETWORK_SUB_TYPE = 'network';
|
|
52365
|
+
const NETWORK_LOGS_CONFIG = 'networkLogs';
|
|
52366
|
+
const NETWORK_LOGS_CONFIG_ALLOWED_REQUEST_HEADERS = 'networkLogs.allowedRequestHeaders';
|
|
52367
|
+
const NETWORK_LOGS_CONFIG_ALLOWED_RESPONSE_HEADERS = 'networkLogs.allowedResponseHeaders';
|
|
52368
|
+
const NETWORK_LOGS_CONFIG_CAPTURE_REQUEST_BODY = 'networkLogs.captureRequestBody';
|
|
52369
|
+
const NETWORK_LOGS_CONFIG_CAPTURE_RESPONSE_BODY = 'networkLogs.captureResponseBody';
|
|
52370
|
+
const NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS = 'networkLogs.excludeRequestUrls';
|
|
52371
|
+
const allowedRequestHeaders = {
|
|
52255
52372
|
'content-type': true, 'content-length': true, 'accept': true, 'accept-language': true
|
|
52256
52373
|
};
|
|
52257
|
-
|
|
52374
|
+
const allowedResponseHeaders = {
|
|
52258
52375
|
'cache-control': true, 'content-length': true, 'content-type': true, 'content-language': true
|
|
52259
52376
|
};
|
|
52260
52377
|
return {
|
|
52261
52378
|
name: 'NetworkCapture',
|
|
52262
|
-
initialize
|
|
52263
|
-
teardown
|
|
52264
|
-
handleRequest
|
|
52265
|
-
handleResponse
|
|
52266
|
-
handleError
|
|
52267
|
-
startCapture
|
|
52268
|
-
createNetworkEvent
|
|
52269
|
-
send
|
|
52270
|
-
onPtmPaused
|
|
52271
|
-
onPtmUnpaused
|
|
52272
|
-
onAppHidden
|
|
52273
|
-
onAppUnloaded
|
|
52274
|
-
setCaptureState
|
|
52275
|
-
recordingStarted
|
|
52276
|
-
recordingStopped
|
|
52277
|
-
addConfigOptions
|
|
52278
|
-
processHeaderConfig
|
|
52279
|
-
extractHeaders
|
|
52280
|
-
setupBodyCallbacks
|
|
52281
|
-
processBody
|
|
52282
|
-
processRequestBody
|
|
52283
|
-
processResponseBody
|
|
52284
|
-
buildExcludeRequestUrls
|
|
52285
|
-
isUrlExcluded
|
|
52379
|
+
initialize,
|
|
52380
|
+
teardown,
|
|
52381
|
+
handleRequest,
|
|
52382
|
+
handleResponse,
|
|
52383
|
+
handleError,
|
|
52384
|
+
startCapture,
|
|
52385
|
+
createNetworkEvent,
|
|
52386
|
+
send,
|
|
52387
|
+
onPtmPaused,
|
|
52388
|
+
onPtmUnpaused,
|
|
52389
|
+
onAppHidden,
|
|
52390
|
+
onAppUnloaded,
|
|
52391
|
+
setCaptureState,
|
|
52392
|
+
recordingStarted,
|
|
52393
|
+
recordingStopped,
|
|
52394
|
+
addConfigOptions,
|
|
52395
|
+
processHeaderConfig,
|
|
52396
|
+
extractHeaders,
|
|
52397
|
+
setupBodyCallbacks,
|
|
52398
|
+
processBody,
|
|
52399
|
+
processRequestBody,
|
|
52400
|
+
processResponseBody,
|
|
52401
|
+
buildExcludeRequestUrls,
|
|
52402
|
+
isUrlExcluded,
|
|
52286
52403
|
get isCapturingNetworkLogs() {
|
|
52287
52404
|
return isCapturingNetworkLogs;
|
|
52288
52405
|
},
|
|
@@ -52317,9 +52434,9 @@ function NetworkCapture() {
|
|
|
52317
52434
|
function initialize(pendo, PluginAPI) {
|
|
52318
52435
|
pluginAPI = PluginAPI;
|
|
52319
52436
|
globalPendo = pendo;
|
|
52320
|
-
|
|
52437
|
+
const { ConfigReader } = pluginAPI;
|
|
52321
52438
|
ConfigReader.addOption(CAPTURE_NETWORK_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
|
|
52322
|
-
|
|
52439
|
+
const captureNetworkEnabled = ConfigReader.get(CAPTURE_NETWORK_CONFIG);
|
|
52323
52440
|
if (!captureNetworkEnabled)
|
|
52324
52441
|
return;
|
|
52325
52442
|
buffer = new DevlogBuffer(pendo, pluginAPI);
|
|
@@ -52330,7 +52447,7 @@ function NetworkCapture() {
|
|
|
52330
52447
|
processHeaderConfig(NETWORK_LOGS_CONFIG_ALLOWED_RESPONSE_HEADERS, allowedResponseHeaders);
|
|
52331
52448
|
setupBodyCallbacks();
|
|
52332
52449
|
buildExcludeRequestUrls();
|
|
52333
|
-
sendInterval = setInterval(
|
|
52450
|
+
sendInterval = setInterval(() => {
|
|
52334
52451
|
if (!sendQueue.failed()) {
|
|
52335
52452
|
send();
|
|
52336
52453
|
}
|
|
@@ -52346,7 +52463,7 @@ function NetworkCapture() {
|
|
|
52346
52463
|
pendoDevlogBaseUrl = pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, globalPendo.apiKey);
|
|
52347
52464
|
}
|
|
52348
52465
|
function addConfigOptions() {
|
|
52349
|
-
|
|
52466
|
+
const { ConfigReader } = pluginAPI;
|
|
52350
52467
|
ConfigReader.addOption(NETWORK_LOGS_CONFIG, [ConfigReader.sources.SNIPPET_SRC], {});
|
|
52351
52468
|
/**
|
|
52352
52469
|
* Additional request headers to capture in network logs.
|
|
@@ -52406,17 +52523,17 @@ function NetworkCapture() {
|
|
|
52406
52523
|
ConfigReader.addOption(NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS, [ConfigReader.sources.SNIPPET_SRC], []);
|
|
52407
52524
|
}
|
|
52408
52525
|
function processHeaderConfig(configHeaderName, targetHeaders) {
|
|
52409
|
-
|
|
52526
|
+
const configHeaders = pluginAPI.ConfigReader.get(configHeaderName);
|
|
52410
52527
|
if (!configHeaders || configHeaders.length === 0)
|
|
52411
52528
|
return;
|
|
52412
|
-
globalPendo._.each(configHeaders,
|
|
52529
|
+
globalPendo._.each(configHeaders, (header) => {
|
|
52413
52530
|
if (!header || !globalPendo._.isString(header))
|
|
52414
52531
|
return;
|
|
52415
52532
|
targetHeaders[header.toLowerCase()] = true;
|
|
52416
52533
|
});
|
|
52417
52534
|
}
|
|
52418
52535
|
function setupBodyCallbacks() {
|
|
52419
|
-
|
|
52536
|
+
const config = pluginAPI.ConfigReader.get(NETWORK_LOGS_CONFIG);
|
|
52420
52537
|
if (!config)
|
|
52421
52538
|
return;
|
|
52422
52539
|
if (globalPendo._.isFunction(config.captureRequestBody)) {
|
|
@@ -52427,11 +52544,11 @@ function NetworkCapture() {
|
|
|
52427
52544
|
}
|
|
52428
52545
|
}
|
|
52429
52546
|
function buildExcludeRequestUrls() {
|
|
52430
|
-
|
|
52547
|
+
const requestUrls = pluginAPI.ConfigReader.get(NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS);
|
|
52431
52548
|
if (!requestUrls || requestUrls.length === 0)
|
|
52432
52549
|
return;
|
|
52433
|
-
globalPendo._.each(requestUrls,
|
|
52434
|
-
|
|
52550
|
+
globalPendo._.each(requestUrls, (requestUrl) => {
|
|
52551
|
+
const processedRequestUrl = processUrlPattern(requestUrl);
|
|
52435
52552
|
if (!processedRequestUrl)
|
|
52436
52553
|
return;
|
|
52437
52554
|
excludeRequestUrls.push(processedRequestUrl);
|
|
@@ -52440,13 +52557,13 @@ function NetworkCapture() {
|
|
|
52440
52557
|
function processUrlPattern(url) {
|
|
52441
52558
|
if (!url)
|
|
52442
52559
|
return;
|
|
52443
|
-
|
|
52560
|
+
const isRegex = globalPendo._.isRegExp(url);
|
|
52444
52561
|
if (!globalPendo._.isString(url) && !isRegex)
|
|
52445
52562
|
return;
|
|
52446
52563
|
if (isRegex)
|
|
52447
52564
|
return url;
|
|
52448
|
-
|
|
52449
|
-
return new RegExp(
|
|
52565
|
+
const escapedUrl = pluginAPI.util.escapeRegExp(url);
|
|
52566
|
+
return new RegExp(`^${escapedUrl}$`);
|
|
52450
52567
|
}
|
|
52451
52568
|
function onPtmPaused() {
|
|
52452
52569
|
isPtmPaused = true;
|
|
@@ -52454,9 +52571,8 @@ function NetworkCapture() {
|
|
|
52454
52571
|
function onPtmUnpaused() {
|
|
52455
52572
|
isPtmPaused = false;
|
|
52456
52573
|
if (!buffer.isEmpty()) {
|
|
52457
|
-
for (
|
|
52458
|
-
|
|
52459
|
-
pluginAPI.Events.eventCaptured.trigger(event_1);
|
|
52574
|
+
for (const event of buffer.events) {
|
|
52575
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
52460
52576
|
}
|
|
52461
52577
|
send();
|
|
52462
52578
|
}
|
|
@@ -52467,12 +52583,11 @@ function NetworkCapture() {
|
|
|
52467
52583
|
function onAppUnloaded() {
|
|
52468
52584
|
send({ unload: true });
|
|
52469
52585
|
}
|
|
52470
|
-
function setCaptureState(
|
|
52471
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
|
|
52586
|
+
function setCaptureState({ shouldCapture = false, reason = '' } = {}) {
|
|
52472
52587
|
if (shouldCapture === isCapturingNetworkLogs)
|
|
52473
52588
|
return;
|
|
52474
52589
|
isCapturingNetworkLogs = shouldCapture;
|
|
52475
|
-
pluginAPI.log.info(
|
|
52590
|
+
pluginAPI.log.info(`[NetworkCapture] Network request capture ${shouldCapture ? 'started' : 'stopped'}${reason ? `: ${reason}` : ''}`);
|
|
52476
52591
|
}
|
|
52477
52592
|
function recordingStarted() {
|
|
52478
52593
|
return setCaptureState({ shouldCapture: true, reason: 'recording started' });
|
|
@@ -52507,7 +52622,7 @@ function NetworkCapture() {
|
|
|
52507
52622
|
return false;
|
|
52508
52623
|
if (excludeRequestUrls.length === 0)
|
|
52509
52624
|
return false;
|
|
52510
|
-
return globalPendo._.some(excludeRequestUrls,
|
|
52625
|
+
return globalPendo._.some(excludeRequestUrls, (excludeRequestUrl) => {
|
|
52511
52626
|
return excludeRequestUrl.test(url);
|
|
52512
52627
|
});
|
|
52513
52628
|
}
|
|
@@ -52521,7 +52636,7 @@ function NetworkCapture() {
|
|
|
52521
52636
|
return;
|
|
52522
52637
|
if (!response)
|
|
52523
52638
|
return;
|
|
52524
|
-
|
|
52639
|
+
const request = requestMap[response.requestId];
|
|
52525
52640
|
if (!request)
|
|
52526
52641
|
return;
|
|
52527
52642
|
// Skip capturing successful devlog events to avoid infinite loops
|
|
@@ -52533,9 +52648,9 @@ function NetworkCapture() {
|
|
|
52533
52648
|
delete requestMap[response.requestId];
|
|
52534
52649
|
return;
|
|
52535
52650
|
}
|
|
52536
|
-
|
|
52537
|
-
request
|
|
52538
|
-
response
|
|
52651
|
+
const networkEvent = createNetworkEvent({
|
|
52652
|
+
request,
|
|
52653
|
+
response
|
|
52539
52654
|
});
|
|
52540
52655
|
if (!isPtmPaused) {
|
|
52541
52656
|
pluginAPI.Events.eventCaptured.trigger(networkEvent);
|
|
@@ -52543,8 +52658,7 @@ function NetworkCapture() {
|
|
|
52543
52658
|
buffer.push(networkEvent);
|
|
52544
52659
|
delete requestMap[response.requestId];
|
|
52545
52660
|
}
|
|
52546
|
-
function handleError(
|
|
52547
|
-
var error = _a.error, context = _a.context;
|
|
52661
|
+
function handleError({ error, context }) {
|
|
52548
52662
|
if (!isCapturingNetworkLogs)
|
|
52549
52663
|
return;
|
|
52550
52664
|
if (error.requestId && requestMap[error.requestId]) {
|
|
@@ -52558,13 +52672,13 @@ function NetworkCapture() {
|
|
|
52558
52672
|
}
|
|
52559
52673
|
}
|
|
52560
52674
|
function extractHeaders(headers, allowedHeaders) {
|
|
52561
|
-
|
|
52675
|
+
const { keys, reduce } = globalPendo._;
|
|
52562
52676
|
if (!headers || !allowedHeaders)
|
|
52563
52677
|
return [];
|
|
52564
|
-
return reduce(keys(headers),
|
|
52565
|
-
|
|
52678
|
+
return reduce(keys(headers), (acc, key) => {
|
|
52679
|
+
const normalizedKey = key.toLowerCase();
|
|
52566
52680
|
if (allowedHeaders[normalizedKey]) {
|
|
52567
|
-
acc.push(
|
|
52681
|
+
acc.push(`${key}: ${headers[key]}`);
|
|
52568
52682
|
}
|
|
52569
52683
|
return acc;
|
|
52570
52684
|
}, []);
|
|
@@ -52572,16 +52686,15 @@ function NetworkCapture() {
|
|
|
52572
52686
|
function processBody(body, contentType) {
|
|
52573
52687
|
if (!body || !globalPendo._.isString(body))
|
|
52574
52688
|
return '';
|
|
52575
|
-
|
|
52689
|
+
const processedBody = maskSensitiveFields({ string: body, contentType, _: globalPendo._ });
|
|
52576
52690
|
return truncate(processedBody, true);
|
|
52577
52691
|
}
|
|
52578
|
-
function processRequestBody(
|
|
52579
|
-
var request = _a.request;
|
|
52692
|
+
function processRequestBody({ request }) {
|
|
52580
52693
|
if (!request || !request.body || !requestBodyCb)
|
|
52581
52694
|
return '';
|
|
52582
52695
|
try {
|
|
52583
|
-
|
|
52584
|
-
|
|
52696
|
+
const body = requestBodyCb(request.body, { request });
|
|
52697
|
+
const contentType = globalPendo._.get(request, 'headers.content-type', '');
|
|
52585
52698
|
return processBody(body, contentType);
|
|
52586
52699
|
}
|
|
52587
52700
|
catch (error) {
|
|
@@ -52589,13 +52702,12 @@ function NetworkCapture() {
|
|
|
52589
52702
|
return '[Failed to process request body]';
|
|
52590
52703
|
}
|
|
52591
52704
|
}
|
|
52592
|
-
function processResponseBody(
|
|
52593
|
-
var response = _a.response;
|
|
52705
|
+
function processResponseBody({ response }) {
|
|
52594
52706
|
if (!response || !response.body || !responseBodyCb)
|
|
52595
52707
|
return '';
|
|
52596
52708
|
try {
|
|
52597
|
-
|
|
52598
|
-
|
|
52709
|
+
const body = responseBodyCb(response.body, { response });
|
|
52710
|
+
const contentType = globalPendo._.get(response, 'headers.content-type', '');
|
|
52599
52711
|
return processBody(body, contentType);
|
|
52600
52712
|
}
|
|
52601
52713
|
catch (error) {
|
|
@@ -52603,34 +52715,32 @@ function NetworkCapture() {
|
|
|
52603
52715
|
return '[Failed to process response body]';
|
|
52604
52716
|
}
|
|
52605
52717
|
}
|
|
52606
|
-
function createNetworkEvent(
|
|
52607
|
-
|
|
52608
|
-
|
|
52609
|
-
|
|
52610
|
-
|
|
52611
|
-
var networkEvent = __assign(__assign({}, devLogEnvelope), { subType: NETWORK_SUB_TYPE, devLogMethod: request.method, devLogStatusCode: response.status, devLogRequestUrl: request.url, devLogRequestHeaders: requestHeaders, devLogResponseHeaders: responseHeaders, devLogCount: 1 });
|
|
52718
|
+
function createNetworkEvent({ request, response }) {
|
|
52719
|
+
const devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
|
|
52720
|
+
const requestHeaders = extractHeaders(request.headers, allowedRequestHeaders);
|
|
52721
|
+
const responseHeaders = extractHeaders(response.headers, allowedResponseHeaders);
|
|
52722
|
+
const networkEvent = Object.assign(Object.assign({}, devLogEnvelope), { subType: NETWORK_SUB_TYPE, devLogMethod: request.method, devLogStatusCode: response.status, devLogRequestUrl: request.url, devLogRequestHeaders: requestHeaders, devLogResponseHeaders: responseHeaders, devLogCount: 1 });
|
|
52612
52723
|
if (requestBodyCb) {
|
|
52613
|
-
networkEvent.devLogRequestBody = processRequestBody({ request
|
|
52724
|
+
networkEvent.devLogRequestBody = processRequestBody({ request });
|
|
52614
52725
|
}
|
|
52615
52726
|
if (responseBodyCb) {
|
|
52616
|
-
networkEvent.devLogResponseBody = processResponseBody({ response
|
|
52727
|
+
networkEvent.devLogResponseBody = processResponseBody({ response });
|
|
52617
52728
|
}
|
|
52618
52729
|
return networkEvent;
|
|
52619
52730
|
}
|
|
52620
|
-
function send(
|
|
52621
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
|
|
52731
|
+
function send({ unload = false, hidden = false } = {}) {
|
|
52622
52732
|
if (!buffer || buffer.isEmpty())
|
|
52623
52733
|
return;
|
|
52624
52734
|
if (!globalPendo.isSendingEvents()) {
|
|
52625
52735
|
buffer.clear();
|
|
52626
52736
|
return;
|
|
52627
52737
|
}
|
|
52628
|
-
|
|
52738
|
+
const payloads = buffer.pack();
|
|
52629
52739
|
if (unload || hidden) {
|
|
52630
52740
|
sendQueue.drain(payloads, unload);
|
|
52631
52741
|
}
|
|
52632
52742
|
else {
|
|
52633
|
-
sendQueue.push
|
|
52743
|
+
sendQueue.push(...payloads);
|
|
52634
52744
|
}
|
|
52635
52745
|
}
|
|
52636
52746
|
}
|
|
@@ -52960,18 +53070,23 @@ var predictGuidesScript = function (_a) {
|
|
|
52960
53070
|
log('[predict] no recordId found in URL, aborting');
|
|
52961
53071
|
return;
|
|
52962
53072
|
}
|
|
53073
|
+
if (!designerServer) {
|
|
53074
|
+
log('[predict] no designerServer found, aborting');
|
|
53075
|
+
return;
|
|
53076
|
+
}
|
|
52963
53077
|
var predictBaseUrl = getPredictBaseUrl(designerServer);
|
|
53078
|
+
log("[predict] predictBaseUrl: ".concat(predictBaseUrl));
|
|
52964
53079
|
cleanupArray.push(setupMessageListener({ token: token, forceAccountId: configuration === null || configuration === void 0 ? void 0 : configuration.forceAccountId, cleanup: cleanup, pendo: pendo, predictBaseUrl: predictBaseUrl }));
|
|
52965
53080
|
cleanupArray.push(createFloatingModal({ recordId: recordId, configuration: configuration, predictBaseUrl: predictBaseUrl }));
|
|
52966
53081
|
};
|
|
52967
53082
|
|
|
52968
|
-
|
|
52969
|
-
|
|
52970
|
-
|
|
52971
|
-
|
|
53083
|
+
const PredictGuides = () => {
|
|
53084
|
+
let pluginApiRef = null;
|
|
53085
|
+
let cleanupArray = [];
|
|
53086
|
+
const cleanup = () => {
|
|
52972
53087
|
var _a;
|
|
52973
53088
|
(_a = pluginApiRef === null || pluginApiRef === void 0 ? void 0 : pluginApiRef.log) === null || _a === void 0 ? void 0 : _a.debug('[predict] cleaning up');
|
|
52974
|
-
for (
|
|
53089
|
+
for (let i = 0; i < cleanupArray.length; i++) {
|
|
52975
53090
|
try {
|
|
52976
53091
|
cleanupArray[i]();
|
|
52977
53092
|
}
|
|
@@ -52979,79 +53094,105 @@ var PredictGuides = function () {
|
|
|
52979
53094
|
}
|
|
52980
53095
|
cleanupArray = [];
|
|
52981
53096
|
};
|
|
52982
|
-
|
|
52983
|
-
var _a;
|
|
53097
|
+
const initialize = (_pendo, PluginAPI) => {
|
|
52984
53098
|
pluginApiRef = PluginAPI;
|
|
52985
|
-
|
|
52986
|
-
|
|
53099
|
+
const configReader = PluginAPI.ConfigReader;
|
|
53100
|
+
const PREDICT_GUIDES_CONFIG = 'predictGuides';
|
|
52987
53101
|
configReader.addOption(PREDICT_GUIDES_CONFIG, [
|
|
52988
53102
|
configReader.sources.SNIPPET_SRC,
|
|
52989
53103
|
configReader.sources.PENDO_CONFIG_SRC
|
|
52990
53104
|
], false);
|
|
52991
|
-
|
|
53105
|
+
const predictGuidesEnabled = configReader.get(PREDICT_GUIDES_CONFIG);
|
|
52992
53106
|
if (!predictGuidesEnabled)
|
|
52993
53107
|
return;
|
|
52994
|
-
|
|
52995
|
-
var designerServer = (_a = PluginAPI.hosts) === null || _a === void 0 ? void 0 : _a.DESIGNER_SERVER;
|
|
53108
|
+
const log = PluginAPI.log.debug.bind(PluginAPI.log);
|
|
52996
53109
|
pluginApiRef.Events.urlChanged.on(cleanup);
|
|
52997
|
-
|
|
53110
|
+
const script = {
|
|
52998
53111
|
name: 'PredictFrameScript',
|
|
52999
|
-
script
|
|
53000
|
-
|
|
53001
|
-
|
|
53112
|
+
script(step, _guide, pendo) {
|
|
53113
|
+
var _a, _b;
|
|
53114
|
+
const designerServer = ((_a = pendo === null || pendo === void 0 ? void 0 : pendo.getConfigValue) === null || _a === void 0 ? void 0 : _a.call(pendo, 'designerServer')) ||
|
|
53115
|
+
((_b = pendo === null || pendo === void 0 ? void 0 : pendo.getConfigValue) === null || _b === void 0 ? void 0 : _b.call(pendo, 'server'));
|
|
53116
|
+
predictGuidesScript({ step, pendo, cleanupArray, cleanup, log, designerServer });
|
|
53117
|
+
this.on('unmounted', (evt) => {
|
|
53002
53118
|
if (evt.reason !== 'hidden')
|
|
53003
53119
|
cleanup();
|
|
53004
53120
|
});
|
|
53005
53121
|
},
|
|
53006
|
-
test
|
|
53007
|
-
|
|
53122
|
+
test(step, _guide) {
|
|
53123
|
+
const stepName = step.name || '';
|
|
53008
53124
|
return PREDICT_STEP_REGEX.test(stepName);
|
|
53009
53125
|
}
|
|
53010
53126
|
};
|
|
53011
53127
|
pluginApiRef.GlobalRuntime.addGlobalScript(script);
|
|
53012
53128
|
};
|
|
53013
|
-
|
|
53129
|
+
const teardown = () => {
|
|
53014
53130
|
var _a, _b;
|
|
53015
53131
|
cleanup();
|
|
53016
53132
|
(_b = (_a = pluginApiRef === null || pluginApiRef === void 0 ? void 0 : pluginApiRef.Events) === null || _a === void 0 ? void 0 : _a.urlChanged) === null || _b === void 0 ? void 0 : _b.off(cleanup);
|
|
53017
53133
|
};
|
|
53018
53134
|
return {
|
|
53019
53135
|
name: 'PredictGuides',
|
|
53020
|
-
initialize
|
|
53021
|
-
teardown
|
|
53022
|
-
};
|
|
53023
|
-
};
|
|
53024
|
-
|
|
53025
|
-
|
|
53026
|
-
|
|
53027
|
-
|
|
53028
|
-
|
|
53029
|
-
|
|
53030
|
-
|
|
53031
|
-
|
|
53032
|
-
|
|
53033
|
-
|
|
53034
|
-
|
|
53035
|
-
|
|
53036
|
-
|
|
53037
|
-
|
|
53038
|
-
|
|
53039
|
-
|
|
53040
|
-
|
|
53041
|
-
|
|
53136
|
+
initialize,
|
|
53137
|
+
teardown
|
|
53138
|
+
};
|
|
53139
|
+
};
|
|
53140
|
+
|
|
53141
|
+
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
53142
|
+
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
53143
|
+
const MESSAGE_CONTENT = 'messageContent';
|
|
53144
|
+
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
53145
|
+
const MESSAGE_ID_PATTERN = 'messageIdPattern';
|
|
53146
|
+
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
53147
|
+
const REACTION_ACTIVE = 'reactionActive';
|
|
53148
|
+
const STREAMING_ACTIVE = 'streamingActive';
|
|
53149
|
+
const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
53150
|
+
const THUMB_DOWN = 'thumbDown';
|
|
53151
|
+
const THUMB_UP = 'thumbUp';
|
|
53152
|
+
const TURN_CONTAINER = 'turnContainer';
|
|
53153
|
+
const USER_MESSAGE = 'userMessage';
|
|
53154
|
+
const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
|
|
53155
|
+
const CUSTOM_AGENT_ID = 'customAgentId';
|
|
53156
|
+
const CUSTOM_AGENT_NAME = 'customAgentName';
|
|
53157
|
+
const REQUIRED_SELECTORS = [
|
|
53042
53158
|
ASSISTANT_MESSAGE,
|
|
53043
53159
|
CONVERSATION_ID_URL_PATTERN,
|
|
53044
53160
|
STREAMING_ACTIVE,
|
|
53045
53161
|
TURN_CONTAINER,
|
|
53046
53162
|
USER_MESSAGE
|
|
53047
53163
|
];
|
|
53048
|
-
|
|
53049
|
-
|
|
53050
|
-
|
|
53051
|
-
|
|
53052
|
-
|
|
53053
|
-
|
|
53054
|
-
|
|
53164
|
+
const SUPPORTED_PRESETS = ['chatgpt-full', 'gemini-full', 'claude-full', 'copilot-full'];
|
|
53165
|
+
const STREAMING_END_SETTLE_MS = 500;
|
|
53166
|
+
const SUBMISSION_START_RETRY_MS = 1000;
|
|
53167
|
+
const SUBMISSION_START_MAX_ATTEMPTS = 4;
|
|
53168
|
+
class DOMConversation {
|
|
53169
|
+
// Returns the list of required selector types that are missing or empty
|
|
53170
|
+
// in the given cssSelectors config. An empty array means the config is
|
|
53171
|
+
// valid for instantiation.
|
|
53172
|
+
static validateConfig(cssSelectors) {
|
|
53173
|
+
if (!Array.isArray(cssSelectors)) {
|
|
53174
|
+
return REQUIRED_SELECTORS.slice();
|
|
53175
|
+
}
|
|
53176
|
+
const present = new Set();
|
|
53177
|
+
for (const cfg of cssSelectors) {
|
|
53178
|
+
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
53179
|
+
continue;
|
|
53180
|
+
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
53181
|
+
try {
|
|
53182
|
+
RegExp(cfg.cssSelector);
|
|
53183
|
+
}
|
|
53184
|
+
catch (e) {
|
|
53185
|
+
continue;
|
|
53186
|
+
}
|
|
53187
|
+
}
|
|
53188
|
+
present.add(cfg.type);
|
|
53189
|
+
}
|
|
53190
|
+
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
53191
|
+
}
|
|
53192
|
+
static supportedPreset(preset) {
|
|
53193
|
+
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
53194
|
+
}
|
|
53195
|
+
constructor(pendo, PluginAPI, id, cssSelectors) {
|
|
53055
53196
|
this.selectors = {};
|
|
53056
53197
|
this.listeners = [];
|
|
53057
53198
|
this.isActive = true;
|
|
@@ -53070,88 +53211,61 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53070
53211
|
this.Sizzle = pendo.Sizzle;
|
|
53071
53212
|
this.id = id;
|
|
53072
53213
|
if (!this._.isArray(cssSelectors)) {
|
|
53073
|
-
this.api.log.error(
|
|
53214
|
+
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
53074
53215
|
cssSelectors = [];
|
|
53075
53216
|
}
|
|
53076
|
-
this._.each(cssSelectors,
|
|
53217
|
+
this._.each(cssSelectors, (cfg) => {
|
|
53077
53218
|
if (cfg && cfg.type) {
|
|
53078
|
-
|
|
53219
|
+
this.selectors[cfg.type] = cfg.cssSelector;
|
|
53079
53220
|
}
|
|
53080
53221
|
});
|
|
53081
53222
|
this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
|
|
53082
|
-
|
|
53223
|
+
const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
|
|
53083
53224
|
if (customAgentIdUrlPattern) { // this is optional
|
|
53084
53225
|
try {
|
|
53085
53226
|
this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
|
|
53086
53227
|
}
|
|
53087
53228
|
catch (error) {
|
|
53088
|
-
this.api.log.error(
|
|
53229
|
+
this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
|
|
53089
53230
|
}
|
|
53090
53231
|
}
|
|
53091
|
-
|
|
53232
|
+
const messageIdPattern = this.selectors[MESSAGE_ID_PATTERN];
|
|
53092
53233
|
if (messageIdPattern) { // optional: gates the request node until its id is fully rendered
|
|
53093
53234
|
try {
|
|
53094
53235
|
this.messageIdRegex = new RegExp(messageIdPattern);
|
|
53095
53236
|
}
|
|
53096
53237
|
catch (error) {
|
|
53097
|
-
this.api.log.error(
|
|
53238
|
+
this.api.log.error(`bad messageIdPattern ${messageIdPattern}`, { error });
|
|
53098
53239
|
}
|
|
53099
53240
|
}
|
|
53100
53241
|
this.root = document.body;
|
|
53101
53242
|
this.setupReactionListener();
|
|
53102
53243
|
this.setupStreamingObserver();
|
|
53103
53244
|
}
|
|
53104
|
-
|
|
53105
|
-
// in the given cssSelectors config. An empty array means the config is
|
|
53106
|
-
// valid for instantiation.
|
|
53107
|
-
DOMConversation.validateConfig = function (cssSelectors) {
|
|
53108
|
-
if (!Array.isArray(cssSelectors)) {
|
|
53109
|
-
return REQUIRED_SELECTORS.slice();
|
|
53110
|
-
}
|
|
53111
|
-
var present = new Set();
|
|
53112
|
-
for (var _i = 0, cssSelectors_1 = cssSelectors; _i < cssSelectors_1.length; _i++) {
|
|
53113
|
-
var cfg = cssSelectors_1[_i];
|
|
53114
|
-
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
53115
|
-
continue;
|
|
53116
|
-
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
53117
|
-
try {
|
|
53118
|
-
RegExp(cfg.cssSelector);
|
|
53119
|
-
}
|
|
53120
|
-
catch (e) {
|
|
53121
|
-
continue;
|
|
53122
|
-
}
|
|
53123
|
-
}
|
|
53124
|
-
present.add(cfg.type);
|
|
53125
|
-
}
|
|
53126
|
-
return REQUIRED_SELECTORS.filter(function (r) { return !present.has(r); });
|
|
53127
|
-
};
|
|
53128
|
-
DOMConversation.supportedPreset = function (preset) {
|
|
53129
|
-
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
53130
|
-
};
|
|
53131
|
-
DOMConversation.prototype.setupReactionListener = function () {
|
|
53245
|
+
setupReactionListener() {
|
|
53132
53246
|
if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
|
|
53133
53247
|
return;
|
|
53134
53248
|
this.reactionClickHandler = this.handleReactionClick.bind(this);
|
|
53135
53249
|
this.root.addEventListener('click', this.reactionClickHandler, true);
|
|
53136
|
-
}
|
|
53137
|
-
|
|
53138
|
-
|
|
53250
|
+
}
|
|
53251
|
+
handleReactionClick(evt) {
|
|
53252
|
+
const target = evt.target;
|
|
53139
53253
|
if (!target || target.nodeType !== 1)
|
|
53140
53254
|
return;
|
|
53141
|
-
|
|
53142
|
-
|
|
53143
|
-
|
|
53255
|
+
const upSelector = this.findSelector(THUMB_UP);
|
|
53256
|
+
const downSelector = this.findSelector(THUMB_DOWN);
|
|
53257
|
+
const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
|
|
53144
53258
|
if (!thumb.length)
|
|
53145
53259
|
return;
|
|
53146
|
-
|
|
53147
|
-
|
|
53148
|
-
|
|
53149
|
-
|
|
53150
|
-
|
|
53260
|
+
const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
|
|
53261
|
+
const activeSelector = this.findSelector(REACTION_ACTIVE);
|
|
53262
|
+
const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
|
|
53263
|
+
const direction = isUp ? 'positive' : 'negative';
|
|
53264
|
+
const content = wasPressed ? 'unreact' : direction;
|
|
53151
53265
|
// the thumb may live inside the assistant message (e.g. copilot) or in a separate
|
|
53152
53266
|
// turn footer alongside it (e.g. chatgpt/gemini); handle both
|
|
53153
|
-
|
|
53154
|
-
|
|
53267
|
+
const assistantSelector = this.findSelector(ASSISTANT_MESSAGE);
|
|
53268
|
+
let assistantNode = thumb.closest(assistantSelector);
|
|
53155
53269
|
if (!assistantNode.length) {
|
|
53156
53270
|
assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
|
|
53157
53271
|
.find(assistantSelector);
|
|
@@ -53159,16 +53273,16 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53159
53273
|
this.emit('user_reaction', {
|
|
53160
53274
|
agentId: this.id,
|
|
53161
53275
|
messageId: this.getMessageId(assistantNode),
|
|
53162
|
-
content
|
|
53276
|
+
content
|
|
53163
53277
|
});
|
|
53164
|
-
}
|
|
53278
|
+
}
|
|
53165
53279
|
// observe the streaming indicator
|
|
53166
|
-
|
|
53280
|
+
setupStreamingObserver() {
|
|
53167
53281
|
this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
53168
53282
|
this.stopStreamingEndTimer();
|
|
53169
|
-
|
|
53170
|
-
|
|
53171
|
-
|
|
53283
|
+
const MutationObserver = getZoneSafeMethod(this._, 'MutationObserver');
|
|
53284
|
+
const observer = new MutationObserver(this.handleMutation.bind(this));
|
|
53285
|
+
const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
|
|
53172
53286
|
observer.observe(this.root, {
|
|
53173
53287
|
childList: true,
|
|
53174
53288
|
subtree: true,
|
|
@@ -53176,7 +53290,7 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53176
53290
|
attributeFilter: attrName ? [attrName] : undefined
|
|
53177
53291
|
});
|
|
53178
53292
|
this.observers.push(observer);
|
|
53179
|
-
}
|
|
53293
|
+
}
|
|
53180
53294
|
// look for changes in the state of the streaming indicator.
|
|
53181
53295
|
// streaming started -> a prompt has been submitted
|
|
53182
53296
|
// streaming ended -> got a response
|
|
@@ -53185,8 +53299,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53185
53299
|
// we don't send the agent_response immediately when the streaming indicator is cleared
|
|
53186
53300
|
// because it clears slightly before the final text chunk is committed to the DOM so the
|
|
53187
53301
|
// end-handling is deferred by a short settle window
|
|
53188
|
-
|
|
53189
|
-
|
|
53302
|
+
handleMutation() {
|
|
53303
|
+
const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
53190
53304
|
if (isStreaming === this.wasStreaming)
|
|
53191
53305
|
return;
|
|
53192
53306
|
if (isStreaming) { // started streaming
|
|
@@ -53204,9 +53318,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53204
53318
|
this.startStreamingEndTimer();
|
|
53205
53319
|
}
|
|
53206
53320
|
this.wasStreaming = isStreaming;
|
|
53207
|
-
}
|
|
53208
|
-
|
|
53209
|
-
if (attempt === void 0) { attempt = 1; }
|
|
53321
|
+
}
|
|
53322
|
+
onSubmissionStart(attempt = 1) {
|
|
53210
53323
|
this.requestNode = this.findLastRequestNode();
|
|
53211
53324
|
if (this.requestNode) {
|
|
53212
53325
|
this.handleUserMessage(this.requestNode);
|
|
@@ -53217,10 +53330,10 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53217
53330
|
if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
|
|
53218
53331
|
this.startSubmissionStartRetryTimer(attempt + 1);
|
|
53219
53332
|
}
|
|
53220
|
-
}
|
|
53221
|
-
|
|
53333
|
+
}
|
|
53334
|
+
onSubmissionEnd() {
|
|
53222
53335
|
this.stopSubmissionStartRetryTimer();
|
|
53223
|
-
|
|
53336
|
+
let requestNode = this.requestNode;
|
|
53224
53337
|
this.requestNode = null;
|
|
53225
53338
|
if (!requestNode) {
|
|
53226
53339
|
// onSubmissionStart didn't send, send it now
|
|
@@ -53229,26 +53342,26 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53229
53342
|
return;
|
|
53230
53343
|
this.handleUserMessage(requestNode);
|
|
53231
53344
|
}
|
|
53232
|
-
|
|
53345
|
+
const requestEl = requestNode[0];
|
|
53233
53346
|
if (!requestEl)
|
|
53234
53347
|
return;
|
|
53235
53348
|
// the request is the latest user message, so any assistant message that
|
|
53236
53349
|
// follows it in the DOM is a response to it. document order is already
|
|
53237
53350
|
// chronological, so we emit as we go
|
|
53238
|
-
|
|
53239
|
-
for (
|
|
53240
|
-
|
|
53351
|
+
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
53352
|
+
for (let i = 0; i < assistantNodes.length; i++) {
|
|
53353
|
+
const el = assistantNodes[i];
|
|
53241
53354
|
if (requestEl.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
53242
53355
|
this.handleAssistantMessage(this.dom(el));
|
|
53243
53356
|
}
|
|
53244
53357
|
}
|
|
53245
|
-
}
|
|
53246
|
-
|
|
53247
|
-
|
|
53358
|
+
}
|
|
53359
|
+
extractContent(node) {
|
|
53360
|
+
let source = node;
|
|
53248
53361
|
// optional: content inside a descendant
|
|
53249
|
-
|
|
53362
|
+
const contentSelector = this.findSelector(MESSAGE_CONTENT);
|
|
53250
53363
|
if (contentSelector) {
|
|
53251
|
-
|
|
53364
|
+
const contentNode = node.find(contentSelector);
|
|
53252
53365
|
if (contentNode.length) {
|
|
53253
53366
|
source = contentNode;
|
|
53254
53367
|
}
|
|
@@ -53256,59 +53369,59 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53256
53369
|
// .text() reads innerText, which is empty for content-visibility:auto / off-screen subtrees
|
|
53257
53370
|
// (e.g. claude.ai's scrolled-up messages). Keep innerText as the primary source so agents
|
|
53258
53371
|
// whose content already works are unchanged, and fall back to textContent only when it's empty.
|
|
53259
|
-
|
|
53372
|
+
const primary = source.text().trim();
|
|
53260
53373
|
if (primary)
|
|
53261
53374
|
return primary;
|
|
53262
53375
|
return source[0].textContent.trim();
|
|
53263
|
-
}
|
|
53264
|
-
|
|
53265
|
-
|
|
53376
|
+
}
|
|
53377
|
+
getMessageId(node) {
|
|
53378
|
+
const attr = this.findSelector(MESSAGE_ID_ATTR);
|
|
53266
53379
|
if (!attr) {
|
|
53267
53380
|
return this.syntheticMessageId(node[0]);
|
|
53268
53381
|
}
|
|
53269
53382
|
return node.attr(attr);
|
|
53270
|
-
}
|
|
53383
|
+
}
|
|
53271
53384
|
// Agents with no DOM message id (e.g. claude.ai) get a synthetic id based on the role and
|
|
53272
53385
|
// position in document order.
|
|
53273
|
-
|
|
53386
|
+
syntheticMessageId(el) {
|
|
53274
53387
|
if (!el)
|
|
53275
53388
|
return undefined;
|
|
53276
|
-
|
|
53277
|
-
|
|
53278
|
-
|
|
53279
|
-
|
|
53280
|
-
for (
|
|
53389
|
+
const userSelector = this.findSelector(USER_MESSAGE);
|
|
53390
|
+
const isUser = userSelector && this.Sizzle.matchesSelector(el, userSelector);
|
|
53391
|
+
const role = isUser ? 'u' : 'a';
|
|
53392
|
+
const siblings = this.select(isUser ? USER_MESSAGE : ASSISTANT_MESSAGE);
|
|
53393
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
53281
53394
|
if (siblings[i] === el) {
|
|
53282
|
-
return
|
|
53395
|
+
return `${role}-${i}`;
|
|
53283
53396
|
}
|
|
53284
53397
|
}
|
|
53285
53398
|
return undefined; // el isn't among the rendered messages — no meaningful index
|
|
53286
|
-
}
|
|
53287
|
-
|
|
53399
|
+
}
|
|
53400
|
+
handleUserMessage(node) {
|
|
53288
53401
|
this.emit('prompt', {
|
|
53289
53402
|
agentId: this.id,
|
|
53290
53403
|
messageId: this.getMessageId(node),
|
|
53291
53404
|
content: this.extractContent(node)
|
|
53292
53405
|
});
|
|
53293
|
-
}
|
|
53294
|
-
|
|
53295
|
-
|
|
53296
|
-
|
|
53406
|
+
}
|
|
53407
|
+
handleAssistantMessage(node) {
|
|
53408
|
+
const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
|
|
53409
|
+
const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
|
|
53297
53410
|
this.emit('agent_response', {
|
|
53298
53411
|
agentId: this.id,
|
|
53299
53412
|
messageId: this.getMessageId(node),
|
|
53300
53413
|
agentModelsUsed: modelUsed ? [modelUsed] : [],
|
|
53301
53414
|
content: this.extractContent(node)
|
|
53302
53415
|
});
|
|
53303
|
-
}
|
|
53304
|
-
|
|
53416
|
+
}
|
|
53417
|
+
findLastRequestNode() {
|
|
53305
53418
|
if (!this.getConversationId())
|
|
53306
53419
|
return null;
|
|
53307
|
-
|
|
53420
|
+
const node = this._.last(this.select(USER_MESSAGE));
|
|
53308
53421
|
if (!node)
|
|
53309
53422
|
return null;
|
|
53310
|
-
|
|
53311
|
-
|
|
53423
|
+
const $node = this.dom(node);
|
|
53424
|
+
const messageId = this.getMessageId($node);
|
|
53312
53425
|
if (!messageId)
|
|
53313
53426
|
return null;
|
|
53314
53427
|
// the node may still be rendering (e.g. a framework interpolating an
|
|
@@ -53320,98 +53433,96 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53320
53433
|
return null;
|
|
53321
53434
|
this.lastReturnedMessageId = messageId;
|
|
53322
53435
|
return $node;
|
|
53323
|
-
}
|
|
53324
|
-
|
|
53436
|
+
}
|
|
53437
|
+
findSelector(type) {
|
|
53325
53438
|
return this.selectors[type];
|
|
53326
|
-
}
|
|
53327
|
-
|
|
53439
|
+
}
|
|
53440
|
+
select(type) {
|
|
53328
53441
|
return this.dom(this.findSelector(type), this.root);
|
|
53329
|
-
}
|
|
53330
|
-
|
|
53331
|
-
|
|
53442
|
+
}
|
|
53443
|
+
getConversationId() {
|
|
53444
|
+
const m = location.href.match(this.conversationIdRegex);
|
|
53332
53445
|
if (!m)
|
|
53333
53446
|
return null;
|
|
53334
53447
|
return m[1] !== undefined ? m[1] : m[0];
|
|
53335
|
-
}
|
|
53336
|
-
|
|
53448
|
+
}
|
|
53449
|
+
getCustomAgentId() {
|
|
53337
53450
|
if (!this.customAgentIdRegex)
|
|
53338
53451
|
return undefined;
|
|
53339
53452
|
// The id may live in the page URL (e.g. gemini /gem/<id>) or,
|
|
53340
53453
|
// when customAgentId is set, in the href of a DOM element
|
|
53341
|
-
|
|
53454
|
+
let source = location.href;
|
|
53342
53455
|
if (this.findSelector(CUSTOM_AGENT_ID)) {
|
|
53343
|
-
|
|
53456
|
+
const node = this.select(CUSTOM_AGENT_ID);
|
|
53344
53457
|
if (!node.length)
|
|
53345
53458
|
return undefined;
|
|
53346
53459
|
source = node.attr('href') || '';
|
|
53347
53460
|
}
|
|
53348
|
-
|
|
53461
|
+
const m = source.match(this.customAgentIdRegex);
|
|
53349
53462
|
if (!m)
|
|
53350
53463
|
return undefined;
|
|
53351
53464
|
return m[1] !== undefined ? m[1] : m[0];
|
|
53352
|
-
}
|
|
53353
|
-
|
|
53465
|
+
}
|
|
53466
|
+
getCustomAgentName() {
|
|
53354
53467
|
if (!this.findSelector(CUSTOM_AGENT_NAME))
|
|
53355
53468
|
return '';
|
|
53356
|
-
|
|
53469
|
+
const node = this.select(CUSTOM_AGENT_NAME);
|
|
53357
53470
|
if (!node.length)
|
|
53358
53471
|
return '';
|
|
53359
53472
|
return node.text().trim();
|
|
53360
|
-
}
|
|
53361
|
-
|
|
53362
|
-
|
|
53473
|
+
}
|
|
53474
|
+
addCustomAgentInfo(eventPayload) {
|
|
53475
|
+
const customAgentId = this.getCustomAgentId();
|
|
53363
53476
|
if (!customAgentId)
|
|
53364
53477
|
return;
|
|
53365
53478
|
eventPayload.customAgentId = customAgentId;
|
|
53366
|
-
|
|
53479
|
+
const customAgentName = this.getCustomAgentName();
|
|
53367
53480
|
if (customAgentName) {
|
|
53368
53481
|
eventPayload.customAgentName = customAgentName;
|
|
53369
53482
|
}
|
|
53370
|
-
}
|
|
53371
|
-
|
|
53483
|
+
}
|
|
53484
|
+
onSubmit(callback) {
|
|
53372
53485
|
this.listeners.push(callback);
|
|
53373
|
-
}
|
|
53374
|
-
|
|
53486
|
+
}
|
|
53487
|
+
emit(eventType, eventPayload) {
|
|
53375
53488
|
eventPayload.conversationId = this.getConversationId();
|
|
53376
53489
|
this.addCustomAgentInfo(eventPayload);
|
|
53377
|
-
this._.each(this.listeners,
|
|
53378
|
-
}
|
|
53379
|
-
|
|
53380
|
-
var _this = this;
|
|
53490
|
+
this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
|
|
53491
|
+
}
|
|
53492
|
+
startStreamingEndTimer() {
|
|
53381
53493
|
this.stopStreamingEndTimer();
|
|
53382
|
-
this.streamingEndTimer = setTimeout$1(
|
|
53383
|
-
|
|
53384
|
-
|
|
53494
|
+
this.streamingEndTimer = setTimeout$1(() => {
|
|
53495
|
+
this.streamingEndTimer = null;
|
|
53496
|
+
this.onSubmissionEnd();
|
|
53385
53497
|
}, STREAMING_END_SETTLE_MS);
|
|
53386
|
-
}
|
|
53387
|
-
|
|
53498
|
+
}
|
|
53499
|
+
stopStreamingEndTimer() {
|
|
53388
53500
|
if (!this.streamingEndTimer)
|
|
53389
53501
|
return;
|
|
53390
53502
|
clearTimeout(this.streamingEndTimer);
|
|
53391
53503
|
this.streamingEndTimer = null;
|
|
53392
|
-
}
|
|
53393
|
-
|
|
53394
|
-
var _this = this;
|
|
53504
|
+
}
|
|
53505
|
+
startSubmissionStartRetryTimer(attempt) {
|
|
53395
53506
|
this.stopSubmissionStartRetryTimer();
|
|
53396
|
-
this.submissionStartRetryTimer = setTimeout$1(
|
|
53397
|
-
|
|
53398
|
-
|
|
53507
|
+
this.submissionStartRetryTimer = setTimeout$1(() => {
|
|
53508
|
+
this.submissionStartRetryTimer = null;
|
|
53509
|
+
this.onSubmissionStart(attempt);
|
|
53399
53510
|
}, SUBMISSION_START_RETRY_MS);
|
|
53400
|
-
}
|
|
53401
|
-
|
|
53511
|
+
}
|
|
53512
|
+
stopSubmissionStartRetryTimer() {
|
|
53402
53513
|
if (!this.submissionStartRetryTimer)
|
|
53403
53514
|
return;
|
|
53404
53515
|
clearTimeout(this.submissionStartRetryTimer);
|
|
53405
53516
|
this.submissionStartRetryTimer = null;
|
|
53406
|
-
}
|
|
53407
|
-
|
|
53517
|
+
}
|
|
53518
|
+
suspend() {
|
|
53408
53519
|
this.isActive = false;
|
|
53409
|
-
}
|
|
53410
|
-
|
|
53520
|
+
}
|
|
53521
|
+
resume() {
|
|
53411
53522
|
this.isActive = true;
|
|
53412
|
-
}
|
|
53413
|
-
|
|
53414
|
-
this._.each(this.observers,
|
|
53523
|
+
}
|
|
53524
|
+
teardown() {
|
|
53525
|
+
this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
|
|
53415
53526
|
this.observers = [];
|
|
53416
53527
|
if (this.reactionClickHandler && this.root) {
|
|
53417
53528
|
this.root.removeEventListener('click', this.reactionClickHandler, true);
|
|
@@ -53420,9 +53531,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53420
53531
|
this.stopStreamingEndTimer();
|
|
53421
53532
|
this.stopSubmissionStartRetryTimer();
|
|
53422
53533
|
this.listeners = [];
|
|
53423
|
-
}
|
|
53424
|
-
|
|
53425
|
-
}());
|
|
53534
|
+
}
|
|
53535
|
+
}
|
|
53426
53536
|
|
|
53427
53537
|
/*
|
|
53428
53538
|
* Conversation Analytics Plugin
|
|
@@ -53432,21 +53542,21 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53432
53542
|
* The sibling built-in PromptAnalytics plugin owns the network + DOMPrompt AI-agents
|
|
53433
53543
|
*/
|
|
53434
53544
|
function ConversationAnalytics() {
|
|
53435
|
-
|
|
53436
|
-
|
|
53437
|
-
|
|
53438
|
-
|
|
53439
|
-
|
|
53440
|
-
|
|
53441
|
-
|
|
53545
|
+
let pendo;
|
|
53546
|
+
let api;
|
|
53547
|
+
let _;
|
|
53548
|
+
let log;
|
|
53549
|
+
let conversations = [];
|
|
53550
|
+
let agentsCache = new Map();
|
|
53551
|
+
const CONFIG_NAME = 'aiAgents';
|
|
53442
53552
|
return {
|
|
53443
53553
|
name: 'ConversationAnalytics',
|
|
53444
|
-
initialize
|
|
53445
|
-
teardown
|
|
53446
|
-
onConfigLoaded
|
|
53447
|
-
observeConversation
|
|
53448
|
-
sendConversationEvent
|
|
53449
|
-
reEvaluatePageRules
|
|
53554
|
+
initialize,
|
|
53555
|
+
teardown,
|
|
53556
|
+
onConfigLoaded,
|
|
53557
|
+
observeConversation,
|
|
53558
|
+
sendConversationEvent,
|
|
53559
|
+
reEvaluatePageRules
|
|
53450
53560
|
};
|
|
53451
53561
|
function initialize(pendoGlobal, PluginAPI) {
|
|
53452
53562
|
var _a;
|
|
@@ -53454,7 +53564,7 @@ function ConversationAnalytics() {
|
|
|
53454
53564
|
api = PluginAPI;
|
|
53455
53565
|
_ = pendo._;
|
|
53456
53566
|
log = api.log;
|
|
53457
|
-
|
|
53567
|
+
const { ConfigReader } = api;
|
|
53458
53568
|
ConfigReader.addOption(CONFIG_NAME, [
|
|
53459
53569
|
ConfigReader.sources.PENDO_CONFIG_SRC,
|
|
53460
53570
|
ConfigReader.sources.SNIPPET_SRC
|
|
@@ -53467,13 +53577,12 @@ function ConversationAnalytics() {
|
|
|
53467
53577
|
// Test if the current URL matches the page rule for an agent. The raw matcher lives in core
|
|
53468
53578
|
// and is reached through PluginAPI (independent plugins cannot import it directly); it falls
|
|
53469
53579
|
// back to the normalized URL internally when no URL is passed.
|
|
53470
|
-
function testPageRule(pageRule, agentId) {
|
|
53471
|
-
if (agentId === void 0) { agentId = 'unknown'; }
|
|
53580
|
+
function testPageRule(pageRule, agentId = 'unknown') {
|
|
53472
53581
|
// Convert //*/agent pattern to work with full URLs
|
|
53473
|
-
|
|
53582
|
+
let fixedPageRule = pageRule;
|
|
53474
53583
|
if (Array.isArray(pageRule)) {
|
|
53475
|
-
|
|
53476
|
-
fixedPageRule = _.map(validRules,
|
|
53584
|
+
const validRules = _.filter(pageRule, rule => rule && rule.trim() !== '');
|
|
53585
|
+
fixedPageRule = _.map(validRules, rule => rule.startsWith('//*/') ? rule.substring(1) : rule);
|
|
53477
53586
|
}
|
|
53478
53587
|
else if (typeof pageRule === 'string' && pageRule.startsWith('//*/')) {
|
|
53479
53588
|
fixedPageRule = pageRule.substring(1);
|
|
@@ -53485,9 +53594,9 @@ function ConversationAnalytics() {
|
|
|
53485
53594
|
});
|
|
53486
53595
|
}
|
|
53487
53596
|
function reEvaluatePageRules() {
|
|
53488
|
-
_.each(conversations,
|
|
53489
|
-
|
|
53490
|
-
|
|
53597
|
+
_.each(conversations, conversation => {
|
|
53598
|
+
const agent = findAgentById(conversation.id);
|
|
53599
|
+
const shouldBeActive = agent && testPageRule(agent.pageRule, agent.id);
|
|
53491
53600
|
if (shouldBeActive) {
|
|
53492
53601
|
conversation.resume();
|
|
53493
53602
|
}
|
|
@@ -53495,14 +53604,14 @@ function ConversationAnalytics() {
|
|
|
53495
53604
|
conversation.suspend();
|
|
53496
53605
|
}
|
|
53497
53606
|
});
|
|
53498
|
-
|
|
53499
|
-
|
|
53500
|
-
_.each(allAgents,
|
|
53607
|
+
const currentlyActiveIds = _.map(_.filter(conversations, conversation => conversation.isActive), conversation => conversation.id);
|
|
53608
|
+
const allAgents = api.ConfigReader.get(CONFIG_NAME) || [];
|
|
53609
|
+
_.each(allAgents, aiAgent => {
|
|
53501
53610
|
if (!isConversationAgent(aiAgent)) {
|
|
53502
53611
|
return;
|
|
53503
53612
|
}
|
|
53504
|
-
|
|
53505
|
-
|
|
53613
|
+
const isCurrentlyActive = _.contains(currentlyActiveIds, aiAgent.id);
|
|
53614
|
+
const shouldBeActive = testPageRule(aiAgent.pageRule, aiAgent.id);
|
|
53506
53615
|
if (shouldBeActive && !isCurrentlyActive) {
|
|
53507
53616
|
observeConversation(aiAgent);
|
|
53508
53617
|
}
|
|
@@ -53516,13 +53625,12 @@ function ConversationAnalytics() {
|
|
|
53516
53625
|
function isConversationAgent(agent) {
|
|
53517
53626
|
return DOMConversation.supportedPreset(agent.preset);
|
|
53518
53627
|
}
|
|
53519
|
-
function onConfigLoaded(aiAgents) {
|
|
53520
|
-
if (aiAgents === void 0) { aiAgents = []; }
|
|
53628
|
+
function onConfigLoaded(aiAgents = []) {
|
|
53521
53629
|
if (!aiAgents || !_.isArray(aiAgents) || aiAgents.length === 0) {
|
|
53522
53630
|
return;
|
|
53523
53631
|
}
|
|
53524
53632
|
agentsCache.clear();
|
|
53525
|
-
_.each(aiAgents,
|
|
53633
|
+
_.each(aiAgents, aiAgent => {
|
|
53526
53634
|
if (!isConversationAgent(aiAgent)) {
|
|
53527
53635
|
return;
|
|
53528
53636
|
}
|
|
@@ -53533,24 +53641,24 @@ function ConversationAnalytics() {
|
|
|
53533
53641
|
});
|
|
53534
53642
|
}
|
|
53535
53643
|
function observeConversation(config) {
|
|
53536
|
-
|
|
53644
|
+
const { id, cssSelectors } = config;
|
|
53537
53645
|
// Check if this agent is already being tracked
|
|
53538
|
-
|
|
53646
|
+
const existing = _.find(conversations, conversation => conversation.id === id);
|
|
53539
53647
|
if (existing) {
|
|
53540
53648
|
return;
|
|
53541
53649
|
}
|
|
53542
|
-
|
|
53650
|
+
const missing = DOMConversation.validateConfig(cssSelectors);
|
|
53543
53651
|
if (missing.length) {
|
|
53544
|
-
log.error('aiAgent config missing required selectors', { agentId: id, missing
|
|
53652
|
+
log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
53545
53653
|
return;
|
|
53546
53654
|
}
|
|
53547
|
-
|
|
53655
|
+
const conversation = new DOMConversation(pendo, api, id, cssSelectors);
|
|
53548
53656
|
conversation.onSubmit(sendConversationEvent);
|
|
53549
53657
|
conversations.push(conversation);
|
|
53550
53658
|
}
|
|
53551
53659
|
function sendConversationEvent(eventType, eventPayload) {
|
|
53552
53660
|
// Block event if the conversation is suspended
|
|
53553
|
-
|
|
53661
|
+
const conversation = _.find(conversations, c => c.id === eventPayload.agentId);
|
|
53554
53662
|
if (conversation && !conversation.isActive) {
|
|
53555
53663
|
return;
|
|
53556
53664
|
}
|
|
@@ -53558,7 +53666,7 @@ function ConversationAnalytics() {
|
|
|
53558
53666
|
api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
|
|
53559
53667
|
}
|
|
53560
53668
|
function teardown() {
|
|
53561
|
-
_.each(conversations,
|
|
53669
|
+
_.each(conversations, conversation => conversation.teardown());
|
|
53562
53670
|
conversations = [];
|
|
53563
53671
|
agentsCache.clear();
|
|
53564
53672
|
}
|