@pendo/agent 2.333.0 → 2.333.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dom.esm.js +1 -1
- package/dist/pendo.module.js +745 -692
- package/dist/pendo.module.min.js +102 -4
- package/dist/servers.json +7 -7
- package/package.json +1 -1
package/dist/pendo.module.js
CHANGED
|
@@ -4028,8 +4028,8 @@ let SERVER = '';
|
|
|
4028
4028
|
let ASSET_HOST = '';
|
|
4029
4029
|
let ASSET_PATH = '';
|
|
4030
4030
|
let DESIGNER_SERVER = '';
|
|
4031
|
-
let VERSION = '2.333.
|
|
4032
|
-
let PACKAGE_VERSION = '2.333.
|
|
4031
|
+
let VERSION = '2.333.1_';
|
|
4032
|
+
let PACKAGE_VERSION = '2.333.1';
|
|
4033
4033
|
let LOADER = 'xhr';
|
|
4034
4034
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
4035
4035
|
/**
|
|
@@ -23217,7 +23217,7 @@ function autofocusRuntimeScript(step, guide, pendo) {
|
|
|
23217
23217
|
if (pendo._.get(step, 'attributes.isAutoFocus')) {
|
|
23218
23218
|
BuildingBlockGuides.autofocusStep(step, guideContainer);
|
|
23219
23219
|
BuildingBlockGuides.trapFocusStep(step, guideContainer);
|
|
23220
|
-
step.hiddenElements = BuildingBlockGuides.
|
|
23220
|
+
step.hiddenElements = BuildingBlockGuides.addAriaHiddenOutsideGuide(step.guideElement[0]);
|
|
23221
23221
|
}
|
|
23222
23222
|
if (isGuideRCType(guide)) {
|
|
23223
23223
|
BuildingBlockGuides.attachRCFocusHandlers();
|
|
@@ -29559,7 +29559,7 @@ var BuildingBlockGuides = (function () {
|
|
|
29559
29559
|
autofocusStep,
|
|
29560
29560
|
trapFocusStep,
|
|
29561
29561
|
attachRCFocusHandlers,
|
|
29562
|
-
|
|
29562
|
+
addAriaHiddenOutsideGuide,
|
|
29563
29563
|
renderResourceCenterModule: BuildingBlockResourceCenter.renderResourceCenterModule,
|
|
29564
29564
|
buildNodeFromJSON,
|
|
29565
29565
|
attachImgLoadHandlers,
|
|
@@ -30145,22 +30145,21 @@ var BuildingBlockGuides = (function () {
|
|
|
30145
30145
|
domElem.append(endFocusBumper);
|
|
30146
30146
|
return [startFocusBumper, endFocusBumper];
|
|
30147
30147
|
}
|
|
30148
|
-
function
|
|
30148
|
+
function addAriaHiddenOutsideGuide(elem, hidden = []) {
|
|
30149
30149
|
if (!elem || elem === getBody())
|
|
30150
30150
|
return hidden;
|
|
30151
|
-
const supportsInert = isNaN(msie);
|
|
30152
|
-
const disableAttribute = supportsInert ? 'inert' : 'aria-hidden';
|
|
30153
30151
|
const siblings = getSiblings(elem);
|
|
30154
30152
|
_.each(siblings, (s) => {
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
|
|
30153
|
+
if (hidden.indexOf(s) === -1 && s.getAttribute('aria-hidden') !== 'true') {
|
|
30154
|
+
const tagName = s.tagName.toLowerCase();
|
|
30155
|
+
if (tagName !== 'script' && tagName !== 'style') {
|
|
30156
|
+
s.setAttribute('aria-hidden', 'true');
|
|
30157
|
+
hidden.push(s);
|
|
30158
|
+
}
|
|
30160
30159
|
}
|
|
30161
30160
|
});
|
|
30162
30161
|
if (elem.parentNode) {
|
|
30163
|
-
|
|
30162
|
+
addAriaHiddenOutsideGuide(elem.parentNode, hidden);
|
|
30164
30163
|
}
|
|
30165
30164
|
return hidden;
|
|
30166
30165
|
}
|
|
@@ -32966,11 +32965,10 @@ function GuideStep(guide) {
|
|
|
32966
32965
|
try {
|
|
32967
32966
|
if (el && typeof el.removeAttribute === 'function') {
|
|
32968
32967
|
el.removeAttribute('aria-hidden');
|
|
32969
|
-
el.removeAttribute('inert');
|
|
32970
32968
|
}
|
|
32971
32969
|
}
|
|
32972
32970
|
catch (e) {
|
|
32973
|
-
log.error('unable to remove
|
|
32971
|
+
log.error('unable to remove aria-hidden from element', { error: e });
|
|
32974
32972
|
}
|
|
32975
32973
|
});
|
|
32976
32974
|
this.hiddenElements.length = 0;
|
|
@@ -41674,20 +41672,20 @@ function getZoneSafeMethod(_, method, target) {
|
|
|
41674
41672
|
}
|
|
41675
41673
|
|
|
41676
41674
|
// Does not support submit and go to
|
|
41677
|
-
|
|
41678
|
-
|
|
41675
|
+
const goToRegex = new RegExp(guideMarkdownUtil.goToString);
|
|
41676
|
+
const PollBranching = {
|
|
41679
41677
|
name: 'PollBranching',
|
|
41680
|
-
script
|
|
41681
|
-
|
|
41682
|
-
|
|
41678
|
+
script(step, guide, pendo) {
|
|
41679
|
+
let isAdvanceIntercepted = false;
|
|
41680
|
+
const branchingQuestions = initialBranchingSetup(step, pendo);
|
|
41683
41681
|
if (branchingQuestions) {
|
|
41684
41682
|
// If there are too many branching questions saved, exit and run the guide normally.
|
|
41685
41683
|
if (pendo._.size(branchingQuestions) > 1)
|
|
41686
41684
|
return;
|
|
41687
|
-
this.on('beforeAdvance',
|
|
41688
|
-
|
|
41689
|
-
|
|
41690
|
-
|
|
41685
|
+
this.on('beforeAdvance', (evt) => {
|
|
41686
|
+
const noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
|
|
41687
|
+
const responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
|
|
41688
|
+
let noGotoLabel;
|
|
41691
41689
|
if (responseLabel) {
|
|
41692
41690
|
noGotoLabel = pendo._.isNull(responseLabel.getAttribute('goToStep'));
|
|
41693
41691
|
}
|
|
@@ -41698,58 +41696,58 @@ var PollBranching = {
|
|
|
41698
41696
|
});
|
|
41699
41697
|
}
|
|
41700
41698
|
},
|
|
41701
|
-
test
|
|
41699
|
+
test(step, guide, pendo) {
|
|
41702
41700
|
var _a;
|
|
41703
|
-
|
|
41701
|
+
let branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41704
41702
|
return !pendo._.isUndefined(branchingQuestions) && pendo._.size(branchingQuestions);
|
|
41705
41703
|
},
|
|
41706
|
-
designerListener
|
|
41707
|
-
|
|
41708
|
-
|
|
41704
|
+
designerListener(pendo) {
|
|
41705
|
+
const target = pendo.dom.getBody();
|
|
41706
|
+
const config = {
|
|
41709
41707
|
attributeFilter: ['data-layout'],
|
|
41710
41708
|
attributes: true,
|
|
41711
41709
|
childList: true,
|
|
41712
41710
|
characterData: true,
|
|
41713
41711
|
subtree: true
|
|
41714
41712
|
};
|
|
41715
|
-
|
|
41716
|
-
|
|
41713
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41714
|
+
const observer = new MutationObserver(applyBranchingIndicators);
|
|
41717
41715
|
observer.observe(target, config);
|
|
41718
41716
|
function applyBranchingIndicators(mutations) {
|
|
41719
41717
|
pendo._.each(mutations, function (mutation) {
|
|
41720
41718
|
var _a;
|
|
41721
|
-
|
|
41719
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
|
|
41722
41720
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41723
41721
|
if (mutation.addedNodes[0].querySelector('._pendo-multi-choice-poll-select-border')) {
|
|
41724
41722
|
if (pendo._.size(pendo.dom('._pendo-multi-choice-poll-question:contains("{branching/}")'))) {
|
|
41725
41723
|
pendo
|
|
41726
41724
|
.dom('._pendo-multi-choice-poll-question:contains("{branching/}")')
|
|
41727
|
-
.each(
|
|
41728
|
-
pendo._.each(pendo.dom(
|
|
41725
|
+
.each((question, index) => {
|
|
41726
|
+
pendo._.each(pendo.dom(`#${question.id} *`), (element) => {
|
|
41729
41727
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41730
41728
|
});
|
|
41731
41729
|
pendo
|
|
41732
|
-
.dom(
|
|
41730
|
+
.dom(`#${question.id} p`)
|
|
41733
41731
|
.css({ display: 'inline-block !important' })
|
|
41734
41732
|
.append(branchingIcon('#999', '20px'))
|
|
41735
41733
|
.attr({ title: 'Custom Branching Added' });
|
|
41736
|
-
|
|
41737
|
-
if (pendo.dom(
|
|
41734
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41735
|
+
if (pendo.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]) {
|
|
41738
41736
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41739
41737
|
pendo
|
|
41740
|
-
.dom(
|
|
41738
|
+
.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]
|
|
41741
41739
|
.textContent.trim();
|
|
41742
41740
|
}
|
|
41743
|
-
|
|
41741
|
+
let pollLabels = pendo.dom(`label[for*=${dataPendoPollId}]`);
|
|
41744
41742
|
if (pendo._.size(pollLabels)) {
|
|
41745
|
-
pendo._.forEach(pollLabels,
|
|
41743
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41746
41744
|
if (goToRegex.test(label.textContent)) {
|
|
41747
|
-
|
|
41745
|
+
let labelTitle = goToRegex.exec(label.textContent)[2];
|
|
41748
41746
|
guideMarkdownUtil.removeMarkdownSyntax(label, goToRegex, '', pendo);
|
|
41749
41747
|
pendo
|
|
41750
41748
|
.dom(label)
|
|
41751
41749
|
.append(branchingIcon('#999', '14px'))
|
|
41752
|
-
.attr({ title:
|
|
41750
|
+
.attr({ title: `Branching to step ${labelTitle}` });
|
|
41753
41751
|
}
|
|
41754
41752
|
});
|
|
41755
41753
|
}
|
|
@@ -41757,9 +41755,9 @@ var PollBranching = {
|
|
|
41757
41755
|
pendo
|
|
41758
41756
|
.dom(question)
|
|
41759
41757
|
.append(branchingErrorHTML(question.dataset.pendoPollId));
|
|
41760
|
-
pendo.dom(
|
|
41758
|
+
pendo.dom(`#${question.id} #pendo-ps-branching-svg`).remove();
|
|
41761
41759
|
pendo
|
|
41762
|
-
.dom(
|
|
41760
|
+
.dom(`#${question.id} p`)
|
|
41763
41761
|
.css({ display: 'inline-block !important' })
|
|
41764
41762
|
.append(branchingIcon('red', '20px'))
|
|
41765
41763
|
.attr({ title: 'Unsupported Branching configuration' });
|
|
@@ -41771,31 +41769,49 @@ var PollBranching = {
|
|
|
41771
41769
|
});
|
|
41772
41770
|
}
|
|
41773
41771
|
function branchingErrorHTML(dataPendoPollId) {
|
|
41774
|
-
return
|
|
41772
|
+
return `<div style="text-align:lrft; font-size: 14px; color: red;
|
|
41773
|
+
font-style: italic; margin-top: 0px;" class="branching-wrapper"
|
|
41774
|
+
name="${dataPendoPollId}">
|
|
41775
|
+
* Branching Error: Multiple branching polls not supported</div>`;
|
|
41775
41776
|
}
|
|
41776
41777
|
function branchingIcon(color, size) {
|
|
41777
|
-
return
|
|
41778
|
+
return `<svg id="pendo-ps-branching-svg" viewBox="0 0 24 24" fill="none"
|
|
41779
|
+
style="margin-left: 5px;
|
|
41780
|
+
height:${size}; width:${size}; display:inline; vertical-align:middle;" xmlns="http://www.w3.org/2000/svg">
|
|
41781
|
+
<g stroke-width="0"></g>
|
|
41782
|
+
<g stroke-linecap="round" stroke-linejoin="round"></g>
|
|
41783
|
+
<g> <circle cx="4" cy="7" r="2" stroke="${color}"
|
|
41784
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41785
|
+
<circle cx="20" cy="7" r="2" stroke="${color}"
|
|
41786
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41787
|
+
<circle cx="20" cy="17" r="2" stroke="${color}" stroke-width="2"
|
|
41788
|
+
stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41789
|
+
<path d="M18 7H6" stroke="${color}" stroke-width="2"
|
|
41790
|
+
stroke-linecap="round" stroke-linejoin="round"></path>
|
|
41791
|
+
<path d="M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18"
|
|
41792
|
+
stroke="${color}" stroke-width="2" stroke-linecap="round"
|
|
41793
|
+
stroke-linejoin="round"></path> </g></svg>`;
|
|
41778
41794
|
}
|
|
41779
41795
|
}
|
|
41780
41796
|
};
|
|
41781
41797
|
function initialBranchingSetup(step, pendo) {
|
|
41782
|
-
|
|
41783
|
-
pendo._.forEach(questions,
|
|
41784
|
-
|
|
41785
|
-
pendo._.each(step.guideElement.find(
|
|
41798
|
+
const questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41799
|
+
pendo._.forEach(questions, (question) => {
|
|
41800
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41801
|
+
pendo._.each(step.guideElement.find(`#${question.id} *`), (element) => {
|
|
41786
41802
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41787
41803
|
});
|
|
41788
|
-
|
|
41789
|
-
pendo._.forEach(pollLabels,
|
|
41804
|
+
let pollLabels = step.guideElement.find(`label[for*=${dataPendoPollId}]`);
|
|
41805
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41790
41806
|
if (pendo._.isNull(goToRegex.exec(label.textContent))) {
|
|
41791
41807
|
return;
|
|
41792
41808
|
}
|
|
41793
|
-
|
|
41794
|
-
|
|
41809
|
+
let gotoSubstring = goToRegex.exec(label.textContent)[1];
|
|
41810
|
+
let gotoIndex = goToRegex.exec(label.textContent)[2];
|
|
41795
41811
|
label.setAttribute('goToStep', gotoIndex);
|
|
41796
41812
|
guideMarkdownUtil.removeMarkdownSyntax(label, gotoSubstring, '', pendo);
|
|
41797
41813
|
});
|
|
41798
|
-
|
|
41814
|
+
let pollChoiceContainer = step.guideElement.find(`[data-pendo-poll-id=${dataPendoPollId}]._pendo-multi-choice-poll-select-border`);
|
|
41799
41815
|
if (pollChoiceContainer && pollChoiceContainer.length) {
|
|
41800
41816
|
pollChoiceContainer[0].setAttribute('branching', '');
|
|
41801
41817
|
}
|
|
@@ -41804,15 +41820,15 @@ function initialBranchingSetup(step, pendo) {
|
|
|
41804
41820
|
}
|
|
41805
41821
|
function branchingGoToStep(event, step, guide, pendo) {
|
|
41806
41822
|
var _a;
|
|
41807
|
-
|
|
41808
|
-
|
|
41809
|
-
|
|
41810
|
-
|
|
41823
|
+
let checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
41824
|
+
let checkedPollLabel = step.guideElement.find(`label[for="${checkedPollInputId}"]`)[0];
|
|
41825
|
+
let checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
|
|
41826
|
+
let pollStepIndex = checkedPollLabelStepIndex - 1;
|
|
41811
41827
|
if (pollStepIndex < 0)
|
|
41812
41828
|
return;
|
|
41813
|
-
|
|
41829
|
+
const destinationObject = {
|
|
41814
41830
|
destinationStepId: guide.steps[pollStepIndex].id,
|
|
41815
|
-
step
|
|
41831
|
+
step
|
|
41816
41832
|
};
|
|
41817
41833
|
pendo.goToStep(destinationObject);
|
|
41818
41834
|
event.cancel = true;
|
|
@@ -41833,10 +41849,10 @@ function encodeMetadataForUrl(value, urlBeforePlaceholder) {
|
|
|
41833
41849
|
return window.encodeURI(str);
|
|
41834
41850
|
}
|
|
41835
41851
|
|
|
41836
|
-
|
|
41852
|
+
const MetadataSubstitution = {
|
|
41837
41853
|
name: 'MetadataSubstitution',
|
|
41838
|
-
script
|
|
41839
|
-
|
|
41854
|
+
script(step, guide, pendo) {
|
|
41855
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41840
41856
|
if (step.domJson) {
|
|
41841
41857
|
findSubstitutableUrlsInJson(step.domJson, placeholderData, pendo);
|
|
41842
41858
|
}
|
|
@@ -41844,22 +41860,22 @@ var MetadataSubstitution = {
|
|
|
41844
41860
|
pendo._.each(placeholderData, function (placeholder) {
|
|
41845
41861
|
processPlaceholder(placeholder, pendo);
|
|
41846
41862
|
});
|
|
41847
|
-
|
|
41848
|
-
|
|
41849
|
-
updateGuideContainer(containerId,
|
|
41863
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41864
|
+
const context = step.guideElement;
|
|
41865
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41850
41866
|
}
|
|
41851
41867
|
},
|
|
41852
|
-
designerListener
|
|
41853
|
-
|
|
41868
|
+
designerListener(pendo) {
|
|
41869
|
+
const target = pendo.dom.getBody();
|
|
41854
41870
|
if (pendo.designerv2) {
|
|
41855
41871
|
pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
|
|
41856
41872
|
var _a;
|
|
41857
41873
|
if (!document.querySelector(guideMarkdownUtil.containerSelector))
|
|
41858
41874
|
return;
|
|
41859
|
-
|
|
41875
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41860
41876
|
if (!step)
|
|
41861
41877
|
return;
|
|
41862
|
-
|
|
41878
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41863
41879
|
if (step.buildingBlocks) {
|
|
41864
41880
|
findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
|
|
41865
41881
|
}
|
|
@@ -41869,32 +41885,32 @@ var MetadataSubstitution = {
|
|
|
41869
41885
|
return;
|
|
41870
41886
|
processPlaceholder(placeholder, pendo);
|
|
41871
41887
|
});
|
|
41872
|
-
|
|
41873
|
-
|
|
41874
|
-
updateGuideContainer(containerId,
|
|
41888
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41889
|
+
const context = step.guideElement;
|
|
41890
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41875
41891
|
}
|
|
41876
41892
|
};
|
|
41877
41893
|
}
|
|
41878
|
-
|
|
41894
|
+
const config = {
|
|
41879
41895
|
attributeFilter: ['data-layout'],
|
|
41880
41896
|
attributes: true,
|
|
41881
41897
|
childList: true,
|
|
41882
41898
|
characterData: true,
|
|
41883
41899
|
subtree: true
|
|
41884
41900
|
};
|
|
41885
|
-
|
|
41886
|
-
|
|
41901
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41902
|
+
const observer = new MutationObserver(applySubstitutionIndicators);
|
|
41887
41903
|
observer.observe(target, config);
|
|
41888
41904
|
function applySubstitutionIndicators(mutations) {
|
|
41889
41905
|
pendo._.each(mutations, function (mutation) {
|
|
41890
41906
|
var _a;
|
|
41891
41907
|
if (mutation.addedNodes.length) {
|
|
41892
41908
|
if (document.querySelector(guideMarkdownUtil.containerSelector)) {
|
|
41893
|
-
|
|
41894
|
-
|
|
41909
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41910
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41895
41911
|
if (!step)
|
|
41896
41912
|
return;
|
|
41897
|
-
|
|
41913
|
+
const pendoBlocks = step.buildingBlocks;
|
|
41898
41914
|
if (!pendo._.isUndefined(pendoBlocks)) {
|
|
41899
41915
|
findSubstitutableUrlsInJson(pendoBlocks, placeholderData, pendo);
|
|
41900
41916
|
}
|
|
@@ -41904,9 +41920,9 @@ var MetadataSubstitution = {
|
|
|
41904
41920
|
return;
|
|
41905
41921
|
processPlaceholder(placeholder, pendo);
|
|
41906
41922
|
});
|
|
41907
|
-
|
|
41908
|
-
|
|
41909
|
-
updateGuideContainer(containerId,
|
|
41923
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41924
|
+
const context = step.guideElement;
|
|
41925
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41910
41926
|
}
|
|
41911
41927
|
}
|
|
41912
41928
|
}
|
|
@@ -41915,18 +41931,18 @@ var MetadataSubstitution = {
|
|
|
41915
41931
|
}
|
|
41916
41932
|
};
|
|
41917
41933
|
function processPlaceholder(placeholder, pendo) {
|
|
41918
|
-
|
|
41919
|
-
|
|
41920
|
-
|
|
41934
|
+
let match;
|
|
41935
|
+
const { data, target } = placeholder;
|
|
41936
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41921
41937
|
while ((match = matchPlaceholder(placeholder, subRegex))) {
|
|
41922
|
-
|
|
41923
|
-
|
|
41938
|
+
const usedArrayPath = Array.isArray(match) && match.length >= 2;
|
|
41939
|
+
const currentStr = target === 'textContent'
|
|
41924
41940
|
? data[target]
|
|
41925
41941
|
: decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
|
|
41926
|
-
|
|
41942
|
+
const matched = usedArrayPath ? match : subRegex.exec(currentStr);
|
|
41927
41943
|
if (!matched)
|
|
41928
41944
|
continue;
|
|
41929
|
-
|
|
41945
|
+
const mdValue = getSubstituteValue(matched, pendo);
|
|
41930
41946
|
substituteMetadataByTarget(data, target, mdValue, matched);
|
|
41931
41947
|
}
|
|
41932
41948
|
}
|
|
@@ -41935,50 +41951,50 @@ function matchPlaceholder(placeholder, regex) {
|
|
|
41935
41951
|
return placeholder.data[placeholder.target].match(regex);
|
|
41936
41952
|
}
|
|
41937
41953
|
else {
|
|
41938
|
-
|
|
41954
|
+
const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
|
|
41939
41955
|
? (placeholder.data.getAttribute(placeholder.target) || '')
|
|
41940
41956
|
: placeholder.data[placeholder.target];
|
|
41941
41957
|
return decodeURI(raw).match(regex);
|
|
41942
41958
|
}
|
|
41943
41959
|
}
|
|
41944
41960
|
function getMetadataValueCaseInsensitive(metadata, type, property) {
|
|
41945
|
-
|
|
41961
|
+
const kind = metadata && metadata[type];
|
|
41946
41962
|
if (!kind || typeof kind !== 'object')
|
|
41947
41963
|
return undefined;
|
|
41948
|
-
|
|
41964
|
+
const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
|
|
41949
41965
|
if (direct !== undefined) {
|
|
41950
41966
|
return direct;
|
|
41951
41967
|
}
|
|
41952
|
-
|
|
41953
|
-
|
|
41954
|
-
|
|
41968
|
+
const propLower = property.toLowerCase();
|
|
41969
|
+
const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
|
|
41970
|
+
const value = key !== undefined ? kind[key] : undefined;
|
|
41955
41971
|
return value;
|
|
41956
41972
|
}
|
|
41957
41973
|
function getSubstituteValue(match, pendo) {
|
|
41958
41974
|
if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
|
|
41959
41975
|
return;
|
|
41960
41976
|
}
|
|
41961
|
-
|
|
41962
|
-
|
|
41963
|
-
|
|
41977
|
+
let type = match[1];
|
|
41978
|
+
let property = match[2];
|
|
41979
|
+
let defaultValue = match[3];
|
|
41964
41980
|
if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
|
|
41965
41981
|
return;
|
|
41966
41982
|
}
|
|
41967
|
-
|
|
41968
|
-
|
|
41983
|
+
const metadata = pendo.getSerializedMetadata();
|
|
41984
|
+
let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
|
|
41969
41985
|
if (mdValue === undefined || mdValue === null)
|
|
41970
41986
|
mdValue = defaultValue || '';
|
|
41971
41987
|
return mdValue;
|
|
41972
41988
|
}
|
|
41973
41989
|
function substituteMetadataByTarget(data, target, mdValue, matched) {
|
|
41974
|
-
|
|
41975
|
-
|
|
41990
|
+
const isElement = data && typeof data.getAttribute === 'function';
|
|
41991
|
+
const current = (target === 'href' || target === 'value') && isElement
|
|
41976
41992
|
? (data.getAttribute(target) || '')
|
|
41977
41993
|
: data[target];
|
|
41978
41994
|
if (target === 'href' || target === 'value') {
|
|
41979
|
-
|
|
41980
|
-
|
|
41981
|
-
|
|
41995
|
+
const decodedUrl = decodeURI(current);
|
|
41996
|
+
const urlBeforePlaceholder = decodedUrl.slice(0, decodedUrl.indexOf(matched[0]));
|
|
41997
|
+
const safeValue = encodeMetadataForUrl(mdValue, urlBeforePlaceholder);
|
|
41982
41998
|
data[target] = decodedUrl.replace(matched[0], safeValue);
|
|
41983
41999
|
}
|
|
41984
42000
|
else {
|
|
@@ -41992,9 +42008,8 @@ function updateGuideContainer(containerId, context, pendo) {
|
|
|
41992
42008
|
pendo.flexElement(pendo.dom(guideMarkdownUtil.containerSelector));
|
|
41993
42009
|
pendo.BuildingBlocks.BuildingBlockGuides.recalculateGuideHeight(containerId, context);
|
|
41994
42010
|
}
|
|
41995
|
-
function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
41996
|
-
|
|
41997
|
-
var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
42011
|
+
function findSubstitutableUrlsInJson(originalData, placeholderData = [], pendo) {
|
|
42012
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41998
42013
|
if ((originalData.name === 'url' || originalData.name === 'href') && originalData.value) {
|
|
41999
42014
|
if (subRegex.test(originalData.value)) {
|
|
42000
42015
|
placeholderData.push({
|
|
@@ -42004,37 +42019,37 @@ function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
|
42004
42019
|
}
|
|
42005
42020
|
}
|
|
42006
42021
|
if (originalData.properties && originalData.id === 'href_link_block') {
|
|
42007
|
-
pendo._.each(originalData.properties,
|
|
42022
|
+
pendo._.each(originalData.properties, (prop) => {
|
|
42008
42023
|
findSubstitutableUrlsInJson(prop, placeholderData, pendo);
|
|
42009
42024
|
});
|
|
42010
42025
|
}
|
|
42011
42026
|
if (originalData.views) {
|
|
42012
|
-
pendo._.each(originalData.views,
|
|
42027
|
+
pendo._.each(originalData.views, (view) => {
|
|
42013
42028
|
findSubstitutableUrlsInJson(view, placeholderData, pendo);
|
|
42014
42029
|
});
|
|
42015
42030
|
}
|
|
42016
42031
|
if (originalData.parameters) {
|
|
42017
|
-
pendo._.each(originalData.parameters,
|
|
42032
|
+
pendo._.each(originalData.parameters, (param) => {
|
|
42018
42033
|
findSubstitutableUrlsInJson(param, placeholderData, pendo);
|
|
42019
42034
|
});
|
|
42020
42035
|
}
|
|
42021
42036
|
if (originalData.actions) {
|
|
42022
|
-
pendo._.each(originalData.actions,
|
|
42037
|
+
pendo._.each(originalData.actions, (action) => {
|
|
42023
42038
|
findSubstitutableUrlsInJson(action, placeholderData, pendo);
|
|
42024
42039
|
});
|
|
42025
42040
|
}
|
|
42026
42041
|
if (originalData.children) {
|
|
42027
|
-
pendo._.each(originalData.children,
|
|
42042
|
+
pendo._.each(originalData.children, (child) => {
|
|
42028
42043
|
findSubstitutableUrlsInJson(child, placeholderData, pendo);
|
|
42029
42044
|
});
|
|
42030
42045
|
}
|
|
42031
42046
|
return placeholderData;
|
|
42032
42047
|
}
|
|
42033
42048
|
function findSubstitutableElements(pendo) {
|
|
42034
|
-
|
|
42049
|
+
let elements = pendo.dom(`${guideMarkdownUtil.containerSelector} *:not(.pendo-inline-ui)`);
|
|
42035
42050
|
return pendo._.chain(elements)
|
|
42036
42051
|
.filter(function (placeholder) {
|
|
42037
|
-
|
|
42052
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
42038
42053
|
if (placeholder.localName === 'a') {
|
|
42039
42054
|
return subRegex.test(decodeURI(placeholder.href)) || subRegex.test(placeholder.textContent);
|
|
42040
42055
|
}
|
|
@@ -42090,25 +42105,51 @@ function findSubstitutableElements(pendo) {
|
|
|
42090
42105
|
.value();
|
|
42091
42106
|
}
|
|
42092
42107
|
function substitutionIcon(color, size) {
|
|
42093
|
-
return (
|
|
42094
|
-
|
|
42095
|
-
|
|
42096
|
-
|
|
42097
|
-
|
|
42098
|
-
|
|
42108
|
+
return (`<div title="Metadata Substitution added">
|
|
42109
|
+
<svg id="pendo-ps-substitution-icon" viewBox="0 0 24 24"
|
|
42110
|
+
preserveAspectRatio="xMidYMid meet"
|
|
42111
|
+
height=${size} width=${size} title="Metadata Substitution"
|
|
42112
|
+
style="bottom:5px; right:10px; position: absolute;"
|
|
42113
|
+
fill="none" xmlns="http://www.w3.org/2000/svg" stroke="${color}"
|
|
42114
|
+
transform="matrix(1, 0, 0, 1, 0, 0)rotate(0)">
|
|
42115
|
+
<g stroke-width="0"></g>
|
|
42116
|
+
<g stroke-linecap="round" stroke-linejoin="round"
|
|
42117
|
+
stroke="${color}" stroke-width="0.528"></g>
|
|
42118
|
+
<g><path fill-rule="evenodd" clip-rule="evenodd"
|
|
42119
|
+
d="M5 5.5C4.17157 5.5 3.5 6.17157 3.5 7V10C3.5 10.8284
|
|
42120
|
+
4.17157 11.5 5 11.5H8C8.82843 11.5 9.5 10.8284 9.5
|
|
42121
|
+
10V9H17V11C17 11.2761 17.2239 11.5 17.5 11.5C17.7761
|
|
42122
|
+
11.5 18 11.2761 18 11V8.5C18 8.22386 17.7761 8 17.5
|
|
42123
|
+
8H9.5V7C9.5 6.17157 8.82843 5.5 8 5.5H5ZM8.5 7C8.5
|
|
42124
|
+
6.72386 8.27614 6.5 8 6.5H5C4.72386 6.5 4.5 6.72386
|
|
42125
|
+
4.5 7V10C4.5 10.2761 4.72386 10.5 5 10.5H8C8.27614
|
|
42126
|
+
10.5 8.5 10.2761 8.5 10V7Z" fill="${color}"></path>
|
|
42127
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
42128
|
+
d="M7 13C7 12.7239 6.77614 12.5 6.5 12.5C6.22386 12.5
|
|
42129
|
+
6 12.7239 6 13V15.5C6 15.7761 6.22386 16 6.5
|
|
42130
|
+
16H14.5V17C14.5 17.8284 15.1716 18.5 16 18.5H19C19.8284
|
|
42131
|
+
18.5 20.5 17.8284 20.5 17V14C20.5 13.1716 19.8284 12.5
|
|
42132
|
+
19 12.5H16C15.1716 12.5 14.5 13.1716 14.5
|
|
42133
|
+
14V15H7V13ZM15.5 17C15.5 17.2761 15.7239 17.5 16
|
|
42134
|
+
17.5H19C19.2761 17.5 19.5 17.2761 19.5 17V14C19.5
|
|
42135
|
+
13.7239 19.2761 13.5 19 13.5H16C15.7239 13.5 15.5
|
|
42136
|
+
13.7239 15.5 14V17Z" fill="${color}"></path> </g></svg></div>`);
|
|
42137
|
+
}
|
|
42138
|
+
|
|
42139
|
+
const requiredElement = '<span class="_pendo-required-indicator" style="color:red; font-style:italic;" title="Question is required"> *</span>';
|
|
42140
|
+
const requiredSyntax = '{required/}';
|
|
42141
|
+
const RequiredQuestions = {
|
|
42099
42142
|
name: 'RequiredQuestions',
|
|
42100
|
-
script
|
|
42143
|
+
script(step, guide, pendo) {
|
|
42101
42144
|
var _a;
|
|
42102
|
-
|
|
42103
|
-
|
|
42104
|
-
|
|
42105
|
-
});
|
|
42106
|
-
var requiredQuestions = processRequiredQuestions();
|
|
42145
|
+
let requiredPollIds = [];
|
|
42146
|
+
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'));
|
|
42147
|
+
const requiredQuestions = processRequiredQuestions();
|
|
42107
42148
|
if (requiredQuestions) {
|
|
42108
|
-
pendo._.forEach(requiredQuestions,
|
|
42149
|
+
pendo._.forEach(requiredQuestions, (question) => {
|
|
42109
42150
|
if (question.classList.contains('_pendo-open-text-poll-question')) {
|
|
42110
|
-
|
|
42111
|
-
step.attachEvent(step.guideElement.find(
|
|
42151
|
+
let pollId = question.dataset.pendoPollId;
|
|
42152
|
+
step.attachEvent(step.guideElement.find(`[data-pendo-poll-id=${pollId}]._pendo-open-text-poll-input`)[0], 'input', function () {
|
|
42112
42153
|
evaluateRequiredQuestions(requiredQuestions);
|
|
42113
42154
|
});
|
|
42114
42155
|
}
|
|
@@ -42120,13 +42161,11 @@ var RequiredQuestions = {
|
|
|
42120
42161
|
});
|
|
42121
42162
|
}
|
|
42122
42163
|
function getEligibleQuestions() {
|
|
42123
|
-
|
|
42124
|
-
|
|
42125
|
-
|
|
42126
|
-
|
|
42127
|
-
|
|
42128
|
-
var allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
42129
|
-
return pendo._.reduce(allQuestions, function (eligibleQuestions, question) {
|
|
42164
|
+
const pollQuestions = pendo._.toArray(step.guideElement.find(`[class*=-poll-question]:contains(${requiredSyntax})`));
|
|
42165
|
+
const surveyMatches = pendo._.toArray(step.guideElement.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`));
|
|
42166
|
+
const surveyQuestions = pendo._.filter(surveyMatches, (candidate) => !pendo._.some(surveyMatches, (other) => other !== candidate && candidate.contains(other)));
|
|
42167
|
+
const allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
42168
|
+
return pendo._.reduce(allQuestions, (eligibleQuestions, question) => {
|
|
42130
42169
|
if (question.classList.contains('_pendo-yes-no-poll-question'))
|
|
42131
42170
|
return eligibleQuestions;
|
|
42132
42171
|
eligibleQuestions.push(question);
|
|
@@ -42134,24 +42173,22 @@ var RequiredQuestions = {
|
|
|
42134
42173
|
}, []);
|
|
42135
42174
|
}
|
|
42136
42175
|
function ownsRequiredText(element) {
|
|
42137
|
-
return pendo._.some(element.childNodes,
|
|
42138
|
-
return node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1;
|
|
42139
|
-
});
|
|
42176
|
+
return pendo._.some(element.childNodes, (node) => node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1);
|
|
42140
42177
|
}
|
|
42141
42178
|
function processRequiredQuestions() {
|
|
42142
|
-
|
|
42179
|
+
let questions = getEligibleQuestions();
|
|
42143
42180
|
if (questions) {
|
|
42144
|
-
pendo._.forEach(questions,
|
|
42145
|
-
|
|
42181
|
+
pendo._.forEach(questions, question => {
|
|
42182
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
42146
42183
|
requiredPollIds.push(dataPendoPollId);
|
|
42147
|
-
|
|
42148
|
-
|
|
42149
|
-
pendo._.each(candidates,
|
|
42184
|
+
const candidates = step.guideElement.find(`#${question.id} *, #${question.id}`);
|
|
42185
|
+
const textHost = pendo._.find(candidates, ownsRequiredText) || question;
|
|
42186
|
+
pendo._.each(candidates, (element) => {
|
|
42150
42187
|
guideMarkdownUtil.removeMarkdownSyntax(element, requiredSyntax, '', pendo);
|
|
42151
42188
|
});
|
|
42152
|
-
|
|
42189
|
+
const textHostEl = pendo.dom(textHost);
|
|
42153
42190
|
if (textHostEl.find('._pendo-required-indicator').length === 0) {
|
|
42154
|
-
|
|
42191
|
+
const questionParagraph = textHostEl.find('p');
|
|
42155
42192
|
if (questionParagraph && questionParagraph.length) {
|
|
42156
42193
|
pendo.dom(questionParagraph[0]).append(requiredElement);
|
|
42157
42194
|
}
|
|
@@ -42162,7 +42199,15 @@ var RequiredQuestions = {
|
|
|
42162
42199
|
});
|
|
42163
42200
|
}
|
|
42164
42201
|
if (pendo._.size(requiredPollIds)) {
|
|
42165
|
-
|
|
42202
|
+
const disabledButtonStyles = `<style type=text/css
|
|
42203
|
+
id=_pendo-guide-required-disabled>
|
|
42204
|
+
._pendo-button:disabled, ._pendo-buttons[disabled] {
|
|
42205
|
+
border: 1px solid #999999 !important;
|
|
42206
|
+
background-color: #cccccc !important;
|
|
42207
|
+
color: #666666 !important;
|
|
42208
|
+
pointer-events: none !important;
|
|
42209
|
+
}
|
|
42210
|
+
</style>`;
|
|
42166
42211
|
if (pendo.dom('#_pendo-guide-required-disabled').length === 0) {
|
|
42167
42212
|
pendo.dom('head').append(disabledButtonStyles);
|
|
42168
42213
|
}
|
|
@@ -42173,11 +42218,15 @@ var RequiredQuestions = {
|
|
|
42173
42218
|
function evaluateRequiredQuestions(questions) {
|
|
42174
42219
|
if (questions.length === 0)
|
|
42175
42220
|
return;
|
|
42176
|
-
|
|
42177
|
-
|
|
42178
|
-
responses = responses.concat(pendo._.map(questions,
|
|
42179
|
-
|
|
42180
|
-
|
|
42221
|
+
let allRequiredComplete = true;
|
|
42222
|
+
let responses = [];
|
|
42223
|
+
responses = responses.concat(pendo._.map(questions, (question) => {
|
|
42224
|
+
let pollId = question.getAttribute('data-pendo-poll-id');
|
|
42225
|
+
let input = step.guideElement.find(`
|
|
42226
|
+
[data-pendo-poll-id=${pollId}] textarea,
|
|
42227
|
+
[data-pendo-poll-id=${pollId}] input:text,
|
|
42228
|
+
[data-pendo-poll-id=${pollId}] select,
|
|
42229
|
+
[data-pendo-poll-id=${pollId}] input:radio:checked`);
|
|
42181
42230
|
if (input && input.length && input[0].value) {
|
|
42182
42231
|
return input[0].value;
|
|
42183
42232
|
}
|
|
@@ -42194,50 +42243,50 @@ var RequiredQuestions = {
|
|
|
42194
42243
|
}
|
|
42195
42244
|
function disableEligibleButtons(buttons) {
|
|
42196
42245
|
pendo._.each(buttons, function (button) {
|
|
42197
|
-
if (step.guideElement.find(
|
|
42198
|
-
step.guideElement.find(
|
|
42199
|
-
step.guideElement.find(
|
|
42246
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
42247
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = true;
|
|
42248
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = 'Please complete all required questions.';
|
|
42200
42249
|
}
|
|
42201
42250
|
});
|
|
42202
42251
|
}
|
|
42203
42252
|
function enableEligibleButtons(buttons) {
|
|
42204
42253
|
pendo._.each(buttons, function (button) {
|
|
42205
|
-
if (step.guideElement.find(
|
|
42206
|
-
step.guideElement.find(
|
|
42207
|
-
step.guideElement.find(
|
|
42254
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
42255
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = false;
|
|
42256
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = '';
|
|
42208
42257
|
}
|
|
42209
42258
|
});
|
|
42210
42259
|
}
|
|
42211
42260
|
},
|
|
42212
|
-
test
|
|
42261
|
+
test(step, guide, pendo) {
|
|
42213
42262
|
var _a, _b;
|
|
42214
|
-
|
|
42215
|
-
|
|
42263
|
+
const pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(`[class*=-poll-question]:contains(${requiredSyntax})`);
|
|
42264
|
+
const surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`);
|
|
42216
42265
|
return (!pendo._.isUndefined(pollQuestions) && pendo._.size(pollQuestions)) ||
|
|
42217
42266
|
(!pendo._.isUndefined(surveyQuestions) && pendo._.size(surveyQuestions));
|
|
42218
42267
|
},
|
|
42219
|
-
designerListener
|
|
42220
|
-
|
|
42221
|
-
|
|
42222
|
-
|
|
42268
|
+
designerListener(pendo) {
|
|
42269
|
+
const requiredQuestions = [];
|
|
42270
|
+
const target = pendo.dom.getBody();
|
|
42271
|
+
const config = {
|
|
42223
42272
|
attributeFilter: ['data-layout'],
|
|
42224
42273
|
attributes: true,
|
|
42225
42274
|
childList: true,
|
|
42226
42275
|
characterData: true,
|
|
42227
42276
|
subtree: true
|
|
42228
42277
|
};
|
|
42229
|
-
|
|
42230
|
-
|
|
42278
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42279
|
+
const observer = new MutationObserver(applyRequiredIndicators);
|
|
42231
42280
|
observer.observe(target, config);
|
|
42232
42281
|
function applyRequiredIndicators(mutations) {
|
|
42233
42282
|
pendo._.each(mutations, function (mutation) {
|
|
42234
42283
|
var _a;
|
|
42235
|
-
|
|
42284
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
42236
42285
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
42237
|
-
|
|
42286
|
+
let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
|
|
42238
42287
|
if (eligiblePolls) {
|
|
42239
42288
|
pendo._.each(eligiblePolls, function (poll) {
|
|
42240
|
-
|
|
42289
|
+
let dataPendoPollId;
|
|
42241
42290
|
if (poll.classList.contains('_pendo-open-text-poll-wrapper') ||
|
|
42242
42291
|
poll.classList.contains('_pendo-number-scale-poll-wrapper')) {
|
|
42243
42292
|
dataPendoPollId = poll.getAttribute('name');
|
|
@@ -42245,31 +42294,31 @@ var RequiredQuestions = {
|
|
|
42245
42294
|
else {
|
|
42246
42295
|
dataPendoPollId = poll.getAttribute('data-pendo-poll-id');
|
|
42247
42296
|
}
|
|
42248
|
-
|
|
42249
|
-
|
|
42250
|
-
pendo.dom(
|
|
42297
|
+
let questionText;
|
|
42298
|
+
const questionElement = pendo.dom(`[class*="-poll-question"][data-pendo-poll-id=${dataPendoPollId}]`)[0] ||
|
|
42299
|
+
pendo.dom(`.bb-text[data-pendo-poll-id=${dataPendoPollId}]`)[0];
|
|
42251
42300
|
if (questionElement) {
|
|
42252
42301
|
questionText = questionElement.textContent;
|
|
42253
42302
|
}
|
|
42254
|
-
|
|
42303
|
+
const requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
|
|
42255
42304
|
if (requiredSyntaxIndex > -1) {
|
|
42256
|
-
pendo._.each(pendo.dom(
|
|
42257
|
-
pendo._.each(pendo.dom(
|
|
42305
|
+
pendo._.each(pendo.dom(`[data-pendo-poll-id=${dataPendoPollId}]:not(.pendo-radio)`), (element) => {
|
|
42306
|
+
pendo._.each(pendo.dom(`#${element.id} *:not(".pendo-radio"), #${element.id}:not(".pendo-radio")`), (item) => {
|
|
42258
42307
|
guideMarkdownUtil.removeMarkdownSyntax(item, requiredSyntax, '', pendo);
|
|
42259
42308
|
});
|
|
42260
42309
|
});
|
|
42261
|
-
|
|
42262
|
-
|
|
42263
|
-
|
|
42264
|
-
|
|
42265
|
-
pendo._.each(pendo.dom(
|
|
42266
|
-
pendo._.each(el.childNodes,
|
|
42310
|
+
const pollTextSelector = `.bb-text[data-pendo-poll-id=${dataPendoPollId}]`;
|
|
42311
|
+
const pollParagraphSelector = `${pollTextSelector} p`;
|
|
42312
|
+
const pollListItemSelector = `${pollTextSelector} li`;
|
|
42313
|
+
const pollIndicatorSelector = `${pollTextSelector} ._pendo-required-indicator`;
|
|
42314
|
+
pendo._.each(pendo.dom(`${pollParagraphSelector}, ${pollListItemSelector}`), (el) => {
|
|
42315
|
+
pendo._.each(el.childNodes, (node) => {
|
|
42267
42316
|
if (node.nodeType === 3 && node.nodeValue.indexOf(requiredSyntax) !== -1) {
|
|
42268
42317
|
node.nodeValue = node.nodeValue.split(requiredSyntax).join('');
|
|
42269
42318
|
}
|
|
42270
42319
|
});
|
|
42271
42320
|
});
|
|
42272
|
-
|
|
42321
|
+
const hasIndicator = pendo.dom(pollIndicatorSelector).length !== 0;
|
|
42273
42322
|
if (!hasIndicator) {
|
|
42274
42323
|
if (pendo.dom(pollParagraphSelector).length !== 0 || pendo.dom(pollListItemSelector).length !== 0) {
|
|
42275
42324
|
pendo.dom(pollParagraphSelector).append(requiredElement);
|
|
@@ -42280,7 +42329,7 @@ var RequiredQuestions = {
|
|
|
42280
42329
|
}
|
|
42281
42330
|
}
|
|
42282
42331
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
42283
|
-
|
|
42332
|
+
let questionIndex = requiredQuestions.indexOf(dataPendoPollId);
|
|
42284
42333
|
if (questionIndex !== -1) {
|
|
42285
42334
|
requiredQuestions.splice(questionIndex, 1);
|
|
42286
42335
|
}
|
|
@@ -42291,7 +42340,7 @@ var RequiredQuestions = {
|
|
|
42291
42340
|
}
|
|
42292
42341
|
else {
|
|
42293
42342
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
42294
|
-
|
|
42343
|
+
let index = requiredQuestions.indexOf(dataPendoPollId);
|
|
42295
42344
|
if (index !== -1) {
|
|
42296
42345
|
requiredQuestions.splice(index, 1);
|
|
42297
42346
|
}
|
|
@@ -42305,54 +42354,54 @@ var RequiredQuestions = {
|
|
|
42305
42354
|
}
|
|
42306
42355
|
};
|
|
42307
42356
|
|
|
42308
|
-
|
|
42309
|
-
|
|
42310
|
-
script
|
|
42311
|
-
|
|
42312
|
-
|
|
42313
|
-
|
|
42314
|
-
|
|
42315
|
-
|
|
42357
|
+
const skipStepRegex = new RegExp(guideMarkdownUtil.skipStepString);
|
|
42358
|
+
const SkipToEligibleStep = {
|
|
42359
|
+
script(step, guide, pendo) {
|
|
42360
|
+
let isAdvanceIntercepted = false;
|
|
42361
|
+
let isPreviousIntercepted = false;
|
|
42362
|
+
let guideContainer = step.guideElement.find(guideMarkdownUtil.containerSelector);
|
|
42363
|
+
let guideContainerAriaLabel = guideContainer.attr('aria-label');
|
|
42364
|
+
let stepNumberOrAuto = skipStepRegex.exec(guideContainerAriaLabel)[1];
|
|
42316
42365
|
if (guideContainer) {
|
|
42317
42366
|
guideContainer.attr({ 'aria-label': guideContainer.attr('aria-label').replace(skipStepRegex, '') });
|
|
42318
42367
|
}
|
|
42319
|
-
this.on('beforeAdvance',
|
|
42368
|
+
this.on('beforeAdvance', (evt) => {
|
|
42320
42369
|
if (guide.getPositionOfStep(step) === guide.steps.length || pendo._.isUndefined(stepNumberOrAuto))
|
|
42321
42370
|
return; // exit on the last step of a guide or when we don't have an argument
|
|
42322
|
-
|
|
42371
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'next');
|
|
42323
42372
|
if (!isAdvanceIntercepted && stepNumberOrAuto) {
|
|
42324
42373
|
isAdvanceIntercepted = true;
|
|
42325
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
42374
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
42326
42375
|
evt.cancel = true;
|
|
42327
42376
|
}
|
|
42328
42377
|
});
|
|
42329
|
-
this.on('beforePrevious',
|
|
42378
|
+
this.on('beforePrevious', (evt) => {
|
|
42330
42379
|
if (pendo._.isUndefined(stepNumberOrAuto))
|
|
42331
42380
|
return;
|
|
42332
|
-
|
|
42381
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'previous');
|
|
42333
42382
|
if (!isPreviousIntercepted && stepNumberOrAuto) {
|
|
42334
42383
|
isPreviousIntercepted = true;
|
|
42335
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
42384
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
42336
42385
|
evt.cancel = true;
|
|
42337
42386
|
}
|
|
42338
42387
|
});
|
|
42339
42388
|
function findEligibleSkipStep(stepNumber, direction) {
|
|
42340
42389
|
// Find the next eligible step by using getPosition of step (1 based)
|
|
42341
42390
|
// getPosition - 2 gives the previous step
|
|
42342
|
-
|
|
42343
|
-
|
|
42391
|
+
let skipForwardStep = findStepOnPage(guide.getPositionOfStep(step), 'next', stepNumber);
|
|
42392
|
+
let skipPreviousStep = findStepOnPage(guide.getPositionOfStep(step) - 2, 'previous', stepNumber);
|
|
42344
42393
|
if (skipForwardStep && direction == 'next') {
|
|
42345
|
-
pendo.goToStep({ destinationStepId: skipForwardStep, step
|
|
42394
|
+
pendo.goToStep({ destinationStepId: skipForwardStep, step });
|
|
42346
42395
|
}
|
|
42347
42396
|
if (skipPreviousStep && direction == 'previous') {
|
|
42348
|
-
pendo.goToStep({ destinationStepId: skipPreviousStep, step
|
|
42397
|
+
pendo.goToStep({ destinationStepId: skipPreviousStep, step });
|
|
42349
42398
|
}
|
|
42350
42399
|
return direction === 'next' ? skipForwardStep : skipPreviousStep;
|
|
42351
42400
|
}
|
|
42352
42401
|
function findStepOnPage(stepIndex, direction, stepNumber) {
|
|
42353
42402
|
if (pendo._.isNaN(stepIndex))
|
|
42354
42403
|
return;
|
|
42355
|
-
|
|
42404
|
+
let $step = guide.steps[stepIndex];
|
|
42356
42405
|
if ($step && !$step.canShow()) {
|
|
42357
42406
|
if (stepNumber !== 'auto') {
|
|
42358
42407
|
return guide.steps[stepNumber - 1];
|
|
@@ -42369,34 +42418,34 @@ var SkipToEligibleStep = {
|
|
|
42369
42418
|
}
|
|
42370
42419
|
}
|
|
42371
42420
|
},
|
|
42372
|
-
test
|
|
42421
|
+
test(step, guide, pendo) {
|
|
42373
42422
|
var _a;
|
|
42374
|
-
|
|
42423
|
+
const guideContainerAriaLabel = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(guideMarkdownUtil.containerSelector).attr('aria-label');
|
|
42375
42424
|
return pendo._.isString(guideContainerAriaLabel) && guideContainerAriaLabel.indexOf('{skipStep') !== -1;
|
|
42376
42425
|
},
|
|
42377
|
-
designerListener
|
|
42378
|
-
|
|
42379
|
-
|
|
42426
|
+
designerListener(pendo) {
|
|
42427
|
+
const target = pendo.dom.getBody();
|
|
42428
|
+
const config = {
|
|
42380
42429
|
attributeFilter: ['data-layout'],
|
|
42381
42430
|
attributes: true,
|
|
42382
42431
|
childList: true,
|
|
42383
42432
|
characterData: true,
|
|
42384
42433
|
subtree: true
|
|
42385
42434
|
};
|
|
42386
|
-
|
|
42387
|
-
|
|
42435
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42436
|
+
const observer = new MutationObserver(applySkipStepIndicator);
|
|
42388
42437
|
observer.observe(target, config);
|
|
42389
42438
|
// create an observer instance
|
|
42390
42439
|
function applySkipStepIndicator(mutations) {
|
|
42391
42440
|
pendo._.each(mutations, function (mutation) {
|
|
42392
42441
|
var _a, _b;
|
|
42393
|
-
|
|
42442
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
42394
42443
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
42395
|
-
|
|
42396
|
-
|
|
42444
|
+
let guideContainer = mutation.addedNodes[0].querySelectorAll(guideMarkdownUtil.containerSelector);
|
|
42445
|
+
let guideContainerAriaLabel = (_b = guideContainer[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label');
|
|
42397
42446
|
if (guideContainerAriaLabel) {
|
|
42398
42447
|
if (guideContainerAriaLabel.match(skipStepRegex)) {
|
|
42399
|
-
|
|
42448
|
+
let fullSkipStepString = guideContainerAriaLabel.match(skipStepRegex)[0];
|
|
42400
42449
|
guideContainerAriaLabel.replace(fullSkipStepString, '');
|
|
42401
42450
|
if (!pendo.dom('#_pendoSkipIcon').length) {
|
|
42402
42451
|
pendo.dom(guideMarkdownUtil.containerSelector).append(skipIcon('#999', '30px').trim());
|
|
@@ -42407,30 +42456,48 @@ var SkipToEligibleStep = {
|
|
|
42407
42456
|
});
|
|
42408
42457
|
}
|
|
42409
42458
|
function skipIcon(color, size) {
|
|
42410
|
-
return (
|
|
42459
|
+
return (`<div title="Skip step added"><svg id="_pendoSkipIcon" version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
42460
|
+
width="${size}" height="${size}" viewBox="0 0 512.000000 512.000000"
|
|
42461
|
+
preserveAspectRatio="xMidYMid meet" style="bottom:5px; right:10px; position: absolute;">
|
|
42462
|
+
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
|
|
42463
|
+
fill="${color}" stroke="none">
|
|
42464
|
+
<path d="M2185 4469 c-363 -38 -739 -186 -1034 -407 -95 -71 -273 -243 -357
|
|
42465
|
+
-343 -205 -246 -364 -577 -429 -897 -25 -121 -45 -288 -45 -373 l0 -49 160 0
|
|
42466
|
+
160 0 0 48 c0 26 5 88 10 137 68 593 417 1103 940 1374 1100 570 2418 -137
|
|
42467
|
+
2560 -1374 5 -49 10 -111 10 -137 l0 -47 -155 -3 -155 -3 235 -235 235 -236
|
|
42468
|
+
235 236 235 235 -155 3 -155 3 0 48 c0 27 -5 95 -10 152 -100 989 -878 1767
|
|
42469
|
+
-1869 1868 -117 12 -298 12 -416 0z"/>
|
|
42470
|
+
<path d="M320 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42471
|
+
<path d="M960 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42472
|
+
<path d="M1600 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42473
|
+
<path d="M2240 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42474
|
+
<path d="M2880 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42475
|
+
<path d="M3840 1440 l0 -160 480 0 480 0 0 160 0 160 -480 0 -480 0 0 -160z"/>
|
|
42476
|
+
</g></svg></div>
|
|
42477
|
+
`);
|
|
42411
42478
|
}
|
|
42412
42479
|
}
|
|
42413
42480
|
};
|
|
42414
42481
|
|
|
42415
42482
|
function GuideMarkdown() {
|
|
42416
|
-
|
|
42417
|
-
|
|
42418
|
-
|
|
42483
|
+
let guideMarkdown;
|
|
42484
|
+
let pluginApi;
|
|
42485
|
+
let globalPendo;
|
|
42419
42486
|
return {
|
|
42420
42487
|
name: 'GuideMarkdown',
|
|
42421
42488
|
initialize: init,
|
|
42422
|
-
teardown
|
|
42489
|
+
teardown
|
|
42423
42490
|
};
|
|
42424
42491
|
function init(pendo, PluginAPI) {
|
|
42425
42492
|
globalPendo = pendo;
|
|
42426
42493
|
pluginApi = PluginAPI;
|
|
42427
|
-
|
|
42428
|
-
|
|
42494
|
+
const configReader = PluginAPI.ConfigReader;
|
|
42495
|
+
const GUIDEMARKDOWN_CONFIG = 'guideMarkdown';
|
|
42429
42496
|
configReader.addOption(GUIDEMARKDOWN_CONFIG, [
|
|
42430
42497
|
configReader.sources.SNIPPET_SRC,
|
|
42431
42498
|
configReader.sources.PENDO_CONFIG_SRC
|
|
42432
42499
|
], false);
|
|
42433
|
-
|
|
42500
|
+
const markdownScriptsEnabled = configReader.get(GUIDEMARKDOWN_CONFIG);
|
|
42434
42501
|
if (!markdownScriptsEnabled)
|
|
42435
42502
|
return;
|
|
42436
42503
|
guideMarkdown = [PollBranching, MetadataSubstitution, RequiredQuestions, SkipToEligibleStep];
|
|
@@ -43489,8 +43556,8 @@ function Feedback() {
|
|
|
43489
43556
|
var widgetLoaded = false;
|
|
43490
43557
|
var feedbackAllowedProductId = '';
|
|
43491
43558
|
var initialized = false;
|
|
43492
|
-
|
|
43493
|
-
|
|
43559
|
+
const PING_COOKIE = 'feedback_ping_sent';
|
|
43560
|
+
const PING_COOKIE_EXPIRATION = 1000 * 60 * 60;
|
|
43494
43561
|
var overflowMediaQuery = '@media only screen and (max-device-width:1112px){#feedback-widget{overflow-y:scroll}}';
|
|
43495
43562
|
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%)}}';
|
|
43496
43563
|
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)}}';
|
|
@@ -43510,28 +43577,28 @@ function Feedback() {
|
|
|
43510
43577
|
feedbackStyles: 'pendo-feedback-styles',
|
|
43511
43578
|
feedbackFrameStyles: 'pendo-feedback-visible-buttons-styles'
|
|
43512
43579
|
};
|
|
43513
|
-
|
|
43514
|
-
|
|
43580
|
+
let globalPendo;
|
|
43581
|
+
let pluginApi;
|
|
43515
43582
|
return {
|
|
43516
43583
|
name: 'Feedback',
|
|
43517
|
-
initialize
|
|
43518
|
-
teardown
|
|
43519
|
-
validate
|
|
43584
|
+
initialize,
|
|
43585
|
+
teardown,
|
|
43586
|
+
validate
|
|
43520
43587
|
};
|
|
43521
43588
|
function initialize(pendo, PluginAPI) {
|
|
43522
43589
|
globalPendo = pendo;
|
|
43523
43590
|
pluginApi = PluginAPI;
|
|
43524
43591
|
var publicFeedback = {
|
|
43525
|
-
ping
|
|
43526
|
-
init
|
|
43592
|
+
ping,
|
|
43593
|
+
init,
|
|
43527
43594
|
initialized: getInitialized,
|
|
43528
|
-
loginAndRedirect
|
|
43529
|
-
openFeedback
|
|
43530
|
-
initializeFeedbackOnce
|
|
43531
|
-
isFeedbackLoaded
|
|
43532
|
-
convertPendoToFeedbackOptions
|
|
43595
|
+
loginAndRedirect,
|
|
43596
|
+
openFeedback,
|
|
43597
|
+
initializeFeedbackOnce,
|
|
43598
|
+
isFeedbackLoaded,
|
|
43599
|
+
convertPendoToFeedbackOptions,
|
|
43533
43600
|
isUnsupportedIE: pendo._.partial(isUnsupportedIE, PluginAPI),
|
|
43534
|
-
removeFeedbackWidget
|
|
43601
|
+
removeFeedbackWidget
|
|
43535
43602
|
};
|
|
43536
43603
|
pendo.feedback = publicFeedback;
|
|
43537
43604
|
pendo.getFeedbackSettings = getFeedbackSettings;
|
|
@@ -43562,7 +43629,7 @@ function Feedback() {
|
|
|
43562
43629
|
localStorageOnly: true
|
|
43563
43630
|
});
|
|
43564
43631
|
return {
|
|
43565
|
-
validate
|
|
43632
|
+
validate
|
|
43566
43633
|
};
|
|
43567
43634
|
}
|
|
43568
43635
|
function teardown() {
|
|
@@ -43582,18 +43649,18 @@ function Feedback() {
|
|
|
43582
43649
|
return result;
|
|
43583
43650
|
}
|
|
43584
43651
|
function pingOrInitialize() {
|
|
43585
|
-
|
|
43652
|
+
const options = getPendoOptions();
|
|
43586
43653
|
if (initialized) {
|
|
43587
|
-
|
|
43654
|
+
const feedbackOptions = convertPendoToFeedbackOptions(options);
|
|
43588
43655
|
ping(feedbackOptions);
|
|
43589
43656
|
}
|
|
43590
43657
|
else if (shouldInitializeFeedback() && !globalPendo._.isEmpty(options)) {
|
|
43591
|
-
|
|
43592
|
-
init(options, settings)
|
|
43658
|
+
const settings = pluginApi.ConfigReader.get('feedbackSettings');
|
|
43659
|
+
init(options, settings).catch(globalPendo._.noop);
|
|
43593
43660
|
}
|
|
43594
43661
|
}
|
|
43595
43662
|
function handleIdentityChange(event) {
|
|
43596
|
-
|
|
43663
|
+
const visitorId = globalPendo._.get(event, 'data.0.visitor_id') || globalPendo._.get(event, 'data.0.options.visitor.id');
|
|
43597
43664
|
if (globalPendo.isAnonymousVisitor(visitorId)) {
|
|
43598
43665
|
removeFeedbackWidget();
|
|
43599
43666
|
return;
|
|
@@ -43663,9 +43730,9 @@ function Feedback() {
|
|
|
43663
43730
|
if (toSend.data && toSend.data !== '{}' && toSend.data !== 'null') {
|
|
43664
43731
|
return globalPendo.ajax
|
|
43665
43732
|
.postJSON(getFullUrl('/widget/pendo_ping'), toSend)
|
|
43666
|
-
.then(
|
|
43733
|
+
.then((response) => {
|
|
43667
43734
|
onWidgetPingResponse(response);
|
|
43668
|
-
})
|
|
43735
|
+
}).catch(() => { onPingFailure(); });
|
|
43669
43736
|
}
|
|
43670
43737
|
}
|
|
43671
43738
|
return pluginApi.q.resolve();
|
|
@@ -43799,10 +43866,10 @@ function Feedback() {
|
|
|
43799
43866
|
return globalPendo.ajax.postJSON(getFullUrl('/analytics'), toSend);
|
|
43800
43867
|
}
|
|
43801
43868
|
function addOverlay() {
|
|
43802
|
-
|
|
43869
|
+
const widget = globalPendo.dom(`#${elemIds.feedbackWidget}`);
|
|
43803
43870
|
if (!widget)
|
|
43804
43871
|
return;
|
|
43805
|
-
|
|
43872
|
+
const overlayStyles = {
|
|
43806
43873
|
'position': 'fixed',
|
|
43807
43874
|
'top': '0',
|
|
43808
43875
|
'right': '0',
|
|
@@ -43814,7 +43881,7 @@ function Feedback() {
|
|
|
43814
43881
|
'animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both',
|
|
43815
43882
|
'-webkit-animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both'
|
|
43816
43883
|
};
|
|
43817
|
-
|
|
43884
|
+
const overlayElement = globalPendo.dom(document.createElement('div'));
|
|
43818
43885
|
overlayElement.attr('id', 'feedback-overlay');
|
|
43819
43886
|
overlayElement.css(overlayStyles);
|
|
43820
43887
|
overlayElement.appendTo(widget.getParent());
|
|
@@ -43919,22 +43986,22 @@ function Feedback() {
|
|
|
43919
43986
|
}
|
|
43920
43987
|
}
|
|
43921
43988
|
function buildOuterTriggerDiv(positionInfo) {
|
|
43922
|
-
|
|
43923
|
-
|
|
43924
|
-
|
|
43989
|
+
const horizontalStyles = getHorizontalPositionStyles(positionInfo);
|
|
43990
|
+
const verticalStyles = getVerticalPositionStyles(positionInfo);
|
|
43991
|
+
const styles = globalPendo._.extend({
|
|
43925
43992
|
'position': 'fixed',
|
|
43926
43993
|
'height': '43px',
|
|
43927
43994
|
'opacity': '1 !important',
|
|
43928
43995
|
'z-index': '9001'
|
|
43929
43996
|
}, horizontalStyles, verticalStyles);
|
|
43930
|
-
|
|
43997
|
+
const outerTrigger = globalPendo.dom(document.createElement('div'));
|
|
43931
43998
|
outerTrigger.attr('id', elemIds.feedbackTrigger);
|
|
43932
43999
|
outerTrigger.css(styles);
|
|
43933
44000
|
outerTrigger.attr('data-turbolinks-permanent', '');
|
|
43934
44001
|
return outerTrigger;
|
|
43935
44002
|
}
|
|
43936
44003
|
function buildNotification() {
|
|
43937
|
-
|
|
44004
|
+
const styles = {
|
|
43938
44005
|
'background-color': '#D85039',
|
|
43939
44006
|
'color': '#fff',
|
|
43940
44007
|
'border-radius': '50%',
|
|
@@ -43951,20 +44018,20 @@ function Feedback() {
|
|
|
43951
44018
|
'animation-delay': '1s',
|
|
43952
44019
|
'animation-iteration-count': '1'
|
|
43953
44020
|
};
|
|
43954
|
-
|
|
44021
|
+
const notification = globalPendo.dom(document.createElement('span'));
|
|
43955
44022
|
notification.attr('id', 'feedback-trigger-notification');
|
|
43956
44023
|
notification.css(styles);
|
|
43957
44024
|
return notification;
|
|
43958
44025
|
}
|
|
43959
44026
|
function buildTriggerButton(settings, positionInfo) {
|
|
43960
|
-
|
|
44027
|
+
let borderRadius;
|
|
43961
44028
|
if (positionInfo.horizontalPosition === 'left') {
|
|
43962
44029
|
borderRadius = '0 0 5px 5px';
|
|
43963
44030
|
}
|
|
43964
44031
|
else {
|
|
43965
44032
|
borderRadius = '3px 3px 0 0';
|
|
43966
44033
|
}
|
|
43967
|
-
|
|
44034
|
+
const styles = {
|
|
43968
44035
|
'border': 'none',
|
|
43969
44036
|
'padding': '11px 18px 14px 18px',
|
|
43970
44037
|
'background-color': settings.triggerColor,
|
|
@@ -43975,21 +44042,32 @@ function Feedback() {
|
|
|
43975
44042
|
'cursor': 'pointer',
|
|
43976
44043
|
'text-align': 'left'
|
|
43977
44044
|
};
|
|
43978
|
-
|
|
44045
|
+
const triggerButton = globalPendo.dom(document.createElement('button'));
|
|
43979
44046
|
triggerButton.attr('id', elemIds.feedbackTriggerButton);
|
|
43980
44047
|
triggerButton.css(styles);
|
|
43981
44048
|
triggerButton.text(settings.triggerText);
|
|
43982
44049
|
return triggerButton;
|
|
43983
44050
|
}
|
|
43984
44051
|
function addTriggerPseudoStyles() {
|
|
43985
|
-
|
|
44052
|
+
const pseudoStyles = `
|
|
44053
|
+
#feedback-trigger button:hover {
|
|
44054
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
44055
|
+
outline: none !important;
|
|
44056
|
+
background: #3e566f !important;
|
|
44057
|
+
}
|
|
44058
|
+
#feedback-trigger button:focus {
|
|
44059
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
44060
|
+
outline: none !important;
|
|
44061
|
+
background: #3e566f !important;
|
|
44062
|
+
}
|
|
44063
|
+
`;
|
|
43986
44064
|
pluginApi.util.addInlineStyles('pendo-feedback-trigger-styles', pseudoStyles);
|
|
43987
44065
|
}
|
|
43988
44066
|
function createTrigger(settings, positionInfo) {
|
|
43989
44067
|
addTriggerPseudoStyles();
|
|
43990
|
-
|
|
43991
|
-
|
|
43992
|
-
|
|
44068
|
+
const triggerElement = buildOuterTriggerDiv(positionInfo);
|
|
44069
|
+
const notificationElement = buildNotification();
|
|
44070
|
+
const triggerButtonElement = buildTriggerButton(settings, positionInfo);
|
|
43993
44071
|
triggerElement.append(notificationElement);
|
|
43994
44072
|
triggerElement.append(triggerButtonElement);
|
|
43995
44073
|
triggerElement.appendTo(globalPendo.dom.getBody());
|
|
@@ -44013,7 +44091,7 @@ function Feedback() {
|
|
|
44013
44091
|
iframeWrapper.css(getWidgetOriginalStyles());
|
|
44014
44092
|
iframeWrapper.attr('id', elemIds.feedbackWidget);
|
|
44015
44093
|
iframeWrapper.attr('data-turbolinks-permanent', 'true');
|
|
44016
|
-
iframeWrapper.addClass(
|
|
44094
|
+
iframeWrapper.addClass(`buttonIs-${horizontalPosition}`);
|
|
44017
44095
|
return iframeWrapper;
|
|
44018
44096
|
}
|
|
44019
44097
|
function buildIframeContainer() {
|
|
@@ -44030,13 +44108,22 @@ function Feedback() {
|
|
|
44030
44108
|
return iframeContainer;
|
|
44031
44109
|
}
|
|
44032
44110
|
function addWidgetVisibleButtonStyles(buttonStylePosition) {
|
|
44033
|
-
|
|
44034
|
-
|
|
44111
|
+
let side = buttonStylePosition === 'left' ? 'left' : 'right'; // just in case something was not left or right for some reason
|
|
44112
|
+
const styles = `
|
|
44113
|
+
.buttonIs-${side}.visible {
|
|
44114
|
+
${side}: 0 !important;
|
|
44115
|
+
width: 470px !important;
|
|
44116
|
+
animation-direction: alternate-reverse !important;
|
|
44117
|
+
animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
44118
|
+
-webkit-animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
44119
|
+
z-index: 9002 !important;
|
|
44120
|
+
}
|
|
44121
|
+
`;
|
|
44035
44122
|
pluginApi.util.addInlineStyles(elemIds.feedbackFrameStyles, styles);
|
|
44036
44123
|
}
|
|
44037
44124
|
function initialiseWidgetFrame(horizontalPosition) {
|
|
44038
44125
|
addWidgetVisibleButtonStyles(horizontalPosition);
|
|
44039
|
-
|
|
44126
|
+
const iframeElement = buildIframeWrapper(horizontalPosition);
|
|
44040
44127
|
iframeElement.append(buildIframeContainer());
|
|
44041
44128
|
iframeElement.appendTo(globalPendo.dom.getBody());
|
|
44042
44129
|
subscribeToIframeMessages();
|
|
@@ -44060,7 +44147,7 @@ function Feedback() {
|
|
|
44060
44147
|
return widgetLoaded;
|
|
44061
44148
|
}
|
|
44062
44149
|
function getPendoOptions() {
|
|
44063
|
-
|
|
44150
|
+
let options = pluginApi.ConfigReader.getLocalConfig();
|
|
44064
44151
|
if (!globalPendo._.isObject(options))
|
|
44065
44152
|
options = {};
|
|
44066
44153
|
if (!globalPendo._.isObject(options.visitor))
|
|
@@ -44088,7 +44175,7 @@ function Feedback() {
|
|
|
44088
44175
|
return true;
|
|
44089
44176
|
}
|
|
44090
44177
|
function getQueryParam(url, paramName) {
|
|
44091
|
-
|
|
44178
|
+
const results = new RegExp('[?&]' + paramName + '=([^&#]*)').exec(url);
|
|
44092
44179
|
if (results == null) {
|
|
44093
44180
|
return null;
|
|
44094
44181
|
}
|
|
@@ -44105,13 +44192,13 @@ function Feedback() {
|
|
|
44105
44192
|
return pluginApi.q.reject();
|
|
44106
44193
|
if (!canInitFeedback(pendoOptions))
|
|
44107
44194
|
return pluginApi.q.reject();
|
|
44108
|
-
|
|
44195
|
+
const feedbackOptions = convertPendoToFeedbackOptions(pendoOptions);
|
|
44109
44196
|
try {
|
|
44110
|
-
|
|
44111
|
-
if (
|
|
44197
|
+
const fdbkDst = getQueryParam(globalPendo.url.get(), 'fdbkDst');
|
|
44198
|
+
if (fdbkDst && fdbkDst.startsWith('case')) {
|
|
44112
44199
|
initialized = true;
|
|
44113
44200
|
getFeedbackLoginUrl().then(function (loginUrl) {
|
|
44114
|
-
|
|
44201
|
+
const destinationUrl = loginUrl + '&fdbkDst=' + fdbkDst;
|
|
44115
44202
|
window.location.href = destinationUrl;
|
|
44116
44203
|
});
|
|
44117
44204
|
return;
|
|
@@ -44160,7 +44247,7 @@ function Feedback() {
|
|
|
44160
44247
|
function convertPendoToFeedbackOptions(options) {
|
|
44161
44248
|
var jwtOptions = pluginApi.agent.getJwtInfoCopy();
|
|
44162
44249
|
if (globalPendo._.isEmpty(jwtOptions)) {
|
|
44163
|
-
|
|
44250
|
+
const feedbackOptions = {};
|
|
44164
44251
|
feedbackOptions.user = globalPendo._.pick(options.visitor, 'id', 'full_name', 'firstName', 'lastName', 'email', 'tags', 'custom_allowed_products');
|
|
44165
44252
|
globalPendo._.extend(feedbackOptions.user, { allowed_products: [{ id: feedbackAllowedProductId }] });
|
|
44166
44253
|
feedbackOptions.account = globalPendo._.pick(options.account, 'id', 'name', 'monthly_value', 'is_paying', 'tags');
|
|
@@ -49750,17 +49837,6 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49750
49837
|
return SessionRecorderBuffer;
|
|
49751
49838
|
}());
|
|
49752
49839
|
|
|
49753
|
-
var __assign = function() {
|
|
49754
|
-
__assign = Object.assign || function __assign(t) {
|
|
49755
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
49756
|
-
s = arguments[i];
|
|
49757
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
49758
|
-
}
|
|
49759
|
-
return t;
|
|
49760
|
-
};
|
|
49761
|
-
return __assign.apply(this, arguments);
|
|
49762
|
-
};
|
|
49763
|
-
|
|
49764
49840
|
function __rest(s, e) {
|
|
49765
49841
|
var t = {};
|
|
49766
49842
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -51544,12 +51620,12 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51544
51620
|
}
|
|
51545
51621
|
}
|
|
51546
51622
|
|
|
51547
|
-
|
|
51623
|
+
const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
|
|
51548
51624
|
function matchHostedResources(recordingEvent, stringifiedRecordingPayload) {
|
|
51549
|
-
|
|
51550
|
-
|
|
51625
|
+
const fontURLRegex = /https:\/\/[^"\\\s]+?\.(woff2?|ttf|otf|eot)(\?[^"\\\s]*)?\b/g;
|
|
51626
|
+
const matches = stringifiedRecordingPayload.match(fontURLRegex);
|
|
51551
51627
|
// de-duplicate matches
|
|
51552
|
-
|
|
51628
|
+
const hostedResources = matches ? Array.from(new Set(matches)) : [];
|
|
51553
51629
|
return {
|
|
51554
51630
|
type: 'recording',
|
|
51555
51631
|
visitorId: recordingEvent.visitorId,
|
|
@@ -51564,7 +51640,7 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51564
51640
|
recordingPayloadMetadata: [],
|
|
51565
51641
|
sequence: 0,
|
|
51566
51642
|
recordingPayloadCount: 0,
|
|
51567
|
-
hostedResources
|
|
51643
|
+
hostedResources
|
|
51568
51644
|
};
|
|
51569
51645
|
}
|
|
51570
51646
|
// keep in mind changes here may need addressing in the extension worker proxy as well
|
|
@@ -51572,69 +51648,69 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51572
51648
|
try {
|
|
51573
51649
|
if (e.data.type === 'init' && e.data.lockID) {
|
|
51574
51650
|
if (navigator.locks) {
|
|
51575
|
-
navigator.locks.request(e.data.lockID,
|
|
51651
|
+
navigator.locks.request(e.data.lockID, () => {
|
|
51576
51652
|
postMessage({ ready: true });
|
|
51577
51653
|
// This unresolved promise keeps the lock held with the worker until the worker is
|
|
51578
51654
|
// terminated at which point the lock is released.
|
|
51579
|
-
return new Promise$2(
|
|
51655
|
+
return new Promise$2(() => { });
|
|
51580
51656
|
});
|
|
51581
51657
|
}
|
|
51582
51658
|
return;
|
|
51583
51659
|
}
|
|
51584
51660
|
if (e.data.url && e.data.payload) {
|
|
51585
|
-
|
|
51661
|
+
let { url, payload, shouldCacheResources } = e.data;
|
|
51586
51662
|
if (Object.keys(payload).length === 0) {
|
|
51587
51663
|
postMessage({
|
|
51588
51664
|
type: 'emptyPayload'
|
|
51589
51665
|
});
|
|
51590
51666
|
}
|
|
51591
|
-
|
|
51592
|
-
|
|
51667
|
+
const { sequence } = payload;
|
|
51668
|
+
const stringifiedRecordingPayload = JSON.stringify(payload.recordingPayload);
|
|
51593
51669
|
// calculate and post back the recording payload size before the payload is compressed
|
|
51594
|
-
|
|
51595
|
-
|
|
51670
|
+
const recordingPayloadSize = new TextEncoder().encode(stringifiedRecordingPayload).length;
|
|
51671
|
+
const exceedsPayloadSizeLimit = recordingPayloadSize >= ONE_HUNDRED_MB_IN_BYTES;
|
|
51596
51672
|
postMessage({
|
|
51597
51673
|
type: 'recordingPayloadSize',
|
|
51598
|
-
recordingPayloadSize
|
|
51599
|
-
exceedsPayloadSizeLimit
|
|
51674
|
+
recordingPayloadSize,
|
|
51675
|
+
exceedsPayloadSizeLimit
|
|
51600
51676
|
});
|
|
51601
51677
|
// don't attempt to send the payload if it exceeds the allowed limit
|
|
51602
51678
|
if (exceedsPayloadSizeLimit)
|
|
51603
51679
|
return;
|
|
51604
51680
|
if (shouldCacheResources) {
|
|
51605
|
-
|
|
51681
|
+
const hostedResourcesEvent = matchHostedResources(payload, stringifiedRecordingPayload);
|
|
51606
51682
|
if (hostedResourcesEvent.hostedResources.length) {
|
|
51607
51683
|
postMessage({
|
|
51608
51684
|
type: 'hostedResources',
|
|
51609
|
-
hostedResourcesEvent
|
|
51685
|
+
hostedResourcesEvent
|
|
51610
51686
|
});
|
|
51611
51687
|
}
|
|
51612
51688
|
}
|
|
51613
51689
|
payload.recordingSize = recordingPayloadSize;
|
|
51614
|
-
|
|
51690
|
+
const body = compress(payload, 'binary');
|
|
51615
51691
|
// we want to calculate ct (current time) as close as we can to the actual POST request
|
|
51616
51692
|
// so that it's as accurate as possible
|
|
51617
|
-
url =
|
|
51693
|
+
url = `${url}&ct=${new Date().getTime()}`;
|
|
51618
51694
|
fetch(url, {
|
|
51619
51695
|
method: 'POST',
|
|
51620
|
-
body
|
|
51696
|
+
body
|
|
51621
51697
|
}).then(function (response) {
|
|
51622
51698
|
if (response.status < 200 || response.status >= 300) {
|
|
51623
51699
|
postMessage({
|
|
51624
|
-
error: new Error(
|
|
51700
|
+
error: new Error(`received status code ${response.status}: ${response.statusText}`),
|
|
51625
51701
|
status: response.status,
|
|
51626
|
-
sequence
|
|
51702
|
+
sequence
|
|
51627
51703
|
});
|
|
51628
51704
|
}
|
|
51629
51705
|
else {
|
|
51630
51706
|
postMessage({
|
|
51631
|
-
sequence
|
|
51707
|
+
sequence
|
|
51632
51708
|
});
|
|
51633
51709
|
}
|
|
51634
|
-
})
|
|
51710
|
+
}).catch(function (e) {
|
|
51635
51711
|
postMessage({
|
|
51636
51712
|
error: e,
|
|
51637
|
-
sequence
|
|
51713
|
+
sequence
|
|
51638
51714
|
});
|
|
51639
51715
|
});
|
|
51640
51716
|
}
|
|
@@ -51945,7 +52021,7 @@ function includes(str, substring) {
|
|
|
51945
52021
|
function getResourceType(blockedURI, directive) {
|
|
51946
52022
|
if (!directive || typeof directive !== 'string')
|
|
51947
52023
|
return 'resource';
|
|
51948
|
-
|
|
52024
|
+
const d = directive.toLowerCase();
|
|
51949
52025
|
if (blockedURI === 'inline') {
|
|
51950
52026
|
if (includes(d, 'script-src-attr')) {
|
|
51951
52027
|
return 'inline event handler';
|
|
@@ -52004,12 +52080,11 @@ function getResourceType(blockedURI, directive) {
|
|
|
52004
52080
|
function getDirective(policy, directiveName) {
|
|
52005
52081
|
if (!policy || !directiveName)
|
|
52006
52082
|
return '';
|
|
52007
|
-
|
|
52008
|
-
for (
|
|
52009
|
-
|
|
52010
|
-
|
|
52011
|
-
|
|
52012
|
-
if (lower === needle || lower.startsWith("".concat(needle, " "))) {
|
|
52083
|
+
const needle = directiveName.toLowerCase();
|
|
52084
|
+
for (const directive of policy.split(';')) {
|
|
52085
|
+
const trimmed = directive.trim();
|
|
52086
|
+
const lower = trimmed.toLowerCase();
|
|
52087
|
+
if (lower === needle || lower.startsWith(`${needle} `)) {
|
|
52013
52088
|
return trimmed;
|
|
52014
52089
|
}
|
|
52015
52090
|
}
|
|
@@ -52031,7 +52106,7 @@ function getDirective(policy, directiveName) {
|
|
|
52031
52106
|
function getArticle(phrase) {
|
|
52032
52107
|
if (!phrase || typeof phrase !== 'string')
|
|
52033
52108
|
return 'A';
|
|
52034
|
-
|
|
52109
|
+
const c = phrase.trim().charAt(0).toLowerCase();
|
|
52035
52110
|
return includes('aeiou', c) ? 'An' : 'A';
|
|
52036
52111
|
}
|
|
52037
52112
|
/**
|
|
@@ -52074,47 +52149,46 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
|
|
|
52074
52149
|
return 'Content Security Policy: Unknown violation occurred.';
|
|
52075
52150
|
}
|
|
52076
52151
|
try {
|
|
52077
|
-
|
|
52152
|
+
const reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
|
|
52078
52153
|
// special case for frame-ancestors since it doesn't fit our template at all
|
|
52079
52154
|
if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
|
|
52080
|
-
return
|
|
52155
|
+
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}".`;
|
|
52081
52156
|
}
|
|
52082
|
-
|
|
52083
|
-
|
|
52084
|
-
|
|
52085
|
-
|
|
52086
|
-
|
|
52087
|
-
|
|
52088
|
-
return
|
|
52157
|
+
const resourceType = getResourceType(blockedURI, directive);
|
|
52158
|
+
const article = getArticle(resourceType);
|
|
52159
|
+
const source = formatBlockedUri(blockedURI);
|
|
52160
|
+
const directiveValue = getDirective(originalPolicy, directive);
|
|
52161
|
+
const policyDisplay = directiveValue || directive;
|
|
52162
|
+
const resourceDescription = `${article} ${resourceType}${source ? ` from ${source}` : ''}`;
|
|
52163
|
+
return `Content Security Policy${reportOnlyText}: ${resourceDescription} was blocked by your site's \`${policyDisplay}\` policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
52089
52164
|
}
|
|
52090
52165
|
catch (error) {
|
|
52091
|
-
return
|
|
52166
|
+
return `Content Security Policy: Error formatting violation message: ${error.message}`;
|
|
52092
52167
|
}
|
|
52093
52168
|
}
|
|
52094
52169
|
|
|
52095
|
-
|
|
52096
|
-
|
|
52170
|
+
const MAX_LENGTH = 1000;
|
|
52171
|
+
const PII_PATTERN = {
|
|
52097
52172
|
ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
52098
52173
|
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
52099
52174
|
creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
|
|
52100
52175
|
httpsUrls: /https:\/\/[^\s]+/g,
|
|
52101
52176
|
email: /[\w._+-]+@[\w.-]+\.\w+/g
|
|
52102
52177
|
};
|
|
52103
|
-
|
|
52104
|
-
|
|
52105
|
-
|
|
52106
|
-
|
|
52107
|
-
|
|
52178
|
+
const PII_REPLACEMENT = '*'.repeat(10);
|
|
52179
|
+
const JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
|
|
52180
|
+
const UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
|
|
52181
|
+
const joinedKeys = JSON_PII_KEYS.join('|');
|
|
52182
|
+
const keyPattern = `"([^"]*(?:${joinedKeys})[^"]*)"`;
|
|
52108
52183
|
// only scrub strings, numbers, and booleans
|
|
52109
|
-
|
|
52184
|
+
const acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
|
|
52110
52185
|
/**
|
|
52111
52186
|
* Truncates a string to the max length
|
|
52112
52187
|
* @access private
|
|
52113
52188
|
* @param {String} string
|
|
52114
52189
|
* @returns {String}
|
|
52115
52190
|
*/
|
|
52116
|
-
function truncate(string, includeEllipsis) {
|
|
52117
|
-
if (includeEllipsis === void 0) { includeEllipsis = false; }
|
|
52191
|
+
function truncate(string, includeEllipsis = false) {
|
|
52118
52192
|
if (string.length <= MAX_LENGTH)
|
|
52119
52193
|
return string;
|
|
52120
52194
|
if (includeEllipsis) {
|
|
@@ -52131,7 +52205,7 @@ function truncate(string, includeEllipsis) {
|
|
|
52131
52205
|
* @returns {String}
|
|
52132
52206
|
*/
|
|
52133
52207
|
function generateLogKey(methodName, message, stackTrace) {
|
|
52134
|
-
return
|
|
52208
|
+
return `${methodName}|${message}|${stackTrace}`;
|
|
52135
52209
|
}
|
|
52136
52210
|
/**
|
|
52137
52211
|
* Checks if a string has 2 or more digits, a https URL, or an email address
|
|
@@ -52148,13 +52222,12 @@ function mightContainPII(string) {
|
|
|
52148
52222
|
* @param {String} string
|
|
52149
52223
|
* @returns {String}
|
|
52150
52224
|
*/
|
|
52151
|
-
function scrubPII(
|
|
52152
|
-
var string = _a.string, _ = _a._;
|
|
52225
|
+
function scrubPII({ string, _ }) {
|
|
52153
52226
|
if (!string || typeof string !== 'string')
|
|
52154
52227
|
return string;
|
|
52155
52228
|
if (!mightContainPII(string))
|
|
52156
52229
|
return string;
|
|
52157
|
-
return _.reduce(_.values(PII_PATTERN),
|
|
52230
|
+
return _.reduce(_.values(PII_PATTERN), (str, pattern) => str.replace(pattern, PII_REPLACEMENT), string);
|
|
52158
52231
|
}
|
|
52159
52232
|
/**
|
|
52160
52233
|
* Scrub PII from a stringified JSON object
|
|
@@ -52163,14 +52236,12 @@ function scrubPII(_a) {
|
|
|
52163
52236
|
* @returns {String}
|
|
52164
52237
|
*/
|
|
52165
52238
|
function scrubJsonPII(string) {
|
|
52166
|
-
|
|
52239
|
+
const fullScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*[\\{\\[]`, 'i');
|
|
52167
52240
|
if (fullScrubRegex.test(string)) {
|
|
52168
52241
|
return UNABLE_TO_DISPLAY_BODY;
|
|
52169
52242
|
}
|
|
52170
|
-
|
|
52171
|
-
return string.replace(keyValueScrubRegex,
|
|
52172
|
-
return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
|
|
52173
|
-
});
|
|
52243
|
+
const keyValueScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*${acceptedValues}`, 'gi');
|
|
52244
|
+
return string.replace(keyValueScrubRegex, (match, key) => `"${key}":"${PII_REPLACEMENT}"`);
|
|
52174
52245
|
}
|
|
52175
52246
|
/**
|
|
52176
52247
|
* Checks if a string is a JSON object
|
|
@@ -52182,7 +52253,7 @@ function scrubJsonPII(string) {
|
|
|
52182
52253
|
function mightContainJson(string, contentType) {
|
|
52183
52254
|
if (!string || typeof string !== 'string')
|
|
52184
52255
|
return false;
|
|
52185
|
-
|
|
52256
|
+
const firstChar = string.charAt(0);
|
|
52186
52257
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
52187
52258
|
return true;
|
|
52188
52259
|
}
|
|
@@ -52195,20 +52266,19 @@ function mightContainJson(string, contentType) {
|
|
|
52195
52266
|
* @param {String} contentType
|
|
52196
52267
|
* @returns {String}
|
|
52197
52268
|
*/
|
|
52198
|
-
function maskSensitiveFields(
|
|
52199
|
-
var string = _a.string, contentType = _a.contentType, _ = _a._;
|
|
52269
|
+
function maskSensitiveFields({ string, contentType, _ }) {
|
|
52200
52270
|
if (!string || typeof string !== 'string')
|
|
52201
52271
|
return string;
|
|
52202
52272
|
if (mightContainJson(string, contentType)) {
|
|
52203
52273
|
string = scrubJsonPII(string);
|
|
52204
52274
|
}
|
|
52205
52275
|
if (mightContainPII(string)) {
|
|
52206
|
-
string = scrubPII({ string
|
|
52276
|
+
string = scrubPII({ string, _ });
|
|
52207
52277
|
}
|
|
52208
52278
|
return string;
|
|
52209
52279
|
}
|
|
52210
52280
|
|
|
52211
|
-
|
|
52281
|
+
const DEV_LOG_TYPE = 'devlog';
|
|
52212
52282
|
function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
52213
52283
|
return {
|
|
52214
52284
|
browser_time: pluginAPI.util.getNow(),
|
|
@@ -52219,12 +52289,12 @@ function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
|
52219
52289
|
};
|
|
52220
52290
|
}
|
|
52221
52291
|
|
|
52222
|
-
|
|
52223
|
-
|
|
52224
|
-
|
|
52225
|
-
|
|
52226
|
-
|
|
52227
|
-
|
|
52292
|
+
const TOKEN_MAX_SIZE = 100;
|
|
52293
|
+
const TOKEN_REFILL_RATE = 10;
|
|
52294
|
+
const TOKEN_REFRESH_INTERVAL = 1000;
|
|
52295
|
+
const MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
|
|
52296
|
+
class DevlogBuffer {
|
|
52297
|
+
constructor(pendo, pluginAPI) {
|
|
52228
52298
|
this.pendo = pendo;
|
|
52229
52299
|
this.pluginAPI = pluginAPI;
|
|
52230
52300
|
this.events = [];
|
|
@@ -52235,36 +52305,36 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
52235
52305
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
52236
52306
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
52237
52307
|
}
|
|
52238
|
-
|
|
52308
|
+
isEmpty() {
|
|
52239
52309
|
return this.events.length === 0 && this.payloads.length === 0;
|
|
52240
|
-
}
|
|
52241
|
-
|
|
52242
|
-
|
|
52310
|
+
}
|
|
52311
|
+
refillTokens() {
|
|
52312
|
+
const now = this.pluginAPI.util.getNow();
|
|
52243
52313
|
if (now >= this.nextRefillTime) {
|
|
52244
|
-
|
|
52245
|
-
|
|
52246
|
-
|
|
52314
|
+
const timeSinceLastRefill = now - this.lastRefillTime;
|
|
52315
|
+
const secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
|
|
52316
|
+
const tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
|
|
52247
52317
|
this.tokens = Math.min(this.tokens + tokensToRefill, TOKEN_MAX_SIZE);
|
|
52248
52318
|
this.lastRefillTime = now;
|
|
52249
52319
|
this.nextRefillTime = now + TOKEN_REFRESH_INTERVAL;
|
|
52250
52320
|
}
|
|
52251
|
-
}
|
|
52252
|
-
|
|
52321
|
+
}
|
|
52322
|
+
clear() {
|
|
52253
52323
|
this.events = [];
|
|
52254
52324
|
this.lastEvent = null;
|
|
52255
52325
|
this.uncompressedSize = 0;
|
|
52256
|
-
}
|
|
52257
|
-
|
|
52326
|
+
}
|
|
52327
|
+
hasTokenAvailable() {
|
|
52258
52328
|
this.refillTokens();
|
|
52259
52329
|
return this.tokens > 0;
|
|
52260
|
-
}
|
|
52261
|
-
|
|
52330
|
+
}
|
|
52331
|
+
estimateEventSize(event) {
|
|
52262
52332
|
return JSON.stringify(event).length;
|
|
52263
|
-
}
|
|
52264
|
-
|
|
52333
|
+
}
|
|
52334
|
+
push(event) {
|
|
52265
52335
|
if (!this.hasTokenAvailable())
|
|
52266
52336
|
return false;
|
|
52267
|
-
|
|
52337
|
+
const eventSize = this.estimateEventSize(event);
|
|
52268
52338
|
if (this.uncompressedSize + eventSize > MAX_UNCOMPRESSED_SIZE) {
|
|
52269
52339
|
this.compressCurrentChunk();
|
|
52270
52340
|
}
|
|
@@ -52273,55 +52343,54 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
52273
52343
|
this.events.push(event);
|
|
52274
52344
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
52275
52345
|
return true;
|
|
52276
|
-
}
|
|
52277
|
-
|
|
52346
|
+
}
|
|
52347
|
+
compressCurrentChunk() {
|
|
52278
52348
|
if (this.events.length === 0)
|
|
52279
52349
|
return;
|
|
52280
|
-
|
|
52350
|
+
const jzb = this.pendo.compress(this.events);
|
|
52281
52351
|
this.payloads.push(jzb);
|
|
52282
52352
|
this.clear();
|
|
52283
|
-
}
|
|
52284
|
-
|
|
52285
|
-
|
|
52353
|
+
}
|
|
52354
|
+
generateUrl() {
|
|
52355
|
+
const queryParams = {
|
|
52286
52356
|
v: this.pendo.VERSION,
|
|
52287
52357
|
ct: this.pluginAPI.util.getNow()
|
|
52288
52358
|
};
|
|
52289
52359
|
return this.pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, this.pendo.apiKey, queryParams);
|
|
52290
|
-
}
|
|
52291
|
-
|
|
52360
|
+
}
|
|
52361
|
+
pack() {
|
|
52292
52362
|
if (this.isEmpty())
|
|
52293
52363
|
return;
|
|
52294
|
-
|
|
52364
|
+
const url = this.generateUrl();
|
|
52295
52365
|
this.compressCurrentChunk();
|
|
52296
|
-
|
|
52297
|
-
jzb
|
|
52298
|
-
url
|
|
52299
|
-
})
|
|
52366
|
+
const payloads = this.pendo._.map(this.payloads, (jzb) => ({
|
|
52367
|
+
jzb,
|
|
52368
|
+
url
|
|
52369
|
+
}));
|
|
52300
52370
|
this.payloads = [];
|
|
52301
52371
|
return payloads;
|
|
52302
|
-
}
|
|
52303
|
-
|
|
52304
|
-
}());
|
|
52372
|
+
}
|
|
52373
|
+
}
|
|
52305
52374
|
|
|
52306
|
-
|
|
52307
|
-
|
|
52375
|
+
class DevlogTransport {
|
|
52376
|
+
constructor(globalPendo, pluginAPI) {
|
|
52308
52377
|
this.pendo = globalPendo;
|
|
52309
52378
|
this.pluginAPI = pluginAPI;
|
|
52310
52379
|
}
|
|
52311
|
-
|
|
52312
|
-
|
|
52380
|
+
buildGetUrl(baseUrl, jzb) {
|
|
52381
|
+
const params = {};
|
|
52313
52382
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
52314
52383
|
this.pluginAPI.agent.addAccountIdParams(params, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
52315
52384
|
}
|
|
52316
|
-
|
|
52385
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
52317
52386
|
if (!this.pendo._.isEmpty(jwtOptions)) {
|
|
52318
52387
|
this.pendo._.extend(params, jwtOptions);
|
|
52319
52388
|
}
|
|
52320
52389
|
params.jzb = jzb;
|
|
52321
|
-
|
|
52322
|
-
return
|
|
52323
|
-
}
|
|
52324
|
-
|
|
52390
|
+
const queryString = this.pendo._.map(params, (value, key) => `${key}=${value}`).join('&');
|
|
52391
|
+
return `${baseUrl}${baseUrl.indexOf('?') !== -1 ? '&' : '?'}${queryString}`;
|
|
52392
|
+
}
|
|
52393
|
+
get(url, options) {
|
|
52325
52394
|
options.method = 'GET';
|
|
52326
52395
|
if (this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
52327
52396
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
@@ -52329,90 +52398,86 @@ var DevlogTransport = /** @class */ (function () {
|
|
|
52329
52398
|
else {
|
|
52330
52399
|
return this.pendo.ajax.get(url);
|
|
52331
52400
|
}
|
|
52332
|
-
}
|
|
52333
|
-
|
|
52334
|
-
|
|
52335
|
-
var getUrl = this.buildGetUrl(url, jzb);
|
|
52401
|
+
}
|
|
52402
|
+
sendRequestWithGet({ url, jzb }) {
|
|
52403
|
+
const getUrl = this.buildGetUrl(url, jzb);
|
|
52336
52404
|
return this.get(getUrl, {
|
|
52337
52405
|
headers: {
|
|
52338
52406
|
'Content-Type': 'application/octet-stream'
|
|
52339
52407
|
}
|
|
52340
52408
|
});
|
|
52341
|
-
}
|
|
52342
|
-
|
|
52409
|
+
}
|
|
52410
|
+
post(url, options) {
|
|
52343
52411
|
options.method = 'POST';
|
|
52344
52412
|
if (options.keepalive && this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
52345
52413
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
52346
52414
|
}
|
|
52347
52415
|
else if (options.keepalive && this.pluginAPI.transmit.sendBeacon.supported()) {
|
|
52348
|
-
|
|
52416
|
+
const result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
|
|
52349
52417
|
return result ? Promise$2.resolve() : Promise$2.reject(new Error('sendBeacon failed to send devlog data'));
|
|
52350
52418
|
}
|
|
52351
52419
|
else {
|
|
52352
52420
|
return this.pendo.ajax.post(url, options.body);
|
|
52353
52421
|
}
|
|
52354
|
-
}
|
|
52355
|
-
|
|
52356
|
-
|
|
52357
|
-
|
|
52358
|
-
var bodyPayload = {
|
|
52422
|
+
}
|
|
52423
|
+
sendRequestWithPost({ url, jzb }, isUnload) {
|
|
52424
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
52425
|
+
const bodyPayload = {
|
|
52359
52426
|
events: jzb,
|
|
52360
52427
|
browser_time: this.pluginAPI.util.getNow()
|
|
52361
52428
|
};
|
|
52362
52429
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
52363
52430
|
this.pluginAPI.agent.addAccountIdParams(bodyPayload, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
52364
52431
|
}
|
|
52365
|
-
|
|
52432
|
+
const body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
|
|
52366
52433
|
return this.post(url, {
|
|
52367
|
-
body
|
|
52434
|
+
body,
|
|
52368
52435
|
headers: {
|
|
52369
52436
|
'Content-Type': 'application/json'
|
|
52370
52437
|
},
|
|
52371
52438
|
keepalive: isUnload
|
|
52372
52439
|
});
|
|
52373
|
-
}
|
|
52374
|
-
|
|
52375
|
-
|
|
52376
|
-
var compressedLength = jzb.length;
|
|
52440
|
+
}
|
|
52441
|
+
sendRequest({ url, jzb }, isUnload) {
|
|
52442
|
+
const compressedLength = jzb.length;
|
|
52377
52443
|
if (compressedLength <= this.pluginAPI.constants.ENCODED_EVENT_MAX_LENGTH && !this.pluginAPI.ConfigReader.get('sendEventsWithPostOnly')) {
|
|
52378
|
-
return this.sendRequestWithGet({ url
|
|
52444
|
+
return this.sendRequestWithGet({ url, jzb });
|
|
52379
52445
|
}
|
|
52380
|
-
return this.sendRequestWithPost({ url
|
|
52381
|
-
}
|
|
52382
|
-
|
|
52383
|
-
}());
|
|
52446
|
+
return this.sendRequestWithPost({ url, jzb }, isUnload);
|
|
52447
|
+
}
|
|
52448
|
+
}
|
|
52384
52449
|
|
|
52385
52450
|
function ConsoleCapture() {
|
|
52386
|
-
|
|
52387
|
-
|
|
52388
|
-
|
|
52389
|
-
|
|
52390
|
-
|
|
52391
|
-
|
|
52392
|
-
|
|
52393
|
-
|
|
52394
|
-
|
|
52395
|
-
|
|
52396
|
-
|
|
52397
|
-
|
|
52451
|
+
let pluginAPI;
|
|
52452
|
+
let _;
|
|
52453
|
+
let globalPendo;
|
|
52454
|
+
let buffer;
|
|
52455
|
+
let sendQueue;
|
|
52456
|
+
let sendInterval;
|
|
52457
|
+
let transport;
|
|
52458
|
+
let isPtmPaused;
|
|
52459
|
+
let isCapturingConsoleLogs = false;
|
|
52460
|
+
const CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
|
|
52461
|
+
const CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
|
|
52462
|
+
const DEV_LOG_SUB_TYPE = 'console';
|
|
52398
52463
|
// deduplicate logs
|
|
52399
|
-
|
|
52464
|
+
let lastLogKey = '';
|
|
52400
52465
|
return {
|
|
52401
52466
|
name: 'ConsoleCapture',
|
|
52402
|
-
initialize
|
|
52403
|
-
teardown
|
|
52404
|
-
addIntercepts
|
|
52405
|
-
createConsoleEvent
|
|
52406
|
-
captureStackTrace
|
|
52407
|
-
send
|
|
52408
|
-
setCaptureState
|
|
52409
|
-
recordingStarted
|
|
52410
|
-
recordingStopped
|
|
52411
|
-
onAppHidden
|
|
52412
|
-
onAppUnloaded
|
|
52413
|
-
onPtmPaused
|
|
52414
|
-
onPtmUnpaused
|
|
52415
|
-
securityPolicyViolationFn
|
|
52467
|
+
initialize,
|
|
52468
|
+
teardown,
|
|
52469
|
+
addIntercepts,
|
|
52470
|
+
createConsoleEvent,
|
|
52471
|
+
captureStackTrace,
|
|
52472
|
+
send,
|
|
52473
|
+
setCaptureState,
|
|
52474
|
+
recordingStarted,
|
|
52475
|
+
recordingStopped,
|
|
52476
|
+
onAppHidden,
|
|
52477
|
+
onAppUnloaded,
|
|
52478
|
+
onPtmPaused,
|
|
52479
|
+
onPtmUnpaused,
|
|
52480
|
+
securityPolicyViolationFn,
|
|
52416
52481
|
get isCapturingConsoleLogs() {
|
|
52417
52482
|
return isCapturingConsoleLogs;
|
|
52418
52483
|
},
|
|
@@ -52429,16 +52494,16 @@ function ConsoleCapture() {
|
|
|
52429
52494
|
function initialize(pendo, PluginAPI) {
|
|
52430
52495
|
_ = pendo._;
|
|
52431
52496
|
pluginAPI = PluginAPI;
|
|
52432
|
-
|
|
52497
|
+
const { ConfigReader } = pluginAPI;
|
|
52433
52498
|
ConfigReader.addOption(CAPTURE_CONSOLE_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
|
|
52434
|
-
|
|
52499
|
+
const captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
|
|
52435
52500
|
if (!captureConsoleEnabled)
|
|
52436
52501
|
return;
|
|
52437
52502
|
globalPendo = pendo;
|
|
52438
52503
|
buffer = new DevlogBuffer(pendo, pluginAPI);
|
|
52439
52504
|
transport = new DevlogTransport(pendo, pluginAPI);
|
|
52440
52505
|
sendQueue = new pluginAPI.SendQueue(transport.sendRequest.bind(transport));
|
|
52441
|
-
sendInterval = setInterval(
|
|
52506
|
+
sendInterval = setInterval(() => {
|
|
52442
52507
|
if (!sendQueue.failed()) {
|
|
52443
52508
|
send();
|
|
52444
52509
|
}
|
|
@@ -52464,19 +52529,17 @@ function ConsoleCapture() {
|
|
|
52464
52529
|
function onPtmUnpaused() {
|
|
52465
52530
|
isPtmPaused = false;
|
|
52466
52531
|
if (!buffer.isEmpty()) {
|
|
52467
|
-
for (
|
|
52468
|
-
|
|
52469
|
-
pluginAPI.Events.eventCaptured.trigger(event_1);
|
|
52532
|
+
for (const event of buffer.events) {
|
|
52533
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
52470
52534
|
}
|
|
52471
52535
|
send();
|
|
52472
52536
|
}
|
|
52473
52537
|
}
|
|
52474
|
-
function setCaptureState(
|
|
52475
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
|
|
52538
|
+
function setCaptureState({ shouldCapture = false, reason = '' } = {}) {
|
|
52476
52539
|
if (shouldCapture === isCapturingConsoleLogs)
|
|
52477
52540
|
return;
|
|
52478
52541
|
isCapturingConsoleLogs = shouldCapture;
|
|
52479
|
-
pluginAPI.log.info(
|
|
52542
|
+
pluginAPI.log.info(`[ConsoleCapture] Console log capture ${shouldCapture ? 'started' : 'stopped'}${reason ? `: ${reason}` : ''}`);
|
|
52480
52543
|
}
|
|
52481
52544
|
function recordingStarted() {
|
|
52482
52545
|
setCaptureState({ shouldCapture: true, reason: 'recording started' });
|
|
@@ -52496,12 +52559,12 @@ function ConsoleCapture() {
|
|
|
52496
52559
|
}
|
|
52497
52560
|
function addIntercepts() {
|
|
52498
52561
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52499
|
-
|
|
52562
|
+
const originalMethod = console[methodName];
|
|
52500
52563
|
if (!originalMethod)
|
|
52501
52564
|
return;
|
|
52502
52565
|
console[methodName] = _.wrap(originalMethod, function (originalFn) {
|
|
52503
52566
|
// slice 1 to omit originalFn
|
|
52504
|
-
|
|
52567
|
+
const args = _.toArray(arguments).slice(1);
|
|
52505
52568
|
originalFn.apply(console, args);
|
|
52506
52569
|
createConsoleEvent(args, methodName);
|
|
52507
52570
|
});
|
|
@@ -52513,10 +52576,10 @@ function ConsoleCapture() {
|
|
|
52513
52576
|
function securityPolicyViolationFn(evt) {
|
|
52514
52577
|
if (!evt || typeof evt !== 'object')
|
|
52515
52578
|
return;
|
|
52516
|
-
|
|
52517
|
-
|
|
52518
|
-
|
|
52519
|
-
|
|
52579
|
+
const { blockedURI, violatedDirective, effectiveDirective, disposition, originalPolicy } = evt;
|
|
52580
|
+
const directive = violatedDirective || effectiveDirective;
|
|
52581
|
+
const isReportOnly = disposition === 'report';
|
|
52582
|
+
const message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
|
|
52520
52583
|
if (isReportOnly) {
|
|
52521
52584
|
createConsoleEvent([message], 'warn', { skipStackTrace: true, skipScrubPII: true });
|
|
52522
52585
|
}
|
|
@@ -52524,13 +52587,12 @@ function ConsoleCapture() {
|
|
|
52524
52587
|
createConsoleEvent([message], 'error', { skipStackTrace: true, skipScrubPII: true });
|
|
52525
52588
|
}
|
|
52526
52589
|
}
|
|
52527
|
-
function createConsoleEvent(args, methodName,
|
|
52528
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.skipStackTrace, skipStackTrace = _c === void 0 ? false : _c, _d = _b.skipScrubPII, skipScrubPII = _d === void 0 ? false : _d;
|
|
52590
|
+
function createConsoleEvent(args, methodName, { skipStackTrace = false, skipScrubPII = false } = {}) {
|
|
52529
52591
|
if (!isCapturingConsoleLogs || !args || args.length === 0 || !_.contains(CONSOLE_METHODS, methodName))
|
|
52530
52592
|
return;
|
|
52531
52593
|
// stringify args
|
|
52532
|
-
|
|
52533
|
-
|
|
52594
|
+
let message = _.compact(_.map(args, arg => {
|
|
52595
|
+
let stringifiedArg;
|
|
52534
52596
|
try {
|
|
52535
52597
|
stringifiedArg = stringify(arg);
|
|
52536
52598
|
}
|
|
@@ -52542,22 +52604,22 @@ function ConsoleCapture() {
|
|
|
52542
52604
|
if (!message)
|
|
52543
52605
|
return;
|
|
52544
52606
|
// capture stack trace
|
|
52545
|
-
|
|
52607
|
+
let stackTrace = '';
|
|
52546
52608
|
if (!skipStackTrace) {
|
|
52547
|
-
|
|
52609
|
+
const maxStackFrames = methodName === 'error' ? 4 : 1;
|
|
52548
52610
|
stackTrace = captureStackTrace(maxStackFrames);
|
|
52549
52611
|
}
|
|
52550
52612
|
// truncate message and stack trace
|
|
52551
52613
|
message = truncate(message);
|
|
52552
52614
|
stackTrace = truncate(stackTrace);
|
|
52553
52615
|
// de-duplicate log
|
|
52554
|
-
|
|
52616
|
+
const logKey = generateLogKey(methodName, message, stackTrace);
|
|
52555
52617
|
if (isExistingDuplicateLog(logKey)) {
|
|
52556
52618
|
buffer.lastEvent.devLogCount++;
|
|
52557
52619
|
return;
|
|
52558
52620
|
}
|
|
52559
|
-
|
|
52560
|
-
|
|
52621
|
+
const devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
|
|
52622
|
+
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 });
|
|
52561
52623
|
if (!buffer.hasTokenAvailable())
|
|
52562
52624
|
return consoleEvent;
|
|
52563
52625
|
if (!isPtmPaused) {
|
|
@@ -52569,8 +52631,8 @@ function ConsoleCapture() {
|
|
|
52569
52631
|
}
|
|
52570
52632
|
function captureStackTrace(maxStackFrames) {
|
|
52571
52633
|
try {
|
|
52572
|
-
|
|
52573
|
-
return _.map(stackFrames,
|
|
52634
|
+
const stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
|
|
52635
|
+
return _.map(stackFrames, frame => frame.toString()).join('\n');
|
|
52574
52636
|
}
|
|
52575
52637
|
catch (error) {
|
|
52576
52638
|
return '';
|
|
@@ -52582,22 +52644,21 @@ function ConsoleCapture() {
|
|
|
52582
52644
|
function updateLastLog(logKey) {
|
|
52583
52645
|
lastLogKey = logKey;
|
|
52584
52646
|
}
|
|
52585
|
-
function send(
|
|
52586
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
|
|
52647
|
+
function send({ unload = false, hidden = false } = {}) {
|
|
52587
52648
|
if (!buffer || buffer.isEmpty())
|
|
52588
52649
|
return;
|
|
52589
52650
|
if (!globalPendo.isSendingEvents()) {
|
|
52590
52651
|
buffer.clear();
|
|
52591
52652
|
return;
|
|
52592
52653
|
}
|
|
52593
|
-
|
|
52654
|
+
const payloads = buffer.pack();
|
|
52594
52655
|
if (!payloads || payloads.length === 0)
|
|
52595
52656
|
return;
|
|
52596
52657
|
if (unload || hidden) {
|
|
52597
52658
|
sendQueue.drain(payloads, unload);
|
|
52598
52659
|
}
|
|
52599
52660
|
else {
|
|
52600
|
-
sendQueue.push
|
|
52661
|
+
sendQueue.push(...payloads);
|
|
52601
52662
|
}
|
|
52602
52663
|
}
|
|
52603
52664
|
function teardown() {
|
|
@@ -52621,7 +52682,7 @@ function ConsoleCapture() {
|
|
|
52621
52682
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52622
52683
|
if (!console[methodName])
|
|
52623
52684
|
return _.noop;
|
|
52624
|
-
|
|
52685
|
+
const unwrap = console[methodName]._pendoUnwrap;
|
|
52625
52686
|
if (_.isFunction(unwrap)) {
|
|
52626
52687
|
unwrap();
|
|
52627
52688
|
}
|
|
@@ -55507,44 +55568,69 @@ const PredictGuides = () => {
|
|
|
55507
55568
|
};
|
|
55508
55569
|
};
|
|
55509
55570
|
|
|
55510
|
-
|
|
55511
|
-
|
|
55512
|
-
|
|
55513
|
-
|
|
55514
|
-
|
|
55515
|
-
|
|
55516
|
-
|
|
55517
|
-
|
|
55518
|
-
|
|
55519
|
-
|
|
55520
|
-
|
|
55521
|
-
|
|
55522
|
-
|
|
55523
|
-
|
|
55524
|
-
|
|
55525
|
-
|
|
55526
|
-
|
|
55571
|
+
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
55572
|
+
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
55573
|
+
const MESSAGE_CONTENT = 'messageContent';
|
|
55574
|
+
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
55575
|
+
const MESSAGE_ID_PATTERN = 'messageIdPattern';
|
|
55576
|
+
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
55577
|
+
const REACTION_ACTIVE = 'reactionActive';
|
|
55578
|
+
const STREAMING_ACTIVE = 'streamingActive';
|
|
55579
|
+
const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
55580
|
+
const THUMB_DOWN = 'thumbDown';
|
|
55581
|
+
const THUMB_UP = 'thumbUp';
|
|
55582
|
+
const TURN_CONTAINER = 'turnContainer';
|
|
55583
|
+
const USER_MESSAGE = 'userMessage';
|
|
55584
|
+
const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
|
|
55585
|
+
const CUSTOM_AGENT_ID = 'customAgentId';
|
|
55586
|
+
const CUSTOM_AGENT_NAME = 'customAgentName';
|
|
55587
|
+
const REQUIRED_SELECTORS = [
|
|
55527
55588
|
ASSISTANT_MESSAGE,
|
|
55528
55589
|
CONVERSATION_ID_URL_PATTERN,
|
|
55529
55590
|
STREAMING_ACTIVE,
|
|
55530
55591
|
TURN_CONTAINER,
|
|
55531
55592
|
USER_MESSAGE
|
|
55532
55593
|
];
|
|
55533
|
-
|
|
55594
|
+
const SUPPORTED_PRESETS = [
|
|
55534
55595
|
'chatgpt-full',
|
|
55535
55596
|
'gemini-full',
|
|
55536
55597
|
'claude-full',
|
|
55537
55598
|
'copilot-full',
|
|
55538
55599
|
'copilot-m365-full'
|
|
55539
55600
|
];
|
|
55540
|
-
|
|
55541
|
-
|
|
55542
|
-
|
|
55543
|
-
|
|
55544
|
-
|
|
55545
|
-
|
|
55546
|
-
|
|
55547
|
-
|
|
55601
|
+
const STREAMING_END_SETTLE_MS = 500;
|
|
55602
|
+
const SUBMISSION_START_RETRY_MS = 1000;
|
|
55603
|
+
const SUBMISSION_START_MAX_ATTEMPTS = 4;
|
|
55604
|
+
const NEW_CONVERSATION_TTL_MS = 5 * 60 * 1000;
|
|
55605
|
+
const NEW_CONVERSATION_KEY = 'pendo_pca_new_conv';
|
|
55606
|
+
class DOMConversation {
|
|
55607
|
+
// Returns the list of required selector types that are missing or empty
|
|
55608
|
+
// in the given cssSelectors config. An empty array means the config is
|
|
55609
|
+
// valid for instantiation.
|
|
55610
|
+
static validateConfig(cssSelectors) {
|
|
55611
|
+
if (!Array.isArray(cssSelectors)) {
|
|
55612
|
+
return REQUIRED_SELECTORS.slice();
|
|
55613
|
+
}
|
|
55614
|
+
const present = new Set();
|
|
55615
|
+
for (const cfg of cssSelectors) {
|
|
55616
|
+
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
55617
|
+
continue;
|
|
55618
|
+
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
55619
|
+
try {
|
|
55620
|
+
RegExp(cfg.cssSelector);
|
|
55621
|
+
}
|
|
55622
|
+
catch (e) {
|
|
55623
|
+
continue;
|
|
55624
|
+
}
|
|
55625
|
+
}
|
|
55626
|
+
present.add(cfg.type);
|
|
55627
|
+
}
|
|
55628
|
+
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
55629
|
+
}
|
|
55630
|
+
static supportedPreset(preset) {
|
|
55631
|
+
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
55632
|
+
}
|
|
55633
|
+
constructor(pendo, PluginAPI, id, cssSelectors) {
|
|
55548
55634
|
this.selectors = {};
|
|
55549
55635
|
this.listeners = [];
|
|
55550
55636
|
this.isActive = true;
|
|
@@ -55563,88 +55649,61 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55563
55649
|
this.Sizzle = pendo.Sizzle;
|
|
55564
55650
|
this.id = id;
|
|
55565
55651
|
if (!this._.isArray(cssSelectors)) {
|
|
55566
|
-
this.api.log.error(
|
|
55652
|
+
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
55567
55653
|
cssSelectors = [];
|
|
55568
55654
|
}
|
|
55569
|
-
this._.each(cssSelectors,
|
|
55655
|
+
this._.each(cssSelectors, (cfg) => {
|
|
55570
55656
|
if (cfg && cfg.type) {
|
|
55571
|
-
|
|
55657
|
+
this.selectors[cfg.type] = cfg.cssSelector;
|
|
55572
55658
|
}
|
|
55573
55659
|
});
|
|
55574
55660
|
this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
|
|
55575
|
-
|
|
55661
|
+
const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
|
|
55576
55662
|
if (customAgentIdUrlPattern) { // this is optional
|
|
55577
55663
|
try {
|
|
55578
55664
|
this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
|
|
55579
55665
|
}
|
|
55580
55666
|
catch (error) {
|
|
55581
|
-
this.api.log.error(
|
|
55667
|
+
this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
|
|
55582
55668
|
}
|
|
55583
55669
|
}
|
|
55584
|
-
|
|
55670
|
+
const messageIdPattern = this.selectors[MESSAGE_ID_PATTERN];
|
|
55585
55671
|
if (messageIdPattern) { // optional: gates the request node until its id is fully rendered
|
|
55586
55672
|
try {
|
|
55587
55673
|
this.messageIdRegex = new RegExp(messageIdPattern);
|
|
55588
55674
|
}
|
|
55589
55675
|
catch (error) {
|
|
55590
|
-
this.api.log.error(
|
|
55676
|
+
this.api.log.error(`bad messageIdPattern ${messageIdPattern}`, { error });
|
|
55591
55677
|
}
|
|
55592
55678
|
}
|
|
55593
55679
|
this.root = document.body;
|
|
55594
55680
|
this.setupReactionListener();
|
|
55595
55681
|
this.setupStreamingObserver();
|
|
55596
55682
|
}
|
|
55597
|
-
|
|
55598
|
-
// in the given cssSelectors config. An empty array means the config is
|
|
55599
|
-
// valid for instantiation.
|
|
55600
|
-
DOMConversation.validateConfig = function (cssSelectors) {
|
|
55601
|
-
if (!Array.isArray(cssSelectors)) {
|
|
55602
|
-
return REQUIRED_SELECTORS.slice();
|
|
55603
|
-
}
|
|
55604
|
-
var present = new Set();
|
|
55605
|
-
for (var _i = 0, cssSelectors_1 = cssSelectors; _i < cssSelectors_1.length; _i++) {
|
|
55606
|
-
var cfg = cssSelectors_1[_i];
|
|
55607
|
-
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
55608
|
-
continue;
|
|
55609
|
-
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
55610
|
-
try {
|
|
55611
|
-
RegExp(cfg.cssSelector);
|
|
55612
|
-
}
|
|
55613
|
-
catch (e) {
|
|
55614
|
-
continue;
|
|
55615
|
-
}
|
|
55616
|
-
}
|
|
55617
|
-
present.add(cfg.type);
|
|
55618
|
-
}
|
|
55619
|
-
return REQUIRED_SELECTORS.filter(function (r) { return !present.has(r); });
|
|
55620
|
-
};
|
|
55621
|
-
DOMConversation.supportedPreset = function (preset) {
|
|
55622
|
-
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
55623
|
-
};
|
|
55624
|
-
DOMConversation.prototype.setupReactionListener = function () {
|
|
55683
|
+
setupReactionListener() {
|
|
55625
55684
|
if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
|
|
55626
55685
|
return;
|
|
55627
55686
|
this.reactionClickHandler = this.handleReactionClick.bind(this);
|
|
55628
55687
|
this.root.addEventListener('click', this.reactionClickHandler, true);
|
|
55629
|
-
}
|
|
55630
|
-
|
|
55631
|
-
|
|
55688
|
+
}
|
|
55689
|
+
handleReactionClick(evt) {
|
|
55690
|
+
const target = evt.target;
|
|
55632
55691
|
if (!target || target.nodeType !== 1)
|
|
55633
55692
|
return;
|
|
55634
|
-
|
|
55635
|
-
|
|
55636
|
-
|
|
55693
|
+
const upSelector = this.findSelector(THUMB_UP);
|
|
55694
|
+
const downSelector = this.findSelector(THUMB_DOWN);
|
|
55695
|
+
const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
|
|
55637
55696
|
if (!thumb.length)
|
|
55638
55697
|
return;
|
|
55639
|
-
|
|
55640
|
-
|
|
55641
|
-
|
|
55642
|
-
|
|
55643
|
-
|
|
55698
|
+
const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
|
|
55699
|
+
const activeSelector = this.findSelector(REACTION_ACTIVE);
|
|
55700
|
+
const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
|
|
55701
|
+
const direction = isUp ? 'positive' : 'negative';
|
|
55702
|
+
const content = wasPressed ? 'unreact' : direction;
|
|
55644
55703
|
// the thumb may live inside the assistant message (e.g. copilot) or in a separate
|
|
55645
55704
|
// turn footer alongside it (e.g. chatgpt/gemini); handle both
|
|
55646
|
-
|
|
55647
|
-
|
|
55705
|
+
const assistantSelector = this.findSelector(ASSISTANT_MESSAGE);
|
|
55706
|
+
let assistantNode = thumb.closest(assistantSelector);
|
|
55648
55707
|
if (!assistantNode.length) {
|
|
55649
55708
|
assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
|
|
55650
55709
|
.find(assistantSelector);
|
|
@@ -55652,15 +55711,15 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55652
55711
|
this.emit('user_reaction', {
|
|
55653
55712
|
agentId: this.id,
|
|
55654
55713
|
messageId: this.getMessageId(assistantNode),
|
|
55655
|
-
content
|
|
55714
|
+
content
|
|
55656
55715
|
});
|
|
55657
|
-
}
|
|
55716
|
+
}
|
|
55658
55717
|
// On a new M365 conversation the browser does a full page reload to the
|
|
55659
55718
|
// conversation URL. the old page sets FRESH_CONVERSATION_KEY when streaming starts
|
|
55660
55719
|
// without a conversation id; the new page picks it up here and triggers onSubmissionEnd
|
|
55661
55720
|
// to scan the already-rendered messages.
|
|
55662
|
-
|
|
55663
|
-
|
|
55721
|
+
tryFlushNewConversation() {
|
|
55722
|
+
const ts = +this.api.sessionStorage.getItem(NEW_CONVERSATION_KEY);
|
|
55664
55723
|
if (!ts)
|
|
55665
55724
|
return;
|
|
55666
55725
|
this.api.sessionStorage.removeItem(NEW_CONVERSATION_KEY);
|
|
@@ -55669,14 +55728,14 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55669
55728
|
if (!this.getConversationId())
|
|
55670
55729
|
return;
|
|
55671
55730
|
this.startStreamingEndTimer();
|
|
55672
|
-
}
|
|
55731
|
+
}
|
|
55673
55732
|
// observe the streaming indicator
|
|
55674
|
-
|
|
55733
|
+
setupStreamingObserver() {
|
|
55675
55734
|
this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
55676
55735
|
this.stopStreamingEndTimer();
|
|
55677
|
-
|
|
55678
|
-
|
|
55679
|
-
|
|
55736
|
+
const MutationObserver = getZoneSafeMethod(this._, 'MutationObserver');
|
|
55737
|
+
const observer = new MutationObserver(this.handleMutation.bind(this));
|
|
55738
|
+
const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
|
|
55680
55739
|
observer.observe(this.root, {
|
|
55681
55740
|
childList: true,
|
|
55682
55741
|
subtree: true,
|
|
@@ -55684,7 +55743,7 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55684
55743
|
attributeFilter: attrName ? [attrName] : undefined
|
|
55685
55744
|
});
|
|
55686
55745
|
this.observers.push(observer);
|
|
55687
|
-
}
|
|
55746
|
+
}
|
|
55688
55747
|
// look for changes in the state of the streaming indicator.
|
|
55689
55748
|
// streaming started -> a prompt has been submitted
|
|
55690
55749
|
// streaming ended -> got a response
|
|
@@ -55693,8 +55752,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55693
55752
|
// we don't send the agent_response immediately when the streaming indicator is cleared
|
|
55694
55753
|
// because it clears slightly before the final text chunk is committed to the DOM so the
|
|
55695
55754
|
// end-handling is deferred by a short settle window
|
|
55696
|
-
|
|
55697
|
-
|
|
55755
|
+
handleMutation() {
|
|
55756
|
+
const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
55698
55757
|
if (isStreaming === this.wasStreaming)
|
|
55699
55758
|
return;
|
|
55700
55759
|
if (isStreaming) { // started streaming
|
|
@@ -55717,9 +55776,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55717
55776
|
this.startStreamingEndTimer();
|
|
55718
55777
|
}
|
|
55719
55778
|
this.wasStreaming = isStreaming;
|
|
55720
|
-
}
|
|
55721
|
-
|
|
55722
|
-
if (attempt === void 0) { attempt = 1; }
|
|
55779
|
+
}
|
|
55780
|
+
onSubmissionStart(attempt = 1) {
|
|
55723
55781
|
this.requestNode = this.findLastRequestNode();
|
|
55724
55782
|
if (this.requestNode) {
|
|
55725
55783
|
this.handleUserMessage(this.requestNode);
|
|
@@ -55730,13 +55788,13 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55730
55788
|
if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
|
|
55731
55789
|
this.startSubmissionStartRetryTimer(attempt + 1);
|
|
55732
55790
|
}
|
|
55733
|
-
}
|
|
55734
|
-
|
|
55791
|
+
}
|
|
55792
|
+
onSubmissionEnd() {
|
|
55735
55793
|
this.stopSubmissionStartRetryTimer();
|
|
55736
55794
|
if (this.getConversationId()) {
|
|
55737
55795
|
this.api.sessionStorage.removeItem(NEW_CONVERSATION_KEY);
|
|
55738
55796
|
}
|
|
55739
|
-
|
|
55797
|
+
let requestNode = this.requestNode;
|
|
55740
55798
|
this.requestNode = null;
|
|
55741
55799
|
if (!requestNode) {
|
|
55742
55800
|
// onSubmissionStart didn't send, send it now
|
|
@@ -55745,26 +55803,26 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55745
55803
|
return;
|
|
55746
55804
|
this.handleUserMessage(requestNode);
|
|
55747
55805
|
}
|
|
55748
|
-
|
|
55806
|
+
const requestEl = requestNode[0];
|
|
55749
55807
|
if (!requestEl)
|
|
55750
55808
|
return;
|
|
55751
55809
|
// the request is the latest user message, so any assistant message that
|
|
55752
55810
|
// follows it in the DOM is a response to it. document order is already
|
|
55753
55811
|
// chronological, so we emit as we go
|
|
55754
|
-
|
|
55755
|
-
for (
|
|
55756
|
-
|
|
55812
|
+
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
55813
|
+
for (let i = 0; i < assistantNodes.length; i++) {
|
|
55814
|
+
const el = assistantNodes[i];
|
|
55757
55815
|
if (requestEl.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
55758
55816
|
this.handleAssistantMessage(this.dom(el));
|
|
55759
55817
|
}
|
|
55760
55818
|
}
|
|
55761
|
-
}
|
|
55762
|
-
|
|
55763
|
-
|
|
55819
|
+
}
|
|
55820
|
+
extractContent(node) {
|
|
55821
|
+
let source = node;
|
|
55764
55822
|
// optional: content inside a descendant
|
|
55765
|
-
|
|
55823
|
+
const contentSelector = this.findSelector(MESSAGE_CONTENT);
|
|
55766
55824
|
if (contentSelector) {
|
|
55767
|
-
|
|
55825
|
+
const contentNode = node.find(contentSelector);
|
|
55768
55826
|
if (contentNode.length) {
|
|
55769
55827
|
source = contentNode;
|
|
55770
55828
|
}
|
|
@@ -55772,59 +55830,59 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55772
55830
|
// .text() reads innerText, which is empty for content-visibility:auto / off-screen subtrees
|
|
55773
55831
|
// (e.g. claude.ai's scrolled-up messages). Keep innerText as the primary source so agents
|
|
55774
55832
|
// whose content already works are unchanged, and fall back to textContent only when it's empty.
|
|
55775
|
-
|
|
55833
|
+
const primary = source.text().trim();
|
|
55776
55834
|
if (primary)
|
|
55777
55835
|
return primary;
|
|
55778
55836
|
return source[0].textContent.trim();
|
|
55779
|
-
}
|
|
55780
|
-
|
|
55781
|
-
|
|
55837
|
+
}
|
|
55838
|
+
getMessageId(node) {
|
|
55839
|
+
const attr = this.findSelector(MESSAGE_ID_ATTR);
|
|
55782
55840
|
if (!attr) {
|
|
55783
55841
|
return this.syntheticMessageId(node[0]);
|
|
55784
55842
|
}
|
|
55785
55843
|
return node.attr(attr);
|
|
55786
|
-
}
|
|
55844
|
+
}
|
|
55787
55845
|
// Agents with no DOM message id (e.g. claude.ai) get a synthetic id based on the role and
|
|
55788
55846
|
// position in document order.
|
|
55789
|
-
|
|
55847
|
+
syntheticMessageId(el) {
|
|
55790
55848
|
if (!el)
|
|
55791
55849
|
return undefined;
|
|
55792
|
-
|
|
55793
|
-
|
|
55794
|
-
|
|
55795
|
-
|
|
55796
|
-
for (
|
|
55850
|
+
const userSelector = this.findSelector(USER_MESSAGE);
|
|
55851
|
+
const isUser = userSelector && this.Sizzle.matchesSelector(el, userSelector);
|
|
55852
|
+
const role = isUser ? 'u' : 'a';
|
|
55853
|
+
const siblings = this.select(isUser ? USER_MESSAGE : ASSISTANT_MESSAGE);
|
|
55854
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
55797
55855
|
if (siblings[i] === el) {
|
|
55798
|
-
return
|
|
55856
|
+
return `${role}-${i}`;
|
|
55799
55857
|
}
|
|
55800
55858
|
}
|
|
55801
55859
|
return undefined; // el isn't among the rendered messages — no meaningful index
|
|
55802
|
-
}
|
|
55803
|
-
|
|
55860
|
+
}
|
|
55861
|
+
handleUserMessage(node) {
|
|
55804
55862
|
this.emit('prompt', {
|
|
55805
55863
|
agentId: this.id,
|
|
55806
55864
|
messageId: this.getMessageId(node),
|
|
55807
55865
|
content: this.extractContent(node)
|
|
55808
55866
|
});
|
|
55809
|
-
}
|
|
55810
|
-
|
|
55811
|
-
|
|
55812
|
-
|
|
55867
|
+
}
|
|
55868
|
+
handleAssistantMessage(node) {
|
|
55869
|
+
const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
|
|
55870
|
+
const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
|
|
55813
55871
|
this.emit('agent_response', {
|
|
55814
55872
|
agentId: this.id,
|
|
55815
55873
|
messageId: this.getMessageId(node),
|
|
55816
55874
|
agentModelsUsed: modelUsed ? [modelUsed] : [],
|
|
55817
55875
|
content: this.extractContent(node)
|
|
55818
55876
|
});
|
|
55819
|
-
}
|
|
55820
|
-
|
|
55877
|
+
}
|
|
55878
|
+
findLastRequestNode() {
|
|
55821
55879
|
if (!this.getConversationId())
|
|
55822
55880
|
return null;
|
|
55823
|
-
|
|
55881
|
+
const node = this._.last(this.select(USER_MESSAGE));
|
|
55824
55882
|
if (!node)
|
|
55825
55883
|
return null;
|
|
55826
|
-
|
|
55827
|
-
|
|
55884
|
+
const $node = this.dom(node);
|
|
55885
|
+
const messageId = this.getMessageId($node);
|
|
55828
55886
|
if (!messageId)
|
|
55829
55887
|
return null;
|
|
55830
55888
|
// the node may still be rendering (e.g. a framework interpolating an
|
|
@@ -55836,99 +55894,97 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55836
55894
|
return null;
|
|
55837
55895
|
this.lastReturnedMessageId = messageId;
|
|
55838
55896
|
return $node;
|
|
55839
|
-
}
|
|
55840
|
-
|
|
55897
|
+
}
|
|
55898
|
+
findSelector(type) {
|
|
55841
55899
|
return this.selectors[type];
|
|
55842
|
-
}
|
|
55843
|
-
|
|
55900
|
+
}
|
|
55901
|
+
select(type) {
|
|
55844
55902
|
return this.dom(this.findSelector(type), this.root);
|
|
55845
|
-
}
|
|
55846
|
-
|
|
55847
|
-
|
|
55903
|
+
}
|
|
55904
|
+
getConversationId() {
|
|
55905
|
+
const m = location.href.match(this.conversationIdRegex);
|
|
55848
55906
|
if (!m)
|
|
55849
55907
|
return null;
|
|
55850
55908
|
return m[1] !== undefined ? m[1] : m[0];
|
|
55851
|
-
}
|
|
55852
|
-
|
|
55909
|
+
}
|
|
55910
|
+
getCustomAgentId() {
|
|
55853
55911
|
if (!this.customAgentIdRegex)
|
|
55854
55912
|
return undefined;
|
|
55855
55913
|
// The id may live in the page URL (e.g. gemini /gem/<id>) or,
|
|
55856
55914
|
// when customAgentId is set, in the href of a DOM element
|
|
55857
|
-
|
|
55915
|
+
let source = location.href;
|
|
55858
55916
|
if (this.findSelector(CUSTOM_AGENT_ID)) {
|
|
55859
|
-
|
|
55917
|
+
const node = this.select(CUSTOM_AGENT_ID);
|
|
55860
55918
|
if (!node.length)
|
|
55861
55919
|
return undefined;
|
|
55862
55920
|
source = node.attr('href') || '';
|
|
55863
55921
|
}
|
|
55864
|
-
|
|
55922
|
+
const m = source.match(this.customAgentIdRegex);
|
|
55865
55923
|
if (!m)
|
|
55866
55924
|
return undefined;
|
|
55867
55925
|
return m[1] !== undefined ? m[1] : m[0];
|
|
55868
|
-
}
|
|
55869
|
-
|
|
55926
|
+
}
|
|
55927
|
+
getCustomAgentName() {
|
|
55870
55928
|
if (!this.findSelector(CUSTOM_AGENT_NAME))
|
|
55871
55929
|
return '';
|
|
55872
|
-
|
|
55930
|
+
const node = this.select(CUSTOM_AGENT_NAME);
|
|
55873
55931
|
if (!node.length)
|
|
55874
55932
|
return '';
|
|
55875
55933
|
return node.text().trim();
|
|
55876
|
-
}
|
|
55877
|
-
|
|
55878
|
-
|
|
55934
|
+
}
|
|
55935
|
+
addCustomAgentInfo(eventPayload) {
|
|
55936
|
+
const customAgentId = this.getCustomAgentId();
|
|
55879
55937
|
if (!customAgentId)
|
|
55880
55938
|
return;
|
|
55881
55939
|
eventPayload.customAgentId = customAgentId;
|
|
55882
|
-
|
|
55940
|
+
const customAgentName = this.getCustomAgentName();
|
|
55883
55941
|
if (customAgentName) {
|
|
55884
55942
|
eventPayload.customAgentName = customAgentName;
|
|
55885
55943
|
}
|
|
55886
|
-
}
|
|
55887
|
-
|
|
55944
|
+
}
|
|
55945
|
+
onSubmit(callback) {
|
|
55888
55946
|
this.listeners.push(callback);
|
|
55889
|
-
}
|
|
55890
|
-
|
|
55947
|
+
}
|
|
55948
|
+
emit(eventType, eventPayload) {
|
|
55891
55949
|
eventPayload.conversationId = this.getConversationId();
|
|
55892
55950
|
this.addCustomAgentInfo(eventPayload);
|
|
55893
|
-
this._.each(this.listeners,
|
|
55894
|
-
}
|
|
55895
|
-
|
|
55896
|
-
var _this = this;
|
|
55951
|
+
this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
|
|
55952
|
+
}
|
|
55953
|
+
startStreamingEndTimer() {
|
|
55897
55954
|
this.stopStreamingEndTimer();
|
|
55898
|
-
this.streamingEndTimer = setTimeout$1(
|
|
55899
|
-
|
|
55900
|
-
|
|
55955
|
+
this.streamingEndTimer = setTimeout$1(() => {
|
|
55956
|
+
this.streamingEndTimer = null;
|
|
55957
|
+
this.onSubmissionEnd();
|
|
55901
55958
|
}, STREAMING_END_SETTLE_MS);
|
|
55902
|
-
}
|
|
55903
|
-
|
|
55959
|
+
}
|
|
55960
|
+
stopStreamingEndTimer() {
|
|
55904
55961
|
if (!this.streamingEndTimer)
|
|
55905
55962
|
return;
|
|
55906
55963
|
clearTimeout(this.streamingEndTimer);
|
|
55907
55964
|
this.streamingEndTimer = null;
|
|
55908
|
-
}
|
|
55909
|
-
|
|
55910
|
-
var _this = this;
|
|
55965
|
+
}
|
|
55966
|
+
startSubmissionStartRetryTimer(attempt) {
|
|
55911
55967
|
this.stopSubmissionStartRetryTimer();
|
|
55912
|
-
this.submissionStartRetryTimer = setTimeout$1(
|
|
55913
|
-
|
|
55914
|
-
|
|
55968
|
+
this.submissionStartRetryTimer = setTimeout$1(() => {
|
|
55969
|
+
this.submissionStartRetryTimer = null;
|
|
55970
|
+
this.onSubmissionStart(attempt);
|
|
55915
55971
|
}, SUBMISSION_START_RETRY_MS);
|
|
55916
|
-
}
|
|
55917
|
-
|
|
55972
|
+
}
|
|
55973
|
+
stopSubmissionStartRetryTimer() {
|
|
55918
55974
|
if (!this.submissionStartRetryTimer)
|
|
55919
55975
|
return;
|
|
55920
55976
|
clearTimeout(this.submissionStartRetryTimer);
|
|
55921
55977
|
this.submissionStartRetryTimer = null;
|
|
55922
|
-
}
|
|
55923
|
-
|
|
55978
|
+
}
|
|
55979
|
+
suspend() {
|
|
55924
55980
|
this.isActive = false;
|
|
55925
|
-
}
|
|
55926
|
-
|
|
55981
|
+
}
|
|
55982
|
+
resume() {
|
|
55927
55983
|
this.isActive = true;
|
|
55928
55984
|
this.tryFlushNewConversation();
|
|
55929
|
-
}
|
|
55930
|
-
|
|
55931
|
-
this._.each(this.observers,
|
|
55985
|
+
}
|
|
55986
|
+
teardown() {
|
|
55987
|
+
this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
|
|
55932
55988
|
this.observers = [];
|
|
55933
55989
|
if (this.reactionClickHandler && this.root) {
|
|
55934
55990
|
this.root.removeEventListener('click', this.reactionClickHandler, true);
|
|
@@ -55937,9 +55993,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55937
55993
|
this.stopStreamingEndTimer();
|
|
55938
55994
|
this.stopSubmissionStartRetryTimer();
|
|
55939
55995
|
this.listeners = [];
|
|
55940
|
-
}
|
|
55941
|
-
|
|
55942
|
-
}());
|
|
55996
|
+
}
|
|
55997
|
+
}
|
|
55943
55998
|
|
|
55944
55999
|
/*
|
|
55945
56000
|
* Conversation Analytics Plugin
|
|
@@ -55949,21 +56004,21 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55949
56004
|
* The sibling built-in PromptAnalytics plugin owns the network + DOMPrompt AI-agents
|
|
55950
56005
|
*/
|
|
55951
56006
|
function ConversationAnalytics() {
|
|
55952
|
-
|
|
55953
|
-
|
|
55954
|
-
|
|
55955
|
-
|
|
55956
|
-
|
|
55957
|
-
|
|
55958
|
-
|
|
56007
|
+
let pendo;
|
|
56008
|
+
let api;
|
|
56009
|
+
let _;
|
|
56010
|
+
let log;
|
|
56011
|
+
let conversations = [];
|
|
56012
|
+
let agentsCache = new Map();
|
|
56013
|
+
const CONFIG_NAME = 'aiAgents';
|
|
55959
56014
|
return {
|
|
55960
56015
|
name: 'ConversationAnalytics',
|
|
55961
|
-
initialize
|
|
55962
|
-
teardown
|
|
55963
|
-
onConfigLoaded
|
|
55964
|
-
observeConversation
|
|
55965
|
-
sendConversationEvent
|
|
55966
|
-
reEvaluatePageRules
|
|
56016
|
+
initialize,
|
|
56017
|
+
teardown,
|
|
56018
|
+
onConfigLoaded,
|
|
56019
|
+
observeConversation,
|
|
56020
|
+
sendConversationEvent,
|
|
56021
|
+
reEvaluatePageRules
|
|
55967
56022
|
};
|
|
55968
56023
|
function initialize(pendoGlobal, PluginAPI) {
|
|
55969
56024
|
var _a;
|
|
@@ -55971,7 +56026,7 @@ function ConversationAnalytics() {
|
|
|
55971
56026
|
api = PluginAPI;
|
|
55972
56027
|
_ = pendo._;
|
|
55973
56028
|
log = api.log;
|
|
55974
|
-
|
|
56029
|
+
const { ConfigReader } = api;
|
|
55975
56030
|
ConfigReader.addOption(CONFIG_NAME, [
|
|
55976
56031
|
ConfigReader.sources.PENDO_CONFIG_SRC,
|
|
55977
56032
|
ConfigReader.sources.SNIPPET_SRC
|
|
@@ -55984,13 +56039,12 @@ function ConversationAnalytics() {
|
|
|
55984
56039
|
// Test if the current URL matches the page rule for an agent. The raw matcher lives in core
|
|
55985
56040
|
// and is reached through PluginAPI (independent plugins cannot import it directly); it falls
|
|
55986
56041
|
// back to the normalized URL internally when no URL is passed.
|
|
55987
|
-
function testPageRule(pageRule, agentId) {
|
|
55988
|
-
if (agentId === void 0) { agentId = 'unknown'; }
|
|
56042
|
+
function testPageRule(pageRule, agentId = 'unknown') {
|
|
55989
56043
|
// Convert //*/agent pattern to work with full URLs
|
|
55990
|
-
|
|
56044
|
+
let fixedPageRule = pageRule;
|
|
55991
56045
|
if (Array.isArray(pageRule)) {
|
|
55992
|
-
|
|
55993
|
-
fixedPageRule = _.map(validRules,
|
|
56046
|
+
const validRules = _.filter(pageRule, rule => rule && rule.trim() !== '');
|
|
56047
|
+
fixedPageRule = _.map(validRules, rule => rule.startsWith('//*/') ? rule.substring(1) : rule);
|
|
55994
56048
|
}
|
|
55995
56049
|
else if (typeof pageRule === 'string' && pageRule.startsWith('//*/')) {
|
|
55996
56050
|
fixedPageRule = pageRule.substring(1);
|
|
@@ -56002,9 +56056,9 @@ function ConversationAnalytics() {
|
|
|
56002
56056
|
});
|
|
56003
56057
|
}
|
|
56004
56058
|
function reEvaluatePageRules() {
|
|
56005
|
-
_.each(conversations,
|
|
56006
|
-
|
|
56007
|
-
|
|
56059
|
+
_.each(conversations, conversation => {
|
|
56060
|
+
const agent = findAgentById(conversation.id);
|
|
56061
|
+
const shouldBeActive = agent && testPageRule(agent.pageRule, agent.id);
|
|
56008
56062
|
if (shouldBeActive) {
|
|
56009
56063
|
conversation.resume();
|
|
56010
56064
|
}
|
|
@@ -56012,14 +56066,14 @@ function ConversationAnalytics() {
|
|
|
56012
56066
|
conversation.suspend();
|
|
56013
56067
|
}
|
|
56014
56068
|
});
|
|
56015
|
-
|
|
56016
|
-
|
|
56017
|
-
_.each(allAgents,
|
|
56069
|
+
const currentlyActiveIds = _.map(_.filter(conversations, conversation => conversation.isActive), conversation => conversation.id);
|
|
56070
|
+
const allAgents = api.ConfigReader.get(CONFIG_NAME) || [];
|
|
56071
|
+
_.each(allAgents, aiAgent => {
|
|
56018
56072
|
if (!isConversationAgent(aiAgent)) {
|
|
56019
56073
|
return;
|
|
56020
56074
|
}
|
|
56021
|
-
|
|
56022
|
-
|
|
56075
|
+
const isCurrentlyActive = _.contains(currentlyActiveIds, aiAgent.id);
|
|
56076
|
+
const shouldBeActive = testPageRule(aiAgent.pageRule, aiAgent.id);
|
|
56023
56077
|
if (shouldBeActive && !isCurrentlyActive) {
|
|
56024
56078
|
observeConversation(aiAgent);
|
|
56025
56079
|
}
|
|
@@ -56033,13 +56087,12 @@ function ConversationAnalytics() {
|
|
|
56033
56087
|
function isConversationAgent(agent) {
|
|
56034
56088
|
return DOMConversation.supportedPreset(agent.preset);
|
|
56035
56089
|
}
|
|
56036
|
-
function onConfigLoaded(aiAgents) {
|
|
56037
|
-
if (aiAgents === void 0) { aiAgents = []; }
|
|
56090
|
+
function onConfigLoaded(aiAgents = []) {
|
|
56038
56091
|
if (!aiAgents || !_.isArray(aiAgents) || aiAgents.length === 0) {
|
|
56039
56092
|
return;
|
|
56040
56093
|
}
|
|
56041
56094
|
agentsCache.clear();
|
|
56042
|
-
_.each(aiAgents,
|
|
56095
|
+
_.each(aiAgents, aiAgent => {
|
|
56043
56096
|
if (!isConversationAgent(aiAgent)) {
|
|
56044
56097
|
return;
|
|
56045
56098
|
}
|
|
@@ -56050,24 +56103,24 @@ function ConversationAnalytics() {
|
|
|
56050
56103
|
});
|
|
56051
56104
|
}
|
|
56052
56105
|
function observeConversation(config) {
|
|
56053
|
-
|
|
56106
|
+
const { id, cssSelectors } = config;
|
|
56054
56107
|
// Check if this agent is already being tracked
|
|
56055
|
-
|
|
56108
|
+
const existing = _.find(conversations, conversation => conversation.id === id);
|
|
56056
56109
|
if (existing) {
|
|
56057
56110
|
return;
|
|
56058
56111
|
}
|
|
56059
|
-
|
|
56112
|
+
const missing = DOMConversation.validateConfig(cssSelectors);
|
|
56060
56113
|
if (missing.length) {
|
|
56061
|
-
log.error('aiAgent config missing required selectors', { agentId: id, missing
|
|
56114
|
+
log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
56062
56115
|
return;
|
|
56063
56116
|
}
|
|
56064
|
-
|
|
56117
|
+
const conversation = new DOMConversation(pendo, api, id, cssSelectors);
|
|
56065
56118
|
conversation.onSubmit(sendConversationEvent);
|
|
56066
56119
|
conversations.push(conversation);
|
|
56067
56120
|
}
|
|
56068
56121
|
function sendConversationEvent(eventType, eventPayload) {
|
|
56069
56122
|
// Block event if the conversation is suspended
|
|
56070
|
-
|
|
56123
|
+
const conversation = _.find(conversations, c => c.id === eventPayload.agentId);
|
|
56071
56124
|
if (conversation && !conversation.isActive) {
|
|
56072
56125
|
return;
|
|
56073
56126
|
}
|
|
@@ -56075,7 +56128,7 @@ function ConversationAnalytics() {
|
|
|
56075
56128
|
api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
|
|
56076
56129
|
}
|
|
56077
56130
|
function teardown() {
|
|
56078
|
-
_.each(conversations,
|
|
56131
|
+
_.each(conversations, conversation => conversation.teardown());
|
|
56079
56132
|
conversations = [];
|
|
56080
56133
|
agentsCache.clear();
|
|
56081
56134
|
}
|