@pendo/agent 2.330.2 → 2.331.0
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 +1 -1
- package/dist/pendo.module.js +870 -802
- package/dist/pendo.module.min.js +103 -5
- package/dist/servers.json +7 -7
- package/package.json +1 -1
- package/setup.js +6 -2
- package/setup.test.js +65 -0
package/dist/pendo.module.js
CHANGED
|
@@ -4010,8 +4010,8 @@ let SERVER = '';
|
|
|
4010
4010
|
let ASSET_HOST = '';
|
|
4011
4011
|
let ASSET_PATH = '';
|
|
4012
4012
|
let DESIGNER_SERVER = '';
|
|
4013
|
-
let VERSION = '2.
|
|
4014
|
-
let PACKAGE_VERSION = '2.
|
|
4013
|
+
let VERSION = '2.331.0_';
|
|
4014
|
+
let PACKAGE_VERSION = '2.331.0';
|
|
4015
4015
|
let LOADER = 'xhr';
|
|
4016
4016
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
4017
4017
|
/**
|
|
@@ -28018,7 +28018,7 @@ var EventRouter = function () {
|
|
|
28018
28018
|
if (!currentGuideTerms)
|
|
28019
28019
|
return false;
|
|
28020
28020
|
return currentGuideTerms.some(function (term) {
|
|
28021
|
-
return _.contains(haystack, (term)) && term === text;
|
|
28021
|
+
return _.contains(haystack, (term)) && term.toLowerCase() === text.toLowerCase();
|
|
28022
28022
|
});
|
|
28023
28023
|
}
|
|
28024
28024
|
function searchGuides(evt) {
|
|
@@ -28458,15 +28458,28 @@ var GuideActivity = (function () {
|
|
|
28458
28458
|
return _.isString(appData.id) && appData.id.indexOf('pendo-guide-container') === 0;
|
|
28459
28459
|
}
|
|
28460
28460
|
function getGuideForEvent(appData) {
|
|
28461
|
-
|
|
28462
|
-
|
|
28461
|
+
// A `pendo-g-<id>` container id can be either a stepId or a guideId
|
|
28462
|
+
// (see building-block-guides.js / fetchAndMigrateGuide), so resolve
|
|
28463
|
+
// against both before falling back to the active guide. Without the
|
|
28464
|
+
// guideId match, a click in a guide whose container carries the guideId
|
|
28465
|
+
// drops into the element-blind getActiveGuide() fallback, which can
|
|
28466
|
+
// resolve to a different, higher-priority co-displayed guide.
|
|
28467
|
+
const containerId = getStepIdFromAppData(appData);
|
|
28468
|
+
if (containerId) {
|
|
28463
28469
|
let step;
|
|
28464
|
-
const
|
|
28465
|
-
step = _.find(guide.steps, (step) => step.id ===
|
|
28470
|
+
const guideByStep = _.find(getLocalActiveGuides(), function (guide) {
|
|
28471
|
+
step = _.find(guide.steps, (step) => step.id === containerId);
|
|
28466
28472
|
return !!step;
|
|
28467
28473
|
});
|
|
28468
|
-
if (
|
|
28469
|
-
return { guide, step };
|
|
28474
|
+
if (guideByStep && step) {
|
|
28475
|
+
return { guide: guideByStep, step };
|
|
28476
|
+
}
|
|
28477
|
+
const guideById = _.find(getLocalActiveGuides(), (guide) => guide.id === containerId);
|
|
28478
|
+
if (guideById) {
|
|
28479
|
+
const shownStep = _.find(guideById.steps, (step) => step.isShown());
|
|
28480
|
+
if (shownStep) {
|
|
28481
|
+
return { guide: guideById, step: shownStep };
|
|
28482
|
+
}
|
|
28470
28483
|
}
|
|
28471
28484
|
}
|
|
28472
28485
|
return getActiveGuide();
|
|
@@ -41238,20 +41251,20 @@ function getZoneSafeMethod(_, method, target) {
|
|
|
41238
41251
|
}
|
|
41239
41252
|
|
|
41240
41253
|
// Does not support submit and go to
|
|
41241
|
-
|
|
41242
|
-
|
|
41254
|
+
const goToRegex = new RegExp(guideMarkdownUtil.goToString);
|
|
41255
|
+
const PollBranching = {
|
|
41243
41256
|
name: 'PollBranching',
|
|
41244
|
-
script
|
|
41245
|
-
|
|
41246
|
-
|
|
41257
|
+
script(step, guide, pendo) {
|
|
41258
|
+
let isAdvanceIntercepted = false;
|
|
41259
|
+
const branchingQuestions = initialBranchingSetup(step, pendo);
|
|
41247
41260
|
if (branchingQuestions) {
|
|
41248
41261
|
// If there are too many branching questions saved, exit and run the guide normally.
|
|
41249
41262
|
if (pendo._.size(branchingQuestions) > 1)
|
|
41250
41263
|
return;
|
|
41251
|
-
this.on('beforeAdvance',
|
|
41252
|
-
|
|
41253
|
-
|
|
41254
|
-
|
|
41264
|
+
this.on('beforeAdvance', (evt) => {
|
|
41265
|
+
const noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
|
|
41266
|
+
const responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
|
|
41267
|
+
let noGotoLabel;
|
|
41255
41268
|
if (responseLabel) {
|
|
41256
41269
|
noGotoLabel = pendo._.isNull(responseLabel.getAttribute('goToStep'));
|
|
41257
41270
|
}
|
|
@@ -41262,58 +41275,58 @@ var PollBranching = {
|
|
|
41262
41275
|
});
|
|
41263
41276
|
}
|
|
41264
41277
|
},
|
|
41265
|
-
test
|
|
41278
|
+
test(step, guide, pendo) {
|
|
41266
41279
|
var _a;
|
|
41267
|
-
|
|
41280
|
+
let branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41268
41281
|
return !pendo._.isUndefined(branchingQuestions) && pendo._.size(branchingQuestions);
|
|
41269
41282
|
},
|
|
41270
|
-
designerListener
|
|
41271
|
-
|
|
41272
|
-
|
|
41283
|
+
designerListener(pendo) {
|
|
41284
|
+
const target = pendo.dom.getBody();
|
|
41285
|
+
const config = {
|
|
41273
41286
|
attributeFilter: ['data-layout'],
|
|
41274
41287
|
attributes: true,
|
|
41275
41288
|
childList: true,
|
|
41276
41289
|
characterData: true,
|
|
41277
41290
|
subtree: true
|
|
41278
41291
|
};
|
|
41279
|
-
|
|
41280
|
-
|
|
41292
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41293
|
+
const observer = new MutationObserver(applyBranchingIndicators);
|
|
41281
41294
|
observer.observe(target, config);
|
|
41282
41295
|
function applyBranchingIndicators(mutations) {
|
|
41283
41296
|
pendo._.each(mutations, function (mutation) {
|
|
41284
41297
|
var _a;
|
|
41285
|
-
|
|
41298
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
|
|
41286
41299
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41287
41300
|
if (mutation.addedNodes[0].querySelector('._pendo-multi-choice-poll-select-border')) {
|
|
41288
41301
|
if (pendo._.size(pendo.dom('._pendo-multi-choice-poll-question:contains("{branching/}")'))) {
|
|
41289
41302
|
pendo
|
|
41290
41303
|
.dom('._pendo-multi-choice-poll-question:contains("{branching/}")')
|
|
41291
|
-
.each(
|
|
41292
|
-
pendo._.each(pendo.dom(
|
|
41304
|
+
.each((question, index) => {
|
|
41305
|
+
pendo._.each(pendo.dom(`#${question.id} *`), (element) => {
|
|
41293
41306
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41294
41307
|
});
|
|
41295
41308
|
pendo
|
|
41296
|
-
.dom(
|
|
41309
|
+
.dom(`#${question.id} p`)
|
|
41297
41310
|
.css({ display: 'inline-block !important' })
|
|
41298
41311
|
.append(branchingIcon('#999', '20px'))
|
|
41299
41312
|
.attr({ title: 'Custom Branching Added' });
|
|
41300
|
-
|
|
41301
|
-
if (pendo.dom(
|
|
41313
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41314
|
+
if (pendo.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]) {
|
|
41302
41315
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41303
41316
|
pendo
|
|
41304
|
-
.dom(
|
|
41317
|
+
.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]
|
|
41305
41318
|
.textContent.trim();
|
|
41306
41319
|
}
|
|
41307
|
-
|
|
41320
|
+
let pollLabels = pendo.dom(`label[for*=${dataPendoPollId}]`);
|
|
41308
41321
|
if (pendo._.size(pollLabels)) {
|
|
41309
|
-
pendo._.forEach(pollLabels,
|
|
41322
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41310
41323
|
if (goToRegex.test(label.textContent)) {
|
|
41311
|
-
|
|
41324
|
+
let labelTitle = goToRegex.exec(label.textContent)[2];
|
|
41312
41325
|
guideMarkdownUtil.removeMarkdownSyntax(label, goToRegex, '', pendo);
|
|
41313
41326
|
pendo
|
|
41314
41327
|
.dom(label)
|
|
41315
41328
|
.append(branchingIcon('#999', '14px'))
|
|
41316
|
-
.attr({ title:
|
|
41329
|
+
.attr({ title: `Branching to step ${labelTitle}` });
|
|
41317
41330
|
}
|
|
41318
41331
|
});
|
|
41319
41332
|
}
|
|
@@ -41321,9 +41334,9 @@ var PollBranching = {
|
|
|
41321
41334
|
pendo
|
|
41322
41335
|
.dom(question)
|
|
41323
41336
|
.append(branchingErrorHTML(question.dataset.pendoPollId));
|
|
41324
|
-
pendo.dom(
|
|
41337
|
+
pendo.dom(`#${question.id} #pendo-ps-branching-svg`).remove();
|
|
41325
41338
|
pendo
|
|
41326
|
-
.dom(
|
|
41339
|
+
.dom(`#${question.id} p`)
|
|
41327
41340
|
.css({ display: 'inline-block !important' })
|
|
41328
41341
|
.append(branchingIcon('red', '20px'))
|
|
41329
41342
|
.attr({ title: 'Unsupported Branching configuration' });
|
|
@@ -41335,31 +41348,49 @@ var PollBranching = {
|
|
|
41335
41348
|
});
|
|
41336
41349
|
}
|
|
41337
41350
|
function branchingErrorHTML(dataPendoPollId) {
|
|
41338
|
-
return
|
|
41351
|
+
return `<div style="text-align:lrft; font-size: 14px; color: red;
|
|
41352
|
+
font-style: italic; margin-top: 0px;" class="branching-wrapper"
|
|
41353
|
+
name="${dataPendoPollId}">
|
|
41354
|
+
* Branching Error: Multiple branching polls not supported</div>`;
|
|
41339
41355
|
}
|
|
41340
41356
|
function branchingIcon(color, size) {
|
|
41341
|
-
return
|
|
41357
|
+
return `<svg id="pendo-ps-branching-svg" viewBox="0 0 24 24" fill="none"
|
|
41358
|
+
style="margin-left: 5px;
|
|
41359
|
+
height:${size}; width:${size}; display:inline; vertical-align:middle;" xmlns="http://www.w3.org/2000/svg">
|
|
41360
|
+
<g stroke-width="0"></g>
|
|
41361
|
+
<g stroke-linecap="round" stroke-linejoin="round"></g>
|
|
41362
|
+
<g> <circle cx="4" cy="7" r="2" stroke="${color}"
|
|
41363
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41364
|
+
<circle cx="20" cy="7" r="2" stroke="${color}"
|
|
41365
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41366
|
+
<circle cx="20" cy="17" r="2" stroke="${color}" stroke-width="2"
|
|
41367
|
+
stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41368
|
+
<path d="M18 7H6" stroke="${color}" stroke-width="2"
|
|
41369
|
+
stroke-linecap="round" stroke-linejoin="round"></path>
|
|
41370
|
+
<path d="M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18"
|
|
41371
|
+
stroke="${color}" stroke-width="2" stroke-linecap="round"
|
|
41372
|
+
stroke-linejoin="round"></path> </g></svg>`;
|
|
41342
41373
|
}
|
|
41343
41374
|
}
|
|
41344
41375
|
};
|
|
41345
41376
|
function initialBranchingSetup(step, pendo) {
|
|
41346
|
-
|
|
41347
|
-
pendo._.forEach(questions,
|
|
41348
|
-
|
|
41349
|
-
pendo._.each(step.guideElement.find(
|
|
41377
|
+
const questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41378
|
+
pendo._.forEach(questions, (question) => {
|
|
41379
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41380
|
+
pendo._.each(step.guideElement.find(`#${question.id} *`), (element) => {
|
|
41350
41381
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41351
41382
|
});
|
|
41352
|
-
|
|
41353
|
-
pendo._.forEach(pollLabels,
|
|
41383
|
+
let pollLabels = step.guideElement.find(`label[for*=${dataPendoPollId}]`);
|
|
41384
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41354
41385
|
if (pendo._.isNull(goToRegex.exec(label.textContent))) {
|
|
41355
41386
|
return;
|
|
41356
41387
|
}
|
|
41357
|
-
|
|
41358
|
-
|
|
41388
|
+
let gotoSubstring = goToRegex.exec(label.textContent)[1];
|
|
41389
|
+
let gotoIndex = goToRegex.exec(label.textContent)[2];
|
|
41359
41390
|
label.setAttribute('goToStep', gotoIndex);
|
|
41360
41391
|
guideMarkdownUtil.removeMarkdownSyntax(label, gotoSubstring, '', pendo);
|
|
41361
41392
|
});
|
|
41362
|
-
|
|
41393
|
+
let pollChoiceContainer = step.guideElement.find(`[data-pendo-poll-id=${dataPendoPollId}]._pendo-multi-choice-poll-select-border`);
|
|
41363
41394
|
if (pollChoiceContainer && pollChoiceContainer.length) {
|
|
41364
41395
|
pollChoiceContainer[0].setAttribute('branching', '');
|
|
41365
41396
|
}
|
|
@@ -41368,15 +41399,15 @@ function initialBranchingSetup(step, pendo) {
|
|
|
41368
41399
|
}
|
|
41369
41400
|
function branchingGoToStep(event, step, guide, pendo) {
|
|
41370
41401
|
var _a;
|
|
41371
|
-
|
|
41372
|
-
|
|
41373
|
-
|
|
41374
|
-
|
|
41402
|
+
let checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
41403
|
+
let checkedPollLabel = step.guideElement.find(`label[for="${checkedPollInputId}"]`)[0];
|
|
41404
|
+
let checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
|
|
41405
|
+
let pollStepIndex = checkedPollLabelStepIndex - 1;
|
|
41375
41406
|
if (pollStepIndex < 0)
|
|
41376
41407
|
return;
|
|
41377
|
-
|
|
41408
|
+
const destinationObject = {
|
|
41378
41409
|
destinationStepId: guide.steps[pollStepIndex].id,
|
|
41379
|
-
step
|
|
41410
|
+
step
|
|
41380
41411
|
};
|
|
41381
41412
|
pendo.goToStep(destinationObject);
|
|
41382
41413
|
event.cancel = true;
|
|
@@ -41397,10 +41428,10 @@ function encodeMetadataForUrl(value, urlBeforePlaceholder) {
|
|
|
41397
41428
|
return window.encodeURI(str);
|
|
41398
41429
|
}
|
|
41399
41430
|
|
|
41400
|
-
|
|
41431
|
+
const MetadataSubstitution = {
|
|
41401
41432
|
name: 'MetadataSubstitution',
|
|
41402
|
-
script
|
|
41403
|
-
|
|
41433
|
+
script(step, guide, pendo) {
|
|
41434
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41404
41435
|
if (step.domJson) {
|
|
41405
41436
|
findSubstitutableUrlsInJson(step.domJson, placeholderData, pendo);
|
|
41406
41437
|
}
|
|
@@ -41408,22 +41439,22 @@ var MetadataSubstitution = {
|
|
|
41408
41439
|
pendo._.each(placeholderData, function (placeholder) {
|
|
41409
41440
|
processPlaceholder(placeholder, pendo);
|
|
41410
41441
|
});
|
|
41411
|
-
|
|
41412
|
-
|
|
41413
|
-
updateGuideContainer(containerId,
|
|
41442
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41443
|
+
const context = step.guideElement;
|
|
41444
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41414
41445
|
}
|
|
41415
41446
|
},
|
|
41416
|
-
designerListener
|
|
41417
|
-
|
|
41447
|
+
designerListener(pendo) {
|
|
41448
|
+
const target = pendo.dom.getBody();
|
|
41418
41449
|
if (pendo.designerv2) {
|
|
41419
41450
|
pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
|
|
41420
41451
|
var _a;
|
|
41421
41452
|
if (!document.querySelector(guideMarkdownUtil.containerSelector))
|
|
41422
41453
|
return;
|
|
41423
|
-
|
|
41454
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41424
41455
|
if (!step)
|
|
41425
41456
|
return;
|
|
41426
|
-
|
|
41457
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41427
41458
|
if (step.buildingBlocks) {
|
|
41428
41459
|
findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
|
|
41429
41460
|
}
|
|
@@ -41433,32 +41464,32 @@ var MetadataSubstitution = {
|
|
|
41433
41464
|
return;
|
|
41434
41465
|
processPlaceholder(placeholder, pendo);
|
|
41435
41466
|
});
|
|
41436
|
-
|
|
41437
|
-
|
|
41438
|
-
updateGuideContainer(containerId,
|
|
41467
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41468
|
+
const context = step.guideElement;
|
|
41469
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41439
41470
|
}
|
|
41440
41471
|
};
|
|
41441
41472
|
}
|
|
41442
|
-
|
|
41473
|
+
const config = {
|
|
41443
41474
|
attributeFilter: ['data-layout'],
|
|
41444
41475
|
attributes: true,
|
|
41445
41476
|
childList: true,
|
|
41446
41477
|
characterData: true,
|
|
41447
41478
|
subtree: true
|
|
41448
41479
|
};
|
|
41449
|
-
|
|
41450
|
-
|
|
41480
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41481
|
+
const observer = new MutationObserver(applySubstitutionIndicators);
|
|
41451
41482
|
observer.observe(target, config);
|
|
41452
41483
|
function applySubstitutionIndicators(mutations) {
|
|
41453
41484
|
pendo._.each(mutations, function (mutation) {
|
|
41454
41485
|
var _a;
|
|
41455
41486
|
if (mutation.addedNodes.length) {
|
|
41456
41487
|
if (document.querySelector(guideMarkdownUtil.containerSelector)) {
|
|
41457
|
-
|
|
41458
|
-
|
|
41488
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41489
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41459
41490
|
if (!step)
|
|
41460
41491
|
return;
|
|
41461
|
-
|
|
41492
|
+
const pendoBlocks = step.buildingBlocks;
|
|
41462
41493
|
if (!pendo._.isUndefined(pendoBlocks)) {
|
|
41463
41494
|
findSubstitutableUrlsInJson(pendoBlocks, placeholderData, pendo);
|
|
41464
41495
|
}
|
|
@@ -41468,9 +41499,9 @@ var MetadataSubstitution = {
|
|
|
41468
41499
|
return;
|
|
41469
41500
|
processPlaceholder(placeholder, pendo);
|
|
41470
41501
|
});
|
|
41471
|
-
|
|
41472
|
-
|
|
41473
|
-
updateGuideContainer(containerId,
|
|
41502
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41503
|
+
const context = step.guideElement;
|
|
41504
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41474
41505
|
}
|
|
41475
41506
|
}
|
|
41476
41507
|
}
|
|
@@ -41479,18 +41510,18 @@ var MetadataSubstitution = {
|
|
|
41479
41510
|
}
|
|
41480
41511
|
};
|
|
41481
41512
|
function processPlaceholder(placeholder, pendo) {
|
|
41482
|
-
|
|
41483
|
-
|
|
41484
|
-
|
|
41513
|
+
let match;
|
|
41514
|
+
const { data, target } = placeholder;
|
|
41515
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41485
41516
|
while ((match = matchPlaceholder(placeholder, subRegex))) {
|
|
41486
|
-
|
|
41487
|
-
|
|
41517
|
+
const usedArrayPath = Array.isArray(match) && match.length >= 2;
|
|
41518
|
+
const currentStr = target === 'textContent'
|
|
41488
41519
|
? data[target]
|
|
41489
41520
|
: decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
|
|
41490
|
-
|
|
41521
|
+
const matched = usedArrayPath ? match : subRegex.exec(currentStr);
|
|
41491
41522
|
if (!matched)
|
|
41492
41523
|
continue;
|
|
41493
|
-
|
|
41524
|
+
const mdValue = getSubstituteValue(matched, pendo);
|
|
41494
41525
|
substituteMetadataByTarget(data, target, mdValue, matched);
|
|
41495
41526
|
}
|
|
41496
41527
|
}
|
|
@@ -41499,50 +41530,50 @@ function matchPlaceholder(placeholder, regex) {
|
|
|
41499
41530
|
return placeholder.data[placeholder.target].match(regex);
|
|
41500
41531
|
}
|
|
41501
41532
|
else {
|
|
41502
|
-
|
|
41533
|
+
const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
|
|
41503
41534
|
? (placeholder.data.getAttribute(placeholder.target) || '')
|
|
41504
41535
|
: placeholder.data[placeholder.target];
|
|
41505
41536
|
return decodeURI(raw).match(regex);
|
|
41506
41537
|
}
|
|
41507
41538
|
}
|
|
41508
41539
|
function getMetadataValueCaseInsensitive(metadata, type, property) {
|
|
41509
|
-
|
|
41540
|
+
const kind = metadata && metadata[type];
|
|
41510
41541
|
if (!kind || typeof kind !== 'object')
|
|
41511
41542
|
return undefined;
|
|
41512
|
-
|
|
41543
|
+
const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
|
|
41513
41544
|
if (direct !== undefined) {
|
|
41514
41545
|
return direct;
|
|
41515
41546
|
}
|
|
41516
|
-
|
|
41517
|
-
|
|
41518
|
-
|
|
41547
|
+
const propLower = property.toLowerCase();
|
|
41548
|
+
const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
|
|
41549
|
+
const value = key !== undefined ? kind[key] : undefined;
|
|
41519
41550
|
return value;
|
|
41520
41551
|
}
|
|
41521
41552
|
function getSubstituteValue(match, pendo) {
|
|
41522
41553
|
if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
|
|
41523
41554
|
return;
|
|
41524
41555
|
}
|
|
41525
|
-
|
|
41526
|
-
|
|
41527
|
-
|
|
41556
|
+
let type = match[1];
|
|
41557
|
+
let property = match[2];
|
|
41558
|
+
let defaultValue = match[3];
|
|
41528
41559
|
if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
|
|
41529
41560
|
return;
|
|
41530
41561
|
}
|
|
41531
|
-
|
|
41532
|
-
|
|
41562
|
+
const metadata = pendo.getSerializedMetadata();
|
|
41563
|
+
let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
|
|
41533
41564
|
if (mdValue === undefined || mdValue === null)
|
|
41534
41565
|
mdValue = defaultValue || '';
|
|
41535
41566
|
return mdValue;
|
|
41536
41567
|
}
|
|
41537
41568
|
function substituteMetadataByTarget(data, target, mdValue, matched) {
|
|
41538
|
-
|
|
41539
|
-
|
|
41569
|
+
const isElement = data && typeof data.getAttribute === 'function';
|
|
41570
|
+
const current = (target === 'href' || target === 'value') && isElement
|
|
41540
41571
|
? (data.getAttribute(target) || '')
|
|
41541
41572
|
: data[target];
|
|
41542
41573
|
if (target === 'href' || target === 'value') {
|
|
41543
|
-
|
|
41544
|
-
|
|
41545
|
-
|
|
41574
|
+
const decodedUrl = decodeURI(current);
|
|
41575
|
+
const urlBeforePlaceholder = decodedUrl.slice(0, decodedUrl.indexOf(matched[0]));
|
|
41576
|
+
const safeValue = encodeMetadataForUrl(mdValue, urlBeforePlaceholder);
|
|
41546
41577
|
data[target] = decodedUrl.replace(matched[0], safeValue);
|
|
41547
41578
|
}
|
|
41548
41579
|
else {
|
|
@@ -41556,9 +41587,8 @@ function updateGuideContainer(containerId, context, pendo) {
|
|
|
41556
41587
|
pendo.flexElement(pendo.dom(guideMarkdownUtil.containerSelector));
|
|
41557
41588
|
pendo.BuildingBlocks.BuildingBlockGuides.recalculateGuideHeight(containerId, context);
|
|
41558
41589
|
}
|
|
41559
|
-
function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
41560
|
-
|
|
41561
|
-
var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41590
|
+
function findSubstitutableUrlsInJson(originalData, placeholderData = [], pendo) {
|
|
41591
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41562
41592
|
if ((originalData.name === 'url' || originalData.name === 'href') && originalData.value) {
|
|
41563
41593
|
if (subRegex.test(originalData.value)) {
|
|
41564
41594
|
placeholderData.push({
|
|
@@ -41568,37 +41598,37 @@ function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
|
41568
41598
|
}
|
|
41569
41599
|
}
|
|
41570
41600
|
if (originalData.properties && originalData.id === 'href_link_block') {
|
|
41571
|
-
pendo._.each(originalData.properties,
|
|
41601
|
+
pendo._.each(originalData.properties, (prop) => {
|
|
41572
41602
|
findSubstitutableUrlsInJson(prop, placeholderData, pendo);
|
|
41573
41603
|
});
|
|
41574
41604
|
}
|
|
41575
41605
|
if (originalData.views) {
|
|
41576
|
-
pendo._.each(originalData.views,
|
|
41606
|
+
pendo._.each(originalData.views, (view) => {
|
|
41577
41607
|
findSubstitutableUrlsInJson(view, placeholderData, pendo);
|
|
41578
41608
|
});
|
|
41579
41609
|
}
|
|
41580
41610
|
if (originalData.parameters) {
|
|
41581
|
-
pendo._.each(originalData.parameters,
|
|
41611
|
+
pendo._.each(originalData.parameters, (param) => {
|
|
41582
41612
|
findSubstitutableUrlsInJson(param, placeholderData, pendo);
|
|
41583
41613
|
});
|
|
41584
41614
|
}
|
|
41585
41615
|
if (originalData.actions) {
|
|
41586
|
-
pendo._.each(originalData.actions,
|
|
41616
|
+
pendo._.each(originalData.actions, (action) => {
|
|
41587
41617
|
findSubstitutableUrlsInJson(action, placeholderData, pendo);
|
|
41588
41618
|
});
|
|
41589
41619
|
}
|
|
41590
41620
|
if (originalData.children) {
|
|
41591
|
-
pendo._.each(originalData.children,
|
|
41621
|
+
pendo._.each(originalData.children, (child) => {
|
|
41592
41622
|
findSubstitutableUrlsInJson(child, placeholderData, pendo);
|
|
41593
41623
|
});
|
|
41594
41624
|
}
|
|
41595
41625
|
return placeholderData;
|
|
41596
41626
|
}
|
|
41597
41627
|
function findSubstitutableElements(pendo) {
|
|
41598
|
-
|
|
41628
|
+
let elements = pendo.dom(`${guideMarkdownUtil.containerSelector} *:not(.pendo-inline-ui)`);
|
|
41599
41629
|
return pendo._.chain(elements)
|
|
41600
41630
|
.filter(function (placeholder) {
|
|
41601
|
-
|
|
41631
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41602
41632
|
if (placeholder.localName === 'a') {
|
|
41603
41633
|
return subRegex.test(decodeURI(placeholder.href)) || subRegex.test(placeholder.textContent);
|
|
41604
41634
|
}
|
|
@@ -41654,25 +41684,51 @@ function findSubstitutableElements(pendo) {
|
|
|
41654
41684
|
.value();
|
|
41655
41685
|
}
|
|
41656
41686
|
function substitutionIcon(color, size) {
|
|
41657
|
-
return (
|
|
41658
|
-
|
|
41659
|
-
|
|
41660
|
-
|
|
41661
|
-
|
|
41662
|
-
|
|
41687
|
+
return (`<div title="Metadata Substitution added">
|
|
41688
|
+
<svg id="pendo-ps-substitution-icon" viewBox="0 0 24 24"
|
|
41689
|
+
preserveAspectRatio="xMidYMid meet"
|
|
41690
|
+
height=${size} width=${size} title="Metadata Substitution"
|
|
41691
|
+
style="bottom:5px; right:10px; position: absolute;"
|
|
41692
|
+
fill="none" xmlns="http://www.w3.org/2000/svg" stroke="${color}"
|
|
41693
|
+
transform="matrix(1, 0, 0, 1, 0, 0)rotate(0)">
|
|
41694
|
+
<g stroke-width="0"></g>
|
|
41695
|
+
<g stroke-linecap="round" stroke-linejoin="round"
|
|
41696
|
+
stroke="${color}" stroke-width="0.528"></g>
|
|
41697
|
+
<g><path fill-rule="evenodd" clip-rule="evenodd"
|
|
41698
|
+
d="M5 5.5C4.17157 5.5 3.5 6.17157 3.5 7V10C3.5 10.8284
|
|
41699
|
+
4.17157 11.5 5 11.5H8C8.82843 11.5 9.5 10.8284 9.5
|
|
41700
|
+
10V9H17V11C17 11.2761 17.2239 11.5 17.5 11.5C17.7761
|
|
41701
|
+
11.5 18 11.2761 18 11V8.5C18 8.22386 17.7761 8 17.5
|
|
41702
|
+
8H9.5V7C9.5 6.17157 8.82843 5.5 8 5.5H5ZM8.5 7C8.5
|
|
41703
|
+
6.72386 8.27614 6.5 8 6.5H5C4.72386 6.5 4.5 6.72386
|
|
41704
|
+
4.5 7V10C4.5 10.2761 4.72386 10.5 5 10.5H8C8.27614
|
|
41705
|
+
10.5 8.5 10.2761 8.5 10V7Z" fill="${color}"></path>
|
|
41706
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
41707
|
+
d="M7 13C7 12.7239 6.77614 12.5 6.5 12.5C6.22386 12.5
|
|
41708
|
+
6 12.7239 6 13V15.5C6 15.7761 6.22386 16 6.5
|
|
41709
|
+
16H14.5V17C14.5 17.8284 15.1716 18.5 16 18.5H19C19.8284
|
|
41710
|
+
18.5 20.5 17.8284 20.5 17V14C20.5 13.1716 19.8284 12.5
|
|
41711
|
+
19 12.5H16C15.1716 12.5 14.5 13.1716 14.5
|
|
41712
|
+
14V15H7V13ZM15.5 17C15.5 17.2761 15.7239 17.5 16
|
|
41713
|
+
17.5H19C19.2761 17.5 19.5 17.2761 19.5 17V14C19.5
|
|
41714
|
+
13.7239 19.2761 13.5 19 13.5H16C15.7239 13.5 15.5
|
|
41715
|
+
13.7239 15.5 14V17Z" fill="${color}"></path> </g></svg></div>`);
|
|
41716
|
+
}
|
|
41717
|
+
|
|
41718
|
+
const requiredElement = '<span class="_pendo-required-indicator" style="color:red; font-style:italic;" title="Question is required"> *</span>';
|
|
41719
|
+
const requiredSyntax = '{required/}';
|
|
41720
|
+
const RequiredQuestions = {
|
|
41663
41721
|
name: 'RequiredQuestions',
|
|
41664
|
-
script
|
|
41722
|
+
script(step, guide, pendo) {
|
|
41665
41723
|
var _a;
|
|
41666
|
-
|
|
41667
|
-
|
|
41668
|
-
|
|
41669
|
-
});
|
|
41670
|
-
var requiredQuestions = processRequiredQuestions();
|
|
41724
|
+
let requiredPollIds = [];
|
|
41725
|
+
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'));
|
|
41726
|
+
const requiredQuestions = processRequiredQuestions();
|
|
41671
41727
|
if (requiredQuestions) {
|
|
41672
|
-
pendo._.forEach(requiredQuestions,
|
|
41728
|
+
pendo._.forEach(requiredQuestions, (question) => {
|
|
41673
41729
|
if (question.classList.contains('_pendo-open-text-poll-question')) {
|
|
41674
|
-
|
|
41675
|
-
step.attachEvent(step.guideElement.find(
|
|
41730
|
+
let pollId = question.dataset.pendoPollId;
|
|
41731
|
+
step.attachEvent(step.guideElement.find(`[data-pendo-poll-id=${pollId}]._pendo-open-text-poll-input`)[0], 'input', function () {
|
|
41676
41732
|
evaluateRequiredQuestions(requiredQuestions);
|
|
41677
41733
|
});
|
|
41678
41734
|
}
|
|
@@ -41684,13 +41740,11 @@ var RequiredQuestions = {
|
|
|
41684
41740
|
});
|
|
41685
41741
|
}
|
|
41686
41742
|
function getEligibleQuestions() {
|
|
41687
|
-
|
|
41688
|
-
|
|
41689
|
-
|
|
41690
|
-
|
|
41691
|
-
|
|
41692
|
-
var allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
41693
|
-
return pendo._.reduce(allQuestions, function (eligibleQuestions, question) {
|
|
41743
|
+
const pollQuestions = pendo._.toArray(step.guideElement.find(`[class*=-poll-question]:contains(${requiredSyntax})`));
|
|
41744
|
+
const surveyMatches = pendo._.toArray(step.guideElement.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`));
|
|
41745
|
+
const surveyQuestions = pendo._.filter(surveyMatches, (candidate) => !pendo._.some(surveyMatches, (other) => other !== candidate && candidate.contains(other)));
|
|
41746
|
+
const allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
41747
|
+
return pendo._.reduce(allQuestions, (eligibleQuestions, question) => {
|
|
41694
41748
|
if (question.classList.contains('_pendo-yes-no-poll-question'))
|
|
41695
41749
|
return eligibleQuestions;
|
|
41696
41750
|
eligibleQuestions.push(question);
|
|
@@ -41698,24 +41752,22 @@ var RequiredQuestions = {
|
|
|
41698
41752
|
}, []);
|
|
41699
41753
|
}
|
|
41700
41754
|
function ownsRequiredText(element) {
|
|
41701
|
-
return pendo._.some(element.childNodes,
|
|
41702
|
-
return node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1;
|
|
41703
|
-
});
|
|
41755
|
+
return pendo._.some(element.childNodes, (node) => node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1);
|
|
41704
41756
|
}
|
|
41705
41757
|
function processRequiredQuestions() {
|
|
41706
|
-
|
|
41758
|
+
let questions = getEligibleQuestions();
|
|
41707
41759
|
if (questions) {
|
|
41708
|
-
pendo._.forEach(questions,
|
|
41709
|
-
|
|
41760
|
+
pendo._.forEach(questions, question => {
|
|
41761
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41710
41762
|
requiredPollIds.push(dataPendoPollId);
|
|
41711
|
-
|
|
41712
|
-
|
|
41713
|
-
pendo._.each(candidates,
|
|
41763
|
+
const candidates = step.guideElement.find(`#${question.id} *, #${question.id}`);
|
|
41764
|
+
const textHost = pendo._.find(candidates, ownsRequiredText) || question;
|
|
41765
|
+
pendo._.each(candidates, (element) => {
|
|
41714
41766
|
guideMarkdownUtil.removeMarkdownSyntax(element, requiredSyntax, '', pendo);
|
|
41715
41767
|
});
|
|
41716
|
-
|
|
41768
|
+
const textHostEl = pendo.dom(textHost);
|
|
41717
41769
|
if (textHostEl.find('._pendo-required-indicator').length === 0) {
|
|
41718
|
-
|
|
41770
|
+
const questionParagraph = textHostEl.find('p');
|
|
41719
41771
|
if (questionParagraph && questionParagraph.length) {
|
|
41720
41772
|
pendo.dom(questionParagraph[0]).append(requiredElement);
|
|
41721
41773
|
}
|
|
@@ -41726,7 +41778,15 @@ var RequiredQuestions = {
|
|
|
41726
41778
|
});
|
|
41727
41779
|
}
|
|
41728
41780
|
if (pendo._.size(requiredPollIds)) {
|
|
41729
|
-
|
|
41781
|
+
const disabledButtonStyles = `<style type=text/css
|
|
41782
|
+
id=_pendo-guide-required-disabled>
|
|
41783
|
+
._pendo-button:disabled, ._pendo-buttons[disabled] {
|
|
41784
|
+
border: 1px solid #999999 !important;
|
|
41785
|
+
background-color: #cccccc !important;
|
|
41786
|
+
color: #666666 !important;
|
|
41787
|
+
pointer-events: none !important;
|
|
41788
|
+
}
|
|
41789
|
+
</style>`;
|
|
41730
41790
|
if (pendo.dom('#_pendo-guide-required-disabled').length === 0) {
|
|
41731
41791
|
pendo.dom('head').append(disabledButtonStyles);
|
|
41732
41792
|
}
|
|
@@ -41737,11 +41797,15 @@ var RequiredQuestions = {
|
|
|
41737
41797
|
function evaluateRequiredQuestions(questions) {
|
|
41738
41798
|
if (questions.length === 0)
|
|
41739
41799
|
return;
|
|
41740
|
-
|
|
41741
|
-
|
|
41742
|
-
responses = responses.concat(pendo._.map(questions,
|
|
41743
|
-
|
|
41744
|
-
|
|
41800
|
+
let allRequiredComplete = true;
|
|
41801
|
+
let responses = [];
|
|
41802
|
+
responses = responses.concat(pendo._.map(questions, (question) => {
|
|
41803
|
+
let pollId = question.getAttribute('data-pendo-poll-id');
|
|
41804
|
+
let input = step.guideElement.find(`
|
|
41805
|
+
[data-pendo-poll-id=${pollId}] textarea,
|
|
41806
|
+
[data-pendo-poll-id=${pollId}] input:text,
|
|
41807
|
+
[data-pendo-poll-id=${pollId}] select,
|
|
41808
|
+
[data-pendo-poll-id=${pollId}] input:radio:checked`);
|
|
41745
41809
|
if (input && input.length && input[0].value) {
|
|
41746
41810
|
return input[0].value;
|
|
41747
41811
|
}
|
|
@@ -41758,50 +41822,50 @@ var RequiredQuestions = {
|
|
|
41758
41822
|
}
|
|
41759
41823
|
function disableEligibleButtons(buttons) {
|
|
41760
41824
|
pendo._.each(buttons, function (button) {
|
|
41761
|
-
if (step.guideElement.find(
|
|
41762
|
-
step.guideElement.find(
|
|
41763
|
-
step.guideElement.find(
|
|
41825
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
41826
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = true;
|
|
41827
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = 'Please complete all required questions.';
|
|
41764
41828
|
}
|
|
41765
41829
|
});
|
|
41766
41830
|
}
|
|
41767
41831
|
function enableEligibleButtons(buttons) {
|
|
41768
41832
|
pendo._.each(buttons, function (button) {
|
|
41769
|
-
if (step.guideElement.find(
|
|
41770
|
-
step.guideElement.find(
|
|
41771
|
-
step.guideElement.find(
|
|
41833
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
41834
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = false;
|
|
41835
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = '';
|
|
41772
41836
|
}
|
|
41773
41837
|
});
|
|
41774
41838
|
}
|
|
41775
41839
|
},
|
|
41776
|
-
test
|
|
41840
|
+
test(step, guide, pendo) {
|
|
41777
41841
|
var _a, _b;
|
|
41778
|
-
|
|
41779
|
-
|
|
41842
|
+
const pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(`[class*=-poll-question]:contains(${requiredSyntax})`);
|
|
41843
|
+
const surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`);
|
|
41780
41844
|
return (!pendo._.isUndefined(pollQuestions) && pendo._.size(pollQuestions)) ||
|
|
41781
41845
|
(!pendo._.isUndefined(surveyQuestions) && pendo._.size(surveyQuestions));
|
|
41782
41846
|
},
|
|
41783
|
-
designerListener
|
|
41784
|
-
|
|
41785
|
-
|
|
41786
|
-
|
|
41847
|
+
designerListener(pendo) {
|
|
41848
|
+
const requiredQuestions = [];
|
|
41849
|
+
const target = pendo.dom.getBody();
|
|
41850
|
+
const config = {
|
|
41787
41851
|
attributeFilter: ['data-layout'],
|
|
41788
41852
|
attributes: true,
|
|
41789
41853
|
childList: true,
|
|
41790
41854
|
characterData: true,
|
|
41791
41855
|
subtree: true
|
|
41792
41856
|
};
|
|
41793
|
-
|
|
41794
|
-
|
|
41857
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41858
|
+
const observer = new MutationObserver(applyRequiredIndicators);
|
|
41795
41859
|
observer.observe(target, config);
|
|
41796
41860
|
function applyRequiredIndicators(mutations) {
|
|
41797
41861
|
pendo._.each(mutations, function (mutation) {
|
|
41798
41862
|
var _a;
|
|
41799
|
-
|
|
41863
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
41800
41864
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41801
|
-
|
|
41865
|
+
let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
|
|
41802
41866
|
if (eligiblePolls) {
|
|
41803
41867
|
pendo._.each(eligiblePolls, function (poll) {
|
|
41804
|
-
|
|
41868
|
+
let dataPendoPollId;
|
|
41805
41869
|
if (poll.classList.contains('_pendo-open-text-poll-wrapper') ||
|
|
41806
41870
|
poll.classList.contains('_pendo-number-scale-poll-wrapper')) {
|
|
41807
41871
|
dataPendoPollId = poll.getAttribute('name');
|
|
@@ -41809,31 +41873,31 @@ var RequiredQuestions = {
|
|
|
41809
41873
|
else {
|
|
41810
41874
|
dataPendoPollId = poll.getAttribute('data-pendo-poll-id');
|
|
41811
41875
|
}
|
|
41812
|
-
|
|
41813
|
-
|
|
41814
|
-
pendo.dom(
|
|
41876
|
+
let questionText;
|
|
41877
|
+
const questionElement = pendo.dom(`[class*="-poll-question"][data-pendo-poll-id=${dataPendoPollId}]`)[0] ||
|
|
41878
|
+
pendo.dom(`.bb-text[data-pendo-poll-id=${dataPendoPollId}]`)[0];
|
|
41815
41879
|
if (questionElement) {
|
|
41816
41880
|
questionText = questionElement.textContent;
|
|
41817
41881
|
}
|
|
41818
|
-
|
|
41882
|
+
const requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
|
|
41819
41883
|
if (requiredSyntaxIndex > -1) {
|
|
41820
|
-
pendo._.each(pendo.dom(
|
|
41821
|
-
pendo._.each(pendo.dom(
|
|
41884
|
+
pendo._.each(pendo.dom(`[data-pendo-poll-id=${dataPendoPollId}]:not(.pendo-radio)`), (element) => {
|
|
41885
|
+
pendo._.each(pendo.dom(`#${element.id} *:not(".pendo-radio"), #${element.id}:not(".pendo-radio")`), (item) => {
|
|
41822
41886
|
guideMarkdownUtil.removeMarkdownSyntax(item, requiredSyntax, '', pendo);
|
|
41823
41887
|
});
|
|
41824
41888
|
});
|
|
41825
|
-
|
|
41826
|
-
|
|
41827
|
-
|
|
41828
|
-
|
|
41829
|
-
pendo._.each(pendo.dom(
|
|
41830
|
-
pendo._.each(el.childNodes,
|
|
41889
|
+
const pollTextSelector = `.bb-text[data-pendo-poll-id=${dataPendoPollId}]`;
|
|
41890
|
+
const pollParagraphSelector = `${pollTextSelector} p`;
|
|
41891
|
+
const pollListItemSelector = `${pollTextSelector} li`;
|
|
41892
|
+
const pollIndicatorSelector = `${pollTextSelector} ._pendo-required-indicator`;
|
|
41893
|
+
pendo._.each(pendo.dom(`${pollParagraphSelector}, ${pollListItemSelector}`), (el) => {
|
|
41894
|
+
pendo._.each(el.childNodes, (node) => {
|
|
41831
41895
|
if (node.nodeType === 3 && node.nodeValue.indexOf(requiredSyntax) !== -1) {
|
|
41832
41896
|
node.nodeValue = node.nodeValue.split(requiredSyntax).join('');
|
|
41833
41897
|
}
|
|
41834
41898
|
});
|
|
41835
41899
|
});
|
|
41836
|
-
|
|
41900
|
+
const hasIndicator = pendo.dom(pollIndicatorSelector).length !== 0;
|
|
41837
41901
|
if (!hasIndicator) {
|
|
41838
41902
|
if (pendo.dom(pollParagraphSelector).length !== 0 || pendo.dom(pollListItemSelector).length !== 0) {
|
|
41839
41903
|
pendo.dom(pollParagraphSelector).append(requiredElement);
|
|
@@ -41844,7 +41908,7 @@ var RequiredQuestions = {
|
|
|
41844
41908
|
}
|
|
41845
41909
|
}
|
|
41846
41910
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
41847
|
-
|
|
41911
|
+
let questionIndex = requiredQuestions.indexOf(dataPendoPollId);
|
|
41848
41912
|
if (questionIndex !== -1) {
|
|
41849
41913
|
requiredQuestions.splice(questionIndex, 1);
|
|
41850
41914
|
}
|
|
@@ -41855,7 +41919,7 @@ var RequiredQuestions = {
|
|
|
41855
41919
|
}
|
|
41856
41920
|
else {
|
|
41857
41921
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
41858
|
-
|
|
41922
|
+
let index = requiredQuestions.indexOf(dataPendoPollId);
|
|
41859
41923
|
if (index !== -1) {
|
|
41860
41924
|
requiredQuestions.splice(index, 1);
|
|
41861
41925
|
}
|
|
@@ -41869,54 +41933,54 @@ var RequiredQuestions = {
|
|
|
41869
41933
|
}
|
|
41870
41934
|
};
|
|
41871
41935
|
|
|
41872
|
-
|
|
41873
|
-
|
|
41874
|
-
script
|
|
41875
|
-
|
|
41876
|
-
|
|
41877
|
-
|
|
41878
|
-
|
|
41879
|
-
|
|
41936
|
+
const skipStepRegex = new RegExp(guideMarkdownUtil.skipStepString);
|
|
41937
|
+
const SkipToEligibleStep = {
|
|
41938
|
+
script(step, guide, pendo) {
|
|
41939
|
+
let isAdvanceIntercepted = false;
|
|
41940
|
+
let isPreviousIntercepted = false;
|
|
41941
|
+
let guideContainer = step.guideElement.find(guideMarkdownUtil.containerSelector);
|
|
41942
|
+
let guideContainerAriaLabel = guideContainer.attr('aria-label');
|
|
41943
|
+
let stepNumberOrAuto = skipStepRegex.exec(guideContainerAriaLabel)[1];
|
|
41880
41944
|
if (guideContainer) {
|
|
41881
41945
|
guideContainer.attr({ 'aria-label': guideContainer.attr('aria-label').replace(skipStepRegex, '') });
|
|
41882
41946
|
}
|
|
41883
|
-
this.on('beforeAdvance',
|
|
41947
|
+
this.on('beforeAdvance', (evt) => {
|
|
41884
41948
|
if (guide.getPositionOfStep(step) === guide.steps.length || pendo._.isUndefined(stepNumberOrAuto))
|
|
41885
41949
|
return; // exit on the last step of a guide or when we don't have an argument
|
|
41886
|
-
|
|
41950
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'next');
|
|
41887
41951
|
if (!isAdvanceIntercepted && stepNumberOrAuto) {
|
|
41888
41952
|
isAdvanceIntercepted = true;
|
|
41889
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
41953
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
41890
41954
|
evt.cancel = true;
|
|
41891
41955
|
}
|
|
41892
41956
|
});
|
|
41893
|
-
this.on('beforePrevious',
|
|
41957
|
+
this.on('beforePrevious', (evt) => {
|
|
41894
41958
|
if (pendo._.isUndefined(stepNumberOrAuto))
|
|
41895
41959
|
return;
|
|
41896
|
-
|
|
41960
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'previous');
|
|
41897
41961
|
if (!isPreviousIntercepted && stepNumberOrAuto) {
|
|
41898
41962
|
isPreviousIntercepted = true;
|
|
41899
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
41963
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
41900
41964
|
evt.cancel = true;
|
|
41901
41965
|
}
|
|
41902
41966
|
});
|
|
41903
41967
|
function findEligibleSkipStep(stepNumber, direction) {
|
|
41904
41968
|
// Find the next eligible step by using getPosition of step (1 based)
|
|
41905
41969
|
// getPosition - 2 gives the previous step
|
|
41906
|
-
|
|
41907
|
-
|
|
41970
|
+
let skipForwardStep = findStepOnPage(guide.getPositionOfStep(step), 'next', stepNumber);
|
|
41971
|
+
let skipPreviousStep = findStepOnPage(guide.getPositionOfStep(step) - 2, 'previous', stepNumber);
|
|
41908
41972
|
if (skipForwardStep && direction == 'next') {
|
|
41909
|
-
pendo.goToStep({ destinationStepId: skipForwardStep, step
|
|
41973
|
+
pendo.goToStep({ destinationStepId: skipForwardStep, step });
|
|
41910
41974
|
}
|
|
41911
41975
|
if (skipPreviousStep && direction == 'previous') {
|
|
41912
|
-
pendo.goToStep({ destinationStepId: skipPreviousStep, step
|
|
41976
|
+
pendo.goToStep({ destinationStepId: skipPreviousStep, step });
|
|
41913
41977
|
}
|
|
41914
41978
|
return direction === 'next' ? skipForwardStep : skipPreviousStep;
|
|
41915
41979
|
}
|
|
41916
41980
|
function findStepOnPage(stepIndex, direction, stepNumber) {
|
|
41917
41981
|
if (pendo._.isNaN(stepIndex))
|
|
41918
41982
|
return;
|
|
41919
|
-
|
|
41983
|
+
let $step = guide.steps[stepIndex];
|
|
41920
41984
|
if ($step && !$step.canShow()) {
|
|
41921
41985
|
if (stepNumber !== 'auto') {
|
|
41922
41986
|
return guide.steps[stepNumber - 1];
|
|
@@ -41933,34 +41997,34 @@ var SkipToEligibleStep = {
|
|
|
41933
41997
|
}
|
|
41934
41998
|
}
|
|
41935
41999
|
},
|
|
41936
|
-
test
|
|
42000
|
+
test(step, guide, pendo) {
|
|
41937
42001
|
var _a;
|
|
41938
|
-
|
|
42002
|
+
const guideContainerAriaLabel = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(guideMarkdownUtil.containerSelector).attr('aria-label');
|
|
41939
42003
|
return pendo._.isString(guideContainerAriaLabel) && guideContainerAriaLabel.indexOf('{skipStep') !== -1;
|
|
41940
42004
|
},
|
|
41941
|
-
designerListener
|
|
41942
|
-
|
|
41943
|
-
|
|
42005
|
+
designerListener(pendo) {
|
|
42006
|
+
const target = pendo.dom.getBody();
|
|
42007
|
+
const config = {
|
|
41944
42008
|
attributeFilter: ['data-layout'],
|
|
41945
42009
|
attributes: true,
|
|
41946
42010
|
childList: true,
|
|
41947
42011
|
characterData: true,
|
|
41948
42012
|
subtree: true
|
|
41949
42013
|
};
|
|
41950
|
-
|
|
41951
|
-
|
|
42014
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42015
|
+
const observer = new MutationObserver(applySkipStepIndicator);
|
|
41952
42016
|
observer.observe(target, config);
|
|
41953
42017
|
// create an observer instance
|
|
41954
42018
|
function applySkipStepIndicator(mutations) {
|
|
41955
42019
|
pendo._.each(mutations, function (mutation) {
|
|
41956
42020
|
var _a, _b;
|
|
41957
|
-
|
|
42021
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
41958
42022
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41959
|
-
|
|
41960
|
-
|
|
42023
|
+
let guideContainer = mutation.addedNodes[0].querySelectorAll(guideMarkdownUtil.containerSelector);
|
|
42024
|
+
let guideContainerAriaLabel = (_b = guideContainer[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label');
|
|
41961
42025
|
if (guideContainerAriaLabel) {
|
|
41962
42026
|
if (guideContainerAriaLabel.match(skipStepRegex)) {
|
|
41963
|
-
|
|
42027
|
+
let fullSkipStepString = guideContainerAriaLabel.match(skipStepRegex)[0];
|
|
41964
42028
|
guideContainerAriaLabel.replace(fullSkipStepString, '');
|
|
41965
42029
|
if (!pendo.dom('#_pendoSkipIcon').length) {
|
|
41966
42030
|
pendo.dom(guideMarkdownUtil.containerSelector).append(skipIcon('#999', '30px').trim());
|
|
@@ -41971,30 +42035,48 @@ var SkipToEligibleStep = {
|
|
|
41971
42035
|
});
|
|
41972
42036
|
}
|
|
41973
42037
|
function skipIcon(color, size) {
|
|
41974
|
-
return (
|
|
42038
|
+
return (`<div title="Skip step added"><svg id="_pendoSkipIcon" version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
42039
|
+
width="${size}" height="${size}" viewBox="0 0 512.000000 512.000000"
|
|
42040
|
+
preserveAspectRatio="xMidYMid meet" style="bottom:5px; right:10px; position: absolute;">
|
|
42041
|
+
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
|
|
42042
|
+
fill="${color}" stroke="none">
|
|
42043
|
+
<path d="M2185 4469 c-363 -38 -739 -186 -1034 -407 -95 -71 -273 -243 -357
|
|
42044
|
+
-343 -205 -246 -364 -577 -429 -897 -25 -121 -45 -288 -45 -373 l0 -49 160 0
|
|
42045
|
+
160 0 0 48 c0 26 5 88 10 137 68 593 417 1103 940 1374 1100 570 2418 -137
|
|
42046
|
+
2560 -1374 5 -49 10 -111 10 -137 l0 -47 -155 -3 -155 -3 235 -235 235 -236
|
|
42047
|
+
235 236 235 235 -155 3 -155 3 0 48 c0 27 -5 95 -10 152 -100 989 -878 1767
|
|
42048
|
+
-1869 1868 -117 12 -298 12 -416 0z"/>
|
|
42049
|
+
<path d="M320 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42050
|
+
<path d="M960 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42051
|
+
<path d="M1600 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42052
|
+
<path d="M2240 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42053
|
+
<path d="M2880 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42054
|
+
<path d="M3840 1440 l0 -160 480 0 480 0 0 160 0 160 -480 0 -480 0 0 -160z"/>
|
|
42055
|
+
</g></svg></div>
|
|
42056
|
+
`);
|
|
41975
42057
|
}
|
|
41976
42058
|
}
|
|
41977
42059
|
};
|
|
41978
42060
|
|
|
41979
42061
|
function GuideMarkdown() {
|
|
41980
|
-
|
|
41981
|
-
|
|
41982
|
-
|
|
42062
|
+
let guideMarkdown;
|
|
42063
|
+
let pluginApi;
|
|
42064
|
+
let globalPendo;
|
|
41983
42065
|
return {
|
|
41984
42066
|
name: 'GuideMarkdown',
|
|
41985
42067
|
initialize: init,
|
|
41986
|
-
teardown
|
|
42068
|
+
teardown
|
|
41987
42069
|
};
|
|
41988
42070
|
function init(pendo, PluginAPI) {
|
|
41989
42071
|
globalPendo = pendo;
|
|
41990
42072
|
pluginApi = PluginAPI;
|
|
41991
|
-
|
|
41992
|
-
|
|
42073
|
+
const configReader = PluginAPI.ConfigReader;
|
|
42074
|
+
const GUIDEMARKDOWN_CONFIG = 'guideMarkdown';
|
|
41993
42075
|
configReader.addOption(GUIDEMARKDOWN_CONFIG, [
|
|
41994
42076
|
configReader.sources.SNIPPET_SRC,
|
|
41995
42077
|
configReader.sources.PENDO_CONFIG_SRC
|
|
41996
42078
|
], false);
|
|
41997
|
-
|
|
42079
|
+
const markdownScriptsEnabled = configReader.get(GUIDEMARKDOWN_CONFIG);
|
|
41998
42080
|
if (!markdownScriptsEnabled)
|
|
41999
42081
|
return;
|
|
42000
42082
|
guideMarkdown = [PollBranching, MetadataSubstitution, RequiredQuestions, SkipToEligibleStep];
|
|
@@ -43033,8 +43115,8 @@ function Feedback() {
|
|
|
43033
43115
|
var widgetLoaded = false;
|
|
43034
43116
|
var feedbackAllowedProductId = '';
|
|
43035
43117
|
var initialized = false;
|
|
43036
|
-
|
|
43037
|
-
|
|
43118
|
+
const PING_COOKIE = 'feedback_ping_sent';
|
|
43119
|
+
const PING_COOKIE_EXPIRATION = 1000 * 60 * 60;
|
|
43038
43120
|
var overflowMediaQuery = '@media only screen and (max-device-width:1112px){#feedback-widget{overflow-y:scroll}}';
|
|
43039
43121
|
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%)}}';
|
|
43040
43122
|
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)}}';
|
|
@@ -43054,28 +43136,28 @@ function Feedback() {
|
|
|
43054
43136
|
feedbackStyles: 'pendo-feedback-styles',
|
|
43055
43137
|
feedbackFrameStyles: 'pendo-feedback-visible-buttons-styles'
|
|
43056
43138
|
};
|
|
43057
|
-
|
|
43058
|
-
|
|
43139
|
+
let globalPendo;
|
|
43140
|
+
let pluginApi;
|
|
43059
43141
|
return {
|
|
43060
43142
|
name: 'Feedback',
|
|
43061
|
-
initialize
|
|
43062
|
-
teardown
|
|
43063
|
-
validate
|
|
43143
|
+
initialize,
|
|
43144
|
+
teardown,
|
|
43145
|
+
validate
|
|
43064
43146
|
};
|
|
43065
43147
|
function initialize(pendo, PluginAPI) {
|
|
43066
43148
|
globalPendo = pendo;
|
|
43067
43149
|
pluginApi = PluginAPI;
|
|
43068
43150
|
var publicFeedback = {
|
|
43069
|
-
ping
|
|
43070
|
-
init
|
|
43151
|
+
ping,
|
|
43152
|
+
init,
|
|
43071
43153
|
initialized: getInitialized,
|
|
43072
|
-
loginAndRedirect
|
|
43073
|
-
openFeedback
|
|
43074
|
-
initializeFeedbackOnce
|
|
43075
|
-
isFeedbackLoaded
|
|
43076
|
-
convertPendoToFeedbackOptions
|
|
43154
|
+
loginAndRedirect,
|
|
43155
|
+
openFeedback,
|
|
43156
|
+
initializeFeedbackOnce,
|
|
43157
|
+
isFeedbackLoaded,
|
|
43158
|
+
convertPendoToFeedbackOptions,
|
|
43077
43159
|
isUnsupportedIE: pendo._.partial(isUnsupportedIE, PluginAPI),
|
|
43078
|
-
removeFeedbackWidget
|
|
43160
|
+
removeFeedbackWidget
|
|
43079
43161
|
};
|
|
43080
43162
|
pendo.feedback = publicFeedback;
|
|
43081
43163
|
pendo.getFeedbackSettings = getFeedbackSettings;
|
|
@@ -43106,7 +43188,7 @@ function Feedback() {
|
|
|
43106
43188
|
localStorageOnly: true
|
|
43107
43189
|
});
|
|
43108
43190
|
return {
|
|
43109
|
-
validate
|
|
43191
|
+
validate
|
|
43110
43192
|
};
|
|
43111
43193
|
}
|
|
43112
43194
|
function teardown() {
|
|
@@ -43126,18 +43208,18 @@ function Feedback() {
|
|
|
43126
43208
|
return result;
|
|
43127
43209
|
}
|
|
43128
43210
|
function pingOrInitialize() {
|
|
43129
|
-
|
|
43211
|
+
const options = getPendoOptions();
|
|
43130
43212
|
if (initialized) {
|
|
43131
|
-
|
|
43213
|
+
const feedbackOptions = convertPendoToFeedbackOptions(options);
|
|
43132
43214
|
ping(feedbackOptions);
|
|
43133
43215
|
}
|
|
43134
43216
|
else if (shouldInitializeFeedback() && !globalPendo._.isEmpty(options)) {
|
|
43135
|
-
|
|
43136
|
-
init(options, settings)
|
|
43217
|
+
const settings = pluginApi.ConfigReader.get('feedbackSettings');
|
|
43218
|
+
init(options, settings).catch(globalPendo._.noop);
|
|
43137
43219
|
}
|
|
43138
43220
|
}
|
|
43139
43221
|
function handleIdentityChange(event) {
|
|
43140
|
-
|
|
43222
|
+
const visitorId = globalPendo._.get(event, 'data.0.visitor_id') || globalPendo._.get(event, 'data.0.options.visitor.id');
|
|
43141
43223
|
if (globalPendo.isAnonymousVisitor(visitorId)) {
|
|
43142
43224
|
removeFeedbackWidget();
|
|
43143
43225
|
return;
|
|
@@ -43207,9 +43289,9 @@ function Feedback() {
|
|
|
43207
43289
|
if (toSend.data && toSend.data !== '{}' && toSend.data !== 'null') {
|
|
43208
43290
|
return globalPendo.ajax
|
|
43209
43291
|
.postJSON(getFullUrl('/widget/pendo_ping'), toSend)
|
|
43210
|
-
.then(
|
|
43292
|
+
.then((response) => {
|
|
43211
43293
|
onWidgetPingResponse(response);
|
|
43212
|
-
})
|
|
43294
|
+
}).catch(() => { onPingFailure(); });
|
|
43213
43295
|
}
|
|
43214
43296
|
}
|
|
43215
43297
|
return pluginApi.q.resolve();
|
|
@@ -43343,10 +43425,10 @@ function Feedback() {
|
|
|
43343
43425
|
return globalPendo.ajax.postJSON(getFullUrl('/analytics'), toSend);
|
|
43344
43426
|
}
|
|
43345
43427
|
function addOverlay() {
|
|
43346
|
-
|
|
43428
|
+
const widget = globalPendo.dom(`#${elemIds.feedbackWidget}`);
|
|
43347
43429
|
if (!widget)
|
|
43348
43430
|
return;
|
|
43349
|
-
|
|
43431
|
+
const overlayStyles = {
|
|
43350
43432
|
'position': 'fixed',
|
|
43351
43433
|
'top': '0',
|
|
43352
43434
|
'right': '0',
|
|
@@ -43358,7 +43440,7 @@ function Feedback() {
|
|
|
43358
43440
|
'animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both',
|
|
43359
43441
|
'-webkit-animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both'
|
|
43360
43442
|
};
|
|
43361
|
-
|
|
43443
|
+
const overlayElement = globalPendo.dom(document.createElement('div'));
|
|
43362
43444
|
overlayElement.attr('id', 'feedback-overlay');
|
|
43363
43445
|
overlayElement.css(overlayStyles);
|
|
43364
43446
|
overlayElement.appendTo(widget.getParent());
|
|
@@ -43463,22 +43545,22 @@ function Feedback() {
|
|
|
43463
43545
|
}
|
|
43464
43546
|
}
|
|
43465
43547
|
function buildOuterTriggerDiv(positionInfo) {
|
|
43466
|
-
|
|
43467
|
-
|
|
43468
|
-
|
|
43548
|
+
const horizontalStyles = getHorizontalPositionStyles(positionInfo);
|
|
43549
|
+
const verticalStyles = getVerticalPositionStyles(positionInfo);
|
|
43550
|
+
const styles = globalPendo._.extend({
|
|
43469
43551
|
'position': 'fixed',
|
|
43470
43552
|
'height': '43px',
|
|
43471
43553
|
'opacity': '1 !important',
|
|
43472
43554
|
'z-index': '9001'
|
|
43473
43555
|
}, horizontalStyles, verticalStyles);
|
|
43474
|
-
|
|
43556
|
+
const outerTrigger = globalPendo.dom(document.createElement('div'));
|
|
43475
43557
|
outerTrigger.attr('id', elemIds.feedbackTrigger);
|
|
43476
43558
|
outerTrigger.css(styles);
|
|
43477
43559
|
outerTrigger.attr('data-turbolinks-permanent', '');
|
|
43478
43560
|
return outerTrigger;
|
|
43479
43561
|
}
|
|
43480
43562
|
function buildNotification() {
|
|
43481
|
-
|
|
43563
|
+
const styles = {
|
|
43482
43564
|
'background-color': '#D85039',
|
|
43483
43565
|
'color': '#fff',
|
|
43484
43566
|
'border-radius': '50%',
|
|
@@ -43495,20 +43577,20 @@ function Feedback() {
|
|
|
43495
43577
|
'animation-delay': '1s',
|
|
43496
43578
|
'animation-iteration-count': '1'
|
|
43497
43579
|
};
|
|
43498
|
-
|
|
43580
|
+
const notification = globalPendo.dom(document.createElement('span'));
|
|
43499
43581
|
notification.attr('id', 'feedback-trigger-notification');
|
|
43500
43582
|
notification.css(styles);
|
|
43501
43583
|
return notification;
|
|
43502
43584
|
}
|
|
43503
43585
|
function buildTriggerButton(settings, positionInfo) {
|
|
43504
|
-
|
|
43586
|
+
let borderRadius;
|
|
43505
43587
|
if (positionInfo.horizontalPosition === 'left') {
|
|
43506
43588
|
borderRadius = '0 0 5px 5px';
|
|
43507
43589
|
}
|
|
43508
43590
|
else {
|
|
43509
43591
|
borderRadius = '3px 3px 0 0';
|
|
43510
43592
|
}
|
|
43511
|
-
|
|
43593
|
+
const styles = {
|
|
43512
43594
|
'border': 'none',
|
|
43513
43595
|
'padding': '11px 18px 14px 18px',
|
|
43514
43596
|
'background-color': settings.triggerColor,
|
|
@@ -43519,21 +43601,32 @@ function Feedback() {
|
|
|
43519
43601
|
'cursor': 'pointer',
|
|
43520
43602
|
'text-align': 'left'
|
|
43521
43603
|
};
|
|
43522
|
-
|
|
43604
|
+
const triggerButton = globalPendo.dom(document.createElement('button'));
|
|
43523
43605
|
triggerButton.attr('id', elemIds.feedbackTriggerButton);
|
|
43524
43606
|
triggerButton.css(styles);
|
|
43525
43607
|
triggerButton.text(settings.triggerText);
|
|
43526
43608
|
return triggerButton;
|
|
43527
43609
|
}
|
|
43528
43610
|
function addTriggerPseudoStyles() {
|
|
43529
|
-
|
|
43611
|
+
const pseudoStyles = `
|
|
43612
|
+
#feedback-trigger button:hover {
|
|
43613
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
43614
|
+
outline: none !important;
|
|
43615
|
+
background: #3e566f !important;
|
|
43616
|
+
}
|
|
43617
|
+
#feedback-trigger button:focus {
|
|
43618
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
43619
|
+
outline: none !important;
|
|
43620
|
+
background: #3e566f !important;
|
|
43621
|
+
}
|
|
43622
|
+
`;
|
|
43530
43623
|
pluginApi.util.addInlineStyles('pendo-feedback-trigger-styles', pseudoStyles);
|
|
43531
43624
|
}
|
|
43532
43625
|
function createTrigger(settings, positionInfo) {
|
|
43533
43626
|
addTriggerPseudoStyles();
|
|
43534
|
-
|
|
43535
|
-
|
|
43536
|
-
|
|
43627
|
+
const triggerElement = buildOuterTriggerDiv(positionInfo);
|
|
43628
|
+
const notificationElement = buildNotification();
|
|
43629
|
+
const triggerButtonElement = buildTriggerButton(settings, positionInfo);
|
|
43537
43630
|
triggerElement.append(notificationElement);
|
|
43538
43631
|
triggerElement.append(triggerButtonElement);
|
|
43539
43632
|
triggerElement.appendTo(globalPendo.dom.getBody());
|
|
@@ -43557,7 +43650,7 @@ function Feedback() {
|
|
|
43557
43650
|
iframeWrapper.css(getWidgetOriginalStyles());
|
|
43558
43651
|
iframeWrapper.attr('id', elemIds.feedbackWidget);
|
|
43559
43652
|
iframeWrapper.attr('data-turbolinks-permanent', 'true');
|
|
43560
|
-
iframeWrapper.addClass(
|
|
43653
|
+
iframeWrapper.addClass(`buttonIs-${horizontalPosition}`);
|
|
43561
43654
|
return iframeWrapper;
|
|
43562
43655
|
}
|
|
43563
43656
|
function buildIframeContainer() {
|
|
@@ -43574,13 +43667,22 @@ function Feedback() {
|
|
|
43574
43667
|
return iframeContainer;
|
|
43575
43668
|
}
|
|
43576
43669
|
function addWidgetVisibleButtonStyles(buttonStylePosition) {
|
|
43577
|
-
|
|
43578
|
-
|
|
43670
|
+
let side = buttonStylePosition === 'left' ? 'left' : 'right'; // just in case something was not left or right for some reason
|
|
43671
|
+
const styles = `
|
|
43672
|
+
.buttonIs-${side}.visible {
|
|
43673
|
+
${side}: 0 !important;
|
|
43674
|
+
width: 470px !important;
|
|
43675
|
+
animation-direction: alternate-reverse !important;
|
|
43676
|
+
animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
43677
|
+
-webkit-animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
43678
|
+
z-index: 9002 !important;
|
|
43679
|
+
}
|
|
43680
|
+
`;
|
|
43579
43681
|
pluginApi.util.addInlineStyles(elemIds.feedbackFrameStyles, styles);
|
|
43580
43682
|
}
|
|
43581
43683
|
function initialiseWidgetFrame(horizontalPosition) {
|
|
43582
43684
|
addWidgetVisibleButtonStyles(horizontalPosition);
|
|
43583
|
-
|
|
43685
|
+
const iframeElement = buildIframeWrapper(horizontalPosition);
|
|
43584
43686
|
iframeElement.append(buildIframeContainer());
|
|
43585
43687
|
iframeElement.appendTo(globalPendo.dom.getBody());
|
|
43586
43688
|
subscribeToIframeMessages();
|
|
@@ -43604,7 +43706,7 @@ function Feedback() {
|
|
|
43604
43706
|
return widgetLoaded;
|
|
43605
43707
|
}
|
|
43606
43708
|
function getPendoOptions() {
|
|
43607
|
-
|
|
43709
|
+
let options = pluginApi.ConfigReader.getLocalConfig();
|
|
43608
43710
|
if (!globalPendo._.isObject(options))
|
|
43609
43711
|
options = {};
|
|
43610
43712
|
if (!globalPendo._.isObject(options.visitor))
|
|
@@ -43632,7 +43734,7 @@ function Feedback() {
|
|
|
43632
43734
|
return true;
|
|
43633
43735
|
}
|
|
43634
43736
|
function getQueryParam(url, paramName) {
|
|
43635
|
-
|
|
43737
|
+
const results = new RegExp('[?&]' + paramName + '=([^&#]*)').exec(url);
|
|
43636
43738
|
if (results == null) {
|
|
43637
43739
|
return null;
|
|
43638
43740
|
}
|
|
@@ -43649,13 +43751,13 @@ function Feedback() {
|
|
|
43649
43751
|
return pluginApi.q.reject();
|
|
43650
43752
|
if (!canInitFeedback(pendoOptions))
|
|
43651
43753
|
return pluginApi.q.reject();
|
|
43652
|
-
|
|
43754
|
+
const feedbackOptions = convertPendoToFeedbackOptions(pendoOptions);
|
|
43653
43755
|
try {
|
|
43654
|
-
|
|
43655
|
-
if (
|
|
43756
|
+
const fdbkDst = getQueryParam(globalPendo.url.get(), 'fdbkDst');
|
|
43757
|
+
if (fdbkDst && fdbkDst.startsWith('case')) {
|
|
43656
43758
|
initialized = true;
|
|
43657
43759
|
getFeedbackLoginUrl().then(function (loginUrl) {
|
|
43658
|
-
|
|
43760
|
+
const destinationUrl = loginUrl + '&fdbkDst=' + fdbkDst;
|
|
43659
43761
|
window.location.href = destinationUrl;
|
|
43660
43762
|
});
|
|
43661
43763
|
return;
|
|
@@ -43704,7 +43806,7 @@ function Feedback() {
|
|
|
43704
43806
|
function convertPendoToFeedbackOptions(options) {
|
|
43705
43807
|
var jwtOptions = pluginApi.agent.getJwtInfoCopy();
|
|
43706
43808
|
if (globalPendo._.isEmpty(jwtOptions)) {
|
|
43707
|
-
|
|
43809
|
+
const feedbackOptions = {};
|
|
43708
43810
|
feedbackOptions.user = globalPendo._.pick(options.visitor, 'id', 'full_name', 'firstName', 'lastName', 'email', 'tags', 'custom_allowed_products');
|
|
43709
43811
|
globalPendo._.extend(feedbackOptions.user, { allowed_products: [{ id: feedbackAllowedProductId }] });
|
|
43710
43812
|
feedbackOptions.account = globalPendo._.pick(options.account, 'id', 'name', 'monthly_value', 'is_paying', 'tags');
|
|
@@ -49239,32 +49341,31 @@ var n;
|
|
|
49239
49341
|
}(n || (n = {}));
|
|
49240
49342
|
return record; }
|
|
49241
49343
|
|
|
49242
|
-
|
|
49243
|
-
|
|
49244
|
-
if (maxCount === void 0) { maxCount = Infinity; }
|
|
49344
|
+
class SessionRecorderBuffer {
|
|
49345
|
+
constructor(interval, maxCount = Infinity) {
|
|
49245
49346
|
this.data = [];
|
|
49246
49347
|
this.sequenceNumber = 0;
|
|
49247
49348
|
this.interval = interval;
|
|
49248
49349
|
this.maxCount = maxCount;
|
|
49249
49350
|
this.doubledMaxCount = maxCount * 2;
|
|
49250
49351
|
}
|
|
49251
|
-
|
|
49352
|
+
isEmpty() {
|
|
49252
49353
|
return this.data.length === 0;
|
|
49253
|
-
}
|
|
49254
|
-
|
|
49354
|
+
}
|
|
49355
|
+
count() {
|
|
49255
49356
|
return this.data.length;
|
|
49256
|
-
}
|
|
49257
|
-
|
|
49357
|
+
}
|
|
49358
|
+
clear() {
|
|
49258
49359
|
this.data.length = 0;
|
|
49259
|
-
}
|
|
49260
|
-
|
|
49360
|
+
}
|
|
49361
|
+
clearSequence() {
|
|
49261
49362
|
this.sequenceNumber = 0;
|
|
49262
|
-
}
|
|
49263
|
-
|
|
49363
|
+
}
|
|
49364
|
+
push(event) {
|
|
49264
49365
|
this.data.push(event);
|
|
49265
49366
|
this.checkRateLimit();
|
|
49266
|
-
}
|
|
49267
|
-
|
|
49367
|
+
}
|
|
49368
|
+
pack(envelope, _) {
|
|
49268
49369
|
var eventsToSend = this.data.splice(0, this.maxCount);
|
|
49269
49370
|
envelope.recordingPayload = eventsToSend;
|
|
49270
49371
|
envelope.sequence = this.sequenceNumber;
|
|
@@ -49272,8 +49373,8 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49272
49373
|
if (eventsToSend.length) {
|
|
49273
49374
|
envelope.browserTime = eventsToSend[0].timestamp;
|
|
49274
49375
|
}
|
|
49275
|
-
envelope.recordingPayloadMetadata = _.map(eventsToSend,
|
|
49276
|
-
|
|
49376
|
+
envelope.recordingPayloadMetadata = _.map(eventsToSend, event => {
|
|
49377
|
+
const metadata = _.pick(event, 'type', 'timestamp');
|
|
49277
49378
|
if (event.data) {
|
|
49278
49379
|
metadata.data = _.pick(event.data, 'source', 'type', 'x', 'y', 'id', 'height', 'width', 'href');
|
|
49279
49380
|
}
|
|
@@ -49281,30 +49382,18 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49281
49382
|
});
|
|
49282
49383
|
this.sequenceNumber += eventsToSend.length;
|
|
49283
49384
|
return envelope;
|
|
49284
|
-
}
|
|
49285
|
-
|
|
49286
|
-
|
|
49385
|
+
}
|
|
49386
|
+
checkRateLimit() {
|
|
49387
|
+
const length = this.data.length;
|
|
49287
49388
|
if (length >= this.doubledMaxCount && length % this.maxCount === 0) {
|
|
49288
|
-
|
|
49389
|
+
const elapsed = this.data[length - 1].timestamp - this.data[length - this.doubledMaxCount].timestamp;
|
|
49289
49390
|
if (elapsed <= this.interval && this.onRateLimit) {
|
|
49290
49391
|
this.onRateLimit();
|
|
49291
49392
|
}
|
|
49292
49393
|
}
|
|
49293
|
-
}
|
|
49294
|
-
|
|
49295
|
-
}());
|
|
49394
|
+
}
|
|
49395
|
+
}
|
|
49296
49396
|
|
|
49297
|
-
var __assign = function() {
|
|
49298
|
-
__assign = Object.assign || function __assign(t) {
|
|
49299
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
49300
|
-
s = arguments[i];
|
|
49301
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
49302
|
-
}
|
|
49303
|
-
return t;
|
|
49304
|
-
};
|
|
49305
|
-
return __assign.apply(this, arguments);
|
|
49306
|
-
};
|
|
49307
|
-
|
|
49308
49397
|
function __rest(s, e) {
|
|
49309
49398
|
var t = {};
|
|
49310
49399
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -49327,52 +49416,24 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
49327
49416
|
});
|
|
49328
49417
|
}
|
|
49329
49418
|
|
|
49330
|
-
function __generator(thisArg, body) {
|
|
49331
|
-
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);
|
|
49332
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
49333
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49334
|
-
function step(op) {
|
|
49335
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
49336
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
49337
|
-
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;
|
|
49338
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
49339
|
-
switch (op[0]) {
|
|
49340
|
-
case 0: case 1: t = op; break;
|
|
49341
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
49342
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
49343
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
49344
|
-
default:
|
|
49345
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
49346
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
49347
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
49348
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
49349
|
-
if (t[2]) _.ops.pop();
|
|
49350
|
-
_.trys.pop(); continue;
|
|
49351
|
-
}
|
|
49352
|
-
op = body.call(thisArg, _);
|
|
49353
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49354
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
49355
|
-
}
|
|
49356
|
-
}
|
|
49357
|
-
|
|
49358
49419
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
49359
49420
|
var e = new Error(message);
|
|
49360
49421
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
49361
49422
|
};
|
|
49362
49423
|
|
|
49363
|
-
|
|
49364
|
-
|
|
49365
|
-
|
|
49366
|
-
|
|
49367
|
-
|
|
49424
|
+
const RECORDING_CONFIG_WORKERURL$1 = 'recording.workerUrl';
|
|
49425
|
+
const MAX_SIZE = 2000000;
|
|
49426
|
+
const RESOURCE_CACHING$1 = 'resourceCaching';
|
|
49427
|
+
class Transport {
|
|
49428
|
+
constructor(WorkerClass, pendo, api) {
|
|
49368
49429
|
this.WorkerClass = WorkerClass;
|
|
49369
49430
|
this.pendo = pendo;
|
|
49370
49431
|
this.api = api;
|
|
49371
49432
|
this.maxSize = MAX_SIZE;
|
|
49372
|
-
this.lockID =
|
|
49433
|
+
this.lockID = `worker-lock-${this.pendo.randomString(16)}`;
|
|
49373
49434
|
this.isResourceCachingEnabled = this.api.ConfigReader.get(RESOURCE_CACHING$1);
|
|
49374
49435
|
}
|
|
49375
|
-
|
|
49436
|
+
start(config) {
|
|
49376
49437
|
if (config.disableWorker)
|
|
49377
49438
|
return;
|
|
49378
49439
|
if (!this.worker) {
|
|
@@ -49382,7 +49443,7 @@ var Transport = /** @class */ (function () {
|
|
|
49382
49443
|
this.worker = config.workerOverride;
|
|
49383
49444
|
}
|
|
49384
49445
|
else {
|
|
49385
|
-
|
|
49446
|
+
const workerUrl = this.api.ConfigReader.get(RECORDING_CONFIG_WORKERURL$1);
|
|
49386
49447
|
this.usesSelfHostedWorker = workerUrl != null;
|
|
49387
49448
|
this.worker = workerUrl ? new Worker(workerUrl) : new this.WorkerClass();
|
|
49388
49449
|
}
|
|
@@ -49396,35 +49457,34 @@ var Transport = /** @class */ (function () {
|
|
|
49396
49457
|
this.worker = null;
|
|
49397
49458
|
}
|
|
49398
49459
|
}
|
|
49399
|
-
}
|
|
49400
|
-
|
|
49460
|
+
}
|
|
49461
|
+
stop() {
|
|
49401
49462
|
if (this.worker) {
|
|
49402
49463
|
this.worker.terminate();
|
|
49403
49464
|
delete this.worker;
|
|
49404
49465
|
}
|
|
49405
|
-
}
|
|
49406
|
-
|
|
49407
|
-
|
|
49408
|
-
|
|
49409
|
-
var payload = envelope.payload;
|
|
49466
|
+
}
|
|
49467
|
+
send(envelope, isUnload, failureCount = 0) {
|
|
49468
|
+
let { url } = envelope;
|
|
49469
|
+
const { payload } = envelope;
|
|
49410
49470
|
if (failureCount > 0) {
|
|
49411
|
-
url =
|
|
49471
|
+
url = `${url}&rt=${failureCount}`;
|
|
49412
49472
|
}
|
|
49413
49473
|
if (this.worker && !isUnload && payload) {
|
|
49414
|
-
|
|
49415
|
-
|
|
49416
|
-
|
|
49417
|
-
|
|
49474
|
+
const deferred = {};
|
|
49475
|
+
deferred.promise = new Promise$2((resolve, reject) => {
|
|
49476
|
+
deferred.resolve = resolve;
|
|
49477
|
+
deferred.reject = reject;
|
|
49418
49478
|
});
|
|
49419
|
-
this.workerResponse =
|
|
49420
|
-
this.worker.postMessage({ url
|
|
49421
|
-
return
|
|
49479
|
+
this.workerResponse = deferred;
|
|
49480
|
+
this.worker.postMessage({ url, payload, shouldCacheResources: this.isResourceCachingEnabled });
|
|
49481
|
+
return deferred.promise;
|
|
49422
49482
|
}
|
|
49423
49483
|
else {
|
|
49424
49484
|
if (!envelope.body) {
|
|
49425
|
-
|
|
49485
|
+
const strPayload = JSON.stringify(payload);
|
|
49426
49486
|
if (strPayload.length > this.maxSize) {
|
|
49427
|
-
|
|
49487
|
+
const error = new Error('maximum recording payload size exceeded');
|
|
49428
49488
|
error.reason = 'HEAVY_EVENT';
|
|
49429
49489
|
error.context = {
|
|
49430
49490
|
size: strPayload.length,
|
|
@@ -49435,14 +49495,14 @@ var Transport = /** @class */ (function () {
|
|
|
49435
49495
|
envelope.body = this.pendo.compress(strPayload, 'binary');
|
|
49436
49496
|
delete envelope.payload;
|
|
49437
49497
|
}
|
|
49438
|
-
url =
|
|
49498
|
+
url = `${url}&ct=${new Date().getTime()}`;
|
|
49439
49499
|
return this.post(url, {
|
|
49440
49500
|
keepalive: isUnload,
|
|
49441
49501
|
body: envelope.body
|
|
49442
49502
|
});
|
|
49443
49503
|
}
|
|
49444
|
-
}
|
|
49445
|
-
|
|
49504
|
+
}
|
|
49505
|
+
post(url, options) {
|
|
49446
49506
|
options.method = 'POST';
|
|
49447
49507
|
if (options.keepalive && this.api.transmit.fetchKeepalive.supported()) {
|
|
49448
49508
|
return this.api.transmit.fetchKeepalive(url, options);
|
|
@@ -49454,57 +49514,46 @@ var Transport = /** @class */ (function () {
|
|
|
49454
49514
|
else {
|
|
49455
49515
|
return this.pendo.ajax.post(url, options.body);
|
|
49456
49516
|
}
|
|
49457
|
-
}
|
|
49458
|
-
|
|
49459
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
49460
|
-
|
|
49461
|
-
|
|
49462
|
-
|
|
49463
|
-
|
|
49464
|
-
|
|
49465
|
-
|
|
49466
|
-
|
|
49467
|
-
|
|
49468
|
-
|
|
49469
|
-
|
|
49470
|
-
|
|
49471
|
-
|
|
49472
|
-
|
|
49473
|
-
|
|
49474
|
-
|
|
49475
|
-
return [2 /*return*/];
|
|
49476
|
-
}
|
|
49477
|
-
// handle POST request response from worker
|
|
49478
|
-
if (messageEvent.data && messageEvent.data.error) {
|
|
49479
|
-
if ((messageEvent.data.status && messageEvent.data.status < 500) ||
|
|
49480
|
-
messageEvent.data.sequence == null) {
|
|
49481
|
-
this.api.log.critical('Failed to send recording data from web worker', { error: messageEvent.data.error });
|
|
49482
|
-
}
|
|
49483
|
-
if (this.workerResponse) {
|
|
49484
|
-
this.workerResponse.reject();
|
|
49485
|
-
this.workerResponse = null;
|
|
49486
|
-
}
|
|
49487
|
-
}
|
|
49488
|
-
if (this.workerResponse) {
|
|
49489
|
-
this.workerResponse.resolve();
|
|
49490
|
-
this.workerResponse = null;
|
|
49491
|
-
}
|
|
49492
|
-
return [2 /*return*/];
|
|
49517
|
+
}
|
|
49518
|
+
_onMessage(messageEvent) {
|
|
49519
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49520
|
+
if (messageEvent.data && messageEvent.data.ready && navigator.locks) {
|
|
49521
|
+
// When the lock is released, we can assume the worker was terminated or closed
|
|
49522
|
+
yield navigator.locks.request(this.lockID, () => { });
|
|
49523
|
+
this.onWorkerMessage({ type: 'workerDied' });
|
|
49524
|
+
}
|
|
49525
|
+
// handle non-POST request responses from worker
|
|
49526
|
+
if (messageEvent.data && messageEvent.data.type) {
|
|
49527
|
+
this.onWorkerMessage(messageEvent.data);
|
|
49528
|
+
return;
|
|
49529
|
+
}
|
|
49530
|
+
// handle POST request response from worker
|
|
49531
|
+
if (messageEvent.data && messageEvent.data.error) {
|
|
49532
|
+
if ((messageEvent.data.status && messageEvent.data.status < 500) ||
|
|
49533
|
+
messageEvent.data.sequence == null) {
|
|
49534
|
+
this.api.log.critical('Failed to send recording data from web worker', { error: messageEvent.data.error });
|
|
49493
49535
|
}
|
|
49494
|
-
|
|
49536
|
+
if (this.workerResponse) {
|
|
49537
|
+
this.workerResponse.reject();
|
|
49538
|
+
this.workerResponse = null;
|
|
49539
|
+
}
|
|
49540
|
+
}
|
|
49541
|
+
if (this.workerResponse) {
|
|
49542
|
+
this.workerResponse.resolve();
|
|
49543
|
+
this.workerResponse = null;
|
|
49544
|
+
}
|
|
49495
49545
|
});
|
|
49496
|
-
}
|
|
49497
|
-
|
|
49546
|
+
}
|
|
49547
|
+
_onError() {
|
|
49498
49548
|
if (this.onError) {
|
|
49499
49549
|
this.onError();
|
|
49500
49550
|
}
|
|
49501
|
-
}
|
|
49502
|
-
|
|
49503
|
-
}());
|
|
49551
|
+
}
|
|
49552
|
+
}
|
|
49504
49553
|
|
|
49505
|
-
|
|
49506
|
-
|
|
49507
|
-
|
|
49554
|
+
const ELEMENT_NODE = 1;
|
|
49555
|
+
const INPUT_MASK = '*'.repeat(10);
|
|
49556
|
+
const NUMBER_INPUT_MASK = '0'.repeat(10);
|
|
49508
49557
|
function isElementNode(node) {
|
|
49509
49558
|
if (!node)
|
|
49510
49559
|
return false;
|
|
@@ -49513,12 +49562,10 @@ function isElementNode(node) {
|
|
|
49513
49562
|
return true;
|
|
49514
49563
|
}
|
|
49515
49564
|
function getParent(elem) {
|
|
49516
|
-
|
|
49565
|
+
const isElementShadowRoot = typeof window.ShadowRoot !== 'undefined' && elem instanceof window.ShadowRoot && elem.host;
|
|
49517
49566
|
return isElementShadowRoot ? elem.host : elem.parentNode;
|
|
49518
49567
|
}
|
|
49519
|
-
function distanceToMatch(node, selector, limit, distance) {
|
|
49520
|
-
if (limit === void 0) { limit = Infinity; }
|
|
49521
|
-
if (distance === void 0) { distance = 0; }
|
|
49568
|
+
function distanceToMatch(node, selector, limit = Infinity, distance = 0) {
|
|
49522
49569
|
if (distance > limit)
|
|
49523
49570
|
return -1;
|
|
49524
49571
|
if (!node)
|
|
@@ -49532,15 +49579,15 @@ function distanceToMatch(node, selector, limit, distance) {
|
|
|
49532
49579
|
return distanceToMatch(getParent(node), selector, limit, distance + 1);
|
|
49533
49580
|
}
|
|
49534
49581
|
function shouldMask(node, options) {
|
|
49535
|
-
|
|
49582
|
+
const { maskAllText, maskTextSelector, unmaskTextSelector } = options;
|
|
49536
49583
|
try {
|
|
49537
|
-
|
|
49584
|
+
const el = isElementNode(node) ? node : node.parentElement;
|
|
49538
49585
|
if (el === null)
|
|
49539
49586
|
return false;
|
|
49540
49587
|
if ((el.tagName || '').toUpperCase() === 'STYLE')
|
|
49541
49588
|
return false;
|
|
49542
|
-
|
|
49543
|
-
|
|
49589
|
+
let maskDistance = -1;
|
|
49590
|
+
let unmaskDistance = -1;
|
|
49544
49591
|
if (maskAllText) {
|
|
49545
49592
|
unmaskDistance = distanceToMatch(el, unmaskTextSelector);
|
|
49546
49593
|
if (unmaskDistance < 0) {
|
|
@@ -49573,8 +49620,8 @@ function isNumberInput(element) {
|
|
|
49573
49620
|
}
|
|
49574
49621
|
function shouldMaskInput(element, maskInputOptions) {
|
|
49575
49622
|
if (maskInputOptions && isElementNode(element)) {
|
|
49576
|
-
|
|
49577
|
-
|
|
49623
|
+
const tagName = (element.tagName || '').toLowerCase();
|
|
49624
|
+
const type = (element.type || '').toLowerCase();
|
|
49578
49625
|
if (maskInputOptions[tagName] || maskInputOptions[type]) {
|
|
49579
49626
|
return true;
|
|
49580
49627
|
}
|
|
@@ -51068,12 +51115,12 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51068
51115
|
}
|
|
51069
51116
|
}
|
|
51070
51117
|
|
|
51071
|
-
|
|
51118
|
+
const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
|
|
51072
51119
|
function matchHostedResources(recordingEvent, stringifiedRecordingPayload) {
|
|
51073
|
-
|
|
51074
|
-
|
|
51120
|
+
const fontURLRegex = /https:\/\/[^"\\\s]+?\.(woff2?|ttf|otf|eot)(\?[^"\\\s]*)?\b/g;
|
|
51121
|
+
const matches = stringifiedRecordingPayload.match(fontURLRegex);
|
|
51075
51122
|
// de-duplicate matches
|
|
51076
|
-
|
|
51123
|
+
const hostedResources = matches ? Array.from(new Set(matches)) : [];
|
|
51077
51124
|
return {
|
|
51078
51125
|
type: 'recording',
|
|
51079
51126
|
visitorId: recordingEvent.visitorId,
|
|
@@ -51088,7 +51135,7 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51088
51135
|
recordingPayloadMetadata: [],
|
|
51089
51136
|
sequence: 0,
|
|
51090
51137
|
recordingPayloadCount: 0,
|
|
51091
|
-
hostedResources
|
|
51138
|
+
hostedResources
|
|
51092
51139
|
};
|
|
51093
51140
|
}
|
|
51094
51141
|
// keep in mind changes here may need addressing in the extension worker proxy as well
|
|
@@ -51096,69 +51143,69 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51096
51143
|
try {
|
|
51097
51144
|
if (e.data.type === 'init' && e.data.lockID) {
|
|
51098
51145
|
if (navigator.locks) {
|
|
51099
|
-
navigator.locks.request(e.data.lockID,
|
|
51146
|
+
navigator.locks.request(e.data.lockID, () => {
|
|
51100
51147
|
postMessage({ ready: true });
|
|
51101
51148
|
// This unresolved promise keeps the lock held with the worker until the worker is
|
|
51102
51149
|
// terminated at which point the lock is released.
|
|
51103
|
-
return new Promise$2(
|
|
51150
|
+
return new Promise$2(() => { });
|
|
51104
51151
|
});
|
|
51105
51152
|
}
|
|
51106
51153
|
return;
|
|
51107
51154
|
}
|
|
51108
51155
|
if (e.data.url && e.data.payload) {
|
|
51109
|
-
|
|
51156
|
+
let { url, payload, shouldCacheResources } = e.data;
|
|
51110
51157
|
if (Object.keys(payload).length === 0) {
|
|
51111
51158
|
postMessage({
|
|
51112
51159
|
type: 'emptyPayload'
|
|
51113
51160
|
});
|
|
51114
51161
|
}
|
|
51115
|
-
|
|
51116
|
-
|
|
51162
|
+
const { sequence } = payload;
|
|
51163
|
+
const stringifiedRecordingPayload = JSON.stringify(payload.recordingPayload);
|
|
51117
51164
|
// calculate and post back the recording payload size before the payload is compressed
|
|
51118
|
-
|
|
51119
|
-
|
|
51165
|
+
const recordingPayloadSize = new TextEncoder().encode(stringifiedRecordingPayload).length;
|
|
51166
|
+
const exceedsPayloadSizeLimit = recordingPayloadSize >= ONE_HUNDRED_MB_IN_BYTES;
|
|
51120
51167
|
postMessage({
|
|
51121
51168
|
type: 'recordingPayloadSize',
|
|
51122
|
-
recordingPayloadSize
|
|
51123
|
-
exceedsPayloadSizeLimit
|
|
51169
|
+
recordingPayloadSize,
|
|
51170
|
+
exceedsPayloadSizeLimit
|
|
51124
51171
|
});
|
|
51125
51172
|
// don't attempt to send the payload if it exceeds the allowed limit
|
|
51126
51173
|
if (exceedsPayloadSizeLimit)
|
|
51127
51174
|
return;
|
|
51128
51175
|
if (shouldCacheResources) {
|
|
51129
|
-
|
|
51176
|
+
const hostedResourcesEvent = matchHostedResources(payload, stringifiedRecordingPayload);
|
|
51130
51177
|
if (hostedResourcesEvent.hostedResources.length) {
|
|
51131
51178
|
postMessage({
|
|
51132
51179
|
type: 'hostedResources',
|
|
51133
|
-
hostedResourcesEvent
|
|
51180
|
+
hostedResourcesEvent
|
|
51134
51181
|
});
|
|
51135
51182
|
}
|
|
51136
51183
|
}
|
|
51137
51184
|
payload.recordingSize = recordingPayloadSize;
|
|
51138
|
-
|
|
51185
|
+
const body = compress(payload, 'binary');
|
|
51139
51186
|
// we want to calculate ct (current time) as close as we can to the actual POST request
|
|
51140
51187
|
// so that it's as accurate as possible
|
|
51141
|
-
url =
|
|
51188
|
+
url = `${url}&ct=${new Date().getTime()}`;
|
|
51142
51189
|
fetch(url, {
|
|
51143
51190
|
method: 'POST',
|
|
51144
|
-
body
|
|
51191
|
+
body
|
|
51145
51192
|
}).then(function (response) {
|
|
51146
51193
|
if (response.status < 200 || response.status >= 300) {
|
|
51147
51194
|
postMessage({
|
|
51148
|
-
error: new Error(
|
|
51195
|
+
error: new Error(`received status code ${response.status}: ${response.statusText}`),
|
|
51149
51196
|
status: response.status,
|
|
51150
|
-
sequence
|
|
51197
|
+
sequence
|
|
51151
51198
|
});
|
|
51152
51199
|
}
|
|
51153
51200
|
else {
|
|
51154
51201
|
postMessage({
|
|
51155
|
-
sequence
|
|
51202
|
+
sequence
|
|
51156
51203
|
});
|
|
51157
51204
|
}
|
|
51158
|
-
})
|
|
51205
|
+
}).catch(function (e) {
|
|
51159
51206
|
postMessage({
|
|
51160
51207
|
error: e,
|
|
51161
|
-
sequence
|
|
51208
|
+
sequence
|
|
51162
51209
|
});
|
|
51163
51210
|
});
|
|
51164
51211
|
}
|
|
@@ -51469,7 +51516,7 @@ function includes(str, substring) {
|
|
|
51469
51516
|
function getResourceType(blockedURI, directive) {
|
|
51470
51517
|
if (!directive || typeof directive !== 'string')
|
|
51471
51518
|
return 'resource';
|
|
51472
|
-
|
|
51519
|
+
const d = directive.toLowerCase();
|
|
51473
51520
|
if (blockedURI === 'inline') {
|
|
51474
51521
|
if (includes(d, 'script-src-attr')) {
|
|
51475
51522
|
return 'inline event handler';
|
|
@@ -51528,12 +51575,11 @@ function getResourceType(blockedURI, directive) {
|
|
|
51528
51575
|
function getDirective(policy, directiveName) {
|
|
51529
51576
|
if (!policy || !directiveName)
|
|
51530
51577
|
return '';
|
|
51531
|
-
|
|
51532
|
-
for (
|
|
51533
|
-
|
|
51534
|
-
|
|
51535
|
-
|
|
51536
|
-
if (lower === needle || lower.startsWith("".concat(needle, " "))) {
|
|
51578
|
+
const needle = directiveName.toLowerCase();
|
|
51579
|
+
for (const directive of policy.split(';')) {
|
|
51580
|
+
const trimmed = directive.trim();
|
|
51581
|
+
const lower = trimmed.toLowerCase();
|
|
51582
|
+
if (lower === needle || lower.startsWith(`${needle} `)) {
|
|
51537
51583
|
return trimmed;
|
|
51538
51584
|
}
|
|
51539
51585
|
}
|
|
@@ -51555,7 +51601,7 @@ function getDirective(policy, directiveName) {
|
|
|
51555
51601
|
function getArticle(phrase) {
|
|
51556
51602
|
if (!phrase || typeof phrase !== 'string')
|
|
51557
51603
|
return 'A';
|
|
51558
|
-
|
|
51604
|
+
const c = phrase.trim().charAt(0).toLowerCase();
|
|
51559
51605
|
return includes('aeiou', c) ? 'An' : 'A';
|
|
51560
51606
|
}
|
|
51561
51607
|
/**
|
|
@@ -51598,47 +51644,46 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
|
|
|
51598
51644
|
return 'Content Security Policy: Unknown violation occurred.';
|
|
51599
51645
|
}
|
|
51600
51646
|
try {
|
|
51601
|
-
|
|
51647
|
+
const reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
|
|
51602
51648
|
// special case for frame-ancestors since it doesn't fit our template at all
|
|
51603
51649
|
if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
|
|
51604
|
-
return
|
|
51650
|
+
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}".`;
|
|
51605
51651
|
}
|
|
51606
|
-
|
|
51607
|
-
|
|
51608
|
-
|
|
51609
|
-
|
|
51610
|
-
|
|
51611
|
-
|
|
51612
|
-
return
|
|
51652
|
+
const resourceType = getResourceType(blockedURI, directive);
|
|
51653
|
+
const article = getArticle(resourceType);
|
|
51654
|
+
const source = formatBlockedUri(blockedURI);
|
|
51655
|
+
const directiveValue = getDirective(originalPolicy, directive);
|
|
51656
|
+
const policyDisplay = directiveValue || directive;
|
|
51657
|
+
const resourceDescription = `${article} ${resourceType}${source ? ` from ${source}` : ''}`;
|
|
51658
|
+
return `Content Security Policy${reportOnlyText}: ${resourceDescription} was blocked by your site's \`${policyDisplay}\` policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
51613
51659
|
}
|
|
51614
51660
|
catch (error) {
|
|
51615
|
-
return
|
|
51661
|
+
return `Content Security Policy: Error formatting violation message: ${error.message}`;
|
|
51616
51662
|
}
|
|
51617
51663
|
}
|
|
51618
51664
|
|
|
51619
|
-
|
|
51620
|
-
|
|
51665
|
+
const MAX_LENGTH = 1000;
|
|
51666
|
+
const PII_PATTERN = {
|
|
51621
51667
|
ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
51622
51668
|
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
51623
51669
|
creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
|
|
51624
51670
|
httpsUrls: /https:\/\/[^\s]+/g,
|
|
51625
51671
|
email: /[\w._+-]+@[\w.-]+\.\w+/g
|
|
51626
51672
|
};
|
|
51627
|
-
|
|
51628
|
-
|
|
51629
|
-
|
|
51630
|
-
|
|
51631
|
-
|
|
51673
|
+
const PII_REPLACEMENT = '*'.repeat(10);
|
|
51674
|
+
const JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
|
|
51675
|
+
const UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
|
|
51676
|
+
const joinedKeys = JSON_PII_KEYS.join('|');
|
|
51677
|
+
const keyPattern = `"([^"]*(?:${joinedKeys})[^"]*)"`;
|
|
51632
51678
|
// only scrub strings, numbers, and booleans
|
|
51633
|
-
|
|
51679
|
+
const acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
|
|
51634
51680
|
/**
|
|
51635
51681
|
* Truncates a string to the max length
|
|
51636
51682
|
* @access private
|
|
51637
51683
|
* @param {String} string
|
|
51638
51684
|
* @returns {String}
|
|
51639
51685
|
*/
|
|
51640
|
-
function truncate(string, includeEllipsis) {
|
|
51641
|
-
if (includeEllipsis === void 0) { includeEllipsis = false; }
|
|
51686
|
+
function truncate(string, includeEllipsis = false) {
|
|
51642
51687
|
if (string.length <= MAX_LENGTH)
|
|
51643
51688
|
return string;
|
|
51644
51689
|
if (includeEllipsis) {
|
|
@@ -51655,7 +51700,7 @@ function truncate(string, includeEllipsis) {
|
|
|
51655
51700
|
* @returns {String}
|
|
51656
51701
|
*/
|
|
51657
51702
|
function generateLogKey(methodName, message, stackTrace) {
|
|
51658
|
-
return
|
|
51703
|
+
return `${methodName}|${message}|${stackTrace}`;
|
|
51659
51704
|
}
|
|
51660
51705
|
/**
|
|
51661
51706
|
* Checks if a string has 2 or more digits, a https URL, or an email address
|
|
@@ -51672,13 +51717,12 @@ function mightContainPII(string) {
|
|
|
51672
51717
|
* @param {String} string
|
|
51673
51718
|
* @returns {String}
|
|
51674
51719
|
*/
|
|
51675
|
-
function scrubPII(
|
|
51676
|
-
var string = _a.string, _ = _a._;
|
|
51720
|
+
function scrubPII({ string, _ }) {
|
|
51677
51721
|
if (!string || typeof string !== 'string')
|
|
51678
51722
|
return string;
|
|
51679
51723
|
if (!mightContainPII(string))
|
|
51680
51724
|
return string;
|
|
51681
|
-
return _.reduce(_.values(PII_PATTERN),
|
|
51725
|
+
return _.reduce(_.values(PII_PATTERN), (str, pattern) => str.replace(pattern, PII_REPLACEMENT), string);
|
|
51682
51726
|
}
|
|
51683
51727
|
/**
|
|
51684
51728
|
* Scrub PII from a stringified JSON object
|
|
@@ -51687,14 +51731,12 @@ function scrubPII(_a) {
|
|
|
51687
51731
|
* @returns {String}
|
|
51688
51732
|
*/
|
|
51689
51733
|
function scrubJsonPII(string) {
|
|
51690
|
-
|
|
51734
|
+
const fullScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*[\\{\\[]`, 'i');
|
|
51691
51735
|
if (fullScrubRegex.test(string)) {
|
|
51692
51736
|
return UNABLE_TO_DISPLAY_BODY;
|
|
51693
51737
|
}
|
|
51694
|
-
|
|
51695
|
-
return string.replace(keyValueScrubRegex,
|
|
51696
|
-
return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
|
|
51697
|
-
});
|
|
51738
|
+
const keyValueScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*${acceptedValues}`, 'gi');
|
|
51739
|
+
return string.replace(keyValueScrubRegex, (match, key) => `"${key}":"${PII_REPLACEMENT}"`);
|
|
51698
51740
|
}
|
|
51699
51741
|
/**
|
|
51700
51742
|
* Checks if a string is a JSON object
|
|
@@ -51706,7 +51748,7 @@ function scrubJsonPII(string) {
|
|
|
51706
51748
|
function mightContainJson(string, contentType) {
|
|
51707
51749
|
if (!string || typeof string !== 'string')
|
|
51708
51750
|
return false;
|
|
51709
|
-
|
|
51751
|
+
const firstChar = string.charAt(0);
|
|
51710
51752
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
51711
51753
|
return true;
|
|
51712
51754
|
}
|
|
@@ -51719,20 +51761,19 @@ function mightContainJson(string, contentType) {
|
|
|
51719
51761
|
* @param {String} contentType
|
|
51720
51762
|
* @returns {String}
|
|
51721
51763
|
*/
|
|
51722
|
-
function maskSensitiveFields(
|
|
51723
|
-
var string = _a.string, contentType = _a.contentType, _ = _a._;
|
|
51764
|
+
function maskSensitiveFields({ string, contentType, _ }) {
|
|
51724
51765
|
if (!string || typeof string !== 'string')
|
|
51725
51766
|
return string;
|
|
51726
51767
|
if (mightContainJson(string, contentType)) {
|
|
51727
51768
|
string = scrubJsonPII(string);
|
|
51728
51769
|
}
|
|
51729
51770
|
if (mightContainPII(string)) {
|
|
51730
|
-
string = scrubPII({ string
|
|
51771
|
+
string = scrubPII({ string, _ });
|
|
51731
51772
|
}
|
|
51732
51773
|
return string;
|
|
51733
51774
|
}
|
|
51734
51775
|
|
|
51735
|
-
|
|
51776
|
+
const DEV_LOG_TYPE = 'devlog';
|
|
51736
51777
|
function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
51737
51778
|
return {
|
|
51738
51779
|
browser_time: pluginAPI.util.getNow(),
|
|
@@ -51743,12 +51784,12 @@ function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
|
51743
51784
|
};
|
|
51744
51785
|
}
|
|
51745
51786
|
|
|
51746
|
-
|
|
51747
|
-
|
|
51748
|
-
|
|
51749
|
-
|
|
51750
|
-
|
|
51751
|
-
|
|
51787
|
+
const TOKEN_MAX_SIZE = 100;
|
|
51788
|
+
const TOKEN_REFILL_RATE = 10;
|
|
51789
|
+
const TOKEN_REFRESH_INTERVAL = 1000;
|
|
51790
|
+
const MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
|
|
51791
|
+
class DevlogBuffer {
|
|
51792
|
+
constructor(pendo, pluginAPI) {
|
|
51752
51793
|
this.pendo = pendo;
|
|
51753
51794
|
this.pluginAPI = pluginAPI;
|
|
51754
51795
|
this.events = [];
|
|
@@ -51759,36 +51800,36 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
51759
51800
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
51760
51801
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
51761
51802
|
}
|
|
51762
|
-
|
|
51803
|
+
isEmpty() {
|
|
51763
51804
|
return this.events.length === 0 && this.payloads.length === 0;
|
|
51764
|
-
}
|
|
51765
|
-
|
|
51766
|
-
|
|
51805
|
+
}
|
|
51806
|
+
refillTokens() {
|
|
51807
|
+
const now = this.pluginAPI.util.getNow();
|
|
51767
51808
|
if (now >= this.nextRefillTime) {
|
|
51768
|
-
|
|
51769
|
-
|
|
51770
|
-
|
|
51809
|
+
const timeSinceLastRefill = now - this.lastRefillTime;
|
|
51810
|
+
const secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
|
|
51811
|
+
const tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
|
|
51771
51812
|
this.tokens = Math.min(this.tokens + tokensToRefill, TOKEN_MAX_SIZE);
|
|
51772
51813
|
this.lastRefillTime = now;
|
|
51773
51814
|
this.nextRefillTime = now + TOKEN_REFRESH_INTERVAL;
|
|
51774
51815
|
}
|
|
51775
|
-
}
|
|
51776
|
-
|
|
51816
|
+
}
|
|
51817
|
+
clear() {
|
|
51777
51818
|
this.events = [];
|
|
51778
51819
|
this.lastEvent = null;
|
|
51779
51820
|
this.uncompressedSize = 0;
|
|
51780
|
-
}
|
|
51781
|
-
|
|
51821
|
+
}
|
|
51822
|
+
hasTokenAvailable() {
|
|
51782
51823
|
this.refillTokens();
|
|
51783
51824
|
return this.tokens > 0;
|
|
51784
|
-
}
|
|
51785
|
-
|
|
51825
|
+
}
|
|
51826
|
+
estimateEventSize(event) {
|
|
51786
51827
|
return JSON.stringify(event).length;
|
|
51787
|
-
}
|
|
51788
|
-
|
|
51828
|
+
}
|
|
51829
|
+
push(event) {
|
|
51789
51830
|
if (!this.hasTokenAvailable())
|
|
51790
51831
|
return false;
|
|
51791
|
-
|
|
51832
|
+
const eventSize = this.estimateEventSize(event);
|
|
51792
51833
|
if (this.uncompressedSize + eventSize > MAX_UNCOMPRESSED_SIZE) {
|
|
51793
51834
|
this.compressCurrentChunk();
|
|
51794
51835
|
}
|
|
@@ -51797,55 +51838,54 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
51797
51838
|
this.events.push(event);
|
|
51798
51839
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
51799
51840
|
return true;
|
|
51800
|
-
}
|
|
51801
|
-
|
|
51841
|
+
}
|
|
51842
|
+
compressCurrentChunk() {
|
|
51802
51843
|
if (this.events.length === 0)
|
|
51803
51844
|
return;
|
|
51804
|
-
|
|
51845
|
+
const jzb = this.pendo.compress(this.events);
|
|
51805
51846
|
this.payloads.push(jzb);
|
|
51806
51847
|
this.clear();
|
|
51807
|
-
}
|
|
51808
|
-
|
|
51809
|
-
|
|
51848
|
+
}
|
|
51849
|
+
generateUrl() {
|
|
51850
|
+
const queryParams = {
|
|
51810
51851
|
v: this.pendo.VERSION,
|
|
51811
51852
|
ct: this.pluginAPI.util.getNow()
|
|
51812
51853
|
};
|
|
51813
51854
|
return this.pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, this.pendo.apiKey, queryParams);
|
|
51814
|
-
}
|
|
51815
|
-
|
|
51855
|
+
}
|
|
51856
|
+
pack() {
|
|
51816
51857
|
if (this.isEmpty())
|
|
51817
51858
|
return;
|
|
51818
|
-
|
|
51859
|
+
const url = this.generateUrl();
|
|
51819
51860
|
this.compressCurrentChunk();
|
|
51820
|
-
|
|
51821
|
-
jzb
|
|
51822
|
-
url
|
|
51823
|
-
})
|
|
51861
|
+
const payloads = this.pendo._.map(this.payloads, (jzb) => ({
|
|
51862
|
+
jzb,
|
|
51863
|
+
url
|
|
51864
|
+
}));
|
|
51824
51865
|
this.payloads = [];
|
|
51825
51866
|
return payloads;
|
|
51826
|
-
}
|
|
51827
|
-
|
|
51828
|
-
}());
|
|
51867
|
+
}
|
|
51868
|
+
}
|
|
51829
51869
|
|
|
51830
|
-
|
|
51831
|
-
|
|
51870
|
+
class DevlogTransport {
|
|
51871
|
+
constructor(globalPendo, pluginAPI) {
|
|
51832
51872
|
this.pendo = globalPendo;
|
|
51833
51873
|
this.pluginAPI = pluginAPI;
|
|
51834
51874
|
}
|
|
51835
|
-
|
|
51836
|
-
|
|
51875
|
+
buildGetUrl(baseUrl, jzb) {
|
|
51876
|
+
const params = {};
|
|
51837
51877
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
51838
51878
|
this.pluginAPI.agent.addAccountIdParams(params, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
51839
51879
|
}
|
|
51840
|
-
|
|
51880
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
51841
51881
|
if (!this.pendo._.isEmpty(jwtOptions)) {
|
|
51842
51882
|
this.pendo._.extend(params, jwtOptions);
|
|
51843
51883
|
}
|
|
51844
51884
|
params.jzb = jzb;
|
|
51845
|
-
|
|
51846
|
-
return
|
|
51847
|
-
}
|
|
51848
|
-
|
|
51885
|
+
const queryString = this.pendo._.map(params, (value, key) => `${key}=${value}`).join('&');
|
|
51886
|
+
return `${baseUrl}${baseUrl.indexOf('?') !== -1 ? '&' : '?'}${queryString}`;
|
|
51887
|
+
}
|
|
51888
|
+
get(url, options) {
|
|
51849
51889
|
options.method = 'GET';
|
|
51850
51890
|
if (this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
51851
51891
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
@@ -51853,90 +51893,86 @@ var DevlogTransport = /** @class */ (function () {
|
|
|
51853
51893
|
else {
|
|
51854
51894
|
return this.pendo.ajax.get(url);
|
|
51855
51895
|
}
|
|
51856
|
-
}
|
|
51857
|
-
|
|
51858
|
-
|
|
51859
|
-
var getUrl = this.buildGetUrl(url, jzb);
|
|
51896
|
+
}
|
|
51897
|
+
sendRequestWithGet({ url, jzb }) {
|
|
51898
|
+
const getUrl = this.buildGetUrl(url, jzb);
|
|
51860
51899
|
return this.get(getUrl, {
|
|
51861
51900
|
headers: {
|
|
51862
51901
|
'Content-Type': 'application/octet-stream'
|
|
51863
51902
|
}
|
|
51864
51903
|
});
|
|
51865
|
-
}
|
|
51866
|
-
|
|
51904
|
+
}
|
|
51905
|
+
post(url, options) {
|
|
51867
51906
|
options.method = 'POST';
|
|
51868
51907
|
if (options.keepalive && this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
51869
51908
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
51870
51909
|
}
|
|
51871
51910
|
else if (options.keepalive && this.pluginAPI.transmit.sendBeacon.supported()) {
|
|
51872
|
-
|
|
51911
|
+
const result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
|
|
51873
51912
|
return result ? Promise$2.resolve() : Promise$2.reject(new Error('sendBeacon failed to send devlog data'));
|
|
51874
51913
|
}
|
|
51875
51914
|
else {
|
|
51876
51915
|
return this.pendo.ajax.post(url, options.body);
|
|
51877
51916
|
}
|
|
51878
|
-
}
|
|
51879
|
-
|
|
51880
|
-
|
|
51881
|
-
|
|
51882
|
-
var bodyPayload = {
|
|
51917
|
+
}
|
|
51918
|
+
sendRequestWithPost({ url, jzb }, isUnload) {
|
|
51919
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
51920
|
+
const bodyPayload = {
|
|
51883
51921
|
events: jzb,
|
|
51884
51922
|
browser_time: this.pluginAPI.util.getNow()
|
|
51885
51923
|
};
|
|
51886
51924
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
51887
51925
|
this.pluginAPI.agent.addAccountIdParams(bodyPayload, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
51888
51926
|
}
|
|
51889
|
-
|
|
51927
|
+
const body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
|
|
51890
51928
|
return this.post(url, {
|
|
51891
|
-
body
|
|
51929
|
+
body,
|
|
51892
51930
|
headers: {
|
|
51893
51931
|
'Content-Type': 'application/json'
|
|
51894
51932
|
},
|
|
51895
51933
|
keepalive: isUnload
|
|
51896
51934
|
});
|
|
51897
|
-
}
|
|
51898
|
-
|
|
51899
|
-
|
|
51900
|
-
var compressedLength = jzb.length;
|
|
51935
|
+
}
|
|
51936
|
+
sendRequest({ url, jzb }, isUnload) {
|
|
51937
|
+
const compressedLength = jzb.length;
|
|
51901
51938
|
if (compressedLength <= this.pluginAPI.constants.ENCODED_EVENT_MAX_LENGTH && !this.pluginAPI.ConfigReader.get('sendEventsWithPostOnly')) {
|
|
51902
|
-
return this.sendRequestWithGet({ url
|
|
51939
|
+
return this.sendRequestWithGet({ url, jzb });
|
|
51903
51940
|
}
|
|
51904
|
-
return this.sendRequestWithPost({ url
|
|
51905
|
-
}
|
|
51906
|
-
|
|
51907
|
-
}());
|
|
51941
|
+
return this.sendRequestWithPost({ url, jzb }, isUnload);
|
|
51942
|
+
}
|
|
51943
|
+
}
|
|
51908
51944
|
|
|
51909
51945
|
function ConsoleCapture() {
|
|
51910
|
-
|
|
51911
|
-
|
|
51912
|
-
|
|
51913
|
-
|
|
51914
|
-
|
|
51915
|
-
|
|
51916
|
-
|
|
51917
|
-
|
|
51918
|
-
|
|
51919
|
-
|
|
51920
|
-
|
|
51921
|
-
|
|
51946
|
+
let pluginAPI;
|
|
51947
|
+
let _;
|
|
51948
|
+
let globalPendo;
|
|
51949
|
+
let buffer;
|
|
51950
|
+
let sendQueue;
|
|
51951
|
+
let sendInterval;
|
|
51952
|
+
let transport;
|
|
51953
|
+
let isPtmPaused;
|
|
51954
|
+
let isCapturingConsoleLogs = false;
|
|
51955
|
+
const CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
|
|
51956
|
+
const CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
|
|
51957
|
+
const DEV_LOG_SUB_TYPE = 'console';
|
|
51922
51958
|
// deduplicate logs
|
|
51923
|
-
|
|
51959
|
+
let lastLogKey = '';
|
|
51924
51960
|
return {
|
|
51925
51961
|
name: 'ConsoleCapture',
|
|
51926
|
-
initialize
|
|
51927
|
-
teardown
|
|
51928
|
-
addIntercepts
|
|
51929
|
-
createConsoleEvent
|
|
51930
|
-
captureStackTrace
|
|
51931
|
-
send
|
|
51932
|
-
setCaptureState
|
|
51933
|
-
recordingStarted
|
|
51934
|
-
recordingStopped
|
|
51935
|
-
onAppHidden
|
|
51936
|
-
onAppUnloaded
|
|
51937
|
-
onPtmPaused
|
|
51938
|
-
onPtmUnpaused
|
|
51939
|
-
securityPolicyViolationFn
|
|
51962
|
+
initialize,
|
|
51963
|
+
teardown,
|
|
51964
|
+
addIntercepts,
|
|
51965
|
+
createConsoleEvent,
|
|
51966
|
+
captureStackTrace,
|
|
51967
|
+
send,
|
|
51968
|
+
setCaptureState,
|
|
51969
|
+
recordingStarted,
|
|
51970
|
+
recordingStopped,
|
|
51971
|
+
onAppHidden,
|
|
51972
|
+
onAppUnloaded,
|
|
51973
|
+
onPtmPaused,
|
|
51974
|
+
onPtmUnpaused,
|
|
51975
|
+
securityPolicyViolationFn,
|
|
51940
51976
|
get isCapturingConsoleLogs() {
|
|
51941
51977
|
return isCapturingConsoleLogs;
|
|
51942
51978
|
},
|
|
@@ -51953,16 +51989,16 @@ function ConsoleCapture() {
|
|
|
51953
51989
|
function initialize(pendo, PluginAPI) {
|
|
51954
51990
|
_ = pendo._;
|
|
51955
51991
|
pluginAPI = PluginAPI;
|
|
51956
|
-
|
|
51992
|
+
const { ConfigReader } = pluginAPI;
|
|
51957
51993
|
ConfigReader.addOption(CAPTURE_CONSOLE_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
|
|
51958
|
-
|
|
51994
|
+
const captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
|
|
51959
51995
|
if (!captureConsoleEnabled)
|
|
51960
51996
|
return;
|
|
51961
51997
|
globalPendo = pendo;
|
|
51962
51998
|
buffer = new DevlogBuffer(pendo, pluginAPI);
|
|
51963
51999
|
transport = new DevlogTransport(pendo, pluginAPI);
|
|
51964
52000
|
sendQueue = new pluginAPI.SendQueue(transport.sendRequest.bind(transport));
|
|
51965
|
-
sendInterval = setInterval(
|
|
52001
|
+
sendInterval = setInterval(() => {
|
|
51966
52002
|
if (!sendQueue.failed()) {
|
|
51967
52003
|
send();
|
|
51968
52004
|
}
|
|
@@ -51988,19 +52024,17 @@ function ConsoleCapture() {
|
|
|
51988
52024
|
function onPtmUnpaused() {
|
|
51989
52025
|
isPtmPaused = false;
|
|
51990
52026
|
if (!buffer.isEmpty()) {
|
|
51991
|
-
for (
|
|
51992
|
-
|
|
51993
|
-
pluginAPI.Events.eventCaptured.trigger(event_1);
|
|
52027
|
+
for (const event of buffer.events) {
|
|
52028
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
51994
52029
|
}
|
|
51995
52030
|
send();
|
|
51996
52031
|
}
|
|
51997
52032
|
}
|
|
51998
|
-
function setCaptureState(
|
|
51999
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
|
|
52033
|
+
function setCaptureState({ shouldCapture = false, reason = '' } = {}) {
|
|
52000
52034
|
if (shouldCapture === isCapturingConsoleLogs)
|
|
52001
52035
|
return;
|
|
52002
52036
|
isCapturingConsoleLogs = shouldCapture;
|
|
52003
|
-
pluginAPI.log.info(
|
|
52037
|
+
pluginAPI.log.info(`[ConsoleCapture] Console log capture ${shouldCapture ? 'started' : 'stopped'}${reason ? `: ${reason}` : ''}`);
|
|
52004
52038
|
}
|
|
52005
52039
|
function recordingStarted() {
|
|
52006
52040
|
setCaptureState({ shouldCapture: true, reason: 'recording started' });
|
|
@@ -52020,12 +52054,12 @@ function ConsoleCapture() {
|
|
|
52020
52054
|
}
|
|
52021
52055
|
function addIntercepts() {
|
|
52022
52056
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52023
|
-
|
|
52057
|
+
const originalMethod = console[methodName];
|
|
52024
52058
|
if (!originalMethod)
|
|
52025
52059
|
return;
|
|
52026
52060
|
console[methodName] = _.wrap(originalMethod, function (originalFn) {
|
|
52027
52061
|
// slice 1 to omit originalFn
|
|
52028
|
-
|
|
52062
|
+
const args = _.toArray(arguments).slice(1);
|
|
52029
52063
|
originalFn.apply(console, args);
|
|
52030
52064
|
createConsoleEvent(args, methodName);
|
|
52031
52065
|
});
|
|
@@ -52037,10 +52071,10 @@ function ConsoleCapture() {
|
|
|
52037
52071
|
function securityPolicyViolationFn(evt) {
|
|
52038
52072
|
if (!evt || typeof evt !== 'object')
|
|
52039
52073
|
return;
|
|
52040
|
-
|
|
52041
|
-
|
|
52042
|
-
|
|
52043
|
-
|
|
52074
|
+
const { blockedURI, violatedDirective, effectiveDirective, disposition, originalPolicy } = evt;
|
|
52075
|
+
const directive = violatedDirective || effectiveDirective;
|
|
52076
|
+
const isReportOnly = disposition === 'report';
|
|
52077
|
+
const message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
|
|
52044
52078
|
if (isReportOnly) {
|
|
52045
52079
|
createConsoleEvent([message], 'warn', { skipStackTrace: true, skipScrubPII: true });
|
|
52046
52080
|
}
|
|
@@ -52048,13 +52082,12 @@ function ConsoleCapture() {
|
|
|
52048
52082
|
createConsoleEvent([message], 'error', { skipStackTrace: true, skipScrubPII: true });
|
|
52049
52083
|
}
|
|
52050
52084
|
}
|
|
52051
|
-
function createConsoleEvent(args, methodName,
|
|
52052
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.skipStackTrace, skipStackTrace = _c === void 0 ? false : _c, _d = _b.skipScrubPII, skipScrubPII = _d === void 0 ? false : _d;
|
|
52085
|
+
function createConsoleEvent(args, methodName, { skipStackTrace = false, skipScrubPII = false } = {}) {
|
|
52053
52086
|
if (!isCapturingConsoleLogs || !args || args.length === 0 || !_.contains(CONSOLE_METHODS, methodName))
|
|
52054
52087
|
return;
|
|
52055
52088
|
// stringify args
|
|
52056
|
-
|
|
52057
|
-
|
|
52089
|
+
let message = _.compact(_.map(args, arg => {
|
|
52090
|
+
let stringifiedArg;
|
|
52058
52091
|
try {
|
|
52059
52092
|
stringifiedArg = stringify(arg);
|
|
52060
52093
|
}
|
|
@@ -52066,22 +52099,22 @@ function ConsoleCapture() {
|
|
|
52066
52099
|
if (!message)
|
|
52067
52100
|
return;
|
|
52068
52101
|
// capture stack trace
|
|
52069
|
-
|
|
52102
|
+
let stackTrace = '';
|
|
52070
52103
|
if (!skipStackTrace) {
|
|
52071
|
-
|
|
52104
|
+
const maxStackFrames = methodName === 'error' ? 4 : 1;
|
|
52072
52105
|
stackTrace = captureStackTrace(maxStackFrames);
|
|
52073
52106
|
}
|
|
52074
52107
|
// truncate message and stack trace
|
|
52075
52108
|
message = truncate(message);
|
|
52076
52109
|
stackTrace = truncate(stackTrace);
|
|
52077
52110
|
// de-duplicate log
|
|
52078
|
-
|
|
52111
|
+
const logKey = generateLogKey(methodName, message, stackTrace);
|
|
52079
52112
|
if (isExistingDuplicateLog(logKey)) {
|
|
52080
52113
|
buffer.lastEvent.devLogCount++;
|
|
52081
52114
|
return;
|
|
52082
52115
|
}
|
|
52083
|
-
|
|
52084
|
-
|
|
52116
|
+
const devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
|
|
52117
|
+
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 });
|
|
52085
52118
|
if (!buffer.hasTokenAvailable())
|
|
52086
52119
|
return consoleEvent;
|
|
52087
52120
|
if (!isPtmPaused) {
|
|
@@ -52093,8 +52126,8 @@ function ConsoleCapture() {
|
|
|
52093
52126
|
}
|
|
52094
52127
|
function captureStackTrace(maxStackFrames) {
|
|
52095
52128
|
try {
|
|
52096
|
-
|
|
52097
|
-
return _.map(stackFrames,
|
|
52129
|
+
const stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
|
|
52130
|
+
return _.map(stackFrames, frame => frame.toString()).join('\n');
|
|
52098
52131
|
}
|
|
52099
52132
|
catch (error) {
|
|
52100
52133
|
return '';
|
|
@@ -52106,22 +52139,21 @@ function ConsoleCapture() {
|
|
|
52106
52139
|
function updateLastLog(logKey) {
|
|
52107
52140
|
lastLogKey = logKey;
|
|
52108
52141
|
}
|
|
52109
|
-
function send(
|
|
52110
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
|
|
52142
|
+
function send({ unload = false, hidden = false } = {}) {
|
|
52111
52143
|
if (!buffer || buffer.isEmpty())
|
|
52112
52144
|
return;
|
|
52113
52145
|
if (!globalPendo.isSendingEvents()) {
|
|
52114
52146
|
buffer.clear();
|
|
52115
52147
|
return;
|
|
52116
52148
|
}
|
|
52117
|
-
|
|
52149
|
+
const payloads = buffer.pack();
|
|
52118
52150
|
if (!payloads || payloads.length === 0)
|
|
52119
52151
|
return;
|
|
52120
52152
|
if (unload || hidden) {
|
|
52121
52153
|
sendQueue.drain(payloads, unload);
|
|
52122
52154
|
}
|
|
52123
52155
|
else {
|
|
52124
|
-
sendQueue.push
|
|
52156
|
+
sendQueue.push(...payloads);
|
|
52125
52157
|
}
|
|
52126
52158
|
}
|
|
52127
52159
|
function teardown() {
|
|
@@ -52145,7 +52177,7 @@ function ConsoleCapture() {
|
|
|
52145
52177
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52146
52178
|
if (!console[methodName])
|
|
52147
52179
|
return _.noop;
|
|
52148
|
-
|
|
52180
|
+
const unwrap = console[methodName]._pendoUnwrap;
|
|
52149
52181
|
if (_.isFunction(unwrap)) {
|
|
52150
52182
|
unwrap();
|
|
52151
52183
|
}
|
|
@@ -52936,35 +52968,60 @@ const PredictGuides = () => {
|
|
|
52936
52968
|
};
|
|
52937
52969
|
};
|
|
52938
52970
|
|
|
52939
|
-
|
|
52940
|
-
|
|
52941
|
-
|
|
52942
|
-
|
|
52943
|
-
|
|
52944
|
-
|
|
52945
|
-
|
|
52946
|
-
|
|
52947
|
-
|
|
52948
|
-
|
|
52949
|
-
|
|
52950
|
-
|
|
52951
|
-
|
|
52952
|
-
|
|
52953
|
-
|
|
52971
|
+
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
52972
|
+
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
52973
|
+
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
52974
|
+
const MESSAGE_ID_PATTERN = 'messageIdPattern';
|
|
52975
|
+
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
52976
|
+
const REACTION_ACTIVE = 'reactionActive';
|
|
52977
|
+
const STREAMING_ACTIVE = 'streamingActive';
|
|
52978
|
+
const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
52979
|
+
const THUMB_DOWN = 'thumbDown';
|
|
52980
|
+
const THUMB_UP = 'thumbUp';
|
|
52981
|
+
const TURN_CONTAINER = 'turnContainer';
|
|
52982
|
+
const USER_MESSAGE = 'userMessage';
|
|
52983
|
+
const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
|
|
52984
|
+
const CUSTOM_AGENT_ID = 'customAgentId';
|
|
52985
|
+
const CUSTOM_AGENT_NAME = 'customAgentName';
|
|
52986
|
+
const REQUIRED_SELECTORS = [
|
|
52954
52987
|
ASSISTANT_MESSAGE,
|
|
52955
52988
|
CONVERSATION_ID_URL_PATTERN,
|
|
52956
|
-
MESSAGE_ID_ATTR,
|
|
52957
52989
|
STREAMING_ACTIVE,
|
|
52958
52990
|
TURN_CONTAINER,
|
|
52959
52991
|
USER_MESSAGE
|
|
52960
52992
|
];
|
|
52961
|
-
|
|
52962
|
-
|
|
52963
|
-
|
|
52964
|
-
|
|
52965
|
-
|
|
52966
|
-
|
|
52967
|
-
|
|
52993
|
+
const SUPPORTED_PRESETS = ['chatgpt-full', 'gemini-full', 'claude-full'];
|
|
52994
|
+
const STREAMING_END_SETTLE_MS = 500;
|
|
52995
|
+
const SUBMISSION_START_RETRY_MS = 1000;
|
|
52996
|
+
const SUBMISSION_START_MAX_ATTEMPTS = 4;
|
|
52997
|
+
class DOMConversation {
|
|
52998
|
+
// Returns the list of required selector types that are missing or empty
|
|
52999
|
+
// in the given cssSelectors config. An empty array means the config is
|
|
53000
|
+
// valid for instantiation.
|
|
53001
|
+
static validateConfig(cssSelectors) {
|
|
53002
|
+
if (!Array.isArray(cssSelectors)) {
|
|
53003
|
+
return REQUIRED_SELECTORS.slice();
|
|
53004
|
+
}
|
|
53005
|
+
const present = new Set();
|
|
53006
|
+
for (const cfg of cssSelectors) {
|
|
53007
|
+
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
53008
|
+
continue;
|
|
53009
|
+
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
53010
|
+
try {
|
|
53011
|
+
RegExp(cfg.cssSelector);
|
|
53012
|
+
}
|
|
53013
|
+
catch (e) {
|
|
53014
|
+
continue;
|
|
53015
|
+
}
|
|
53016
|
+
}
|
|
53017
|
+
present.add(cfg.type);
|
|
53018
|
+
}
|
|
53019
|
+
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
53020
|
+
}
|
|
53021
|
+
static supportedPreset(preset) {
|
|
53022
|
+
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
53023
|
+
}
|
|
53024
|
+
constructor(pendo, PluginAPI, id, cssSelectors) {
|
|
52968
53025
|
this.selectors = {};
|
|
52969
53026
|
this.listeners = [];
|
|
52970
53027
|
this.isActive = true;
|
|
@@ -52983,99 +53040,72 @@ var DOMConversation = /** @class */ (function () {
|
|
|
52983
53040
|
this.Sizzle = pendo.Sizzle;
|
|
52984
53041
|
this.id = id;
|
|
52985
53042
|
if (!this._.isArray(cssSelectors)) {
|
|
52986
|
-
this.api.log.error(
|
|
53043
|
+
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
52987
53044
|
cssSelectors = [];
|
|
52988
53045
|
}
|
|
52989
|
-
this._.each(cssSelectors,
|
|
53046
|
+
this._.each(cssSelectors, (cfg) => {
|
|
52990
53047
|
if (cfg && cfg.type) {
|
|
52991
|
-
|
|
53048
|
+
this.selectors[cfg.type] = cfg.cssSelector;
|
|
52992
53049
|
}
|
|
52993
53050
|
});
|
|
52994
53051
|
this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
|
|
52995
|
-
|
|
53052
|
+
const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
|
|
52996
53053
|
if (customAgentIdUrlPattern) { // this is optional
|
|
52997
53054
|
try {
|
|
52998
53055
|
this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
|
|
52999
53056
|
}
|
|
53000
53057
|
catch (error) {
|
|
53001
|
-
this.api.log.error(
|
|
53058
|
+
this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
|
|
53002
53059
|
}
|
|
53003
53060
|
}
|
|
53004
|
-
|
|
53061
|
+
const messageIdPattern = this.selectors[MESSAGE_ID_PATTERN];
|
|
53005
53062
|
if (messageIdPattern) { // optional: gates the request node until its id is fully rendered
|
|
53006
53063
|
try {
|
|
53007
53064
|
this.messageIdRegex = new RegExp(messageIdPattern);
|
|
53008
53065
|
}
|
|
53009
53066
|
catch (error) {
|
|
53010
|
-
this.api.log.error(
|
|
53067
|
+
this.api.log.error(`bad messageIdPattern ${messageIdPattern}`, { error });
|
|
53011
53068
|
}
|
|
53012
53069
|
}
|
|
53013
53070
|
this.root = document.body;
|
|
53014
53071
|
this.setupReactionListener();
|
|
53015
53072
|
this.setupStreamingObserver();
|
|
53016
53073
|
}
|
|
53017
|
-
|
|
53018
|
-
// in the given cssSelectors config. An empty array means the config is
|
|
53019
|
-
// valid for instantiation.
|
|
53020
|
-
DOMConversation.validateConfig = function (cssSelectors) {
|
|
53021
|
-
if (!Array.isArray(cssSelectors)) {
|
|
53022
|
-
return REQUIRED_SELECTORS.slice();
|
|
53023
|
-
}
|
|
53024
|
-
var present = new Set();
|
|
53025
|
-
for (var _i = 0, cssSelectors_1 = cssSelectors; _i < cssSelectors_1.length; _i++) {
|
|
53026
|
-
var cfg = cssSelectors_1[_i];
|
|
53027
|
-
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
53028
|
-
continue;
|
|
53029
|
-
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
53030
|
-
try {
|
|
53031
|
-
RegExp(cfg.cssSelector);
|
|
53032
|
-
}
|
|
53033
|
-
catch (e) {
|
|
53034
|
-
continue;
|
|
53035
|
-
}
|
|
53036
|
-
}
|
|
53037
|
-
present.add(cfg.type);
|
|
53038
|
-
}
|
|
53039
|
-
return REQUIRED_SELECTORS.filter(function (r) { return !present.has(r); });
|
|
53040
|
-
};
|
|
53041
|
-
DOMConversation.supportedPreset = function (preset) {
|
|
53042
|
-
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
53043
|
-
};
|
|
53044
|
-
DOMConversation.prototype.setupReactionListener = function () {
|
|
53074
|
+
setupReactionListener() {
|
|
53045
53075
|
if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
|
|
53046
53076
|
return;
|
|
53047
53077
|
this.reactionClickHandler = this.handleReactionClick.bind(this);
|
|
53048
53078
|
this.root.addEventListener('click', this.reactionClickHandler, true);
|
|
53049
|
-
}
|
|
53050
|
-
|
|
53051
|
-
|
|
53079
|
+
}
|
|
53080
|
+
handleReactionClick(evt) {
|
|
53081
|
+
const target = evt.target;
|
|
53052
53082
|
if (!target || target.nodeType !== 1)
|
|
53053
53083
|
return;
|
|
53054
|
-
|
|
53055
|
-
|
|
53056
|
-
|
|
53084
|
+
const upSelector = this.findSelector(THUMB_UP);
|
|
53085
|
+
const downSelector = this.findSelector(THUMB_DOWN);
|
|
53086
|
+
const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
|
|
53057
53087
|
if (!thumb.length)
|
|
53058
53088
|
return;
|
|
53059
|
-
|
|
53060
|
-
|
|
53061
|
-
|
|
53062
|
-
|
|
53063
|
-
|
|
53064
|
-
|
|
53089
|
+
const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
|
|
53090
|
+
const activeSelector = this.findSelector(REACTION_ACTIVE);
|
|
53091
|
+
const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
|
|
53092
|
+
const direction = isUp ? 'positive' : 'negative';
|
|
53093
|
+
const content = wasPressed ? 'unreact' : direction;
|
|
53094
|
+
const assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
|
|
53065
53095
|
.find(this.findSelector(ASSISTANT_MESSAGE));
|
|
53066
53096
|
this.emit('user_reaction', {
|
|
53067
53097
|
agentId: this.id,
|
|
53068
53098
|
messageId: this.getMessageId(assistantNode),
|
|
53069
|
-
content
|
|
53099
|
+
content
|
|
53070
53100
|
});
|
|
53071
|
-
}
|
|
53101
|
+
}
|
|
53072
53102
|
// observe the streaming indicator
|
|
53073
|
-
|
|
53103
|
+
setupStreamingObserver() {
|
|
53074
53104
|
this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
53075
53105
|
this.stopStreamingEndTimer();
|
|
53076
|
-
|
|
53077
|
-
|
|
53078
|
-
|
|
53106
|
+
const MutationObserver = getZoneSafeMethod(this._, 'MutationObserver');
|
|
53107
|
+
const observer = new MutationObserver(this.handleMutation.bind(this));
|
|
53108
|
+
const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
|
|
53079
53109
|
observer.observe(this.root, {
|
|
53080
53110
|
childList: true,
|
|
53081
53111
|
subtree: true,
|
|
@@ -53083,7 +53113,7 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53083
53113
|
attributeFilter: attrName ? [attrName] : undefined
|
|
53084
53114
|
});
|
|
53085
53115
|
this.observers.push(observer);
|
|
53086
|
-
}
|
|
53116
|
+
}
|
|
53087
53117
|
// look for changes in the state of the streaming indicator.
|
|
53088
53118
|
// streaming started -> a prompt has been submitted
|
|
53089
53119
|
// streaming ended -> got a response
|
|
@@ -53092,8 +53122,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53092
53122
|
// we don't send the agent_response immediately when the streaming indicator is cleared
|
|
53093
53123
|
// because it clears slightly before the final text chunk is committed to the DOM so the
|
|
53094
53124
|
// end-handling is deferred by a short settle window
|
|
53095
|
-
|
|
53096
|
-
|
|
53125
|
+
handleMutation() {
|
|
53126
|
+
const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
53097
53127
|
if (isStreaming === this.wasStreaming)
|
|
53098
53128
|
return;
|
|
53099
53129
|
if (isStreaming) { // started streaming
|
|
@@ -53111,9 +53141,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53111
53141
|
this.startStreamingEndTimer();
|
|
53112
53142
|
}
|
|
53113
53143
|
this.wasStreaming = isStreaming;
|
|
53114
|
-
}
|
|
53115
|
-
|
|
53116
|
-
if (attempt === void 0) { attempt = 1; }
|
|
53144
|
+
}
|
|
53145
|
+
onSubmissionStart(attempt = 1) {
|
|
53117
53146
|
this.requestNode = this.findLastRequestNode();
|
|
53118
53147
|
if (this.requestNode) {
|
|
53119
53148
|
this.handleUserMessage(this.requestNode);
|
|
@@ -53124,10 +53153,10 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53124
53153
|
if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
|
|
53125
53154
|
this.startSubmissionStartRetryTimer(attempt + 1);
|
|
53126
53155
|
}
|
|
53127
|
-
}
|
|
53128
|
-
|
|
53156
|
+
}
|
|
53157
|
+
onSubmissionEnd() {
|
|
53129
53158
|
this.stopSubmissionStartRetryTimer();
|
|
53130
|
-
|
|
53159
|
+
let requestNode = this.requestNode;
|
|
53131
53160
|
this.requestNode = null;
|
|
53132
53161
|
if (!requestNode) {
|
|
53133
53162
|
// onSubmissionStart didn't send, send it now
|
|
@@ -53136,42 +53165,77 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53136
53165
|
return;
|
|
53137
53166
|
this.handleUserMessage(requestNode);
|
|
53138
53167
|
}
|
|
53139
|
-
|
|
53168
|
+
const requestEl = requestNode[0];
|
|
53140
53169
|
if (!requestEl)
|
|
53141
53170
|
return;
|
|
53142
53171
|
// the request is the latest user message, so any assistant message that
|
|
53143
53172
|
// follows it in the DOM is a response to it. document order is already
|
|
53144
53173
|
// chronological, so we emit as we go
|
|
53145
|
-
|
|
53146
|
-
for (
|
|
53147
|
-
|
|
53174
|
+
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
53175
|
+
for (let i = 0; i < assistantNodes.length; i++) {
|
|
53176
|
+
const el = assistantNodes[i];
|
|
53148
53177
|
if (requestEl.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
53149
53178
|
this.handleAssistantMessage(this.dom(el));
|
|
53150
53179
|
}
|
|
53151
53180
|
}
|
|
53152
|
-
}
|
|
53153
|
-
|
|
53154
|
-
|
|
53155
|
-
|
|
53156
|
-
|
|
53157
|
-
|
|
53158
|
-
|
|
53159
|
-
|
|
53160
|
-
|
|
53161
|
-
}
|
|
53162
|
-
|
|
53163
|
-
|
|
53164
|
-
|
|
53165
|
-
|
|
53166
|
-
|
|
53167
|
-
|
|
53181
|
+
}
|
|
53182
|
+
extractContent(node) {
|
|
53183
|
+
// .text() reads innerText, which is empty for content-visibility:auto / off-screen subtrees
|
|
53184
|
+
// (e.g. claude.ai's scrolled-up messages). Keep innerText as the primary source so agents
|
|
53185
|
+
// whose content already works are unchanged, and fall back to textContent only when it's empty.
|
|
53186
|
+
const primary = node.text().trim();
|
|
53187
|
+
if (primary)
|
|
53188
|
+
return primary;
|
|
53189
|
+
return node[0].textContent.trim();
|
|
53190
|
+
}
|
|
53191
|
+
getMessageId(node) {
|
|
53192
|
+
const attr = this.findSelector(MESSAGE_ID_ATTR);
|
|
53193
|
+
if (!attr) {
|
|
53194
|
+
return this.syntheticMessageId(node[0]);
|
|
53195
|
+
}
|
|
53196
|
+
return node.attr(attr);
|
|
53197
|
+
}
|
|
53198
|
+
// Agents with no DOM message id (e.g. claude.ai) get a synthetic id based on the role and
|
|
53199
|
+
// position in document order.
|
|
53200
|
+
syntheticMessageId(el) {
|
|
53201
|
+
if (!el)
|
|
53202
|
+
return undefined;
|
|
53203
|
+
const userSelector = this.findSelector(USER_MESSAGE);
|
|
53204
|
+
const isUser = userSelector && this.Sizzle.matchesSelector(el, userSelector);
|
|
53205
|
+
const role = isUser ? 'u' : 'a';
|
|
53206
|
+
const siblings = this.select(isUser ? USER_MESSAGE : ASSISTANT_MESSAGE);
|
|
53207
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
53208
|
+
if (siblings[i] === el) {
|
|
53209
|
+
return `${role}-${i}`;
|
|
53210
|
+
}
|
|
53211
|
+
}
|
|
53212
|
+
return undefined; // el isn't among the rendered messages — no meaningful index
|
|
53213
|
+
}
|
|
53214
|
+
handleUserMessage(node) {
|
|
53215
|
+
this.emit('prompt', {
|
|
53216
|
+
agentId: this.id,
|
|
53217
|
+
messageId: this.getMessageId(node),
|
|
53218
|
+
content: this.extractContent(node)
|
|
53219
|
+
});
|
|
53220
|
+
}
|
|
53221
|
+
handleAssistantMessage(node) {
|
|
53222
|
+
const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
|
|
53223
|
+
const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
|
|
53224
|
+
this.emit('agent_response', {
|
|
53225
|
+
agentId: this.id,
|
|
53226
|
+
messageId: this.getMessageId(node),
|
|
53227
|
+
agentModelsUsed: modelUsed ? [modelUsed] : [],
|
|
53228
|
+
content: this.extractContent(node)
|
|
53229
|
+
});
|
|
53230
|
+
}
|
|
53231
|
+
findLastRequestNode() {
|
|
53168
53232
|
if (!this.getConversationId())
|
|
53169
53233
|
return null;
|
|
53170
|
-
|
|
53234
|
+
const node = this._.last(this.select(USER_MESSAGE));
|
|
53171
53235
|
if (!node)
|
|
53172
53236
|
return null;
|
|
53173
|
-
|
|
53174
|
-
|
|
53237
|
+
const $node = this.dom(node);
|
|
53238
|
+
const messageId = this.getMessageId($node);
|
|
53175
53239
|
if (!messageId)
|
|
53176
53240
|
return null;
|
|
53177
53241
|
// the node may still be rendering (e.g. a framework interpolating an
|
|
@@ -53183,89 +53247,96 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53183
53247
|
return null;
|
|
53184
53248
|
this.lastReturnedMessageId = messageId;
|
|
53185
53249
|
return $node;
|
|
53186
|
-
}
|
|
53187
|
-
|
|
53250
|
+
}
|
|
53251
|
+
findSelector(type) {
|
|
53188
53252
|
return this.selectors[type];
|
|
53189
|
-
}
|
|
53190
|
-
|
|
53253
|
+
}
|
|
53254
|
+
select(type) {
|
|
53191
53255
|
return this.dom(this.findSelector(type), this.root);
|
|
53192
|
-
}
|
|
53193
|
-
|
|
53194
|
-
|
|
53256
|
+
}
|
|
53257
|
+
getConversationId() {
|
|
53258
|
+
const m = location.href.match(this.conversationIdRegex);
|
|
53195
53259
|
if (!m)
|
|
53196
53260
|
return null;
|
|
53197
53261
|
return m[1] !== undefined ? m[1] : m[0];
|
|
53198
|
-
}
|
|
53199
|
-
|
|
53262
|
+
}
|
|
53263
|
+
getCustomAgentId() {
|
|
53200
53264
|
if (!this.customAgentIdRegex)
|
|
53201
53265
|
return undefined;
|
|
53202
|
-
|
|
53266
|
+
// The id may live in the page URL (e.g. gemini /gem/<id>) or,
|
|
53267
|
+
// when customAgentId is set, in the href of a DOM element
|
|
53268
|
+
let source = location.href;
|
|
53269
|
+
if (this.findSelector(CUSTOM_AGENT_ID)) {
|
|
53270
|
+
const node = this.select(CUSTOM_AGENT_ID);
|
|
53271
|
+
if (!node.length)
|
|
53272
|
+
return undefined;
|
|
53273
|
+
source = node.attr('href') || '';
|
|
53274
|
+
}
|
|
53275
|
+
const m = source.match(this.customAgentIdRegex);
|
|
53203
53276
|
if (!m)
|
|
53204
53277
|
return undefined;
|
|
53205
53278
|
return m[1] !== undefined ? m[1] : m[0];
|
|
53206
|
-
}
|
|
53207
|
-
|
|
53279
|
+
}
|
|
53280
|
+
getCustomAgentName() {
|
|
53208
53281
|
if (!this.findSelector(CUSTOM_AGENT_NAME))
|
|
53209
53282
|
return '';
|
|
53210
|
-
|
|
53283
|
+
const node = this.select(CUSTOM_AGENT_NAME);
|
|
53211
53284
|
if (!node.length)
|
|
53212
53285
|
return '';
|
|
53213
53286
|
return node.text().trim();
|
|
53214
|
-
}
|
|
53215
|
-
|
|
53216
|
-
|
|
53287
|
+
}
|
|
53288
|
+
addCustomAgentInfo(eventPayload) {
|
|
53289
|
+
const customAgentId = this.getCustomAgentId();
|
|
53217
53290
|
if (!customAgentId)
|
|
53218
53291
|
return;
|
|
53219
53292
|
eventPayload.customAgentId = customAgentId;
|
|
53220
|
-
|
|
53293
|
+
const customAgentName = this.getCustomAgentName();
|
|
53221
53294
|
if (customAgentName) {
|
|
53222
53295
|
eventPayload.customAgentName = customAgentName;
|
|
53223
53296
|
}
|
|
53224
|
-
}
|
|
53225
|
-
|
|
53297
|
+
}
|
|
53298
|
+
onSubmit(callback) {
|
|
53226
53299
|
this.listeners.push(callback);
|
|
53227
|
-
}
|
|
53228
|
-
|
|
53300
|
+
}
|
|
53301
|
+
emit(eventType, eventPayload) {
|
|
53229
53302
|
eventPayload.conversationId = this.getConversationId();
|
|
53230
53303
|
this.addCustomAgentInfo(eventPayload);
|
|
53231
|
-
this._.each(this.listeners,
|
|
53232
|
-
}
|
|
53233
|
-
|
|
53234
|
-
var _this = this;
|
|
53304
|
+
this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
|
|
53305
|
+
}
|
|
53306
|
+
startStreamingEndTimer() {
|
|
53235
53307
|
this.stopStreamingEndTimer();
|
|
53236
|
-
this.streamingEndTimer = setTimeout$1(
|
|
53237
|
-
|
|
53238
|
-
|
|
53308
|
+
this.streamingEndTimer = setTimeout$1(() => {
|
|
53309
|
+
this.streamingEndTimer = null;
|
|
53310
|
+
this.onSubmissionEnd();
|
|
53239
53311
|
}, STREAMING_END_SETTLE_MS);
|
|
53240
|
-
}
|
|
53241
|
-
|
|
53312
|
+
}
|
|
53313
|
+
stopStreamingEndTimer() {
|
|
53242
53314
|
if (!this.streamingEndTimer)
|
|
53243
53315
|
return;
|
|
53244
53316
|
clearTimeout(this.streamingEndTimer);
|
|
53245
53317
|
this.streamingEndTimer = null;
|
|
53246
|
-
}
|
|
53247
|
-
|
|
53248
|
-
var _this = this;
|
|
53318
|
+
}
|
|
53319
|
+
startSubmissionStartRetryTimer(attempt) {
|
|
53249
53320
|
this.stopSubmissionStartRetryTimer();
|
|
53250
|
-
this.submissionStartRetryTimer = setTimeout$1(
|
|
53251
|
-
|
|
53252
|
-
|
|
53321
|
+
this.submissionStartRetryTimer = setTimeout$1(() => {
|
|
53322
|
+
this.submissionStartRetryTimer = null;
|
|
53323
|
+
this.onSubmissionStart(attempt);
|
|
53253
53324
|
}, SUBMISSION_START_RETRY_MS);
|
|
53254
|
-
}
|
|
53255
|
-
|
|
53325
|
+
}
|
|
53326
|
+
stopSubmissionStartRetryTimer() {
|
|
53256
53327
|
if (!this.submissionStartRetryTimer)
|
|
53257
53328
|
return;
|
|
53258
53329
|
clearTimeout(this.submissionStartRetryTimer);
|
|
53259
53330
|
this.submissionStartRetryTimer = null;
|
|
53260
|
-
}
|
|
53261
|
-
|
|
53331
|
+
}
|
|
53332
|
+
suspend() {
|
|
53262
53333
|
this.isActive = false;
|
|
53263
|
-
}
|
|
53264
|
-
|
|
53334
|
+
}
|
|
53335
|
+
resume() {
|
|
53265
53336
|
this.isActive = true;
|
|
53266
|
-
}
|
|
53267
|
-
|
|
53268
|
-
this._.each(this.observers,
|
|
53337
|
+
}
|
|
53338
|
+
teardown() {
|
|
53339
|
+
this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
|
|
53269
53340
|
this.observers = [];
|
|
53270
53341
|
if (this.reactionClickHandler && this.root) {
|
|
53271
53342
|
this.root.removeEventListener('click', this.reactionClickHandler, true);
|
|
@@ -53274,9 +53345,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53274
53345
|
this.stopStreamingEndTimer();
|
|
53275
53346
|
this.stopSubmissionStartRetryTimer();
|
|
53276
53347
|
this.listeners = [];
|
|
53277
|
-
}
|
|
53278
|
-
|
|
53279
|
-
}());
|
|
53348
|
+
}
|
|
53349
|
+
}
|
|
53280
53350
|
|
|
53281
53351
|
/*
|
|
53282
53352
|
* Conversation Analytics Plugin
|
|
@@ -53286,21 +53356,21 @@ var DOMConversation = /** @class */ (function () {
|
|
|
53286
53356
|
* The sibling built-in PromptAnalytics plugin owns the network + DOMPrompt AI-agents
|
|
53287
53357
|
*/
|
|
53288
53358
|
function ConversationAnalytics() {
|
|
53289
|
-
|
|
53290
|
-
|
|
53291
|
-
|
|
53292
|
-
|
|
53293
|
-
|
|
53294
|
-
|
|
53295
|
-
|
|
53359
|
+
let pendo;
|
|
53360
|
+
let api;
|
|
53361
|
+
let _;
|
|
53362
|
+
let log;
|
|
53363
|
+
let conversations = [];
|
|
53364
|
+
let agentsCache = new Map();
|
|
53365
|
+
const CONFIG_NAME = 'aiAgents';
|
|
53296
53366
|
return {
|
|
53297
53367
|
name: 'ConversationAnalytics',
|
|
53298
|
-
initialize
|
|
53299
|
-
teardown
|
|
53300
|
-
onConfigLoaded
|
|
53301
|
-
observeConversation
|
|
53302
|
-
sendConversationEvent
|
|
53303
|
-
reEvaluatePageRules
|
|
53368
|
+
initialize,
|
|
53369
|
+
teardown,
|
|
53370
|
+
onConfigLoaded,
|
|
53371
|
+
observeConversation,
|
|
53372
|
+
sendConversationEvent,
|
|
53373
|
+
reEvaluatePageRules
|
|
53304
53374
|
};
|
|
53305
53375
|
function initialize(pendoGlobal, PluginAPI) {
|
|
53306
53376
|
var _a;
|
|
@@ -53308,7 +53378,7 @@ function ConversationAnalytics() {
|
|
|
53308
53378
|
api = PluginAPI;
|
|
53309
53379
|
_ = pendo._;
|
|
53310
53380
|
log = api.log;
|
|
53311
|
-
|
|
53381
|
+
const { ConfigReader } = api;
|
|
53312
53382
|
ConfigReader.addOption(CONFIG_NAME, [
|
|
53313
53383
|
ConfigReader.sources.PENDO_CONFIG_SRC,
|
|
53314
53384
|
ConfigReader.sources.SNIPPET_SRC
|
|
@@ -53321,13 +53391,12 @@ function ConversationAnalytics() {
|
|
|
53321
53391
|
// Test if the current URL matches the page rule for an agent. The raw matcher lives in core
|
|
53322
53392
|
// and is reached through PluginAPI (independent plugins cannot import it directly); it falls
|
|
53323
53393
|
// back to the normalized URL internally when no URL is passed.
|
|
53324
|
-
function testPageRule(pageRule, agentId) {
|
|
53325
|
-
if (agentId === void 0) { agentId = 'unknown'; }
|
|
53394
|
+
function testPageRule(pageRule, agentId = 'unknown') {
|
|
53326
53395
|
// Convert //*/agent pattern to work with full URLs
|
|
53327
|
-
|
|
53396
|
+
let fixedPageRule = pageRule;
|
|
53328
53397
|
if (Array.isArray(pageRule)) {
|
|
53329
|
-
|
|
53330
|
-
fixedPageRule = _.map(validRules,
|
|
53398
|
+
const validRules = _.filter(pageRule, rule => rule && rule.trim() !== '');
|
|
53399
|
+
fixedPageRule = _.map(validRules, rule => rule.startsWith('//*/') ? rule.substring(1) : rule);
|
|
53331
53400
|
}
|
|
53332
53401
|
else if (typeof pageRule === 'string' && pageRule.startsWith('//*/')) {
|
|
53333
53402
|
fixedPageRule = pageRule.substring(1);
|
|
@@ -53339,9 +53408,9 @@ function ConversationAnalytics() {
|
|
|
53339
53408
|
});
|
|
53340
53409
|
}
|
|
53341
53410
|
function reEvaluatePageRules() {
|
|
53342
|
-
_.each(conversations,
|
|
53343
|
-
|
|
53344
|
-
|
|
53411
|
+
_.each(conversations, conversation => {
|
|
53412
|
+
const agent = findAgentById(conversation.id);
|
|
53413
|
+
const shouldBeActive = agent && testPageRule(agent.pageRule, agent.id);
|
|
53345
53414
|
if (shouldBeActive) {
|
|
53346
53415
|
conversation.resume();
|
|
53347
53416
|
}
|
|
@@ -53349,14 +53418,14 @@ function ConversationAnalytics() {
|
|
|
53349
53418
|
conversation.suspend();
|
|
53350
53419
|
}
|
|
53351
53420
|
});
|
|
53352
|
-
|
|
53353
|
-
|
|
53354
|
-
_.each(allAgents,
|
|
53421
|
+
const currentlyActiveIds = _.map(_.filter(conversations, conversation => conversation.isActive), conversation => conversation.id);
|
|
53422
|
+
const allAgents = api.ConfigReader.get(CONFIG_NAME) || [];
|
|
53423
|
+
_.each(allAgents, aiAgent => {
|
|
53355
53424
|
if (!isConversationAgent(aiAgent)) {
|
|
53356
53425
|
return;
|
|
53357
53426
|
}
|
|
53358
|
-
|
|
53359
|
-
|
|
53427
|
+
const isCurrentlyActive = _.contains(currentlyActiveIds, aiAgent.id);
|
|
53428
|
+
const shouldBeActive = testPageRule(aiAgent.pageRule, aiAgent.id);
|
|
53360
53429
|
if (shouldBeActive && !isCurrentlyActive) {
|
|
53361
53430
|
observeConversation(aiAgent);
|
|
53362
53431
|
}
|
|
@@ -53370,13 +53439,12 @@ function ConversationAnalytics() {
|
|
|
53370
53439
|
function isConversationAgent(agent) {
|
|
53371
53440
|
return DOMConversation.supportedPreset(agent.preset);
|
|
53372
53441
|
}
|
|
53373
|
-
function onConfigLoaded(aiAgents) {
|
|
53374
|
-
if (aiAgents === void 0) { aiAgents = []; }
|
|
53442
|
+
function onConfigLoaded(aiAgents = []) {
|
|
53375
53443
|
if (!aiAgents || !_.isArray(aiAgents) || aiAgents.length === 0) {
|
|
53376
53444
|
return;
|
|
53377
53445
|
}
|
|
53378
53446
|
agentsCache.clear();
|
|
53379
|
-
_.each(aiAgents,
|
|
53447
|
+
_.each(aiAgents, aiAgent => {
|
|
53380
53448
|
if (!isConversationAgent(aiAgent)) {
|
|
53381
53449
|
return;
|
|
53382
53450
|
}
|
|
@@ -53387,24 +53455,24 @@ function ConversationAnalytics() {
|
|
|
53387
53455
|
});
|
|
53388
53456
|
}
|
|
53389
53457
|
function observeConversation(config) {
|
|
53390
|
-
|
|
53458
|
+
const { id, cssSelectors } = config;
|
|
53391
53459
|
// Check if this agent is already being tracked
|
|
53392
|
-
|
|
53460
|
+
const existing = _.find(conversations, conversation => conversation.id === id);
|
|
53393
53461
|
if (existing) {
|
|
53394
53462
|
return;
|
|
53395
53463
|
}
|
|
53396
|
-
|
|
53464
|
+
const missing = DOMConversation.validateConfig(cssSelectors);
|
|
53397
53465
|
if (missing.length) {
|
|
53398
|
-
log.error('aiAgent config missing required selectors', { agentId: id, missing
|
|
53466
|
+
log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
53399
53467
|
return;
|
|
53400
53468
|
}
|
|
53401
|
-
|
|
53469
|
+
const conversation = new DOMConversation(pendo, api, id, cssSelectors);
|
|
53402
53470
|
conversation.onSubmit(sendConversationEvent);
|
|
53403
53471
|
conversations.push(conversation);
|
|
53404
53472
|
}
|
|
53405
53473
|
function sendConversationEvent(eventType, eventPayload) {
|
|
53406
53474
|
// Block event if the conversation is suspended
|
|
53407
|
-
|
|
53475
|
+
const conversation = _.find(conversations, c => c.id === eventPayload.agentId);
|
|
53408
53476
|
if (conversation && !conversation.isActive) {
|
|
53409
53477
|
return;
|
|
53410
53478
|
}
|
|
@@ -53412,7 +53480,7 @@ function ConversationAnalytics() {
|
|
|
53412
53480
|
api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
|
|
53413
53481
|
}
|
|
53414
53482
|
function teardown() {
|
|
53415
|
-
_.each(conversations,
|
|
53483
|
+
_.each(conversations, conversation => conversation.teardown());
|
|
53416
53484
|
conversations = [];
|
|
53417
53485
|
agentsCache.clear();
|
|
53418
53486
|
}
|