@thoughtspot/visual-embed-sdk 1.28.0-alpha.5 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cjs/package.json +2 -2
- package/cjs/src/auth.d.ts.map +1 -1
- package/cjs/src/auth.js +2 -2
- package/cjs/src/auth.js.map +1 -1
- package/cjs/src/authToken.d.ts +0 -6
- package/cjs/src/authToken.d.ts.map +1 -1
- package/cjs/src/authToken.js +0 -6
- package/cjs/src/authToken.js.map +1 -1
- package/cjs/src/embed/app.d.ts +13 -20
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +2 -2
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/base.d.ts +1 -1
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +5 -7
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/base.spec.js +1 -1
- package/cjs/src/embed/base.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +2 -8
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/search.d.ts +5 -11
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +4 -4
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +6 -6
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +18 -9
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +0 -1
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +1 -3
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +12 -0
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +36 -29
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +23 -12
- package/cjs/src/types.js.map +1 -1
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/authToken.d.ts +0 -6
- package/dist/src/authToken.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +13 -20
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +1 -1
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +2 -8
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/search.d.ts +5 -11
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +36 -29
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +1465 -1460
- package/dist/tsembed-react.js +2225 -2233
- package/dist/tsembed.es.js +1850 -1846
- package/dist/tsembed.js +15342 -15352
- package/dist/visual-embed-sdk-react-full.d.ts +54 -75
- package/dist/visual-embed-sdk-react.d.ts +54 -75
- package/dist/visual-embed-sdk.d.ts +54 -75
- package/lib/package.json +2 -2
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +3 -3
- package/lib/src/auth.js.map +1 -1
- package/lib/src/authToken.d.ts +0 -6
- package/lib/src/authToken.d.ts.map +1 -1
- package/lib/src/authToken.js +0 -6
- package/lib/src/authToken.js.map +1 -1
- package/lib/src/embed/app.d.ts +13 -20
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +2 -2
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/base.d.ts +1 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +5 -7
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +2 -2
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +2 -8
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +1 -1
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/search.d.ts +5 -11
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +5 -5
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +9 -9
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +18 -9
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +0 -1
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +0 -1
- package/lib/src/index.js.map +1 -1
- package/lib/src/react/index.spec.js +12 -0
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +36 -29
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +23 -12
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/authService/authService.spec.js +1 -1
- package/lib/src/utils/authService/authService.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +58 -83
- package/package.json +2 -2
- package/src/auth.ts +6 -6
- package/src/authToken.ts +0 -6
- package/src/embed/app.ts +15 -27
- package/src/embed/base.spec.ts +3 -3
- package/src/embed/base.ts +12 -14
- package/src/embed/liveboard.ts +3 -16
- package/src/embed/search.ts +10 -19
- package/src/embed/ts-embed.spec.ts +34 -26
- package/src/embed/ts-embed.ts +39 -43
- package/src/index.ts +0 -2
- package/src/react/index.spec.tsx +29 -0
- package/src/types.ts +37 -29
- package/src/utils/authService/authService.spec.ts +4 -4
package/dist/tsembed-react.js
CHANGED
|
@@ -572,6 +572,7 @@
|
|
|
572
572
|
* .then((data) => data.token);
|
|
573
573
|
* }
|
|
574
574
|
* });
|
|
575
|
+
* });
|
|
575
576
|
* ```
|
|
576
577
|
*/
|
|
577
578
|
AuthType["TrustedAuthToken"] = "AuthServer";
|
|
@@ -606,27 +607,27 @@
|
|
|
606
607
|
})(AuthType || (AuthType = {}));
|
|
607
608
|
(function (HomeLeftNavItem) {
|
|
608
609
|
/**
|
|
609
|
-
* @version SDK: 1.
|
|
610
|
+
* @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
|
|
610
611
|
*/
|
|
611
612
|
HomeLeftNavItem["SearchData"] = "search-data";
|
|
612
613
|
/**
|
|
613
|
-
* @version SDK: 1.
|
|
614
|
+
* @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
|
|
614
615
|
*/
|
|
615
616
|
HomeLeftNavItem["Home"] = "insights-home";
|
|
616
617
|
/**
|
|
617
|
-
* @version SDK: 1.
|
|
618
|
+
* @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
|
|
618
619
|
*/
|
|
619
620
|
HomeLeftNavItem["Liveboards"] = "liveboards";
|
|
620
621
|
/**
|
|
621
|
-
* @version SDK: 1.
|
|
622
|
+
* @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
|
|
622
623
|
*/
|
|
623
624
|
HomeLeftNavItem["Answers"] = "answers";
|
|
624
625
|
/**
|
|
625
|
-
* @version SDK: 1.
|
|
626
|
+
* @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
|
|
626
627
|
*/
|
|
627
628
|
HomeLeftNavItem["MonitorSubscription"] = "monitor-alerts";
|
|
628
629
|
/**
|
|
629
|
-
* @version SDK: 1.
|
|
630
|
+
* @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl
|
|
630
631
|
*/
|
|
631
632
|
HomeLeftNavItem["SpotIQAnalysis"] = "spotiq-analysis";
|
|
632
633
|
})(exports.HomeLeftNavItem || (exports.HomeLeftNavItem = {}));
|
|
@@ -707,10 +708,6 @@
|
|
|
707
708
|
HomepageModule["MyLibrary"] = "MY_LIBRARY";
|
|
708
709
|
/**
|
|
709
710
|
* Trending list
|
|
710
|
-
*
|
|
711
|
-
* **Note**: This option does not apply to the classic homepage.
|
|
712
|
-
* To access the updated modular homepage, set
|
|
713
|
-
* `modularHomeExperience` to `true` (available in Early Access from 9.12.0.cl onwards).
|
|
714
711
|
*/
|
|
715
712
|
HomepageModule["Trending"] = "TRENDING";
|
|
716
713
|
/**
|
|
@@ -904,7 +901,8 @@
|
|
|
904
901
|
*
|
|
905
902
|
* API - API call failure error.
|
|
906
903
|
*
|
|
907
|
-
* FULLSCREEN - Error when presenting a Liveboard or visualization in full screen
|
|
904
|
+
* FULLSCREEN - Error when presenting a Liveboard or visualization in full screen
|
|
905
|
+
* mode.
|
|
908
906
|
*
|
|
909
907
|
* SINGLE_VALUE_FILTER - Error due to multiple values in the single value filter.
|
|
910
908
|
*
|
|
@@ -5713,6 +5711,8 @@
|
|
|
5713
5711
|
|
|
5714
5712
|
var isEqual_1 = isEqual;
|
|
5715
5713
|
|
|
5714
|
+
var name="@thoughtspot/visual-embed-sdk";var version="1.28.0";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^46.9.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports$1,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"45 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
|
|
5715
|
+
|
|
5716
5716
|
/**
|
|
5717
5717
|
* Checks if `value` is `undefined`.
|
|
5718
5718
|
*
|
|
@@ -5985,585 +5985,38 @@
|
|
|
5985
5985
|
throw new Error(INVALID_TOKEN_ERR);
|
|
5986
5986
|
}
|
|
5987
5987
|
};
|
|
5988
|
-
/**
|
|
5989
|
-
* Resets the auth token and a new token will be fetched on the next request.
|
|
5990
|
-
*
|
|
5991
|
-
* @version SDK: 1.28.0 | ThoughtSpot: *
|
|
5992
|
-
* @group Authentication / Init
|
|
5993
|
-
*/
|
|
5994
5988
|
const resetCachedAuthToken = () => {
|
|
5995
5989
|
cachedAuthToken = null;
|
|
5996
5990
|
};
|
|
5997
5991
|
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
*
|
|
6002
|
-
* @returns {@link EmbedConfig} The configuration embed was initialized with.
|
|
6003
|
-
* @version SDK: 1.19.0 | ThoughtSpot: *
|
|
6004
|
-
* @group Global methods
|
|
6005
|
-
*/
|
|
6006
|
-
const getEmbedConfig = () => config;
|
|
6007
|
-
|
|
6008
|
-
/**
|
|
6009
|
-
* Fetch wrapper that adds the authentication token to the request.
|
|
6010
|
-
* Use this to call the ThoughtSpot APIs when using the visual embed sdk.
|
|
6011
|
-
*
|
|
6012
|
-
* @param input
|
|
6013
|
-
* @param init
|
|
6014
|
-
* @version SDK: 1.28.0
|
|
6015
|
-
* @group Global methods
|
|
6016
|
-
*/
|
|
6017
|
-
const tokenizedFetch = async (input, init) => {
|
|
6018
|
-
const embedConfig = getEmbedConfig();
|
|
6019
|
-
if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
|
|
6020
|
-
return fetch(input, init);
|
|
6021
|
-
}
|
|
6022
|
-
const req = new Request(input, init);
|
|
6023
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
6024
|
-
if (authToken) {
|
|
6025
|
-
req.headers.append('Authorization', `Bearer ${authToken}`);
|
|
6026
|
-
}
|
|
6027
|
-
return fetch(req);
|
|
5992
|
+
var Config = {
|
|
5993
|
+
DEBUG: false,
|
|
5994
|
+
LIB_VERSION: '2.45.0'
|
|
6028
5995
|
};
|
|
6029
5996
|
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
'accept-language': 'en-us',
|
|
6048
|
-
},
|
|
6049
|
-
body: JSON.stringify({
|
|
6050
|
-
operationName,
|
|
6051
|
-
query,
|
|
6052
|
-
variables,
|
|
6053
|
-
}),
|
|
6054
|
-
credentials: 'include',
|
|
6055
|
-
});
|
|
6056
|
-
const result = await response.json();
|
|
6057
|
-
const dataValues = Object.values(result.data);
|
|
6058
|
-
return (isCompositeQuery) ? result.data : dataValues[0];
|
|
6059
|
-
}
|
|
6060
|
-
catch (error) {
|
|
6061
|
-
return error;
|
|
6062
|
-
}
|
|
6063
|
-
}
|
|
6064
|
-
|
|
6065
|
-
const getSourceDetailQuery = `
|
|
6066
|
-
query GetSourceDetail($ids: [GUID!]!) {
|
|
6067
|
-
getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
|
|
6068
|
-
id
|
|
6069
|
-
name
|
|
6070
|
-
description
|
|
6071
|
-
authorName
|
|
6072
|
-
authorDisplayName
|
|
6073
|
-
isExternal
|
|
6074
|
-
type
|
|
6075
|
-
created
|
|
6076
|
-
modified
|
|
6077
|
-
columns {
|
|
6078
|
-
id
|
|
6079
|
-
name
|
|
6080
|
-
author
|
|
6081
|
-
authorDisplayName
|
|
6082
|
-
description
|
|
6083
|
-
dataType
|
|
6084
|
-
type
|
|
6085
|
-
modified
|
|
6086
|
-
ownerName
|
|
6087
|
-
owner
|
|
6088
|
-
dataRecency
|
|
6089
|
-
sources {
|
|
6090
|
-
tableId
|
|
6091
|
-
tableName
|
|
6092
|
-
columnId
|
|
6093
|
-
columnName
|
|
6094
|
-
__typename
|
|
6095
|
-
}
|
|
6096
|
-
synonyms
|
|
6097
|
-
cohortAnswerId
|
|
6098
|
-
__typename
|
|
6099
|
-
}
|
|
6100
|
-
relationships
|
|
6101
|
-
destinationRelationships
|
|
6102
|
-
dataSourceId
|
|
6103
|
-
__typename
|
|
6104
|
-
}
|
|
6105
|
-
}
|
|
6106
|
-
`;
|
|
6107
|
-
const sourceDetailCache = new Map();
|
|
6108
|
-
/**
|
|
6109
|
-
*
|
|
6110
|
-
* @param thoughtSpotHost
|
|
6111
|
-
* @param sourceId
|
|
6112
|
-
*/
|
|
6113
|
-
async function getSourceDetail(thoughtSpotHost, sourceId) {
|
|
6114
|
-
if (sourceDetailCache.get(sourceId)) {
|
|
6115
|
-
return sourceDetailCache.get(sourceId);
|
|
6116
|
-
}
|
|
6117
|
-
const details = await graphqlQuery({
|
|
6118
|
-
query: getSourceDetailQuery,
|
|
6119
|
-
variables: {
|
|
6120
|
-
ids: [sourceId],
|
|
6121
|
-
},
|
|
6122
|
-
thoughtSpotHost,
|
|
6123
|
-
});
|
|
6124
|
-
const souceDetails = details[0];
|
|
6125
|
-
if (souceDetails) {
|
|
6126
|
-
sourceDetailCache.set(sourceId, souceDetails);
|
|
6127
|
-
}
|
|
6128
|
-
return souceDetails;
|
|
5997
|
+
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
5998
|
+
var window$1;
|
|
5999
|
+
if (typeof(window) === 'undefined') {
|
|
6000
|
+
var loc = {
|
|
6001
|
+
hostname: ''
|
|
6002
|
+
};
|
|
6003
|
+
window$1 = {
|
|
6004
|
+
navigator: { userAgent: '' },
|
|
6005
|
+
document: {
|
|
6006
|
+
location: loc,
|
|
6007
|
+
referrer: ''
|
|
6008
|
+
},
|
|
6009
|
+
screen: { width: 0, height: 0 },
|
|
6010
|
+
location: loc
|
|
6011
|
+
};
|
|
6012
|
+
} else {
|
|
6013
|
+
window$1 = window;
|
|
6129
6014
|
}
|
|
6130
6015
|
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
acSession {
|
|
6136
|
-
sessionId
|
|
6137
|
-
genNo
|
|
6138
|
-
}
|
|
6139
|
-
}
|
|
6140
|
-
`;
|
|
6141
|
-
const getUnaggregatedAnswerSession = `
|
|
6142
|
-
mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
|
|
6143
|
-
Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
|
|
6144
|
-
${bachSessionId}
|
|
6145
|
-
answer {
|
|
6146
|
-
visualizations {
|
|
6147
|
-
... on TableViz {
|
|
6148
|
-
columns {
|
|
6149
|
-
column {
|
|
6150
|
-
id
|
|
6151
|
-
name
|
|
6152
|
-
referencedColumns {
|
|
6153
|
-
guid
|
|
6154
|
-
displayName
|
|
6155
|
-
}
|
|
6156
|
-
}
|
|
6157
|
-
}
|
|
6158
|
-
}
|
|
6159
|
-
}
|
|
6160
|
-
}
|
|
6161
|
-
}
|
|
6162
|
-
}
|
|
6163
|
-
`;
|
|
6164
|
-
const removeColumns = `
|
|
6165
|
-
mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
|
|
6166
|
-
Answer__removeColumns(
|
|
6167
|
-
session: $session
|
|
6168
|
-
logicalColumnIds: $logicalColumnIds
|
|
6169
|
-
columnIds: $columnIds
|
|
6170
|
-
) {
|
|
6171
|
-
${bachSessionId}
|
|
6172
|
-
}
|
|
6173
|
-
}
|
|
6174
|
-
`;
|
|
6175
|
-
const addColumns = `
|
|
6176
|
-
mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
|
|
6177
|
-
Answer__addColumn(session: $session, columns: $columns) {
|
|
6178
|
-
${bachSessionId}
|
|
6179
|
-
}
|
|
6180
|
-
}
|
|
6181
|
-
`;
|
|
6182
|
-
const getAnswerData = `
|
|
6183
|
-
query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
|
|
6184
|
-
getAnswer(session: $session) {
|
|
6185
|
-
${bachSessionId}
|
|
6186
|
-
answer {
|
|
6187
|
-
id
|
|
6188
|
-
visualizations {
|
|
6189
|
-
id
|
|
6190
|
-
... on TableViz {
|
|
6191
|
-
columns {
|
|
6192
|
-
column {
|
|
6193
|
-
id
|
|
6194
|
-
name
|
|
6195
|
-
type
|
|
6196
|
-
aggregationType
|
|
6197
|
-
dataType
|
|
6198
|
-
}
|
|
6199
|
-
}
|
|
6200
|
-
data(deadline: $deadline, pagination: $dataPaginationParams)
|
|
6201
|
-
}
|
|
6202
|
-
}
|
|
6203
|
-
}
|
|
6204
|
-
}
|
|
6205
|
-
}
|
|
6206
|
-
`;
|
|
6207
|
-
|
|
6208
|
-
// eslint-disable-next-line no-shadow
|
|
6209
|
-
var OperationType;
|
|
6210
|
-
(function (OperationType) {
|
|
6211
|
-
OperationType["GetChartWithData"] = "GetChartWithData";
|
|
6212
|
-
OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
|
|
6213
|
-
})(OperationType || (OperationType = {}));
|
|
6214
|
-
/**
|
|
6215
|
-
* Class representing the answer service provided with the
|
|
6216
|
-
* custom action payload. This service could be used to run
|
|
6217
|
-
* graphql queries in the context of the answer on which the
|
|
6218
|
-
* custom action was triggered.
|
|
6219
|
-
*
|
|
6220
|
-
* @example
|
|
6221
|
-
* ```js
|
|
6222
|
-
* embed.on(EmbedEvent.CustomAction, e => {
|
|
6223
|
-
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
6224
|
-
* 'col name 1'
|
|
6225
|
-
* ]);
|
|
6226
|
-
* const data = await underlying.fetchData(0, 100);
|
|
6227
|
-
* })
|
|
6228
|
-
* ```
|
|
6229
|
-
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
6230
|
-
* @group Events
|
|
6231
|
-
*/
|
|
6232
|
-
class AnswerService {
|
|
6233
|
-
/**
|
|
6234
|
-
* Should not need to be called directly.
|
|
6235
|
-
*
|
|
6236
|
-
* @param session
|
|
6237
|
-
* @param answer
|
|
6238
|
-
* @param thoughtSpotHost
|
|
6239
|
-
* @param selectedPoints
|
|
6240
|
-
*/
|
|
6241
|
-
constructor(session, answer, thoughtSpotHost, selectedPoints) {
|
|
6242
|
-
this.session = session;
|
|
6243
|
-
this.answer = answer;
|
|
6244
|
-
this.thoughtSpotHost = thoughtSpotHost;
|
|
6245
|
-
this.selectedPoints = selectedPoints;
|
|
6246
|
-
this.session = removeTypename(session);
|
|
6247
|
-
}
|
|
6248
|
-
/**
|
|
6249
|
-
* Get the details about the source used in the answer.
|
|
6250
|
-
* This can be used to get the list of all columns in the data source for example.
|
|
6251
|
-
*/
|
|
6252
|
-
async getSourceDetail() {
|
|
6253
|
-
const sourceId = this.answer.sources[0].header.guid;
|
|
6254
|
-
return getSourceDetail(this.thoughtSpotHost, sourceId);
|
|
6255
|
-
}
|
|
6256
|
-
/**
|
|
6257
|
-
* Remove columnIds and return updated answer session.
|
|
6258
|
-
*
|
|
6259
|
-
* @param columnIds
|
|
6260
|
-
* @returns
|
|
6261
|
-
*/
|
|
6262
|
-
async removeColumns(columnIds) {
|
|
6263
|
-
return this.executeQuery(removeColumns, {
|
|
6264
|
-
logicalColumnIds: columnIds,
|
|
6265
|
-
});
|
|
6266
|
-
}
|
|
6267
|
-
/**
|
|
6268
|
-
* Add columnIds and return updated answer session.
|
|
6269
|
-
*
|
|
6270
|
-
* @param columnIds
|
|
6271
|
-
* @returns
|
|
6272
|
-
*/
|
|
6273
|
-
async addColumns(columnIds) {
|
|
6274
|
-
return this.executeQuery(addColumns, {
|
|
6275
|
-
columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
|
|
6276
|
-
});
|
|
6277
|
-
}
|
|
6278
|
-
/**
|
|
6279
|
-
* Fetch data from the answer.
|
|
6280
|
-
*
|
|
6281
|
-
* @param offset
|
|
6282
|
-
* @param size
|
|
6283
|
-
* @returns
|
|
6284
|
-
*/
|
|
6285
|
-
async fetchData(offset = 0, size = 1000) {
|
|
6286
|
-
const { answer } = await this.executeQuery(getAnswerData, {
|
|
6287
|
-
deadline: 0,
|
|
6288
|
-
dataPaginationParams: {
|
|
6289
|
-
isClientPaginated: true,
|
|
6290
|
-
offset,
|
|
6291
|
-
size,
|
|
6292
|
-
},
|
|
6293
|
-
});
|
|
6294
|
-
const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
|
|
6295
|
-
return {
|
|
6296
|
-
columns,
|
|
6297
|
-
data,
|
|
6298
|
-
};
|
|
6299
|
-
}
|
|
6300
|
-
/**
|
|
6301
|
-
* Fetch the data for the answer as a CSV blob. This might be
|
|
6302
|
-
* quicker for larger data.
|
|
6303
|
-
*
|
|
6304
|
-
* @param userLocale
|
|
6305
|
-
* @param includeInfo Include the CSV header in the output
|
|
6306
|
-
* @returns Response
|
|
6307
|
-
*/
|
|
6308
|
-
async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
|
|
6309
|
-
const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
|
|
6310
|
-
return tokenizedFetch(fetchUrl, {
|
|
6311
|
-
credentials: 'include',
|
|
6312
|
-
});
|
|
6313
|
-
}
|
|
6314
|
-
/**
|
|
6315
|
-
* Just get the internal URL for this answer's data
|
|
6316
|
-
* as a CSV blob.
|
|
6317
|
-
*
|
|
6318
|
-
* @param userLocale
|
|
6319
|
-
* @param includeInfo
|
|
6320
|
-
* @returns
|
|
6321
|
-
*/
|
|
6322
|
-
getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
|
|
6323
|
-
return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
|
|
6324
|
-
}
|
|
6325
|
-
/**
|
|
6326
|
-
* Get underlying data given a point and the output column names.
|
|
6327
|
-
* In case of a context menu action, the selectedPoints are
|
|
6328
|
-
* automatically passed.
|
|
6329
|
-
*
|
|
6330
|
-
* @param outputColumnNames
|
|
6331
|
-
* @param selectedPoints
|
|
6332
|
-
* @example
|
|
6333
|
-
* ```js
|
|
6334
|
-
* embed.on(EmbedEvent.CustomAction, e => {
|
|
6335
|
-
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
6336
|
-
* 'col name 1' // The column should exist in the data source.
|
|
6337
|
-
* ]);
|
|
6338
|
-
* const data = await underlying.fetchData(0, 100);
|
|
6339
|
-
* })
|
|
6340
|
-
* ```
|
|
6341
|
-
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
6342
|
-
*/
|
|
6343
|
-
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
6344
|
-
if (!selectedPoints && !this.selectedPoints) {
|
|
6345
|
-
throw new Error('Needs to be triggered in context of a point');
|
|
6346
|
-
}
|
|
6347
|
-
if (!selectedPoints) {
|
|
6348
|
-
selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
|
|
6349
|
-
}
|
|
6350
|
-
const sourceDetail = await this.getSourceDetail();
|
|
6351
|
-
const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
|
|
6352
|
-
const unAggAnswer = await graphqlQuery({
|
|
6353
|
-
query: getUnaggregatedAnswerSession,
|
|
6354
|
-
variables: {
|
|
6355
|
-
session: this.session,
|
|
6356
|
-
columns: selectedPoints,
|
|
6357
|
-
},
|
|
6358
|
-
thoughtSpotHost: this.thoughtSpotHost,
|
|
6359
|
-
});
|
|
6360
|
-
const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
|
|
6361
|
-
const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
|
|
6362
|
-
.map((c) => c.column.referencedColumns[0].guid));
|
|
6363
|
-
const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
|
|
6364
|
-
if (columnsToAdd.length) {
|
|
6365
|
-
await unaggAnswerSession.addColumns(columnsToAdd);
|
|
6366
|
-
}
|
|
6367
|
-
const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
|
|
6368
|
-
if (columnsToRemove.length) {
|
|
6369
|
-
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
6370
|
-
}
|
|
6371
|
-
return unaggAnswerSession;
|
|
6372
|
-
}
|
|
6373
|
-
/**
|
|
6374
|
-
* Execute a custom graphql query in the context of the answer.
|
|
6375
|
-
*
|
|
6376
|
-
* @param query graphql query
|
|
6377
|
-
* @param variables graphql variables
|
|
6378
|
-
* @returns
|
|
6379
|
-
*/
|
|
6380
|
-
async executeQuery(query, variables) {
|
|
6381
|
-
const data = await graphqlQuery({
|
|
6382
|
-
query,
|
|
6383
|
-
variables: {
|
|
6384
|
-
session: this.session,
|
|
6385
|
-
...variables,
|
|
6386
|
-
},
|
|
6387
|
-
thoughtSpotHost: this.thoughtSpotHost,
|
|
6388
|
-
isCompositeQuery: false,
|
|
6389
|
-
});
|
|
6390
|
-
this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
|
|
6391
|
-
return data;
|
|
6392
|
-
}
|
|
6393
|
-
/**
|
|
6394
|
-
* Get the internal session details for the answer.
|
|
6395
|
-
*
|
|
6396
|
-
* @returns
|
|
6397
|
-
*/
|
|
6398
|
-
getSession() {
|
|
6399
|
-
return this.session;
|
|
6400
|
-
}
|
|
6401
|
-
}
|
|
6402
|
-
/**
|
|
6403
|
-
*
|
|
6404
|
-
* @param sourceDetail
|
|
6405
|
-
* @param colNames
|
|
6406
|
-
*/
|
|
6407
|
-
function getGuidsFromColumnNames(sourceDetail, colNames) {
|
|
6408
|
-
const cols = sourceDetail.columns.reduce((colSet, col) => {
|
|
6409
|
-
colSet[col.name] = col;
|
|
6410
|
-
return colSet;
|
|
6411
|
-
}, {});
|
|
6412
|
-
return new Set(colNames.map((colName) => {
|
|
6413
|
-
const col = cols[colName];
|
|
6414
|
-
return col.id;
|
|
6415
|
-
}));
|
|
6416
|
-
}
|
|
6417
|
-
/**
|
|
6418
|
-
*
|
|
6419
|
-
* @param selectedPoints
|
|
6420
|
-
*/
|
|
6421
|
-
function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
|
|
6422
|
-
const underlyingDataPoint = [];
|
|
6423
|
-
/**
|
|
6424
|
-
*
|
|
6425
|
-
* @param colVal
|
|
6426
|
-
*/
|
|
6427
|
-
function addPointFromColVal(colVal) {
|
|
6428
|
-
var _a;
|
|
6429
|
-
const dataType = colVal.column.dataType;
|
|
6430
|
-
const id = colVal.column.id;
|
|
6431
|
-
let dataValue;
|
|
6432
|
-
if (dataType === 'DATE') {
|
|
6433
|
-
if (Number.isFinite(colVal.value)) {
|
|
6434
|
-
dataValue = [{
|
|
6435
|
-
epochRange: {
|
|
6436
|
-
startEpoch: colVal.value,
|
|
6437
|
-
},
|
|
6438
|
-
}];
|
|
6439
|
-
// Case for custom calendar.
|
|
6440
|
-
}
|
|
6441
|
-
else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
|
|
6442
|
-
dataValue = [{
|
|
6443
|
-
epochRange: {
|
|
6444
|
-
startEpoch: colVal.value.v.s,
|
|
6445
|
-
endEpoch: colVal.value.v.e,
|
|
6446
|
-
},
|
|
6447
|
-
}];
|
|
6448
|
-
}
|
|
6449
|
-
}
|
|
6450
|
-
else {
|
|
6451
|
-
dataValue = [{ value: colVal.value }];
|
|
6452
|
-
}
|
|
6453
|
-
underlyingDataPoint.push({
|
|
6454
|
-
columnId: colVal.column.id,
|
|
6455
|
-
dataValue,
|
|
6456
|
-
});
|
|
6457
|
-
}
|
|
6458
|
-
selectedPoints.forEach((p) => {
|
|
6459
|
-
p.selectedAttributes.forEach(addPointFromColVal);
|
|
6460
|
-
});
|
|
6461
|
-
return underlyingDataPoint;
|
|
6462
|
-
}
|
|
6463
|
-
|
|
6464
|
-
const ERROR_MESSAGE = {
|
|
6465
|
-
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
6466
|
-
LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
|
|
6467
|
-
TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
|
|
6468
|
-
SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
|
|
6469
|
-
SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
|
|
6470
|
-
};
|
|
6471
|
-
|
|
6472
|
-
/**
|
|
6473
|
-
* Copyright (c) 2023
|
|
6474
|
-
*
|
|
6475
|
-
* Utilities related to reading configuration objects
|
|
6476
|
-
*
|
|
6477
|
-
* @summary Config-related utils
|
|
6478
|
-
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
6479
|
-
*/
|
|
6480
|
-
const urlRegex = new RegExp([
|
|
6481
|
-
'(^(https?:)//)?',
|
|
6482
|
-
'(([^:/?#]*)(?::([0-9]+))?)',
|
|
6483
|
-
'(/{0,1}[^?#]*)',
|
|
6484
|
-
'(\\?[^#]*|)',
|
|
6485
|
-
'(#.*|)$', // hash
|
|
6486
|
-
].join(''));
|
|
6487
|
-
/**
|
|
6488
|
-
* Parse and construct the ThoughtSpot hostname or IP address
|
|
6489
|
-
* from the embed configuration object.
|
|
6490
|
-
*
|
|
6491
|
-
* @param config
|
|
6492
|
-
*/
|
|
6493
|
-
const getThoughtSpotHost = (config) => {
|
|
6494
|
-
if (!config.thoughtSpotHost) {
|
|
6495
|
-
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
6496
|
-
}
|
|
6497
|
-
const urlParts = config.thoughtSpotHost.match(urlRegex);
|
|
6498
|
-
if (!urlParts) {
|
|
6499
|
-
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
6500
|
-
}
|
|
6501
|
-
const protocol = urlParts[2] || window.location.protocol;
|
|
6502
|
-
const host = urlParts[3];
|
|
6503
|
-
let path = urlParts[6];
|
|
6504
|
-
// Lose the trailing / if any
|
|
6505
|
-
if (path.charAt(path.length - 1) === '/') {
|
|
6506
|
-
path = path.substring(0, path.length - 1);
|
|
6507
|
-
}
|
|
6508
|
-
// const urlParams = urlParts[7];
|
|
6509
|
-
// const hash = urlParts[8];
|
|
6510
|
-
return `${protocol}//${host}${path}`;
|
|
6511
|
-
};
|
|
6512
|
-
const getV2BasePath = (config) => {
|
|
6513
|
-
if (config.basepath) {
|
|
6514
|
-
return config.basepath;
|
|
6515
|
-
}
|
|
6516
|
-
const tsHost = getThoughtSpotHost(config);
|
|
6517
|
-
// This is to handle when e2e's. Search is run on pods for
|
|
6518
|
-
// comp-blink-test-pipeline with baseUrl=https://localhost:8443.
|
|
6519
|
-
// This is to handle when the developer is developing in their local
|
|
6520
|
-
// environment.
|
|
6521
|
-
if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
|
|
6522
|
-
return '';
|
|
6523
|
-
}
|
|
6524
|
-
return 'v2';
|
|
6525
|
-
};
|
|
6526
|
-
/**
|
|
6527
|
-
* It is a good idea to keep URLs under 2000 chars.
|
|
6528
|
-
* If this is ever breached, since we pass view configuration through
|
|
6529
|
-
* URL params, we would like to log a warning.
|
|
6530
|
-
* Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
|
6531
|
-
*/
|
|
6532
|
-
const URL_MAX_LENGTH = 2000;
|
|
6533
|
-
/**
|
|
6534
|
-
* The default CSS dimensions of the embedded app
|
|
6535
|
-
*/
|
|
6536
|
-
const DEFAULT_EMBED_WIDTH = '100%';
|
|
6537
|
-
const DEFAULT_EMBED_HEIGHT = '100%';
|
|
6538
|
-
|
|
6539
|
-
var Config = {
|
|
6540
|
-
DEBUG: false,
|
|
6541
|
-
LIB_VERSION: '2.45.0'
|
|
6542
|
-
};
|
|
6543
|
-
|
|
6544
|
-
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
6545
|
-
var window$1;
|
|
6546
|
-
if (typeof(window) === 'undefined') {
|
|
6547
|
-
var loc = {
|
|
6548
|
-
hostname: ''
|
|
6549
|
-
};
|
|
6550
|
-
window$1 = {
|
|
6551
|
-
navigator: { userAgent: '' },
|
|
6552
|
-
document: {
|
|
6553
|
-
location: loc,
|
|
6554
|
-
referrer: ''
|
|
6555
|
-
},
|
|
6556
|
-
screen: { width: 0, height: 0 },
|
|
6557
|
-
location: loc
|
|
6558
|
-
};
|
|
6559
|
-
} else {
|
|
6560
|
-
window$1 = window;
|
|
6561
|
-
}
|
|
6562
|
-
|
|
6563
|
-
/*
|
|
6564
|
-
* Saved references to long variable names, so that closure compiler can
|
|
6565
|
-
* minimize file size.
|
|
6566
|
-
*/
|
|
6016
|
+
/*
|
|
6017
|
+
* Saved references to long variable names, so that closure compiler can
|
|
6018
|
+
* minimize file size.
|
|
6019
|
+
*/
|
|
6567
6020
|
|
|
6568
6021
|
var ArrayProto = Array.prototype;
|
|
6569
6022
|
var FuncProto = Function.prototype;
|
|
@@ -11456,1886 +10909,2427 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
|
|
|
11456
10909
|
*/
|
|
11457
10910
|
MixpanelLib.prototype.track_with_groups = addOptOutCheckMixpanelLib(function(event_name, properties, groups, callback) {
|
|
11458
10911
|
var tracking_props = _.extend({}, properties || {});
|
|
11459
|
-
_.each(groups, function(v, k) {
|
|
11460
|
-
if (v !== null && v !== undefined) {
|
|
11461
|
-
tracking_props[k] = v;
|
|
11462
|
-
}
|
|
11463
|
-
});
|
|
11464
|
-
return this.track(event_name, tracking_props, callback);
|
|
11465
|
-
});
|
|
11466
|
-
|
|
11467
|
-
MixpanelLib.prototype._create_map_key = function (group_key, group_id) {
|
|
11468
|
-
return group_key + '_' + JSON.stringify(group_id);
|
|
11469
|
-
};
|
|
11470
|
-
|
|
11471
|
-
MixpanelLib.prototype._remove_group_from_cache = function (group_key, group_id) {
|
|
11472
|
-
delete this._cached_groups[this._create_map_key(group_key, group_id)];
|
|
11473
|
-
};
|
|
11474
|
-
|
|
11475
|
-
/**
|
|
11476
|
-
* Look up reference to a Mixpanel group
|
|
11477
|
-
*
|
|
11478
|
-
* ### Usage:
|
|
11479
|
-
*
|
|
11480
|
-
* mixpanel.get_group(group_key, group_id)
|
|
11481
|
-
*
|
|
11482
|
-
* @param {String} group_key Group key
|
|
11483
|
-
* @param {Object} group_id A valid Mixpanel property type
|
|
11484
|
-
* @returns {Object} A MixpanelGroup identifier
|
|
11485
|
-
*/
|
|
11486
|
-
MixpanelLib.prototype.get_group = function (group_key, group_id) {
|
|
11487
|
-
var map_key = this._create_map_key(group_key, group_id);
|
|
11488
|
-
var group = this._cached_groups[map_key];
|
|
11489
|
-
if (group === undefined || group._group_key !== group_key || group._group_id !== group_id) {
|
|
11490
|
-
group = new MixpanelGroup();
|
|
11491
|
-
group._init(this, group_key, group_id);
|
|
11492
|
-
this._cached_groups[map_key] = group;
|
|
11493
|
-
}
|
|
11494
|
-
return group;
|
|
11495
|
-
};
|
|
11496
|
-
|
|
11497
|
-
/**
|
|
11498
|
-
* Track mp_page_view event. This is now ignored by the server.
|
|
11499
|
-
*
|
|
11500
|
-
* @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
|
|
11501
|
-
* @deprecated
|
|
11502
|
-
*/
|
|
11503
|
-
MixpanelLib.prototype.track_pageview = function(page) {
|
|
11504
|
-
if (_.isUndefined(page)) {
|
|
11505
|
-
page = document$1.location.href;
|
|
11506
|
-
}
|
|
11507
|
-
this.track('mp_page_view', _.info.pageviewInfo(page));
|
|
11508
|
-
};
|
|
11509
|
-
|
|
11510
|
-
/**
|
|
11511
|
-
* Track clicks on a set of document elements. Selector must be a
|
|
11512
|
-
* valid query. Elements must exist on the page at the time track_links is called.
|
|
11513
|
-
*
|
|
11514
|
-
* ### Usage:
|
|
11515
|
-
*
|
|
11516
|
-
* // track click for link id #nav
|
|
11517
|
-
* mixpanel.track_links('#nav', 'Clicked Nav Link');
|
|
11518
|
-
*
|
|
11519
|
-
* ### Notes:
|
|
11520
|
-
*
|
|
11521
|
-
* This function will wait up to 300 ms for the Mixpanel
|
|
11522
|
-
* servers to respond. If they have not responded by that time
|
|
11523
|
-
* it will head to the link without ensuring that your event
|
|
11524
|
-
* has been tracked. To configure this timeout please see the
|
|
11525
|
-
* set_config() documentation below.
|
|
11526
|
-
*
|
|
11527
|
-
* If you pass a function in as the properties argument, the
|
|
11528
|
-
* function will receive the DOMElement that triggered the
|
|
11529
|
-
* event as an argument. You are expected to return an object
|
|
11530
|
-
* from the function; any properties defined on this object
|
|
11531
|
-
* will be sent to mixpanel as event properties.
|
|
11532
|
-
*
|
|
11533
|
-
* @type {Function}
|
|
11534
|
-
* @param {Object|String} query A valid DOM query, element or jQuery-esque list
|
|
11535
|
-
* @param {String} event_name The name of the event to track
|
|
11536
|
-
* @param {Object|Function} [properties] A properties object or function that returns a dictionary of properties when passed a DOMElement
|
|
11537
|
-
*/
|
|
11538
|
-
MixpanelLib.prototype.track_links = function() {
|
|
11539
|
-
return this._track_dom.call(this, LinkTracker, arguments);
|
|
11540
|
-
};
|
|
11541
|
-
|
|
11542
|
-
/**
|
|
11543
|
-
* Track form submissions. Selector must be a valid query.
|
|
11544
|
-
*
|
|
11545
|
-
* ### Usage:
|
|
11546
|
-
*
|
|
11547
|
-
* // track submission for form id 'register'
|
|
11548
|
-
* mixpanel.track_forms('#register', 'Created Account');
|
|
11549
|
-
*
|
|
11550
|
-
* ### Notes:
|
|
11551
|
-
*
|
|
11552
|
-
* This function will wait up to 300 ms for the mixpanel
|
|
11553
|
-
* servers to respond, if they have not responded by that time
|
|
11554
|
-
* it will head to the link without ensuring that your event
|
|
11555
|
-
* has been tracked. To configure this timeout please see the
|
|
11556
|
-
* set_config() documentation below.
|
|
11557
|
-
*
|
|
11558
|
-
* If you pass a function in as the properties argument, the
|
|
11559
|
-
* function will receive the DOMElement that triggered the
|
|
11560
|
-
* event as an argument. You are expected to return an object
|
|
11561
|
-
* from the function; any properties defined on this object
|
|
11562
|
-
* will be sent to mixpanel as event properties.
|
|
11563
|
-
*
|
|
11564
|
-
* @type {Function}
|
|
11565
|
-
* @param {Object|String} query A valid DOM query, element or jQuery-esque list
|
|
11566
|
-
* @param {String} event_name The name of the event to track
|
|
11567
|
-
* @param {Object|Function} [properties] This can be a set of properties, or a function that returns a set of properties after being passed a DOMElement
|
|
11568
|
-
*/
|
|
11569
|
-
MixpanelLib.prototype.track_forms = function() {
|
|
11570
|
-
return this._track_dom.call(this, FormTracker, arguments);
|
|
11571
|
-
};
|
|
11572
|
-
|
|
11573
|
-
/**
|
|
11574
|
-
* Time an event by including the time between this call and a
|
|
11575
|
-
* later 'track' call for the same event in the properties sent
|
|
11576
|
-
* with the event.
|
|
11577
|
-
*
|
|
11578
|
-
* ### Usage:
|
|
11579
|
-
*
|
|
11580
|
-
* // time an event named 'Registered'
|
|
11581
|
-
* mixpanel.time_event('Registered');
|
|
11582
|
-
* mixpanel.track('Registered', {'Gender': 'Male', 'Age': 21});
|
|
11583
|
-
*
|
|
11584
|
-
* When called for a particular event name, the next track call for that event
|
|
11585
|
-
* name will include the elapsed time between the 'time_event' and 'track'
|
|
11586
|
-
* calls. This value is stored as seconds in the '$duration' property.
|
|
11587
|
-
*
|
|
11588
|
-
* @param {String} event_name The name of the event.
|
|
11589
|
-
*/
|
|
11590
|
-
MixpanelLib.prototype.time_event = function(event_name) {
|
|
11591
|
-
if (_.isUndefined(event_name)) {
|
|
11592
|
-
this.report_error('No event name provided to mixpanel.time_event');
|
|
11593
|
-
return;
|
|
11594
|
-
}
|
|
11595
|
-
|
|
11596
|
-
if (this._event_is_disabled(event_name)) {
|
|
11597
|
-
return;
|
|
11598
|
-
}
|
|
11599
|
-
|
|
11600
|
-
this['persistence'].set_event_timer(event_name, new Date().getTime());
|
|
11601
|
-
};
|
|
11602
|
-
|
|
11603
|
-
var REGISTER_DEFAULTS = {
|
|
11604
|
-
'persistent': true
|
|
11605
|
-
};
|
|
11606
|
-
/**
|
|
11607
|
-
* Helper to parse options param for register methods, maintaining
|
|
11608
|
-
* legacy support for plain "days" param instead of options object
|
|
11609
|
-
* @param {Number|Object} [days_or_options] 'days' option (Number), or Options object for register methods
|
|
11610
|
-
* @returns {Object} options object
|
|
11611
|
-
*/
|
|
11612
|
-
var options_for_register = function(days_or_options) {
|
|
11613
|
-
var options;
|
|
11614
|
-
if (_.isObject(days_or_options)) {
|
|
11615
|
-
options = days_or_options;
|
|
11616
|
-
} else if (!_.isUndefined(days_or_options)) {
|
|
11617
|
-
options = {'days': days_or_options};
|
|
11618
|
-
} else {
|
|
11619
|
-
options = {};
|
|
11620
|
-
}
|
|
11621
|
-
return _.extend({}, REGISTER_DEFAULTS, options);
|
|
11622
|
-
};
|
|
11623
|
-
|
|
11624
|
-
/**
|
|
11625
|
-
* Register a set of super properties, which are included with all
|
|
11626
|
-
* events. This will overwrite previous super property values.
|
|
11627
|
-
*
|
|
11628
|
-
* ### Usage:
|
|
11629
|
-
*
|
|
11630
|
-
* // register 'Gender' as a super property
|
|
11631
|
-
* mixpanel.register({'Gender': 'Female'});
|
|
11632
|
-
*
|
|
11633
|
-
* // register several super properties when a user signs up
|
|
11634
|
-
* mixpanel.register({
|
|
11635
|
-
* 'Email': 'jdoe@example.com',
|
|
11636
|
-
* 'Account Type': 'Free'
|
|
11637
|
-
* });
|
|
11638
|
-
*
|
|
11639
|
-
* // register only for the current pageload
|
|
11640
|
-
* mixpanel.register({'Name': 'Pat'}, {persistent: false});
|
|
11641
|
-
*
|
|
11642
|
-
* @param {Object} properties An associative array of properties to store about the user
|
|
11643
|
-
* @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11644
|
-
* @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11645
|
-
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
11646
|
-
*/
|
|
11647
|
-
MixpanelLib.prototype.register = function(props, days_or_options) {
|
|
11648
|
-
var options = options_for_register(days_or_options);
|
|
11649
|
-
if (options['persistent']) {
|
|
11650
|
-
this['persistence'].register(props, options['days']);
|
|
11651
|
-
} else {
|
|
11652
|
-
_.extend(this.unpersisted_superprops, props);
|
|
11653
|
-
}
|
|
11654
|
-
};
|
|
11655
|
-
|
|
11656
|
-
/**
|
|
11657
|
-
* Register a set of super properties only once. This will not
|
|
11658
|
-
* overwrite previous super property values, unlike register().
|
|
11659
|
-
*
|
|
11660
|
-
* ### Usage:
|
|
11661
|
-
*
|
|
11662
|
-
* // register a super property for the first time only
|
|
11663
|
-
* mixpanel.register_once({
|
|
11664
|
-
* 'First Login Date': new Date().toISOString()
|
|
11665
|
-
* });
|
|
11666
|
-
*
|
|
11667
|
-
* // register once, only for the current pageload
|
|
11668
|
-
* mixpanel.register_once({
|
|
11669
|
-
* 'First interaction time': new Date().toISOString()
|
|
11670
|
-
* }, 'None', {persistent: false});
|
|
11671
|
-
*
|
|
11672
|
-
* ### Notes:
|
|
11673
|
-
*
|
|
11674
|
-
* If default_value is specified, current super properties
|
|
11675
|
-
* with that value will be overwritten.
|
|
11676
|
-
*
|
|
11677
|
-
* @param {Object} properties An associative array of properties to store about the user
|
|
11678
|
-
* @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
|
|
11679
|
-
* @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11680
|
-
* @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11681
|
-
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
11682
|
-
*/
|
|
11683
|
-
MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
|
|
11684
|
-
var options = options_for_register(days_or_options);
|
|
11685
|
-
if (options['persistent']) {
|
|
11686
|
-
this['persistence'].register_once(props, default_value, options['days']);
|
|
11687
|
-
} else {
|
|
11688
|
-
if (typeof(default_value) === 'undefined') {
|
|
11689
|
-
default_value = 'None';
|
|
11690
|
-
}
|
|
11691
|
-
_.each(props, function(val, prop) {
|
|
11692
|
-
if (!this.unpersisted_superprops.hasOwnProperty(prop) || this.unpersisted_superprops[prop] === default_value) {
|
|
11693
|
-
this.unpersisted_superprops[prop] = val;
|
|
11694
|
-
}
|
|
11695
|
-
}, this);
|
|
11696
|
-
}
|
|
11697
|
-
};
|
|
11698
|
-
|
|
11699
|
-
/**
|
|
11700
|
-
* Delete a super property stored with the current user.
|
|
11701
|
-
*
|
|
11702
|
-
* @param {String} property The name of the super property to remove
|
|
11703
|
-
* @param {Object} [options]
|
|
11704
|
-
* @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
|
|
11705
|
-
*/
|
|
11706
|
-
MixpanelLib.prototype.unregister = function(property, options) {
|
|
11707
|
-
options = options_for_register(options);
|
|
11708
|
-
if (options['persistent']) {
|
|
11709
|
-
this['persistence'].unregister(property);
|
|
11710
|
-
} else {
|
|
11711
|
-
delete this.unpersisted_superprops[property];
|
|
11712
|
-
}
|
|
10912
|
+
_.each(groups, function(v, k) {
|
|
10913
|
+
if (v !== null && v !== undefined) {
|
|
10914
|
+
tracking_props[k] = v;
|
|
10915
|
+
}
|
|
10916
|
+
});
|
|
10917
|
+
return this.track(event_name, tracking_props, callback);
|
|
10918
|
+
});
|
|
10919
|
+
|
|
10920
|
+
MixpanelLib.prototype._create_map_key = function (group_key, group_id) {
|
|
10921
|
+
return group_key + '_' + JSON.stringify(group_id);
|
|
11713
10922
|
};
|
|
11714
10923
|
|
|
11715
|
-
MixpanelLib.prototype.
|
|
11716
|
-
|
|
11717
|
-
props[prop] = value;
|
|
11718
|
-
this.register(props);
|
|
10924
|
+
MixpanelLib.prototype._remove_group_from_cache = function (group_key, group_id) {
|
|
10925
|
+
delete this._cached_groups[this._create_map_key(group_key, group_id)];
|
|
11719
10926
|
};
|
|
11720
10927
|
|
|
11721
10928
|
/**
|
|
11722
|
-
*
|
|
11723
|
-
* devices, tie a user to their events, and create a user profile.
|
|
11724
|
-
* If you never call this method, unique visitors are tracked using
|
|
11725
|
-
* a UUID generated the first time they visit the site.
|
|
11726
|
-
*
|
|
11727
|
-
* Call identify when you know the identity of the current user,
|
|
11728
|
-
* typically after login or signup. We recommend against using
|
|
11729
|
-
* identify for anonymous visitors to your site.
|
|
10929
|
+
* Look up reference to a Mixpanel group
|
|
11730
10930
|
*
|
|
11731
|
-
* ###
|
|
11732
|
-
* If your project has
|
|
11733
|
-
* <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
|
|
11734
|
-
* enabled, the identify method will connect pre- and
|
|
11735
|
-
* post-authentication events when appropriate.
|
|
10931
|
+
* ### Usage:
|
|
11736
10932
|
*
|
|
11737
|
-
*
|
|
11738
|
-
* change the user's local distinct_id to the unique ID you pass.
|
|
11739
|
-
* Events tracked prior to authentication will not be connected
|
|
11740
|
-
* to the same user identity. If ID Merge is disabled, alias can
|
|
11741
|
-
* be used to connect pre- and post-registration events.
|
|
10933
|
+
* mixpanel.get_group(group_key, group_id)
|
|
11742
10934
|
*
|
|
11743
|
-
* @param {String}
|
|
10935
|
+
* @param {String} group_key Group key
|
|
10936
|
+
* @param {Object} group_id A valid Mixpanel property type
|
|
10937
|
+
* @returns {Object} A MixpanelGroup identifier
|
|
11744
10938
|
*/
|
|
11745
|
-
MixpanelLib.prototype.
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
// _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
|
|
11753
|
-
// _union_callback:function A callback to be run if and when the People union queue is flushed
|
|
11754
|
-
// _unset_callback:function A callback to be run if and when the People unset queue is flushed
|
|
11755
|
-
|
|
11756
|
-
var previous_distinct_id = this.get_distinct_id();
|
|
11757
|
-
this.register({'$user_id': new_distinct_id});
|
|
11758
|
-
|
|
11759
|
-
if (!this.get_property('$device_id')) {
|
|
11760
|
-
// The persisted distinct id might not actually be a device id at all
|
|
11761
|
-
// it might be a distinct id of the user from before
|
|
11762
|
-
var device_id = previous_distinct_id;
|
|
11763
|
-
this.register_once({
|
|
11764
|
-
'$had_persisted_distinct_id': true,
|
|
11765
|
-
'$device_id': device_id
|
|
11766
|
-
}, '');
|
|
11767
|
-
}
|
|
11768
|
-
|
|
11769
|
-
// identify only changes the distinct id if it doesn't match either the existing or the alias;
|
|
11770
|
-
// if it's new, blow away the alias as well.
|
|
11771
|
-
if (new_distinct_id !== previous_distinct_id && new_distinct_id !== this.get_property(ALIAS_ID_KEY)) {
|
|
11772
|
-
this.unregister(ALIAS_ID_KEY);
|
|
11773
|
-
this.register({'distinct_id': new_distinct_id});
|
|
11774
|
-
}
|
|
11775
|
-
this._flags.identify_called = true;
|
|
11776
|
-
// Flush any queued up people requests
|
|
11777
|
-
this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
|
|
11778
|
-
|
|
11779
|
-
// send an $identify event any time the distinct_id is changing - logic on the server
|
|
11780
|
-
// will determine whether or not to do anything with it.
|
|
11781
|
-
if (new_distinct_id !== previous_distinct_id) {
|
|
11782
|
-
this.track('$identify', {
|
|
11783
|
-
'distinct_id': new_distinct_id,
|
|
11784
|
-
'$anon_distinct_id': previous_distinct_id
|
|
11785
|
-
}, {skip_hooks: true});
|
|
10939
|
+
MixpanelLib.prototype.get_group = function (group_key, group_id) {
|
|
10940
|
+
var map_key = this._create_map_key(group_key, group_id);
|
|
10941
|
+
var group = this._cached_groups[map_key];
|
|
10942
|
+
if (group === undefined || group._group_key !== group_key || group._group_id !== group_id) {
|
|
10943
|
+
group = new MixpanelGroup();
|
|
10944
|
+
group._init(this, group_key, group_id);
|
|
10945
|
+
this._cached_groups[map_key] = group;
|
|
11786
10946
|
}
|
|
10947
|
+
return group;
|
|
11787
10948
|
};
|
|
11788
10949
|
|
|
11789
10950
|
/**
|
|
11790
|
-
*
|
|
11791
|
-
*
|
|
10951
|
+
* Track mp_page_view event. This is now ignored by the server.
|
|
10952
|
+
*
|
|
10953
|
+
* @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
|
|
10954
|
+
* @deprecated
|
|
11792
10955
|
*/
|
|
11793
|
-
MixpanelLib.prototype.
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
this.
|
|
11798
|
-
'distinct_id': uuid,
|
|
11799
|
-
'$device_id': uuid
|
|
11800
|
-
}, '');
|
|
10956
|
+
MixpanelLib.prototype.track_pageview = function(page) {
|
|
10957
|
+
if (_.isUndefined(page)) {
|
|
10958
|
+
page = document$1.location.href;
|
|
10959
|
+
}
|
|
10960
|
+
this.track('mp_page_view', _.info.pageviewInfo(page));
|
|
11801
10961
|
};
|
|
11802
10962
|
|
|
11803
10963
|
/**
|
|
11804
|
-
*
|
|
11805
|
-
*
|
|
10964
|
+
* Track clicks on a set of document elements. Selector must be a
|
|
10965
|
+
* valid query. Elements must exist on the page at the time track_links is called.
|
|
10966
|
+
*
|
|
10967
|
+
* ### Usage:
|
|
10968
|
+
*
|
|
10969
|
+
* // track click for link id #nav
|
|
10970
|
+
* mixpanel.track_links('#nav', 'Clicked Nav Link');
|
|
11806
10971
|
*
|
|
11807
10972
|
* ### Notes:
|
|
11808
10973
|
*
|
|
11809
|
-
*
|
|
11810
|
-
*
|
|
10974
|
+
* This function will wait up to 300 ms for the Mixpanel
|
|
10975
|
+
* servers to respond. If they have not responded by that time
|
|
10976
|
+
* it will head to the link without ensuring that your event
|
|
10977
|
+
* has been tracked. To configure this timeout please see the
|
|
10978
|
+
* set_config() documentation below.
|
|
11811
10979
|
*
|
|
11812
|
-
*
|
|
11813
|
-
*
|
|
11814
|
-
*
|
|
11815
|
-
*
|
|
11816
|
-
*
|
|
11817
|
-
*
|
|
10980
|
+
* If you pass a function in as the properties argument, the
|
|
10981
|
+
* function will receive the DOMElement that triggered the
|
|
10982
|
+
* event as an argument. You are expected to return an object
|
|
10983
|
+
* from the function; any properties defined on this object
|
|
10984
|
+
* will be sent to mixpanel as event properties.
|
|
10985
|
+
*
|
|
10986
|
+
* @type {Function}
|
|
10987
|
+
* @param {Object|String} query A valid DOM query, element or jQuery-esque list
|
|
10988
|
+
* @param {String} event_name The name of the event to track
|
|
10989
|
+
* @param {Object|Function} [properties] A properties object or function that returns a dictionary of properties when passed a DOMElement
|
|
11818
10990
|
*/
|
|
11819
|
-
MixpanelLib.prototype.
|
|
11820
|
-
return this.
|
|
10991
|
+
MixpanelLib.prototype.track_links = function() {
|
|
10992
|
+
return this._track_dom.call(this, LinkTracker, arguments);
|
|
11821
10993
|
};
|
|
11822
10994
|
|
|
11823
10995
|
/**
|
|
11824
|
-
*
|
|
11825
|
-
* remap one id to another. Multiple aliases can point to the
|
|
11826
|
-
* same identifier.
|
|
10996
|
+
* Track form submissions. Selector must be a valid query.
|
|
11827
10997
|
*
|
|
11828
|
-
*
|
|
10998
|
+
* ### Usage:
|
|
11829
10999
|
*
|
|
11830
|
-
*
|
|
11831
|
-
*
|
|
11832
|
-
* mixpanel.alias('newer_id', 'existing_id');
|
|
11000
|
+
* // track submission for form id 'register'
|
|
11001
|
+
* mixpanel.track_forms('#register', 'Created Account');
|
|
11833
11002
|
*
|
|
11834
|
-
*
|
|
11003
|
+
* ### Notes:
|
|
11835
11004
|
*
|
|
11836
|
-
*
|
|
11837
|
-
*
|
|
11838
|
-
*
|
|
11005
|
+
* This function will wait up to 300 ms for the mixpanel
|
|
11006
|
+
* servers to respond, if they have not responded by that time
|
|
11007
|
+
* it will head to the link without ensuring that your event
|
|
11008
|
+
* has been tracked. To configure this timeout please see the
|
|
11009
|
+
* set_config() documentation below.
|
|
11839
11010
|
*
|
|
11840
|
-
*
|
|
11841
|
-
*
|
|
11011
|
+
* If you pass a function in as the properties argument, the
|
|
11012
|
+
* function will receive the DOMElement that triggered the
|
|
11013
|
+
* event as an argument. You are expected to return an object
|
|
11014
|
+
* from the function; any properties defined on this object
|
|
11015
|
+
* will be sent to mixpanel as event properties.
|
|
11842
11016
|
*
|
|
11843
|
-
*
|
|
11844
|
-
*
|
|
11845
|
-
*
|
|
11017
|
+
* @type {Function}
|
|
11018
|
+
* @param {Object|String} query A valid DOM query, element or jQuery-esque list
|
|
11019
|
+
* @param {String} event_name The name of the event to track
|
|
11020
|
+
* @param {Object|Function} [properties] This can be a set of properties, or a function that returns a set of properties after being passed a DOMElement
|
|
11021
|
+
*/
|
|
11022
|
+
MixpanelLib.prototype.track_forms = function() {
|
|
11023
|
+
return this._track_dom.call(this, FormTracker, arguments);
|
|
11024
|
+
};
|
|
11025
|
+
|
|
11026
|
+
/**
|
|
11027
|
+
* Time an event by including the time between this call and a
|
|
11028
|
+
* later 'track' call for the same event in the properties sent
|
|
11029
|
+
* with the event.
|
|
11846
11030
|
*
|
|
11847
|
-
* ###
|
|
11031
|
+
* ### Usage:
|
|
11848
11032
|
*
|
|
11849
|
-
*
|
|
11850
|
-
*
|
|
11851
|
-
*
|
|
11852
|
-
* ID is first created for a user (e.g., when a user first registers
|
|
11853
|
-
* for an account). Do not use alias multiple times for a single
|
|
11854
|
-
* user without ID Merge enabled.
|
|
11033
|
+
* // time an event named 'Registered'
|
|
11034
|
+
* mixpanel.time_event('Registered');
|
|
11035
|
+
* mixpanel.track('Registered', {'Gender': 'Male', 'Age': 21});
|
|
11855
11036
|
*
|
|
11856
|
-
*
|
|
11857
|
-
*
|
|
11037
|
+
* When called for a particular event name, the next track call for that event
|
|
11038
|
+
* name will include the elapsed time between the 'time_event' and 'track'
|
|
11039
|
+
* calls. This value is stored as seconds in the '$duration' property.
|
|
11040
|
+
*
|
|
11041
|
+
* @param {String} event_name The name of the event.
|
|
11858
11042
|
*/
|
|
11859
|
-
MixpanelLib.prototype.
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
|
|
11864
|
-
this.report_error('Attempting to create alias for existing People user - aborting.');
|
|
11865
|
-
return -2;
|
|
11043
|
+
MixpanelLib.prototype.time_event = function(event_name) {
|
|
11044
|
+
if (_.isUndefined(event_name)) {
|
|
11045
|
+
this.report_error('No event name provided to mixpanel.time_event');
|
|
11046
|
+
return;
|
|
11866
11047
|
}
|
|
11867
11048
|
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
original = this.get_distinct_id();
|
|
11049
|
+
if (this._event_is_disabled(event_name)) {
|
|
11050
|
+
return;
|
|
11871
11051
|
}
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11052
|
+
|
|
11053
|
+
this['persistence'].set_event_timer(event_name, new Date().getTime());
|
|
11054
|
+
};
|
|
11055
|
+
|
|
11056
|
+
var REGISTER_DEFAULTS = {
|
|
11057
|
+
'persistent': true
|
|
11058
|
+
};
|
|
11059
|
+
/**
|
|
11060
|
+
* Helper to parse options param for register methods, maintaining
|
|
11061
|
+
* legacy support for plain "days" param instead of options object
|
|
11062
|
+
* @param {Number|Object} [days_or_options] 'days' option (Number), or Options object for register methods
|
|
11063
|
+
* @returns {Object} options object
|
|
11064
|
+
*/
|
|
11065
|
+
var options_for_register = function(days_or_options) {
|
|
11066
|
+
var options;
|
|
11067
|
+
if (_.isObject(days_or_options)) {
|
|
11068
|
+
options = days_or_options;
|
|
11069
|
+
} else if (!_.isUndefined(days_or_options)) {
|
|
11070
|
+
options = {'days': days_or_options};
|
|
11883
11071
|
} else {
|
|
11884
|
-
|
|
11885
|
-
this.identify(alias);
|
|
11886
|
-
return -1;
|
|
11072
|
+
options = {};
|
|
11887
11073
|
}
|
|
11074
|
+
return _.extend({}, REGISTER_DEFAULTS, options);
|
|
11888
11075
|
};
|
|
11889
11076
|
|
|
11890
11077
|
/**
|
|
11891
|
-
*
|
|
11892
|
-
*
|
|
11893
|
-
* than an automatically generated name. Name tags do not have to
|
|
11894
|
-
* be unique.
|
|
11078
|
+
* Register a set of super properties, which are included with all
|
|
11079
|
+
* events. This will overwrite previous super property values.
|
|
11895
11080
|
*
|
|
11896
|
-
*
|
|
11081
|
+
* ### Usage:
|
|
11897
11082
|
*
|
|
11898
|
-
*
|
|
11899
|
-
*
|
|
11083
|
+
* // register 'Gender' as a super property
|
|
11084
|
+
* mixpanel.register({'Gender': 'Female'});
|
|
11085
|
+
*
|
|
11086
|
+
* // register several super properties when a user signs up
|
|
11087
|
+
* mixpanel.register({
|
|
11088
|
+
* 'Email': 'jdoe@example.com',
|
|
11089
|
+
* 'Account Type': 'Free'
|
|
11090
|
+
* });
|
|
11091
|
+
*
|
|
11092
|
+
* // register only for the current pageload
|
|
11093
|
+
* mixpanel.register({'Name': 'Pat'}, {persistent: false});
|
|
11094
|
+
*
|
|
11095
|
+
* @param {Object} properties An associative array of properties to store about the user
|
|
11096
|
+
* @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11097
|
+
* @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11098
|
+
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
11900
11099
|
*/
|
|
11901
|
-
MixpanelLib.prototype.
|
|
11902
|
-
|
|
11100
|
+
MixpanelLib.prototype.register = function(props, days_or_options) {
|
|
11101
|
+
var options = options_for_register(days_or_options);
|
|
11102
|
+
if (options['persistent']) {
|
|
11103
|
+
this['persistence'].register(props, options['days']);
|
|
11104
|
+
} else {
|
|
11105
|
+
_.extend(this.unpersisted_superprops, props);
|
|
11106
|
+
}
|
|
11903
11107
|
};
|
|
11904
11108
|
|
|
11905
11109
|
/**
|
|
11906
|
-
*
|
|
11907
|
-
*
|
|
11908
|
-
* The default config is:
|
|
11909
|
-
*
|
|
11910
|
-
* {
|
|
11911
|
-
* // HTTP method for tracking requests
|
|
11912
|
-
* api_method: 'POST'
|
|
11913
|
-
*
|
|
11914
|
-
* // transport for sending requests ('XHR' or 'sendBeacon')
|
|
11915
|
-
* // NB: sendBeacon should only be used for scenarios such as
|
|
11916
|
-
* // page unload where a "best-effort" attempt to send is
|
|
11917
|
-
* // acceptable; the sendBeacon API does not support callbacks
|
|
11918
|
-
* // or any way to know the result of the request. Mixpanel
|
|
11919
|
-
* // tracking via sendBeacon will not support any event-
|
|
11920
|
-
* // batching or retry mechanisms.
|
|
11921
|
-
* api_transport: 'XHR'
|
|
11922
|
-
*
|
|
11923
|
-
* // turn on request-batching/queueing/retry
|
|
11924
|
-
* batch_requests: false,
|
|
11925
|
-
*
|
|
11926
|
-
* // maximum number of events/updates to send in a single
|
|
11927
|
-
* // network request
|
|
11928
|
-
* batch_size: 50,
|
|
11929
|
-
*
|
|
11930
|
-
* // milliseconds to wait between sending batch requests
|
|
11931
|
-
* batch_flush_interval_ms: 5000,
|
|
11932
|
-
*
|
|
11933
|
-
* // milliseconds to wait for network responses to batch requests
|
|
11934
|
-
* // before they are considered timed-out and retried
|
|
11935
|
-
* batch_request_timeout_ms: 90000,
|
|
11936
|
-
*
|
|
11937
|
-
* // override value for cookie domain, only useful for ensuring
|
|
11938
|
-
* // correct cross-subdomain cookies on unusual domains like
|
|
11939
|
-
* // subdomain.mainsite.avocat.fr; NB this cannot be used to
|
|
11940
|
-
* // set cookies on a different domain than the current origin
|
|
11941
|
-
* cookie_domain: ''
|
|
11942
|
-
*
|
|
11943
|
-
* // super properties cookie expiration (in days)
|
|
11944
|
-
* cookie_expiration: 365
|
|
11945
|
-
*
|
|
11946
|
-
* // if true, cookie will be set with SameSite=None; Secure
|
|
11947
|
-
* // this is only useful in special situations, like embedded
|
|
11948
|
-
* // 3rd-party iframes that set up a Mixpanel instance
|
|
11949
|
-
* cross_site_cookie: false
|
|
11950
|
-
*
|
|
11951
|
-
* // super properties span subdomains
|
|
11952
|
-
* cross_subdomain_cookie: true
|
|
11953
|
-
*
|
|
11954
|
-
* // debug mode
|
|
11955
|
-
* debug: false
|
|
11956
|
-
*
|
|
11957
|
-
* // if this is true, the mixpanel cookie or localStorage entry
|
|
11958
|
-
* // will be deleted, and no user persistence will take place
|
|
11959
|
-
* disable_persistence: false
|
|
11960
|
-
*
|
|
11961
|
-
* // if this is true, Mixpanel will automatically determine
|
|
11962
|
-
* // City, Region and Country data using the IP address of
|
|
11963
|
-
* //the client
|
|
11964
|
-
* ip: true
|
|
11965
|
-
*
|
|
11966
|
-
* // opt users out of tracking by this Mixpanel instance by default
|
|
11967
|
-
* opt_out_tracking_by_default: false
|
|
11968
|
-
*
|
|
11969
|
-
* // opt users out of browser data storage by this Mixpanel instance by default
|
|
11970
|
-
* opt_out_persistence_by_default: false
|
|
11971
|
-
*
|
|
11972
|
-
* // persistence mechanism used by opt-in/opt-out methods - cookie
|
|
11973
|
-
* // or localStorage - falls back to cookie if localStorage is unavailable
|
|
11974
|
-
* opt_out_tracking_persistence_type: 'localStorage'
|
|
11110
|
+
* Register a set of super properties only once. This will not
|
|
11111
|
+
* overwrite previous super property values, unlike register().
|
|
11975
11112
|
*
|
|
11976
|
-
*
|
|
11977
|
-
* opt_out_tracking_cookie_prefix: null
|
|
11113
|
+
* ### Usage:
|
|
11978
11114
|
*
|
|
11979
|
-
*
|
|
11980
|
-
*
|
|
11981
|
-
*
|
|
11982
|
-
*
|
|
11983
|
-
* persistence: 'cookie'
|
|
11115
|
+
* // register a super property for the first time only
|
|
11116
|
+
* mixpanel.register_once({
|
|
11117
|
+
* 'First Login Date': new Date().toISOString()
|
|
11118
|
+
* });
|
|
11984
11119
|
*
|
|
11985
|
-
*
|
|
11986
|
-
*
|
|
11120
|
+
* // register once, only for the current pageload
|
|
11121
|
+
* mixpanel.register_once({
|
|
11122
|
+
* 'First interaction time': new Date().toISOString()
|
|
11123
|
+
* }, 'None', {persistent: false});
|
|
11987
11124
|
*
|
|
11988
|
-
*
|
|
11989
|
-
* // be sent with track() calls
|
|
11990
|
-
* property_blacklist: []
|
|
11125
|
+
* ### Notes:
|
|
11991
11126
|
*
|
|
11992
|
-
*
|
|
11993
|
-
*
|
|
11994
|
-
* secure_cookie: false
|
|
11127
|
+
* If default_value is specified, current super properties
|
|
11128
|
+
* with that value will be overwritten.
|
|
11995
11129
|
*
|
|
11996
|
-
*
|
|
11997
|
-
*
|
|
11998
|
-
*
|
|
11130
|
+
* @param {Object} properties An associative array of properties to store about the user
|
|
11131
|
+
* @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
|
|
11132
|
+
* @param {Number|Object} [days_or_options] Options object or number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11133
|
+
* @param {boolean} [days_or_options.days] - number of days since the user's last visit to store the super properties (only valid for persisted props)
|
|
11134
|
+
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
11135
|
+
*/
|
|
11136
|
+
MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
|
|
11137
|
+
var options = options_for_register(days_or_options);
|
|
11138
|
+
if (options['persistent']) {
|
|
11139
|
+
this['persistence'].register_once(props, default_value, options['days']);
|
|
11140
|
+
} else {
|
|
11141
|
+
if (typeof(default_value) === 'undefined') {
|
|
11142
|
+
default_value = 'None';
|
|
11143
|
+
}
|
|
11144
|
+
_.each(props, function(val, prop) {
|
|
11145
|
+
if (!this.unpersisted_superprops.hasOwnProperty(prop) || this.unpersisted_superprops[prop] === default_value) {
|
|
11146
|
+
this.unpersisted_superprops[prop] = val;
|
|
11147
|
+
}
|
|
11148
|
+
}, this);
|
|
11149
|
+
}
|
|
11150
|
+
};
|
|
11151
|
+
|
|
11152
|
+
/**
|
|
11153
|
+
* Delete a super property stored with the current user.
|
|
11999
11154
|
*
|
|
12000
|
-
*
|
|
12001
|
-
*
|
|
12002
|
-
*
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
11155
|
+
* @param {String} property The name of the super property to remove
|
|
11156
|
+
* @param {Object} [options]
|
|
11157
|
+
* @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
|
|
11158
|
+
*/
|
|
11159
|
+
MixpanelLib.prototype.unregister = function(property, options) {
|
|
11160
|
+
options = options_for_register(options);
|
|
11161
|
+
if (options['persistent']) {
|
|
11162
|
+
this['persistence'].unregister(property);
|
|
11163
|
+
} else {
|
|
11164
|
+
delete this.unpersisted_superprops[property];
|
|
11165
|
+
}
|
|
11166
|
+
};
|
|
11167
|
+
|
|
11168
|
+
MixpanelLib.prototype._register_single = function(prop, value) {
|
|
11169
|
+
var props = {};
|
|
11170
|
+
props[prop] = value;
|
|
11171
|
+
this.register(props);
|
|
11172
|
+
};
|
|
11173
|
+
|
|
11174
|
+
/**
|
|
11175
|
+
* Identify a user with a unique ID to track user activity across
|
|
11176
|
+
* devices, tie a user to their events, and create a user profile.
|
|
11177
|
+
* If you never call this method, unique visitors are tracked using
|
|
11178
|
+
* a UUID generated the first time they visit the site.
|
|
12006
11179
|
*
|
|
12007
|
-
*
|
|
12008
|
-
*
|
|
12009
|
-
*
|
|
11180
|
+
* Call identify when you know the identity of the current user,
|
|
11181
|
+
* typically after login or signup. We recommend against using
|
|
11182
|
+
* identify for anonymous visitors to your site.
|
|
12010
11183
|
*
|
|
12011
|
-
*
|
|
12012
|
-
*
|
|
12013
|
-
*
|
|
11184
|
+
* ### Notes:
|
|
11185
|
+
* If your project has
|
|
11186
|
+
* <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
|
|
11187
|
+
* enabled, the identify method will connect pre- and
|
|
11188
|
+
* post-authentication events when appropriate.
|
|
12014
11189
|
*
|
|
11190
|
+
* If your project does not have ID Merge enabled, identify will
|
|
11191
|
+
* change the user's local distinct_id to the unique ID you pass.
|
|
11192
|
+
* Events tracked prior to authentication will not be connected
|
|
11193
|
+
* to the same user identity. If ID Merge is disabled, alias can
|
|
11194
|
+
* be used to connect pre- and post-registration events.
|
|
12015
11195
|
*
|
|
12016
|
-
* @param {
|
|
11196
|
+
* @param {String} [unique_id] A string that uniquely identifies a user. If not provided, the distinct_id currently in the persistent store (cookie or localStorage) will be used.
|
|
12017
11197
|
*/
|
|
12018
|
-
MixpanelLib.prototype.
|
|
12019
|
-
|
|
12020
|
-
|
|
11198
|
+
MixpanelLib.prototype.identify = function(
|
|
11199
|
+
new_distinct_id, _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
|
|
11200
|
+
) {
|
|
11201
|
+
// Optional Parameters
|
|
11202
|
+
// _set_callback:function A callback to be run if and when the People set queue is flushed
|
|
11203
|
+
// _add_callback:function A callback to be run if and when the People add queue is flushed
|
|
11204
|
+
// _append_callback:function A callback to be run if and when the People append queue is flushed
|
|
11205
|
+
// _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
|
|
11206
|
+
// _union_callback:function A callback to be run if and when the People union queue is flushed
|
|
11207
|
+
// _unset_callback:function A callback to be run if and when the People unset queue is flushed
|
|
12021
11208
|
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
_.each(this.request_batchers, function(batcher) {
|
|
12025
|
-
batcher.resetBatchSize();
|
|
12026
|
-
});
|
|
12027
|
-
}
|
|
11209
|
+
var previous_distinct_id = this.get_distinct_id();
|
|
11210
|
+
this.register({'$user_id': new_distinct_id});
|
|
12028
11211
|
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
11212
|
+
if (!this.get_property('$device_id')) {
|
|
11213
|
+
// The persisted distinct id might not actually be a device id at all
|
|
11214
|
+
// it might be a distinct id of the user from before
|
|
11215
|
+
var device_id = previous_distinct_id;
|
|
11216
|
+
this.register_once({
|
|
11217
|
+
'$had_persisted_distinct_id': true,
|
|
11218
|
+
'$device_id': device_id
|
|
11219
|
+
}, '');
|
|
11220
|
+
}
|
|
12035
11221
|
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
11222
|
+
// identify only changes the distinct id if it doesn't match either the existing or the alias;
|
|
11223
|
+
// if it's new, blow away the alias as well.
|
|
11224
|
+
if (new_distinct_id !== previous_distinct_id && new_distinct_id !== this.get_property(ALIAS_ID_KEY)) {
|
|
11225
|
+
this.unregister(ALIAS_ID_KEY);
|
|
11226
|
+
this.register({'distinct_id': new_distinct_id});
|
|
12040
11227
|
}
|
|
12041
|
-
|
|
11228
|
+
this._flags.identify_called = true;
|
|
11229
|
+
// Flush any queued up people requests
|
|
11230
|
+
this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
|
|
12042
11231
|
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
11232
|
+
// send an $identify event any time the distinct_id is changing - logic on the server
|
|
11233
|
+
// will determine whether or not to do anything with it.
|
|
11234
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
11235
|
+
this.track('$identify', {
|
|
11236
|
+
'distinct_id': new_distinct_id,
|
|
11237
|
+
'$anon_distinct_id': previous_distinct_id
|
|
11238
|
+
}, {skip_hooks: true});
|
|
11239
|
+
}
|
|
12048
11240
|
};
|
|
12049
11241
|
|
|
12050
11242
|
/**
|
|
12051
|
-
*
|
|
12052
|
-
*
|
|
12053
|
-
* @param {string} hook_name which hook to retrieve
|
|
12054
|
-
* @returns {any|null} return value of user-provided hook, or null if nothing was returned
|
|
11243
|
+
* Clears super properties and generates a new random distinct_id for this instance.
|
|
11244
|
+
* Useful for clearing data when a user logs out.
|
|
12055
11245
|
*/
|
|
12056
|
-
MixpanelLib.prototype.
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
11246
|
+
MixpanelLib.prototype.reset = function() {
|
|
11247
|
+
this['persistence'].clear();
|
|
11248
|
+
this._flags.identify_called = false;
|
|
11249
|
+
var uuid = _.UUID();
|
|
11250
|
+
this.register_once({
|
|
11251
|
+
'distinct_id': uuid,
|
|
11252
|
+
'$device_id': uuid
|
|
11253
|
+
}, '');
|
|
12063
11254
|
};
|
|
12064
11255
|
|
|
12065
11256
|
/**
|
|
12066
|
-
* Returns the
|
|
12067
|
-
*
|
|
11257
|
+
* Returns the current distinct id of the user. This is either the id automatically
|
|
11258
|
+
* generated by the library or the id that has been passed by a call to identify().
|
|
12068
11259
|
*
|
|
12069
11260
|
* ### Notes:
|
|
12070
11261
|
*
|
|
12071
|
-
*
|
|
11262
|
+
* get_distinct_id() can only be called after the Mixpanel library has finished loading.
|
|
12072
11263
|
* init() has a loaded function available to handle this automatically. For example:
|
|
12073
11264
|
*
|
|
12074
|
-
* //
|
|
11265
|
+
* // set distinct_id after the mixpanel library has loaded
|
|
12075
11266
|
* mixpanel.init('YOUR PROJECT TOKEN', {
|
|
12076
11267
|
* loaded: function(mixpanel) {
|
|
12077
|
-
*
|
|
11268
|
+
* distinct_id = mixpanel.get_distinct_id();
|
|
12078
11269
|
* }
|
|
12079
11270
|
* });
|
|
12080
|
-
*
|
|
12081
|
-
* @param {String} property_name The name of the super property you want to retrieve
|
|
12082
|
-
*/
|
|
12083
|
-
MixpanelLib.prototype.get_property = function(property_name) {
|
|
12084
|
-
return this['persistence']['props'][property_name];
|
|
12085
|
-
};
|
|
12086
|
-
|
|
12087
|
-
MixpanelLib.prototype.toString = function() {
|
|
12088
|
-
var name = this.get_config('name');
|
|
12089
|
-
if (name !== PRIMARY_INSTANCE_NAME) {
|
|
12090
|
-
name = PRIMARY_INSTANCE_NAME + '.' + name;
|
|
12091
|
-
}
|
|
12092
|
-
return name;
|
|
12093
|
-
};
|
|
12094
|
-
|
|
12095
|
-
MixpanelLib.prototype._event_is_disabled = function(event_name) {
|
|
12096
|
-
return _.isBlockedUA(userAgent) ||
|
|
12097
|
-
this._flags.disable_all_events ||
|
|
12098
|
-
_.include(this.__disabled_events, event_name);
|
|
12099
|
-
};
|
|
12100
|
-
|
|
12101
|
-
// perform some housekeeping around GDPR opt-in/out state
|
|
12102
|
-
MixpanelLib.prototype._gdpr_init = function() {
|
|
12103
|
-
var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
|
|
12104
|
-
|
|
12105
|
-
// try to convert opt-in/out cookies to localStorage if possible
|
|
12106
|
-
if (is_localStorage_requested && _.localStorage.is_supported()) {
|
|
12107
|
-
if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
|
|
12108
|
-
this.opt_in_tracking({'enable_persistence': false});
|
|
12109
|
-
}
|
|
12110
|
-
if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
|
|
12111
|
-
this.opt_out_tracking({'clear_persistence': false});
|
|
12112
|
-
}
|
|
12113
|
-
this.clear_opt_in_out_tracking({
|
|
12114
|
-
'persistence_type': 'cookie',
|
|
12115
|
-
'enable_persistence': false
|
|
12116
|
-
});
|
|
12117
|
-
}
|
|
12118
|
-
|
|
12119
|
-
// check whether the user has already opted out - if so, clear & disable persistence
|
|
12120
|
-
if (this.has_opted_out_tracking()) {
|
|
12121
|
-
this._gdpr_update_persistence({'clear_persistence': true});
|
|
12122
|
-
|
|
12123
|
-
// check whether we should opt out by default
|
|
12124
|
-
// note: we don't clear persistence here by default since opt-out default state is often
|
|
12125
|
-
// used as an initial state while GDPR information is being collected
|
|
12126
|
-
} else if (!this.has_opted_in_tracking() && (
|
|
12127
|
-
this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
|
|
12128
|
-
)) {
|
|
12129
|
-
_.cookie.remove('mp_optout');
|
|
12130
|
-
this.opt_out_tracking({
|
|
12131
|
-
'clear_persistence': this.get_config('opt_out_persistence_by_default')
|
|
12132
|
-
});
|
|
12133
|
-
}
|
|
12134
|
-
};
|
|
12135
|
-
|
|
12136
|
-
/**
|
|
12137
|
-
* Enable or disable persistence based on options
|
|
12138
|
-
* only enable/disable if persistence is not already in this state
|
|
12139
|
-
* @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
|
|
12140
|
-
* @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
|
|
12141
11271
|
*/
|
|
12142
|
-
MixpanelLib.prototype.
|
|
12143
|
-
|
|
12144
|
-
if (options && options['clear_persistence']) {
|
|
12145
|
-
disabled = true;
|
|
12146
|
-
} else if (options && options['enable_persistence']) {
|
|
12147
|
-
disabled = false;
|
|
12148
|
-
} else {
|
|
12149
|
-
return;
|
|
12150
|
-
}
|
|
12151
|
-
|
|
12152
|
-
if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
|
|
12153
|
-
this['persistence'].set_disabled(disabled);
|
|
12154
|
-
}
|
|
12155
|
-
|
|
12156
|
-
if (disabled) {
|
|
12157
|
-
_.each(this.request_batchers, function(batcher) {
|
|
12158
|
-
batcher.clear();
|
|
12159
|
-
});
|
|
12160
|
-
}
|
|
12161
|
-
};
|
|
12162
|
-
|
|
12163
|
-
// call a base gdpr function after constructing the appropriate token and options args
|
|
12164
|
-
MixpanelLib.prototype._gdpr_call_func = function(func, options) {
|
|
12165
|
-
options = _.extend({
|
|
12166
|
-
'track': _.bind(this.track, this),
|
|
12167
|
-
'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
|
|
12168
|
-
'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
|
|
12169
|
-
'cookie_expiration': this.get_config('cookie_expiration'),
|
|
12170
|
-
'cross_site_cookie': this.get_config('cross_site_cookie'),
|
|
12171
|
-
'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
|
|
12172
|
-
'cookie_domain': this.get_config('cookie_domain'),
|
|
12173
|
-
'secure_cookie': this.get_config('secure_cookie'),
|
|
12174
|
-
'ignore_dnt': this.get_config('ignore_dnt')
|
|
12175
|
-
}, options);
|
|
12176
|
-
|
|
12177
|
-
// check if localStorage can be used for recording opt out status, fall back to cookie if not
|
|
12178
|
-
if (!_.localStorage.is_supported()) {
|
|
12179
|
-
options['persistence_type'] = 'cookie';
|
|
12180
|
-
}
|
|
12181
|
-
|
|
12182
|
-
return func(this.get_config('token'), {
|
|
12183
|
-
track: options['track'],
|
|
12184
|
-
trackEventName: options['track_event_name'],
|
|
12185
|
-
trackProperties: options['track_properties'],
|
|
12186
|
-
persistenceType: options['persistence_type'],
|
|
12187
|
-
persistencePrefix: options['cookie_prefix'],
|
|
12188
|
-
cookieDomain: options['cookie_domain'],
|
|
12189
|
-
cookieExpiration: options['cookie_expiration'],
|
|
12190
|
-
crossSiteCookie: options['cross_site_cookie'],
|
|
12191
|
-
crossSubdomainCookie: options['cross_subdomain_cookie'],
|
|
12192
|
-
secureCookie: options['secure_cookie'],
|
|
12193
|
-
ignoreDnt: options['ignore_dnt']
|
|
12194
|
-
});
|
|
11272
|
+
MixpanelLib.prototype.get_distinct_id = function() {
|
|
11273
|
+
return this.get_property('distinct_id');
|
|
12195
11274
|
};
|
|
12196
11275
|
|
|
12197
11276
|
/**
|
|
12198
|
-
*
|
|
11277
|
+
* The alias method creates an alias which Mixpanel will use to
|
|
11278
|
+
* remap one id to another. Multiple aliases can point to the
|
|
11279
|
+
* same identifier.
|
|
12199
11280
|
*
|
|
12200
|
-
*
|
|
11281
|
+
* The following is a valid use of alias:
|
|
12201
11282
|
*
|
|
12202
|
-
*
|
|
12203
|
-
*
|
|
11283
|
+
* mixpanel.alias('new_id', 'existing_id');
|
|
11284
|
+
* // You can add multiple id aliases to the existing ID
|
|
11285
|
+
* mixpanel.alias('newer_id', 'existing_id');
|
|
12204
11286
|
*
|
|
12205
|
-
*
|
|
12206
|
-
* mixpanel.opt_in_tracking({
|
|
12207
|
-
* track_event_name: 'User opted in',
|
|
12208
|
-
* track_event_properties: {
|
|
12209
|
-
* 'Email': 'jdoe@example.com'
|
|
12210
|
-
* },
|
|
12211
|
-
* cookie_expiration: 30,
|
|
12212
|
-
* secure_cookie: true
|
|
12213
|
-
* });
|
|
11287
|
+
* Aliases can also be chained - the following is a valid example:
|
|
12214
11288
|
*
|
|
12215
|
-
*
|
|
12216
|
-
*
|
|
12217
|
-
*
|
|
12218
|
-
* @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
|
|
12219
|
-
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
12220
|
-
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
12221
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12222
|
-
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
12223
|
-
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
12224
|
-
* @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
|
|
12225
|
-
* @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
|
|
12226
|
-
* @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
|
|
12227
|
-
*/
|
|
12228
|
-
MixpanelLib.prototype.opt_in_tracking = function(options) {
|
|
12229
|
-
options = _.extend({
|
|
12230
|
-
'enable_persistence': true
|
|
12231
|
-
}, options);
|
|
12232
|
-
|
|
12233
|
-
this._gdpr_call_func(optIn, options);
|
|
12234
|
-
this._gdpr_update_persistence(options);
|
|
12235
|
-
};
|
|
12236
|
-
|
|
12237
|
-
/**
|
|
12238
|
-
* Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
11289
|
+
* mixpanel.alias('new_id', 'existing_id');
|
|
11290
|
+
* // chain newer_id - new_id - existing_id
|
|
11291
|
+
* mixpanel.alias('newer_id', 'new_id');
|
|
12239
11292
|
*
|
|
12240
|
-
*
|
|
11293
|
+
* Aliases cannot point to multiple identifiers - the following
|
|
11294
|
+
* example will not work:
|
|
12241
11295
|
*
|
|
12242
|
-
*
|
|
12243
|
-
*
|
|
11296
|
+
* mixpanel.alias('new_id', 'existing_id');
|
|
11297
|
+
* // this is invalid as 'new_id' already points to 'existing_id'
|
|
11298
|
+
* mixpanel.alias('new_id', 'newer_id');
|
|
12244
11299
|
*
|
|
12245
|
-
*
|
|
12246
|
-
* mixpanel.opt_out_tracking({
|
|
12247
|
-
* cookie_expiration: 30,
|
|
12248
|
-
* secure_cookie: true
|
|
12249
|
-
* });
|
|
11300
|
+
* ### Notes:
|
|
12250
11301
|
*
|
|
12251
|
-
*
|
|
12252
|
-
*
|
|
12253
|
-
*
|
|
12254
|
-
*
|
|
12255
|
-
*
|
|
12256
|
-
*
|
|
12257
|
-
*
|
|
12258
|
-
* @param {
|
|
12259
|
-
* @param {
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12267
|
-
|
|
12268
|
-
// delete user and clear charges since these methods may be disabled by opt-out
|
|
12269
|
-
if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
|
|
12270
|
-
this['people'].delete_user();
|
|
12271
|
-
this['people'].clear_charges();
|
|
11302
|
+
* If your project does not have
|
|
11303
|
+
* <a href="https://help.mixpanel.com/hc/en-us/articles/360039133851">ID Merge</a>
|
|
11304
|
+
* enabled, the best practice is to call alias once when a unique
|
|
11305
|
+
* ID is first created for a user (e.g., when a user first registers
|
|
11306
|
+
* for an account). Do not use alias multiple times for a single
|
|
11307
|
+
* user without ID Merge enabled.
|
|
11308
|
+
*
|
|
11309
|
+
* @param {String} alias A unique identifier that you want to use for this user in the future.
|
|
11310
|
+
* @param {String} [original] The current identifier being used for this user.
|
|
11311
|
+
*/
|
|
11312
|
+
MixpanelLib.prototype.alias = function(alias, original) {
|
|
11313
|
+
// If the $people_distinct_id key exists in persistence, there has been a previous
|
|
11314
|
+
// mixpanel.people.identify() call made for this user. It is VERY BAD to make an alias with
|
|
11315
|
+
// this ID, as it will duplicate users.
|
|
11316
|
+
if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
|
|
11317
|
+
this.report_error('Attempting to create alias for existing People user - aborting.');
|
|
11318
|
+
return -2;
|
|
12272
11319
|
}
|
|
12273
11320
|
|
|
12274
|
-
this
|
|
12275
|
-
|
|
11321
|
+
var _this = this;
|
|
11322
|
+
if (_.isUndefined(original)) {
|
|
11323
|
+
original = this.get_distinct_id();
|
|
11324
|
+
}
|
|
11325
|
+
if (alias !== original) {
|
|
11326
|
+
this._register_single(ALIAS_ID_KEY, alias);
|
|
11327
|
+
return this.track('$create_alias', {
|
|
11328
|
+
'alias': alias,
|
|
11329
|
+
'distinct_id': original
|
|
11330
|
+
}, {
|
|
11331
|
+
skip_hooks: true
|
|
11332
|
+
}, function() {
|
|
11333
|
+
// Flush the people queue
|
|
11334
|
+
_this.identify(alias);
|
|
11335
|
+
});
|
|
11336
|
+
} else {
|
|
11337
|
+
this.report_error('alias matches current distinct_id - skipping api call.');
|
|
11338
|
+
this.identify(alias);
|
|
11339
|
+
return -1;
|
|
11340
|
+
}
|
|
12276
11341
|
};
|
|
12277
11342
|
|
|
12278
11343
|
/**
|
|
12279
|
-
*
|
|
12280
|
-
*
|
|
12281
|
-
*
|
|
11344
|
+
* Provide a string to recognize the user by. The string passed to
|
|
11345
|
+
* this method will appear in the Mixpanel Streams product rather
|
|
11346
|
+
* than an automatically generated name. Name tags do not have to
|
|
11347
|
+
* be unique.
|
|
12282
11348
|
*
|
|
12283
|
-
*
|
|
12284
|
-
* // use has_opted_in value
|
|
11349
|
+
* This value will only be included in Streams data.
|
|
12285
11350
|
*
|
|
12286
|
-
* @param {
|
|
12287
|
-
* @
|
|
12288
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12289
|
-
* @returns {boolean} current opt-in status
|
|
11351
|
+
* @param {String} name_tag A human readable name for the user
|
|
11352
|
+
* @deprecated
|
|
12290
11353
|
*/
|
|
12291
|
-
MixpanelLib.prototype.
|
|
12292
|
-
|
|
11354
|
+
MixpanelLib.prototype.name_tag = function(name_tag) {
|
|
11355
|
+
this._register_single('mp_name_tag', name_tag);
|
|
12293
11356
|
};
|
|
12294
11357
|
|
|
12295
11358
|
/**
|
|
12296
|
-
*
|
|
11359
|
+
* Update the configuration of a mixpanel library instance.
|
|
12297
11360
|
*
|
|
12298
|
-
*
|
|
11361
|
+
* The default config is:
|
|
12299
11362
|
*
|
|
12300
|
-
*
|
|
12301
|
-
*
|
|
11363
|
+
* {
|
|
11364
|
+
* // HTTP method for tracking requests
|
|
11365
|
+
* api_method: 'POST'
|
|
12302
11366
|
*
|
|
12303
|
-
*
|
|
12304
|
-
*
|
|
12305
|
-
*
|
|
12306
|
-
*
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12312
|
-
/**
|
|
12313
|
-
* Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
|
|
11367
|
+
* // transport for sending requests ('XHR' or 'sendBeacon')
|
|
11368
|
+
* // NB: sendBeacon should only be used for scenarios such as
|
|
11369
|
+
* // page unload where a "best-effort" attempt to send is
|
|
11370
|
+
* // acceptable; the sendBeacon API does not support callbacks
|
|
11371
|
+
* // or any way to know the result of the request. Mixpanel
|
|
11372
|
+
* // tracking via sendBeacon will not support any event-
|
|
11373
|
+
* // batching or retry mechanisms.
|
|
11374
|
+
* api_transport: 'XHR'
|
|
12314
11375
|
*
|
|
12315
|
-
*
|
|
11376
|
+
* // turn on request-batching/queueing/retry
|
|
11377
|
+
* batch_requests: false,
|
|
12316
11378
|
*
|
|
12317
|
-
*
|
|
12318
|
-
*
|
|
11379
|
+
* // maximum number of events/updates to send in a single
|
|
11380
|
+
* // network request
|
|
11381
|
+
* batch_size: 50,
|
|
12319
11382
|
*
|
|
12320
|
-
*
|
|
12321
|
-
*
|
|
12322
|
-
* mixpanel.clear_opt_in_out_tracking({
|
|
12323
|
-
* cookie_expiration: 30,
|
|
12324
|
-
* secure_cookie: true
|
|
12325
|
-
* });
|
|
11383
|
+
* // milliseconds to wait between sending batch requests
|
|
11384
|
+
* batch_flush_interval_ms: 5000,
|
|
12326
11385
|
*
|
|
12327
|
-
*
|
|
12328
|
-
*
|
|
12329
|
-
*
|
|
12330
|
-
*
|
|
12331
|
-
*
|
|
12332
|
-
*
|
|
12333
|
-
*
|
|
12334
|
-
*
|
|
12335
|
-
*
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12346
|
-
|
|
12347
|
-
|
|
12348
|
-
|
|
12349
|
-
|
|
12350
|
-
|
|
12351
|
-
|
|
12352
|
-
|
|
12353
|
-
|
|
12354
|
-
|
|
12355
|
-
|
|
12356
|
-
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12393
|
-
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
mixpanel_master['init'] = function(token, config, name) {
|
|
12416
|
-
if (name) {
|
|
12417
|
-
// initialize a sub library
|
|
12418
|
-
if (!mixpanel_master[name]) {
|
|
12419
|
-
mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
|
|
12420
|
-
mixpanel_master[name]._loaded();
|
|
12421
|
-
}
|
|
12422
|
-
return mixpanel_master[name];
|
|
12423
|
-
} else {
|
|
12424
|
-
var instance = mixpanel_master;
|
|
12425
|
-
|
|
12426
|
-
if (instances[PRIMARY_INSTANCE_NAME]) {
|
|
12427
|
-
// main mixpanel lib already initialized
|
|
12428
|
-
instance = instances[PRIMARY_INSTANCE_NAME];
|
|
12429
|
-
} else if (token) {
|
|
12430
|
-
// intialize the main mixpanel lib
|
|
12431
|
-
instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
|
|
12432
|
-
instance._loaded();
|
|
12433
|
-
instances[PRIMARY_INSTANCE_NAME] = instance;
|
|
12434
|
-
}
|
|
12435
|
-
|
|
12436
|
-
mixpanel_master = instance;
|
|
12437
|
-
if (init_type === INIT_SNIPPET) {
|
|
12438
|
-
window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
|
|
12439
|
-
}
|
|
12440
|
-
extend_mp();
|
|
12441
|
-
}
|
|
12442
|
-
};
|
|
12443
|
-
};
|
|
12444
|
-
|
|
12445
|
-
var add_dom_loaded_handler = function() {
|
|
12446
|
-
// Cross browser DOM Loaded support
|
|
12447
|
-
function dom_loaded_handler() {
|
|
12448
|
-
// function flag since we only want to execute this once
|
|
12449
|
-
if (dom_loaded_handler.done) { return; }
|
|
12450
|
-
dom_loaded_handler.done = true;
|
|
12451
|
-
|
|
12452
|
-
DOM_LOADED = true;
|
|
12453
|
-
ENQUEUE_REQUESTS = false;
|
|
12454
|
-
|
|
12455
|
-
_.each(instances, function(inst) {
|
|
12456
|
-
inst._dom_loaded();
|
|
12457
|
-
});
|
|
12458
|
-
}
|
|
11386
|
+
* // milliseconds to wait for network responses to batch requests
|
|
11387
|
+
* // before they are considered timed-out and retried
|
|
11388
|
+
* batch_request_timeout_ms: 90000,
|
|
11389
|
+
*
|
|
11390
|
+
* // override value for cookie domain, only useful for ensuring
|
|
11391
|
+
* // correct cross-subdomain cookies on unusual domains like
|
|
11392
|
+
* // subdomain.mainsite.avocat.fr; NB this cannot be used to
|
|
11393
|
+
* // set cookies on a different domain than the current origin
|
|
11394
|
+
* cookie_domain: ''
|
|
11395
|
+
*
|
|
11396
|
+
* // super properties cookie expiration (in days)
|
|
11397
|
+
* cookie_expiration: 365
|
|
11398
|
+
*
|
|
11399
|
+
* // if true, cookie will be set with SameSite=None; Secure
|
|
11400
|
+
* // this is only useful in special situations, like embedded
|
|
11401
|
+
* // 3rd-party iframes that set up a Mixpanel instance
|
|
11402
|
+
* cross_site_cookie: false
|
|
11403
|
+
*
|
|
11404
|
+
* // super properties span subdomains
|
|
11405
|
+
* cross_subdomain_cookie: true
|
|
11406
|
+
*
|
|
11407
|
+
* // debug mode
|
|
11408
|
+
* debug: false
|
|
11409
|
+
*
|
|
11410
|
+
* // if this is true, the mixpanel cookie or localStorage entry
|
|
11411
|
+
* // will be deleted, and no user persistence will take place
|
|
11412
|
+
* disable_persistence: false
|
|
11413
|
+
*
|
|
11414
|
+
* // if this is true, Mixpanel will automatically determine
|
|
11415
|
+
* // City, Region and Country data using the IP address of
|
|
11416
|
+
* //the client
|
|
11417
|
+
* ip: true
|
|
11418
|
+
*
|
|
11419
|
+
* // opt users out of tracking by this Mixpanel instance by default
|
|
11420
|
+
* opt_out_tracking_by_default: false
|
|
11421
|
+
*
|
|
11422
|
+
* // opt users out of browser data storage by this Mixpanel instance by default
|
|
11423
|
+
* opt_out_persistence_by_default: false
|
|
11424
|
+
*
|
|
11425
|
+
* // persistence mechanism used by opt-in/opt-out methods - cookie
|
|
11426
|
+
* // or localStorage - falls back to cookie if localStorage is unavailable
|
|
11427
|
+
* opt_out_tracking_persistence_type: 'localStorage'
|
|
11428
|
+
*
|
|
11429
|
+
* // customize the name of cookie/localStorage set by opt-in/opt-out methods
|
|
11430
|
+
* opt_out_tracking_cookie_prefix: null
|
|
11431
|
+
*
|
|
11432
|
+
* // type of persistent store for super properties (cookie/
|
|
11433
|
+
* // localStorage) if set to 'localStorage', any existing
|
|
11434
|
+
* // mixpanel cookie value with the same persistence_name
|
|
11435
|
+
* // will be transferred to localStorage and deleted
|
|
11436
|
+
* persistence: 'cookie'
|
|
11437
|
+
*
|
|
11438
|
+
* // name for super properties persistent store
|
|
11439
|
+
* persistence_name: ''
|
|
11440
|
+
*
|
|
11441
|
+
* // names of properties/superproperties which should never
|
|
11442
|
+
* // be sent with track() calls
|
|
11443
|
+
* property_blacklist: []
|
|
11444
|
+
*
|
|
11445
|
+
* // if this is true, mixpanel cookies will be marked as
|
|
11446
|
+
* // secure, meaning they will only be transmitted over https
|
|
11447
|
+
* secure_cookie: false
|
|
11448
|
+
*
|
|
11449
|
+
* // the amount of time track_links will
|
|
11450
|
+
* // wait for Mixpanel's servers to respond
|
|
11451
|
+
* track_links_timeout: 300
|
|
11452
|
+
*
|
|
11453
|
+
* // if you set upgrade to be true, the library will check for
|
|
11454
|
+
* // a cookie from our old js library and import super
|
|
11455
|
+
* // properties from it, then the old cookie is deleted
|
|
11456
|
+
* // The upgrade config option only works in the initialization,
|
|
11457
|
+
* // so make sure you set it when you create the library.
|
|
11458
|
+
* upgrade: false
|
|
11459
|
+
*
|
|
11460
|
+
* // extra HTTP request headers to set for each API request, in
|
|
11461
|
+
* // the format {'Header-Name': value}
|
|
11462
|
+
* xhr_headers: {}
|
|
11463
|
+
*
|
|
11464
|
+
* // whether to ignore or respect the web browser's Do Not Track setting
|
|
11465
|
+
* ignore_dnt: false
|
|
11466
|
+
* }
|
|
11467
|
+
*
|
|
11468
|
+
*
|
|
11469
|
+
* @param {Object} config A dictionary of new configuration values to update
|
|
11470
|
+
*/
|
|
11471
|
+
MixpanelLib.prototype.set_config = function(config) {
|
|
11472
|
+
if (_.isObject(config)) {
|
|
11473
|
+
_.extend(this['config'], config);
|
|
12459
11474
|
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
|
|
12465
|
-
return;
|
|
11475
|
+
var new_batch_size = config['batch_size'];
|
|
11476
|
+
if (new_batch_size) {
|
|
11477
|
+
_.each(this.request_batchers, function(batcher) {
|
|
11478
|
+
batcher.resetBatchSize();
|
|
11479
|
+
});
|
|
12466
11480
|
}
|
|
12467
11481
|
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
if (document$1.addEventListener) {
|
|
12472
|
-
if (document$1.readyState === 'complete') {
|
|
12473
|
-
// safari 4 can fire the DOMContentLoaded event before loading all
|
|
12474
|
-
// external JS (including this file). you will see some copypasta
|
|
12475
|
-
// on the internet that checks for 'complete' and 'loaded', but
|
|
12476
|
-
// 'loaded' is an IE thing
|
|
12477
|
-
dom_loaded_handler();
|
|
12478
|
-
} else {
|
|
12479
|
-
document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
|
|
11482
|
+
if (!this.get_config('persistence_name')) {
|
|
11483
|
+
this['config']['persistence_name'] = this['config']['cookie_name'];
|
|
12480
11484
|
}
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
document$1.attachEvent('onreadystatechange', dom_loaded_handler);
|
|
12484
|
-
|
|
12485
|
-
// check to make sure we arn't in a frame
|
|
12486
|
-
var toplevel = false;
|
|
12487
|
-
try {
|
|
12488
|
-
toplevel = window$1.frameElement === null;
|
|
12489
|
-
} catch(e) {
|
|
12490
|
-
// noop
|
|
11485
|
+
if (!this.get_config('disable_persistence')) {
|
|
11486
|
+
this['config']['disable_persistence'] = this['config']['disable_cookie'];
|
|
12491
11487
|
}
|
|
12492
11488
|
|
|
12493
|
-
if (
|
|
12494
|
-
|
|
11489
|
+
if (this['persistence']) {
|
|
11490
|
+
this['persistence'].update_config(this['config']);
|
|
12495
11491
|
}
|
|
11492
|
+
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
12496
11493
|
}
|
|
12497
|
-
|
|
12498
|
-
// fallback handler, always will work
|
|
12499
|
-
_.register_event(window$1, 'load', dom_loaded_handler, true);
|
|
12500
11494
|
};
|
|
12501
11495
|
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
11496
|
+
/**
|
|
11497
|
+
* returns the current config object for the library.
|
|
11498
|
+
*/
|
|
11499
|
+
MixpanelLib.prototype.get_config = function(prop_name) {
|
|
11500
|
+
return this['config'][prop_name];
|
|
11501
|
+
};
|
|
12505
11502
|
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
11503
|
+
/**
|
|
11504
|
+
* Fetch a hook function from config, with safe default, and run it
|
|
11505
|
+
* against the given arguments
|
|
11506
|
+
* @param {string} hook_name which hook to retrieve
|
|
11507
|
+
* @returns {any|null} return value of user-provided hook, or null if nothing was returned
|
|
11508
|
+
*/
|
|
11509
|
+
MixpanelLib.prototype._run_hook = function(hook_name) {
|
|
11510
|
+
var ret = (this['config']['hooks'][hook_name] || IDENTITY_FUNC).apply(this, slice.call(arguments, 1));
|
|
11511
|
+
if (typeof ret === 'undefined') {
|
|
11512
|
+
this.report_error(hook_name + ' hook did not return a value');
|
|
11513
|
+
ret = null;
|
|
11514
|
+
}
|
|
11515
|
+
return ret;
|
|
11516
|
+
};
|
|
12509
11517
|
|
|
12510
|
-
|
|
12511
|
-
|
|
11518
|
+
/**
|
|
11519
|
+
* Returns the value of the super property named property_name. If no such
|
|
11520
|
+
* property is set, get_property() will return the undefined value.
|
|
11521
|
+
*
|
|
11522
|
+
* ### Notes:
|
|
11523
|
+
*
|
|
11524
|
+
* get_property() can only be called after the Mixpanel library has finished loading.
|
|
11525
|
+
* init() has a loaded function available to handle this automatically. For example:
|
|
11526
|
+
*
|
|
11527
|
+
* // grab value for 'user_id' after the mixpanel library has loaded
|
|
11528
|
+
* mixpanel.init('YOUR PROJECT TOKEN', {
|
|
11529
|
+
* loaded: function(mixpanel) {
|
|
11530
|
+
* user_id = mixpanel.get_property('user_id');
|
|
11531
|
+
* }
|
|
11532
|
+
* });
|
|
11533
|
+
*
|
|
11534
|
+
* @param {String} property_name The name of the super property you want to retrieve
|
|
11535
|
+
*/
|
|
11536
|
+
MixpanelLib.prototype.get_property = function(property_name) {
|
|
11537
|
+
return this['persistence']['props'][property_name];
|
|
11538
|
+
};
|
|
12512
11539
|
|
|
12513
|
-
|
|
11540
|
+
MixpanelLib.prototype.toString = function() {
|
|
11541
|
+
var name = this.get_config('name');
|
|
11542
|
+
if (name !== PRIMARY_INSTANCE_NAME) {
|
|
11543
|
+
name = PRIMARY_INSTANCE_NAME + '.' + name;
|
|
11544
|
+
}
|
|
11545
|
+
return name;
|
|
11546
|
+
};
|
|
12514
11547
|
|
|
12515
|
-
|
|
11548
|
+
MixpanelLib.prototype._event_is_disabled = function(event_name) {
|
|
11549
|
+
return _.isBlockedUA(userAgent) ||
|
|
11550
|
+
this._flags.disable_all_events ||
|
|
11551
|
+
_.include(this.__disabled_events, event_name);
|
|
11552
|
+
};
|
|
12516
11553
|
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
11554
|
+
// perform some housekeeping around GDPR opt-in/out state
|
|
11555
|
+
MixpanelLib.prototype._gdpr_init = function() {
|
|
11556
|
+
var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
|
|
12520
11557
|
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
};
|
|
12535
|
-
let isMixpanelInitialized = false;
|
|
12536
|
-
let eventQueue = [];
|
|
12537
|
-
/**
|
|
12538
|
-
* Pushes the event with its Property key-value map to mixpanel.
|
|
12539
|
-
*
|
|
12540
|
-
* @param eventId
|
|
12541
|
-
* @param eventProps
|
|
12542
|
-
*/
|
|
12543
|
-
function uploadMixpanelEvent(eventId, eventProps = {}) {
|
|
12544
|
-
if (!isMixpanelInitialized) {
|
|
12545
|
-
eventQueue.push({ eventId, eventProps });
|
|
12546
|
-
return;
|
|
12547
|
-
}
|
|
12548
|
-
mixpanelInstance.track(eventId, eventProps);
|
|
12549
|
-
}
|
|
12550
|
-
/**
|
|
12551
|
-
*
|
|
12552
|
-
*/
|
|
12553
|
-
function emptyQueue() {
|
|
12554
|
-
if (!isMixpanelInitialized) {
|
|
12555
|
-
return;
|
|
12556
|
-
}
|
|
12557
|
-
eventQueue.forEach((event) => {
|
|
12558
|
-
uploadMixpanelEvent(event.eventId, event.eventProps);
|
|
12559
|
-
});
|
|
12560
|
-
eventQueue = [];
|
|
12561
|
-
}
|
|
12562
|
-
/**
|
|
12563
|
-
*
|
|
12564
|
-
* @param sessionInfo
|
|
12565
|
-
*/
|
|
12566
|
-
function initMixpanel(sessionInfo) {
|
|
12567
|
-
var _a;
|
|
12568
|
-
if (!sessionInfo || !sessionInfo.mixpanelToken) {
|
|
12569
|
-
return;
|
|
12570
|
-
}
|
|
12571
|
-
// On a public cluster the user is anonymous, so don't set the identify to
|
|
12572
|
-
// userGUID
|
|
12573
|
-
const isPublicCluster = !!sessionInfo.isPublicUser;
|
|
12574
|
-
const token = sessionInfo.mixpanelToken;
|
|
12575
|
-
try {
|
|
12576
|
-
if (token) {
|
|
12577
|
-
mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
|
|
12578
|
-
if (!isPublicCluster) {
|
|
12579
|
-
mixpanelInstance.identify(sessionInfo.userGUID);
|
|
12580
|
-
}
|
|
12581
|
-
mixpanelInstance.register_once({
|
|
12582
|
-
clusterId: sessionInfo.clusterId,
|
|
12583
|
-
clusterName: sessionInfo.clusterName,
|
|
12584
|
-
releaseVersion: sessionInfo.releaseVersion,
|
|
12585
|
-
hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
|
|
12586
|
-
});
|
|
12587
|
-
isMixpanelInitialized = true;
|
|
12588
|
-
emptyQueue();
|
|
12589
|
-
}
|
|
12590
|
-
}
|
|
12591
|
-
catch (e) {
|
|
12592
|
-
logger.error('Error initializing mixpanel', e);
|
|
12593
|
-
}
|
|
12594
|
-
}
|
|
11558
|
+
// try to convert opt-in/out cookies to localStorage if possible
|
|
11559
|
+
if (is_localStorage_requested && _.localStorage.is_supported()) {
|
|
11560
|
+
if (!this.has_opted_in_tracking() && this.has_opted_in_tracking({'persistence_type': 'cookie'})) {
|
|
11561
|
+
this.opt_in_tracking({'enable_persistence': false});
|
|
11562
|
+
}
|
|
11563
|
+
if (!this.has_opted_out_tracking() && this.has_opted_out_tracking({'persistence_type': 'cookie'})) {
|
|
11564
|
+
this.opt_out_tracking({'clear_persistence': false});
|
|
11565
|
+
}
|
|
11566
|
+
this.clear_opt_in_out_tracking({
|
|
11567
|
+
'persistence_type': 'cookie',
|
|
11568
|
+
'enable_persistence': false
|
|
11569
|
+
});
|
|
11570
|
+
}
|
|
12595
11571
|
|
|
12596
|
-
|
|
11572
|
+
// check whether the user has already opted out - if so, clear & disable persistence
|
|
11573
|
+
if (this.has_opted_out_tracking()) {
|
|
11574
|
+
this._gdpr_update_persistence({'clear_persistence': true});
|
|
12597
11575
|
|
|
12598
|
-
|
|
12599
|
-
|
|
11576
|
+
// check whether we should opt out by default
|
|
11577
|
+
// note: we don't clear persistence here by default since opt-out default state is often
|
|
11578
|
+
// used as an initial state while GDPR information is being collected
|
|
11579
|
+
} else if (!this.has_opted_in_tracking() && (
|
|
11580
|
+
this.get_config('opt_out_tracking_by_default') || _.cookie.get('mp_optout')
|
|
11581
|
+
)) {
|
|
11582
|
+
_.cookie.remove('mp_optout');
|
|
11583
|
+
this.opt_out_tracking({
|
|
11584
|
+
'clear_persistence': this.get_config('opt_out_persistence_by_default')
|
|
11585
|
+
});
|
|
11586
|
+
}
|
|
11587
|
+
};
|
|
12600
11588
|
|
|
12601
11589
|
/**
|
|
12602
|
-
*
|
|
12603
|
-
*
|
|
12604
|
-
*
|
|
12605
|
-
* @
|
|
12606
|
-
* @private
|
|
11590
|
+
* Enable or disable persistence based on options
|
|
11591
|
+
* only enable/disable if persistence is not already in this state
|
|
11592
|
+
* @param {boolean} [options.clear_persistence] If true, will delete all data stored by the sdk in persistence and disable it
|
|
11593
|
+
* @param {boolean} [options.enable_persistence] If true, will re-enable sdk persistence
|
|
12607
11594
|
*/
|
|
12608
|
-
function
|
|
11595
|
+
MixpanelLib.prototype._gdpr_update_persistence = function(options) {
|
|
11596
|
+
var disabled;
|
|
11597
|
+
if (options && options['clear_persistence']) {
|
|
11598
|
+
disabled = true;
|
|
11599
|
+
} else if (options && options['enable_persistence']) {
|
|
11600
|
+
disabled = false;
|
|
11601
|
+
} else {
|
|
11602
|
+
return;
|
|
11603
|
+
}
|
|
12609
11604
|
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
// If `Object.create(null)` is not supported we prefix the event names with a
|
|
12614
|
-
// character to make sure that the built-in object properties are not
|
|
12615
|
-
// overridden or used as an attack vector.
|
|
12616
|
-
//
|
|
12617
|
-
if (Object.create) {
|
|
12618
|
-
Events.prototype = Object.create(null);
|
|
11605
|
+
if (!this.get_config('disable_persistence') && this['persistence'].disabled !== disabled) {
|
|
11606
|
+
this['persistence'].set_disabled(disabled);
|
|
11607
|
+
}
|
|
12619
11608
|
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
12625
|
-
}
|
|
11609
|
+
if (disabled) {
|
|
11610
|
+
_.each(this.request_batchers, function(batcher) {
|
|
11611
|
+
batcher.clear();
|
|
11612
|
+
});
|
|
11613
|
+
}
|
|
11614
|
+
};
|
|
11615
|
+
|
|
11616
|
+
// call a base gdpr function after constructing the appropriate token and options args
|
|
11617
|
+
MixpanelLib.prototype._gdpr_call_func = function(func, options) {
|
|
11618
|
+
options = _.extend({
|
|
11619
|
+
'track': _.bind(this.track, this),
|
|
11620
|
+
'persistence_type': this.get_config('opt_out_tracking_persistence_type'),
|
|
11621
|
+
'cookie_prefix': this.get_config('opt_out_tracking_cookie_prefix'),
|
|
11622
|
+
'cookie_expiration': this.get_config('cookie_expiration'),
|
|
11623
|
+
'cross_site_cookie': this.get_config('cross_site_cookie'),
|
|
11624
|
+
'cross_subdomain_cookie': this.get_config('cross_subdomain_cookie'),
|
|
11625
|
+
'cookie_domain': this.get_config('cookie_domain'),
|
|
11626
|
+
'secure_cookie': this.get_config('secure_cookie'),
|
|
11627
|
+
'ignore_dnt': this.get_config('ignore_dnt')
|
|
11628
|
+
}, options);
|
|
11629
|
+
|
|
11630
|
+
// check if localStorage can be used for recording opt out status, fall back to cookie if not
|
|
11631
|
+
if (!_.localStorage.is_supported()) {
|
|
11632
|
+
options['persistence_type'] = 'cookie';
|
|
11633
|
+
}
|
|
11634
|
+
|
|
11635
|
+
return func(this.get_config('token'), {
|
|
11636
|
+
track: options['track'],
|
|
11637
|
+
trackEventName: options['track_event_name'],
|
|
11638
|
+
trackProperties: options['track_properties'],
|
|
11639
|
+
persistenceType: options['persistence_type'],
|
|
11640
|
+
persistencePrefix: options['cookie_prefix'],
|
|
11641
|
+
cookieDomain: options['cookie_domain'],
|
|
11642
|
+
cookieExpiration: options['cookie_expiration'],
|
|
11643
|
+
crossSiteCookie: options['cross_site_cookie'],
|
|
11644
|
+
crossSubdomainCookie: options['cross_subdomain_cookie'],
|
|
11645
|
+
secureCookie: options['secure_cookie'],
|
|
11646
|
+
ignoreDnt: options['ignore_dnt']
|
|
11647
|
+
});
|
|
11648
|
+
};
|
|
12626
11649
|
|
|
12627
11650
|
/**
|
|
12628
|
-
*
|
|
11651
|
+
* Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
12629
11652
|
*
|
|
12630
|
-
*
|
|
12631
|
-
*
|
|
12632
|
-
*
|
|
12633
|
-
*
|
|
12634
|
-
*
|
|
11653
|
+
* ### Usage
|
|
11654
|
+
*
|
|
11655
|
+
* // opt user in
|
|
11656
|
+
* mixpanel.opt_in_tracking();
|
|
11657
|
+
*
|
|
11658
|
+
* // opt user in with specific event name, properties, cookie configuration
|
|
11659
|
+
* mixpanel.opt_in_tracking({
|
|
11660
|
+
* track_event_name: 'User opted in',
|
|
11661
|
+
* track_event_properties: {
|
|
11662
|
+
* 'Email': 'jdoe@example.com'
|
|
11663
|
+
* },
|
|
11664
|
+
* cookie_expiration: 30,
|
|
11665
|
+
* secure_cookie: true
|
|
11666
|
+
* });
|
|
11667
|
+
*
|
|
11668
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
11669
|
+
* @param {function} [options.track] Function used for tracking a Mixpanel event to record the opt-in action (default is this Mixpanel instance's track method)
|
|
11670
|
+
* @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
|
|
11671
|
+
* @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
|
|
11672
|
+
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
11673
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11674
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11675
|
+
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
11676
|
+
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
11677
|
+
* @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
|
|
11678
|
+
* @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
|
|
11679
|
+
* @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
|
|
12635
11680
|
*/
|
|
12636
|
-
function
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
11681
|
+
MixpanelLib.prototype.opt_in_tracking = function(options) {
|
|
11682
|
+
options = _.extend({
|
|
11683
|
+
'enable_persistence': true
|
|
11684
|
+
}, options);
|
|
11685
|
+
|
|
11686
|
+
this._gdpr_call_func(optIn, options);
|
|
11687
|
+
this._gdpr_update_persistence(options);
|
|
11688
|
+
};
|
|
12641
11689
|
|
|
12642
11690
|
/**
|
|
12643
|
-
*
|
|
11691
|
+
* Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
12644
11692
|
*
|
|
12645
|
-
*
|
|
12646
|
-
*
|
|
12647
|
-
*
|
|
12648
|
-
*
|
|
12649
|
-
*
|
|
12650
|
-
*
|
|
12651
|
-
*
|
|
11693
|
+
* ### Usage
|
|
11694
|
+
*
|
|
11695
|
+
* // opt user out
|
|
11696
|
+
* mixpanel.opt_out_tracking();
|
|
11697
|
+
*
|
|
11698
|
+
* // opt user out with different cookie configuration from Mixpanel instance
|
|
11699
|
+
* mixpanel.opt_out_tracking({
|
|
11700
|
+
* cookie_expiration: 30,
|
|
11701
|
+
* secure_cookie: true
|
|
11702
|
+
* });
|
|
11703
|
+
*
|
|
11704
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
11705
|
+
* @param {boolean} [options.delete_user=true] If true, will delete the currently identified user's profile and clear all charges after opting the user out
|
|
11706
|
+
* @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
|
|
11707
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11708
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11709
|
+
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
11710
|
+
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
11711
|
+
* @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
|
|
11712
|
+
* @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
|
|
11713
|
+
* @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
|
|
12652
11714
|
*/
|
|
12653
|
-
function
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
var listener = new EE(fn, context || emitter, once)
|
|
12659
|
-
, evt = prefix ? prefix + event : event;
|
|
11715
|
+
MixpanelLib.prototype.opt_out_tracking = function(options) {
|
|
11716
|
+
options = _.extend({
|
|
11717
|
+
'clear_persistence': true,
|
|
11718
|
+
'delete_user': true
|
|
11719
|
+
}, options);
|
|
12660
11720
|
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
11721
|
+
// delete user and clear charges since these methods may be disabled by opt-out
|
|
11722
|
+
if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
|
|
11723
|
+
this['people'].delete_user();
|
|
11724
|
+
this['people'].clear_charges();
|
|
11725
|
+
}
|
|
12664
11726
|
|
|
12665
|
-
|
|
12666
|
-
|
|
11727
|
+
this._gdpr_call_func(optOut, options);
|
|
11728
|
+
this._gdpr_update_persistence(options);
|
|
11729
|
+
};
|
|
12667
11730
|
|
|
12668
11731
|
/**
|
|
12669
|
-
*
|
|
11732
|
+
* Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
12670
11733
|
*
|
|
12671
|
-
*
|
|
12672
|
-
*
|
|
12673
|
-
*
|
|
11734
|
+
* ### Usage
|
|
11735
|
+
*
|
|
11736
|
+
* var has_opted_in = mixpanel.has_opted_in_tracking();
|
|
11737
|
+
* // use has_opted_in value
|
|
11738
|
+
*
|
|
11739
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
11740
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11741
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11742
|
+
* @returns {boolean} current opt-in status
|
|
12674
11743
|
*/
|
|
12675
|
-
function
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
}
|
|
11744
|
+
MixpanelLib.prototype.has_opted_in_tracking = function(options) {
|
|
11745
|
+
return this._gdpr_call_func(hasOptedIn, options);
|
|
11746
|
+
};
|
|
12679
11747
|
|
|
12680
11748
|
/**
|
|
12681
|
-
*
|
|
12682
|
-
* `EventEmitter` interface.
|
|
11749
|
+
* Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
12683
11750
|
*
|
|
12684
|
-
*
|
|
12685
|
-
*
|
|
11751
|
+
* ### Usage
|
|
11752
|
+
*
|
|
11753
|
+
* var has_opted_out = mixpanel.has_opted_out_tracking();
|
|
11754
|
+
* // use has_opted_out value
|
|
11755
|
+
*
|
|
11756
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
11757
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11758
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11759
|
+
* @returns {boolean} current opt-out status
|
|
12686
11760
|
*/
|
|
12687
|
-
function
|
|
12688
|
-
|
|
12689
|
-
|
|
12690
|
-
}
|
|
11761
|
+
MixpanelLib.prototype.has_opted_out_tracking = function(options) {
|
|
11762
|
+
return this._gdpr_call_func(hasOptedOut, options);
|
|
11763
|
+
};
|
|
12691
11764
|
|
|
12692
11765
|
/**
|
|
12693
|
-
*
|
|
12694
|
-
*
|
|
11766
|
+
* Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
|
|
11767
|
+
*
|
|
11768
|
+
* ### Usage
|
|
11769
|
+
*
|
|
11770
|
+
* // clear user's opt-in/out status
|
|
11771
|
+
* mixpanel.clear_opt_in_out_tracking();
|
|
11772
|
+
*
|
|
11773
|
+
* // clear user's opt-in/out status with specific cookie configuration - should match
|
|
11774
|
+
* // configuration used when opt_in_tracking/opt_out_tracking methods were called.
|
|
11775
|
+
* mixpanel.clear_opt_in_out_tracking({
|
|
11776
|
+
* cookie_expiration: 30,
|
|
11777
|
+
* secure_cookie: true
|
|
11778
|
+
* });
|
|
12695
11779
|
*
|
|
12696
|
-
* @
|
|
12697
|
-
* @
|
|
11780
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
11781
|
+
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
11782
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11783
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11784
|
+
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
11785
|
+
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
11786
|
+
* @param {boolean} [options.cross_site_cookie] Whether the opt-in cookie is set as cross-site-enabled (overrides value specified in this Mixpanel instance's config)
|
|
11787
|
+
* @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this Mixpanel instance's config)
|
|
11788
|
+
* @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this Mixpanel instance's config)
|
|
12698
11789
|
*/
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
,
|
|
12703
|
-
|
|
12704
|
-
if (this._eventsCount === 0) return names;
|
|
12705
|
-
|
|
12706
|
-
for (name in (events = this._events)) {
|
|
12707
|
-
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
|
12708
|
-
}
|
|
11790
|
+
MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
|
|
11791
|
+
options = _.extend({
|
|
11792
|
+
'enable_persistence': true
|
|
11793
|
+
}, options);
|
|
12709
11794
|
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
11795
|
+
this._gdpr_call_func(clearOptInOut, options);
|
|
11796
|
+
this._gdpr_update_persistence(options);
|
|
11797
|
+
};
|
|
12713
11798
|
|
|
12714
|
-
|
|
11799
|
+
MixpanelLib.prototype.report_error = function(msg, err) {
|
|
11800
|
+
console$1.error.apply(console$1.error, arguments);
|
|
11801
|
+
try {
|
|
11802
|
+
if (!err && !(msg instanceof Error)) {
|
|
11803
|
+
msg = new Error(msg);
|
|
11804
|
+
}
|
|
11805
|
+
this.get_config('error_reporter')(msg, err);
|
|
11806
|
+
} catch(err) {
|
|
11807
|
+
console$1.error(err);
|
|
11808
|
+
}
|
|
12715
11809
|
};
|
|
12716
11810
|
|
|
12717
|
-
|
|
12718
|
-
* Return the listeners registered for a given event.
|
|
12719
|
-
*
|
|
12720
|
-
* @param {(String|Symbol)} event The event name.
|
|
12721
|
-
* @returns {Array} The registered listeners.
|
|
12722
|
-
* @public
|
|
12723
|
-
*/
|
|
12724
|
-
EventEmitter.prototype.listeners = function listeners(event) {
|
|
12725
|
-
var evt = prefix ? prefix + event : event
|
|
12726
|
-
, handlers = this._events[evt];
|
|
11811
|
+
// EXPORTS (for closure compiler)
|
|
12727
11812
|
|
|
12728
|
-
|
|
12729
|
-
|
|
11813
|
+
// MixpanelLib Exports
|
|
11814
|
+
MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
|
|
11815
|
+
MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
|
|
11816
|
+
MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
|
|
11817
|
+
MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
|
|
11818
|
+
MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
|
|
11819
|
+
MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
|
|
11820
|
+
MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
|
|
11821
|
+
MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
|
|
11822
|
+
MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
|
|
11823
|
+
MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
|
|
11824
|
+
MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
|
|
11825
|
+
MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
|
|
11826
|
+
MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
|
|
11827
|
+
MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
|
|
11828
|
+
MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
|
|
11829
|
+
MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
|
|
11830
|
+
MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
|
|
11831
|
+
MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
|
|
11832
|
+
MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
|
|
11833
|
+
MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
|
|
11834
|
+
MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
|
|
11835
|
+
MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
|
|
11836
|
+
MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
|
|
11837
|
+
MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
|
|
11838
|
+
MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
|
|
11839
|
+
MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
|
|
11840
|
+
MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
|
|
11841
|
+
MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
|
|
11842
|
+
MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
|
|
11843
|
+
MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
|
|
11844
|
+
MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
|
|
12730
11845
|
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
11846
|
+
// MixpanelPersistence Exports
|
|
11847
|
+
MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
|
|
11848
|
+
MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
|
|
11849
|
+
MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
|
|
11850
|
+
MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
|
|
11851
|
+
MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
|
|
12734
11852
|
|
|
12735
|
-
return ee;
|
|
12736
|
-
};
|
|
12737
11853
|
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
*/
|
|
12745
|
-
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
|
12746
|
-
var evt = prefix ? prefix + event : event
|
|
12747
|
-
, listeners = this._events[evt];
|
|
11854
|
+
var instances = {};
|
|
11855
|
+
var extend_mp = function() {
|
|
11856
|
+
// add all the sub mixpanel instances
|
|
11857
|
+
_.each(instances, function(instance, name) {
|
|
11858
|
+
if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
|
|
11859
|
+
});
|
|
12748
11860
|
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
return listeners.length;
|
|
11861
|
+
// add private functions as _
|
|
11862
|
+
mixpanel_master['_'] = _;
|
|
12752
11863
|
};
|
|
12753
11864
|
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
11865
|
+
var override_mp_init_func = function() {
|
|
11866
|
+
// we override the snippets init function to handle the case where a
|
|
11867
|
+
// user initializes the mixpanel library after the script loads & runs
|
|
11868
|
+
mixpanel_master['init'] = function(token, config, name) {
|
|
11869
|
+
if (name) {
|
|
11870
|
+
// initialize a sub library
|
|
11871
|
+
if (!mixpanel_master[name]) {
|
|
11872
|
+
mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
|
|
11873
|
+
mixpanel_master[name]._loaded();
|
|
11874
|
+
}
|
|
11875
|
+
return mixpanel_master[name];
|
|
11876
|
+
} else {
|
|
11877
|
+
var instance = mixpanel_master;
|
|
12763
11878
|
|
|
12764
|
-
|
|
11879
|
+
if (instances[PRIMARY_INSTANCE_NAME]) {
|
|
11880
|
+
// main mixpanel lib already initialized
|
|
11881
|
+
instance = instances[PRIMARY_INSTANCE_NAME];
|
|
11882
|
+
} else if (token) {
|
|
11883
|
+
// intialize the main mixpanel lib
|
|
11884
|
+
instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
|
|
11885
|
+
instance._loaded();
|
|
11886
|
+
instances[PRIMARY_INSTANCE_NAME] = instance;
|
|
11887
|
+
}
|
|
12765
11888
|
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
11889
|
+
mixpanel_master = instance;
|
|
11890
|
+
if (init_type === INIT_SNIPPET) {
|
|
11891
|
+
window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
|
|
11892
|
+
}
|
|
11893
|
+
extend_mp();
|
|
11894
|
+
}
|
|
11895
|
+
};
|
|
11896
|
+
};
|
|
12770
11897
|
|
|
12771
|
-
|
|
12772
|
-
|
|
11898
|
+
var add_dom_loaded_handler = function() {
|
|
11899
|
+
// Cross browser DOM Loaded support
|
|
11900
|
+
function dom_loaded_handler() {
|
|
11901
|
+
// function flag since we only want to execute this once
|
|
11902
|
+
if (dom_loaded_handler.done) { return; }
|
|
11903
|
+
dom_loaded_handler.done = true;
|
|
12773
11904
|
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
case 2: return listeners.fn.call(listeners.context, a1), true;
|
|
12777
|
-
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
|
|
12778
|
-
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
|
12779
|
-
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
|
12780
|
-
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
|
12781
|
-
}
|
|
11905
|
+
DOM_LOADED = true;
|
|
11906
|
+
ENQUEUE_REQUESTS = false;
|
|
12782
11907
|
|
|
12783
|
-
|
|
12784
|
-
|
|
11908
|
+
_.each(instances, function(inst) {
|
|
11909
|
+
inst._dom_loaded();
|
|
11910
|
+
});
|
|
12785
11911
|
}
|
|
12786
11912
|
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
12795
|
-
switch (len) {
|
|
12796
|
-
case 1: listeners[i].fn.call(listeners[i].context); break;
|
|
12797
|
-
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
|
|
12798
|
-
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
|
|
12799
|
-
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
|
|
12800
|
-
default:
|
|
12801
|
-
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
|
|
12802
|
-
args[j - 1] = arguments[j];
|
|
12803
|
-
}
|
|
11913
|
+
function do_scroll_check() {
|
|
11914
|
+
try {
|
|
11915
|
+
document$1.documentElement.doScroll('left');
|
|
11916
|
+
} catch(e) {
|
|
11917
|
+
setTimeout(do_scroll_check, 1);
|
|
11918
|
+
return;
|
|
11919
|
+
}
|
|
12804
11920
|
|
|
12805
|
-
|
|
12806
|
-
}
|
|
11921
|
+
dom_loaded_handler();
|
|
12807
11922
|
}
|
|
12808
|
-
}
|
|
12809
11923
|
|
|
12810
|
-
|
|
12811
|
-
|
|
11924
|
+
if (document$1.addEventListener) {
|
|
11925
|
+
if (document$1.readyState === 'complete') {
|
|
11926
|
+
// safari 4 can fire the DOMContentLoaded event before loading all
|
|
11927
|
+
// external JS (including this file). you will see some copypasta
|
|
11928
|
+
// on the internet that checks for 'complete' and 'loaded', but
|
|
11929
|
+
// 'loaded' is an IE thing
|
|
11930
|
+
dom_loaded_handler();
|
|
11931
|
+
} else {
|
|
11932
|
+
document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
|
|
11933
|
+
}
|
|
11934
|
+
} else if (document$1.attachEvent) {
|
|
11935
|
+
// IE
|
|
11936
|
+
document$1.attachEvent('onreadystatechange', dom_loaded_handler);
|
|
12812
11937
|
|
|
12813
|
-
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
|
|
11938
|
+
// check to make sure we arn't in a frame
|
|
11939
|
+
var toplevel = false;
|
|
11940
|
+
try {
|
|
11941
|
+
toplevel = window$1.frameElement === null;
|
|
11942
|
+
} catch(e) {
|
|
11943
|
+
// noop
|
|
11944
|
+
}
|
|
11945
|
+
|
|
11946
|
+
if (document$1.documentElement.doScroll && toplevel) {
|
|
11947
|
+
do_scroll_check();
|
|
11948
|
+
}
|
|
11949
|
+
}
|
|
12825
11950
|
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
*
|
|
12829
|
-
* @param {(String|Symbol)} event The event name.
|
|
12830
|
-
* @param {Function} fn The listener function.
|
|
12831
|
-
* @param {*} [context=this] The context to invoke the listener with.
|
|
12832
|
-
* @returns {EventEmitter} `this`.
|
|
12833
|
-
* @public
|
|
12834
|
-
*/
|
|
12835
|
-
EventEmitter.prototype.once = function once(event, fn, context) {
|
|
12836
|
-
return addListener(this, event, fn, context, true);
|
|
11951
|
+
// fallback handler, always will work
|
|
11952
|
+
_.register_event(window$1, 'load', dom_loaded_handler, true);
|
|
12837
11953
|
};
|
|
12838
11954
|
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
* @param {(String|Symbol)} event The event name.
|
|
12843
|
-
* @param {Function} fn Only remove the listeners that match this function.
|
|
12844
|
-
* @param {*} context Only remove the listeners that have this context.
|
|
12845
|
-
* @param {Boolean} once Only remove one-time listeners.
|
|
12846
|
-
* @returns {EventEmitter} `this`.
|
|
12847
|
-
* @public
|
|
12848
|
-
*/
|
|
12849
|
-
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
|
12850
|
-
var evt = prefix ? prefix + event : event;
|
|
11955
|
+
function init_as_module() {
|
|
11956
|
+
init_type = INIT_MODULE;
|
|
11957
|
+
mixpanel_master = new MixpanelLib();
|
|
12851
11958
|
|
|
12852
|
-
|
|
12853
|
-
|
|
12854
|
-
|
|
12855
|
-
return this;
|
|
12856
|
-
}
|
|
11959
|
+
override_mp_init_func();
|
|
11960
|
+
mixpanel_master['init']();
|
|
11961
|
+
add_dom_loaded_handler();
|
|
12857
11962
|
|
|
12858
|
-
|
|
11963
|
+
return mixpanel_master;
|
|
11964
|
+
}
|
|
12859
11965
|
|
|
12860
|
-
|
|
12861
|
-
if (
|
|
12862
|
-
listeners.fn === fn &&
|
|
12863
|
-
(!once || listeners.once) &&
|
|
12864
|
-
(!context || listeners.context === context)
|
|
12865
|
-
) {
|
|
12866
|
-
clearEvent(this, evt);
|
|
12867
|
-
}
|
|
12868
|
-
} else {
|
|
12869
|
-
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
|
12870
|
-
if (
|
|
12871
|
-
listeners[i].fn !== fn ||
|
|
12872
|
-
(once && !listeners[i].once) ||
|
|
12873
|
-
(context && listeners[i].context !== context)
|
|
12874
|
-
) {
|
|
12875
|
-
events.push(listeners[i]);
|
|
12876
|
-
}
|
|
12877
|
-
}
|
|
11966
|
+
var mixpanel = init_as_module();
|
|
12878
11967
|
|
|
12879
|
-
|
|
12880
|
-
// Reset the array, or remove it completely if we have no more listeners.
|
|
12881
|
-
//
|
|
12882
|
-
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
|
|
12883
|
-
else clearEvent(this, evt);
|
|
12884
|
-
}
|
|
11968
|
+
var mixpanel_cjs = mixpanel;
|
|
12885
11969
|
|
|
12886
|
-
|
|
11970
|
+
var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
|
|
11971
|
+
'default': mixpanel_cjs
|
|
11972
|
+
}));
|
|
11973
|
+
|
|
11974
|
+
// Needed to avoid error in CJS builds on some bundlers.
|
|
11975
|
+
const mixpanelLib = mixpanel_cjs || mixpanel$1;
|
|
11976
|
+
let mixpanelInstance;
|
|
11977
|
+
const MIXPANEL_EVENT = {
|
|
11978
|
+
VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
|
|
11979
|
+
VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
|
|
11980
|
+
VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
|
|
11981
|
+
VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
|
|
11982
|
+
VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
|
|
11983
|
+
VISUAL_SDK_ON: 'visual-sdk-on',
|
|
11984
|
+
VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
|
|
11985
|
+
VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
|
|
11986
|
+
VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
|
|
11987
|
+
};
|
|
11988
|
+
let isMixpanelInitialized = false;
|
|
11989
|
+
let eventQueue = [];
|
|
11990
|
+
/**
|
|
11991
|
+
* Pushes the event with its Property key-value map to mixpanel.
|
|
11992
|
+
*
|
|
11993
|
+
* @param eventId
|
|
11994
|
+
* @param eventProps
|
|
11995
|
+
*/
|
|
11996
|
+
function uploadMixpanelEvent(eventId, eventProps = {}) {
|
|
11997
|
+
if (!isMixpanelInitialized) {
|
|
11998
|
+
eventQueue.push({ eventId, eventProps });
|
|
11999
|
+
return;
|
|
12000
|
+
}
|
|
12001
|
+
mixpanelInstance.track(eventId, eventProps);
|
|
12002
|
+
}
|
|
12003
|
+
/**
|
|
12004
|
+
*
|
|
12005
|
+
*/
|
|
12006
|
+
function emptyQueue() {
|
|
12007
|
+
if (!isMixpanelInitialized) {
|
|
12008
|
+
return;
|
|
12009
|
+
}
|
|
12010
|
+
eventQueue.forEach((event) => {
|
|
12011
|
+
uploadMixpanelEvent(event.eventId, event.eventProps);
|
|
12012
|
+
});
|
|
12013
|
+
eventQueue = [];
|
|
12014
|
+
}
|
|
12015
|
+
/**
|
|
12016
|
+
*
|
|
12017
|
+
* @param sessionInfo
|
|
12018
|
+
*/
|
|
12019
|
+
function initMixpanel(sessionInfo) {
|
|
12020
|
+
var _a;
|
|
12021
|
+
if (!sessionInfo || !sessionInfo.mixpanelToken) {
|
|
12022
|
+
return;
|
|
12023
|
+
}
|
|
12024
|
+
// On a public cluster the user is anonymous, so don't set the identify to
|
|
12025
|
+
// userGUID
|
|
12026
|
+
const isPublicCluster = !!sessionInfo.isPublicUser;
|
|
12027
|
+
const token = sessionInfo.mixpanelToken;
|
|
12028
|
+
try {
|
|
12029
|
+
if (token) {
|
|
12030
|
+
mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
|
|
12031
|
+
if (!isPublicCluster) {
|
|
12032
|
+
mixpanelInstance.identify(sessionInfo.userGUID);
|
|
12033
|
+
}
|
|
12034
|
+
mixpanelInstance.register_once({
|
|
12035
|
+
clusterId: sessionInfo.clusterId,
|
|
12036
|
+
clusterName: sessionInfo.clusterName,
|
|
12037
|
+
releaseVersion: sessionInfo.releaseVersion,
|
|
12038
|
+
hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
|
|
12039
|
+
});
|
|
12040
|
+
isMixpanelInitialized = true;
|
|
12041
|
+
emptyQueue();
|
|
12042
|
+
}
|
|
12043
|
+
}
|
|
12044
|
+
catch (e) {
|
|
12045
|
+
logger.error('Error initializing mixpanel', e);
|
|
12046
|
+
}
|
|
12047
|
+
}
|
|
12048
|
+
|
|
12049
|
+
let config = {};
|
|
12050
|
+
/**
|
|
12051
|
+
* Gets the configuration embed was initialized with.
|
|
12052
|
+
*
|
|
12053
|
+
* @returns {@link EmbedConfig} The configuration embed was initialized with.
|
|
12054
|
+
* @version SDK: 1.19.0 | ThoughtSpot: *
|
|
12055
|
+
* @group Global methods
|
|
12056
|
+
*/
|
|
12057
|
+
const getEmbedConfig = () => config;
|
|
12058
|
+
|
|
12059
|
+
/**
|
|
12060
|
+
* Fetch wrapper that adds the authentication token to the request.
|
|
12061
|
+
* Use this to call the ThoughtSpot APIs when using the visual embed sdk.
|
|
12062
|
+
*
|
|
12063
|
+
* @param input
|
|
12064
|
+
* @param init
|
|
12065
|
+
* @version SDK: 1.28.0
|
|
12066
|
+
* @group Global methods
|
|
12067
|
+
*/
|
|
12068
|
+
const tokenizedFetch = async (input, init) => {
|
|
12069
|
+
const embedConfig = getEmbedConfig();
|
|
12070
|
+
if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
|
|
12071
|
+
return fetch(input, init);
|
|
12072
|
+
}
|
|
12073
|
+
const req = new Request(input, init);
|
|
12074
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
12075
|
+
if (authToken) {
|
|
12076
|
+
req.headers.append('Authorization', `Bearer ${authToken}`);
|
|
12077
|
+
}
|
|
12078
|
+
return fetch(req);
|
|
12079
|
+
};
|
|
12080
|
+
|
|
12081
|
+
/**
|
|
12082
|
+
*
|
|
12083
|
+
* @param url
|
|
12084
|
+
* @param options
|
|
12085
|
+
*/
|
|
12086
|
+
function tokenisedFailureLoggedFetch(url, options = {}) {
|
|
12087
|
+
return tokenizedFetch(url, options).then(async (r) => {
|
|
12088
|
+
var _a;
|
|
12089
|
+
if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
|
|
12090
|
+
logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
|
|
12091
|
+
}
|
|
12092
|
+
return r;
|
|
12093
|
+
});
|
|
12094
|
+
}
|
|
12095
|
+
/**
|
|
12096
|
+
*
|
|
12097
|
+
* @param authVerificationUrl
|
|
12098
|
+
*/
|
|
12099
|
+
function fetchSessionInfoService(authVerificationUrl) {
|
|
12100
|
+
return tokenisedFailureLoggedFetch(authVerificationUrl, {
|
|
12101
|
+
credentials: 'include',
|
|
12102
|
+
});
|
|
12103
|
+
}
|
|
12104
|
+
|
|
12105
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
12106
|
+
let loggedInStatus = false;
|
|
12107
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
12108
|
+
let samlAuthWindow = null;
|
|
12109
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
12110
|
+
let samlCompletionPromise = null;
|
|
12111
|
+
let sessionInfo = null;
|
|
12112
|
+
let sessionInfoResolver = null;
|
|
12113
|
+
const sessionInfoPromise = new Promise((resolve) => {
|
|
12114
|
+
sessionInfoResolver = resolve;
|
|
12115
|
+
});
|
|
12116
|
+
let releaseVersion = '';
|
|
12117
|
+
const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
|
|
12118
|
+
/**
|
|
12119
|
+
* Enum for auth failure types. This is the parameter passed to the listner
|
|
12120
|
+
* of {@link AuthStatus.FAILURE}.
|
|
12121
|
+
*
|
|
12122
|
+
* @group Authentication / Init
|
|
12123
|
+
*/
|
|
12124
|
+
var AuthFailureType;
|
|
12125
|
+
(function (AuthFailureType) {
|
|
12126
|
+
AuthFailureType["SDK"] = "SDK";
|
|
12127
|
+
AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
|
|
12128
|
+
AuthFailureType["EXPIRY"] = "EXPIRY";
|
|
12129
|
+
AuthFailureType["OTHER"] = "OTHER";
|
|
12130
|
+
})(AuthFailureType || (AuthFailureType = {}));
|
|
12131
|
+
/**
|
|
12132
|
+
* Enum for auth status emitted by the emitter returned from {@link init}.
|
|
12133
|
+
*
|
|
12134
|
+
* @group Authentication / Init
|
|
12135
|
+
*/
|
|
12136
|
+
var AuthStatus;
|
|
12137
|
+
(function (AuthStatus) {
|
|
12138
|
+
/**
|
|
12139
|
+
* Emits when the SDK fails to authenticate
|
|
12140
|
+
*/
|
|
12141
|
+
AuthStatus["FAILURE"] = "FAILURE";
|
|
12142
|
+
/**
|
|
12143
|
+
* Emits when the SDK authenticates successfully
|
|
12144
|
+
*/
|
|
12145
|
+
AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
|
|
12146
|
+
/**
|
|
12147
|
+
* Emits when the app sends an authentication success message
|
|
12148
|
+
*/
|
|
12149
|
+
AuthStatus["SUCCESS"] = "SUCCESS";
|
|
12150
|
+
/**
|
|
12151
|
+
* Emits when a user logs out
|
|
12152
|
+
*/
|
|
12153
|
+
AuthStatus["LOGOUT"] = "LOGOUT";
|
|
12154
|
+
/**
|
|
12155
|
+
* Emitted when inPopup is true in the SAMLRedirect flow and the
|
|
12156
|
+
* popup is waiting to be triggered either programmatically
|
|
12157
|
+
* or by the trigger button.
|
|
12158
|
+
*
|
|
12159
|
+
* @version SDK: 1.19.0
|
|
12160
|
+
*/
|
|
12161
|
+
AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
|
|
12162
|
+
})(AuthStatus || (AuthStatus = {}));
|
|
12163
|
+
/**
|
|
12164
|
+
* Events which can be triggered on the emitter returned from {@link init}.
|
|
12165
|
+
*
|
|
12166
|
+
* @group Authentication / Init
|
|
12167
|
+
*/
|
|
12168
|
+
var AuthEvent;
|
|
12169
|
+
(function (AuthEvent) {
|
|
12170
|
+
/**
|
|
12171
|
+
* Manually trigger the SSO popup. This is useful when
|
|
12172
|
+
* authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
|
|
12173
|
+
*/
|
|
12174
|
+
AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
|
|
12175
|
+
})(AuthEvent || (AuthEvent = {}));
|
|
12176
|
+
/**
|
|
12177
|
+
*
|
|
12178
|
+
*/
|
|
12179
|
+
function notifyAuthSDKSuccess() {
|
|
12180
|
+
{
|
|
12181
|
+
logger.error('SDK not initialized');
|
|
12182
|
+
return;
|
|
12183
|
+
}
|
|
12184
|
+
}
|
|
12185
|
+
/**
|
|
12186
|
+
*
|
|
12187
|
+
*/
|
|
12188
|
+
function notifyAuthSuccess() {
|
|
12189
|
+
{
|
|
12190
|
+
logger.error('SDK not initialized');
|
|
12191
|
+
return;
|
|
12192
|
+
}
|
|
12193
|
+
}
|
|
12194
|
+
/**
|
|
12195
|
+
*
|
|
12196
|
+
* @param failureType
|
|
12197
|
+
*/
|
|
12198
|
+
function notifyAuthFailure(failureType) {
|
|
12199
|
+
{
|
|
12200
|
+
logger.error('SDK not initialized');
|
|
12201
|
+
return;
|
|
12202
|
+
}
|
|
12203
|
+
}
|
|
12204
|
+
/**
|
|
12205
|
+
*
|
|
12206
|
+
*/
|
|
12207
|
+
function notifyLogout() {
|
|
12208
|
+
{
|
|
12209
|
+
logger.error('SDK not initialized');
|
|
12210
|
+
return;
|
|
12211
|
+
}
|
|
12212
|
+
}
|
|
12213
|
+
const initSession = (sessionDetails) => {
|
|
12214
|
+
const embedConfig = getEmbedConfig();
|
|
12215
|
+
if (sessionInfo == null) {
|
|
12216
|
+
sessionInfo = sessionDetails;
|
|
12217
|
+
if (!embedConfig.disableSDKTracking) {
|
|
12218
|
+
initMixpanel(sessionInfo);
|
|
12219
|
+
}
|
|
12220
|
+
sessionInfoResolver(sessionInfo);
|
|
12221
|
+
}
|
|
12222
|
+
};
|
|
12223
|
+
const getSessionDetails = (sessionInfoResp) => {
|
|
12224
|
+
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
12225
|
+
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
12226
|
+
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
12227
|
+
? prodMixpanelToken
|
|
12228
|
+
: devMixpanelToken;
|
|
12229
|
+
return {
|
|
12230
|
+
userGUID: sessionInfoResp.userGUID,
|
|
12231
|
+
mixpanelToken,
|
|
12232
|
+
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
12233
|
+
releaseVersion: sessionInfoResp.releaseVersion,
|
|
12234
|
+
clusterId: sessionInfoResp.configInfo.selfClusterId,
|
|
12235
|
+
clusterName: sessionInfoResp.configInfo.selfClusterName,
|
|
12236
|
+
...sessionInfoResp,
|
|
12237
|
+
};
|
|
12238
|
+
};
|
|
12239
|
+
/**
|
|
12240
|
+
* Check if we are logged into the ThoughtSpot cluster
|
|
12241
|
+
*
|
|
12242
|
+
* @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
|
|
12243
|
+
*/
|
|
12244
|
+
async function isLoggedIn(thoughtSpotHost) {
|
|
12245
|
+
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
12246
|
+
let response = null;
|
|
12247
|
+
try {
|
|
12248
|
+
response = await fetchSessionInfoService(authVerificationUrl);
|
|
12249
|
+
const sessionInfoResp = await response.json();
|
|
12250
|
+
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
12251
|
+
// Store user session details from session info
|
|
12252
|
+
initSession(sessionDetails);
|
|
12253
|
+
releaseVersion = sessionInfoResp.releaseVersion;
|
|
12254
|
+
}
|
|
12255
|
+
catch (e) {
|
|
12256
|
+
return false;
|
|
12257
|
+
}
|
|
12258
|
+
return response.status === 200;
|
|
12259
|
+
}
|
|
12260
|
+
/**
|
|
12261
|
+
* Return releaseVersion if available
|
|
12262
|
+
*/
|
|
12263
|
+
function getReleaseVersion() {
|
|
12264
|
+
return releaseVersion;
|
|
12265
|
+
}
|
|
12266
|
+
/**
|
|
12267
|
+
* Check if we are stuck at the SSO redirect URL
|
|
12268
|
+
*/
|
|
12269
|
+
function isAtSSORedirectUrl() {
|
|
12270
|
+
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
|
|
12271
|
+
}
|
|
12272
|
+
/**
|
|
12273
|
+
* Remove the SSO redirect URL marker
|
|
12274
|
+
*/
|
|
12275
|
+
function removeSSORedirectUrlMarker() {
|
|
12276
|
+
// Note (sunny): This will leave a # around even if it was not in the URL
|
|
12277
|
+
// to begin with. Trying to remove the hash by changing window.location will
|
|
12278
|
+
// reload the page which we don't want. We'll live with adding an
|
|
12279
|
+
// unnecessary hash to the parent page URL until we find any use case where
|
|
12280
|
+
// that creates an issue.
|
|
12281
|
+
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
|
|
12282
|
+
}
|
|
12283
|
+
/**
|
|
12284
|
+
* Perform token based authentication
|
|
12285
|
+
*
|
|
12286
|
+
* @param embedConfig The embed configuration
|
|
12287
|
+
*/
|
|
12288
|
+
const doTokenAuth = async (embedConfig) => {
|
|
12289
|
+
const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
|
|
12290
|
+
if (!authEndpoint && !getAuthToken) {
|
|
12291
|
+
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12292
|
+
}
|
|
12293
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12294
|
+
if (!loggedInStatus) {
|
|
12295
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
12296
|
+
let resp;
|
|
12297
|
+
try {
|
|
12298
|
+
resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
|
|
12299
|
+
}
|
|
12300
|
+
catch (e) {
|
|
12301
|
+
resp = await fetchAuthService(thoughtSpotHost, username, authToken);
|
|
12302
|
+
}
|
|
12303
|
+
// token login issues a 302 when successful
|
|
12304
|
+
loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
|
|
12305
|
+
if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
|
|
12306
|
+
// When 3rd party cookie access is blocked, this will fail because
|
|
12307
|
+
// cookies will not be sent with the call.
|
|
12308
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12309
|
+
}
|
|
12310
|
+
}
|
|
12311
|
+
return loggedInStatus;
|
|
12312
|
+
};
|
|
12313
|
+
/**
|
|
12314
|
+
* Validate embedConfig parameters required for cookielessTokenAuth
|
|
12315
|
+
*
|
|
12316
|
+
* @param embedConfig The embed configuration
|
|
12317
|
+
*/
|
|
12318
|
+
const doCookielessTokenAuth = async (embedConfig) => {
|
|
12319
|
+
const { authEndpoint, getAuthToken } = embedConfig;
|
|
12320
|
+
if (!authEndpoint && !getAuthToken) {
|
|
12321
|
+
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12322
|
+
}
|
|
12323
|
+
let authSuccess = false;
|
|
12324
|
+
try {
|
|
12325
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
12326
|
+
if (authToken) {
|
|
12327
|
+
authSuccess = true;
|
|
12328
|
+
}
|
|
12329
|
+
}
|
|
12330
|
+
catch {
|
|
12331
|
+
authSuccess = false;
|
|
12332
|
+
}
|
|
12333
|
+
return authSuccess;
|
|
12334
|
+
};
|
|
12335
|
+
/**
|
|
12336
|
+
* Perform basic authentication to the ThoughtSpot cluster using the cluster
|
|
12337
|
+
* credentials.
|
|
12338
|
+
*
|
|
12339
|
+
* Warning: This feature is primarily intended for developer testing. It is
|
|
12340
|
+
* strongly advised not to use this authentication method in production.
|
|
12341
|
+
*
|
|
12342
|
+
* @param embedConfig The embed configuration
|
|
12343
|
+
*/
|
|
12344
|
+
const doBasicAuth = async (embedConfig) => {
|
|
12345
|
+
const { thoughtSpotHost, username, password } = embedConfig;
|
|
12346
|
+
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
12347
|
+
if (!loggedIn) {
|
|
12348
|
+
const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
|
|
12349
|
+
loggedInStatus = response.ok;
|
|
12350
|
+
if (embedConfig.detectCookieAccessSlow) {
|
|
12351
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12352
|
+
}
|
|
12353
|
+
}
|
|
12354
|
+
else {
|
|
12355
|
+
loggedInStatus = true;
|
|
12356
|
+
}
|
|
12357
|
+
return loggedInStatus;
|
|
12358
|
+
};
|
|
12359
|
+
/**
|
|
12360
|
+
*
|
|
12361
|
+
* @param ssoURL
|
|
12362
|
+
* @param triggerContainer
|
|
12363
|
+
* @param triggerText
|
|
12364
|
+
*/
|
|
12365
|
+
async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
|
|
12366
|
+
const openPopup = () => {
|
|
12367
|
+
if (samlAuthWindow === null || samlAuthWindow.closed) {
|
|
12368
|
+
samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
|
|
12369
|
+
}
|
|
12370
|
+
else {
|
|
12371
|
+
samlAuthWindow.focus();
|
|
12372
|
+
}
|
|
12373
|
+
};
|
|
12374
|
+
const containerEl = getDOMNode(triggerContainer);
|
|
12375
|
+
if (containerEl) {
|
|
12376
|
+
containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
|
|
12377
|
+
const authElem = document.getElementById('ts-auth-btn');
|
|
12378
|
+
authElem.textContent = triggerText;
|
|
12379
|
+
authElem.addEventListener('click', openPopup, { once: true });
|
|
12380
|
+
}
|
|
12381
|
+
samlCompletionPromise = samlCompletionPromise
|
|
12382
|
+
|| new Promise((resolve, reject) => {
|
|
12383
|
+
window.addEventListener('message', (e) => {
|
|
12384
|
+
if (e.data.type === exports.EmbedEvent.SAMLComplete) {
|
|
12385
|
+
e.source.close();
|
|
12386
|
+
resolve();
|
|
12387
|
+
}
|
|
12388
|
+
});
|
|
12389
|
+
});
|
|
12390
|
+
return samlCompletionPromise;
|
|
12391
|
+
}
|
|
12392
|
+
/**
|
|
12393
|
+
* Perform SAML authentication
|
|
12394
|
+
*
|
|
12395
|
+
* @param embedConfig The embed configuration
|
|
12396
|
+
* @param ssoEndPoint
|
|
12397
|
+
*/
|
|
12398
|
+
const doSSOAuth = async (embedConfig, ssoEndPoint) => {
|
|
12399
|
+
const { thoughtSpotHost } = embedConfig;
|
|
12400
|
+
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
12401
|
+
if (loggedIn) {
|
|
12402
|
+
if (isAtSSORedirectUrl()) {
|
|
12403
|
+
removeSSORedirectUrlMarker();
|
|
12404
|
+
}
|
|
12405
|
+
loggedInStatus = true;
|
|
12406
|
+
return;
|
|
12407
|
+
}
|
|
12408
|
+
// we have already tried authentication and it did not succeed, restore
|
|
12409
|
+
// the current URL to the original one and invoke the callback.
|
|
12410
|
+
if (isAtSSORedirectUrl()) {
|
|
12411
|
+
removeSSORedirectUrlMarker();
|
|
12412
|
+
loggedInStatus = false;
|
|
12413
|
+
return;
|
|
12414
|
+
}
|
|
12415
|
+
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
12416
|
+
if (embedConfig.inPopup) {
|
|
12417
|
+
await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
|
|
12418
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12419
|
+
return;
|
|
12420
|
+
}
|
|
12421
|
+
window.location.href = ssoURL;
|
|
12422
|
+
};
|
|
12423
|
+
const doSamlAuth = async (embedConfig) => {
|
|
12424
|
+
const { thoughtSpotHost } = embedConfig;
|
|
12425
|
+
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
12426
|
+
// loaded again and the same JS will execute again.
|
|
12427
|
+
const ssoRedirectUrl = embedConfig.inPopup
|
|
12428
|
+
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
12429
|
+
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
12430
|
+
// bring back the page to the same URL
|
|
12431
|
+
const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
12432
|
+
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
12433
|
+
return loggedInStatus;
|
|
12434
|
+
};
|
|
12435
|
+
const doOIDCAuth = async (embedConfig) => {
|
|
12436
|
+
const { thoughtSpotHost } = embedConfig;
|
|
12437
|
+
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
12438
|
+
// loaded again and the same JS will execute again.
|
|
12439
|
+
const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
|
|
12440
|
+
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
12441
|
+
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
12442
|
+
// bring back the page to the same URL
|
|
12443
|
+
const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
12444
|
+
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
12445
|
+
return loggedInStatus;
|
|
12446
|
+
};
|
|
12447
|
+
/**
|
|
12448
|
+
* Perform authentication on the ThoughtSpot cluster
|
|
12449
|
+
*
|
|
12450
|
+
* @param embedConfig The embed configuration
|
|
12451
|
+
*/
|
|
12452
|
+
const authenticate = async (embedConfig) => {
|
|
12453
|
+
const { authType } = embedConfig;
|
|
12454
|
+
switch (authType) {
|
|
12455
|
+
case AuthType.SSO:
|
|
12456
|
+
case AuthType.SAMLRedirect:
|
|
12457
|
+
case AuthType.SAML:
|
|
12458
|
+
return doSamlAuth(embedConfig);
|
|
12459
|
+
case AuthType.OIDC:
|
|
12460
|
+
case AuthType.OIDCRedirect:
|
|
12461
|
+
return doOIDCAuth(embedConfig);
|
|
12462
|
+
case AuthType.AuthServer:
|
|
12463
|
+
case AuthType.TrustedAuthToken:
|
|
12464
|
+
return doTokenAuth(embedConfig);
|
|
12465
|
+
case AuthType.TrustedAuthTokenCookieless:
|
|
12466
|
+
return doCookielessTokenAuth(embedConfig);
|
|
12467
|
+
case AuthType.Basic:
|
|
12468
|
+
return doBasicAuth(embedConfig);
|
|
12469
|
+
default:
|
|
12470
|
+
return Promise.resolve(true);
|
|
12471
|
+
}
|
|
12887
12472
|
};
|
|
12888
12473
|
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
*/
|
|
12896
|
-
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
|
12897
|
-
var evt;
|
|
12898
|
-
|
|
12899
|
-
if (event) {
|
|
12900
|
-
evt = prefix ? prefix + event : event;
|
|
12901
|
-
if (this._events[evt]) clearEvent(this, evt);
|
|
12902
|
-
} else {
|
|
12903
|
-
this._events = new Events();
|
|
12904
|
-
this._eventsCount = 0;
|
|
12905
|
-
}
|
|
12906
|
-
|
|
12907
|
-
return this;
|
|
12474
|
+
const ERROR_MESSAGE = {
|
|
12475
|
+
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
12476
|
+
LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
|
|
12477
|
+
TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
|
|
12478
|
+
SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
|
|
12479
|
+
SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
|
|
12908
12480
|
};
|
|
12909
12481
|
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
|
|
12921
|
-
|
|
12922
|
-
|
|
12923
|
-
|
|
12924
|
-
|
|
12925
|
-
|
|
12926
|
-
|
|
12927
|
-
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12482
|
+
/**
|
|
12483
|
+
* Copyright (c) 2023
|
|
12484
|
+
*
|
|
12485
|
+
* Utilities related to reading configuration objects
|
|
12486
|
+
*
|
|
12487
|
+
* @summary Config-related utils
|
|
12488
|
+
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
12489
|
+
*/
|
|
12490
|
+
const urlRegex = new RegExp([
|
|
12491
|
+
'(^(https?:)//)?',
|
|
12492
|
+
'(([^:/?#]*)(?::([0-9]+))?)',
|
|
12493
|
+
'(/{0,1}[^?#]*)',
|
|
12494
|
+
'(\\?[^#]*|)',
|
|
12495
|
+
'(#.*|)$', // hash
|
|
12496
|
+
].join(''));
|
|
12497
|
+
/**
|
|
12498
|
+
* Parse and construct the ThoughtSpot hostname or IP address
|
|
12499
|
+
* from the embed configuration object.
|
|
12500
|
+
*
|
|
12501
|
+
* @param config
|
|
12502
|
+
*/
|
|
12503
|
+
const getThoughtSpotHost = (config) => {
|
|
12504
|
+
if (!config.thoughtSpotHost) {
|
|
12505
|
+
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
12506
|
+
}
|
|
12507
|
+
const urlParts = config.thoughtSpotHost.match(urlRegex);
|
|
12508
|
+
if (!urlParts) {
|
|
12509
|
+
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
12510
|
+
}
|
|
12511
|
+
const protocol = urlParts[2] || window.location.protocol;
|
|
12512
|
+
const host = urlParts[3];
|
|
12513
|
+
let path = urlParts[6];
|
|
12514
|
+
// Lose the trailing / if any
|
|
12515
|
+
if (path.charAt(path.length - 1) === '/') {
|
|
12516
|
+
path = path.substring(0, path.length - 1);
|
|
12517
|
+
}
|
|
12518
|
+
// const urlParams = urlParts[7];
|
|
12519
|
+
// const hash = urlParts[8];
|
|
12520
|
+
return `${protocol}//${host}${path}`;
|
|
12521
|
+
};
|
|
12522
|
+
const getV2BasePath = (config) => {
|
|
12523
|
+
if (config.basepath) {
|
|
12524
|
+
return config.basepath;
|
|
12525
|
+
}
|
|
12526
|
+
const tsHost = getThoughtSpotHost(config);
|
|
12527
|
+
// This is to handle when e2e's. Search is run on pods for
|
|
12528
|
+
// comp-blink-test-pipeline with baseUrl=https://localhost:8443.
|
|
12529
|
+
// This is to handle when the developer is developing in their local
|
|
12530
|
+
// environment.
|
|
12531
|
+
if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
|
|
12532
|
+
return '';
|
|
12533
|
+
}
|
|
12534
|
+
return 'v2';
|
|
12535
|
+
};
|
|
12536
|
+
/**
|
|
12537
|
+
* It is a good idea to keep URLs under 2000 chars.
|
|
12538
|
+
* If this is ever breached, since we pass view configuration through
|
|
12539
|
+
* URL params, we would like to log a warning.
|
|
12540
|
+
* Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
|
12541
|
+
*/
|
|
12542
|
+
const URL_MAX_LENGTH = 2000;
|
|
12543
|
+
/**
|
|
12544
|
+
* The default CSS dimensions of the embedded app
|
|
12545
|
+
*/
|
|
12546
|
+
const DEFAULT_EMBED_WIDTH = '100%';
|
|
12547
|
+
const DEFAULT_EMBED_HEIGHT = '100%';
|
|
12947
12548
|
|
|
12948
12549
|
/**
|
|
12949
12550
|
*
|
|
12950
|
-
* @param
|
|
12951
|
-
* @param
|
|
12551
|
+
* @param root0
|
|
12552
|
+
* @param root0.query
|
|
12553
|
+
* @param root0.variables
|
|
12554
|
+
* @param root0.thoughtSpotHost
|
|
12555
|
+
* @param root0.isCompositeQuery
|
|
12952
12556
|
*/
|
|
12953
|
-
function
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12557
|
+
async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
|
|
12558
|
+
const operationName = getOperationNameFromQuery(query);
|
|
12559
|
+
try {
|
|
12560
|
+
const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
|
|
12561
|
+
method: 'POST',
|
|
12562
|
+
headers: {
|
|
12563
|
+
'content-type': 'application/json;charset=UTF-8',
|
|
12564
|
+
'x-requested-by': 'ThoughtSpot',
|
|
12565
|
+
accept: '*/*',
|
|
12566
|
+
'accept-language': 'en-us',
|
|
12567
|
+
},
|
|
12568
|
+
body: JSON.stringify({
|
|
12569
|
+
operationName,
|
|
12570
|
+
query,
|
|
12571
|
+
variables,
|
|
12572
|
+
}),
|
|
12573
|
+
credentials: 'include',
|
|
12574
|
+
});
|
|
12575
|
+
const result = await response.json();
|
|
12576
|
+
const dataValues = Object.values(result.data);
|
|
12577
|
+
return (isCompositeQuery) ? result.data : dataValues[0];
|
|
12578
|
+
}
|
|
12579
|
+
catch (error) {
|
|
12580
|
+
return error;
|
|
12581
|
+
}
|
|
12582
|
+
}
|
|
12583
|
+
|
|
12584
|
+
const getSourceDetailQuery = `
|
|
12585
|
+
query GetSourceDetail($ids: [GUID!]!) {
|
|
12586
|
+
getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
|
|
12587
|
+
id
|
|
12588
|
+
name
|
|
12589
|
+
description
|
|
12590
|
+
authorName
|
|
12591
|
+
authorDisplayName
|
|
12592
|
+
isExternal
|
|
12593
|
+
type
|
|
12594
|
+
created
|
|
12595
|
+
modified
|
|
12596
|
+
columns {
|
|
12597
|
+
id
|
|
12598
|
+
name
|
|
12599
|
+
author
|
|
12600
|
+
authorDisplayName
|
|
12601
|
+
description
|
|
12602
|
+
dataType
|
|
12603
|
+
type
|
|
12604
|
+
modified
|
|
12605
|
+
ownerName
|
|
12606
|
+
owner
|
|
12607
|
+
dataRecency
|
|
12608
|
+
sources {
|
|
12609
|
+
tableId
|
|
12610
|
+
tableName
|
|
12611
|
+
columnId
|
|
12612
|
+
columnName
|
|
12613
|
+
__typename
|
|
12614
|
+
}
|
|
12615
|
+
synonyms
|
|
12616
|
+
cohortAnswerId
|
|
12617
|
+
__typename
|
|
12618
|
+
}
|
|
12619
|
+
relationships
|
|
12620
|
+
destinationRelationships
|
|
12621
|
+
dataSourceId
|
|
12622
|
+
__typename
|
|
12623
|
+
}
|
|
12624
|
+
}
|
|
12625
|
+
`;
|
|
12626
|
+
const sourceDetailCache = new Map();
|
|
12962
12627
|
/**
|
|
12963
12628
|
*
|
|
12964
|
-
* @param
|
|
12629
|
+
* @param thoughtSpotHost
|
|
12630
|
+
* @param sourceId
|
|
12965
12631
|
*/
|
|
12966
|
-
function
|
|
12967
|
-
|
|
12968
|
-
|
|
12632
|
+
async function getSourceDetail(thoughtSpotHost, sourceId) {
|
|
12633
|
+
if (sourceDetailCache.get(sourceId)) {
|
|
12634
|
+
return sourceDetailCache.get(sourceId);
|
|
12635
|
+
}
|
|
12636
|
+
const details = await graphqlQuery({
|
|
12637
|
+
query: getSourceDetailQuery,
|
|
12638
|
+
variables: {
|
|
12639
|
+
ids: [sourceId],
|
|
12640
|
+
},
|
|
12641
|
+
thoughtSpotHost,
|
|
12969
12642
|
});
|
|
12643
|
+
const souceDetails = details[0];
|
|
12644
|
+
if (souceDetails) {
|
|
12645
|
+
sourceDetailCache.set(sourceId, souceDetails);
|
|
12646
|
+
}
|
|
12647
|
+
return souceDetails;
|
|
12970
12648
|
}
|
|
12971
12649
|
|
|
12972
|
-
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
12650
|
+
const bachSessionId = `
|
|
12651
|
+
id {
|
|
12652
|
+
sessionId
|
|
12653
|
+
genNo
|
|
12654
|
+
acSession {
|
|
12655
|
+
sessionId
|
|
12656
|
+
genNo
|
|
12657
|
+
}
|
|
12658
|
+
}
|
|
12659
|
+
`;
|
|
12660
|
+
const getUnaggregatedAnswerSession = `
|
|
12661
|
+
mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
|
|
12662
|
+
Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
|
|
12663
|
+
${bachSessionId}
|
|
12664
|
+
answer {
|
|
12665
|
+
visualizations {
|
|
12666
|
+
... on TableViz {
|
|
12667
|
+
columns {
|
|
12668
|
+
column {
|
|
12669
|
+
id
|
|
12670
|
+
name
|
|
12671
|
+
referencedColumns {
|
|
12672
|
+
guid
|
|
12673
|
+
displayName
|
|
12674
|
+
}
|
|
12675
|
+
}
|
|
12676
|
+
}
|
|
12677
|
+
}
|
|
12678
|
+
}
|
|
12679
|
+
}
|
|
12680
|
+
}
|
|
12681
|
+
}
|
|
12682
|
+
`;
|
|
12683
|
+
const removeColumns = `
|
|
12684
|
+
mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
|
|
12685
|
+
Answer__removeColumns(
|
|
12686
|
+
session: $session
|
|
12687
|
+
logicalColumnIds: $logicalColumnIds
|
|
12688
|
+
columnIds: $columnIds
|
|
12689
|
+
) {
|
|
12690
|
+
${bachSessionId}
|
|
12691
|
+
}
|
|
12692
|
+
}
|
|
12693
|
+
`;
|
|
12694
|
+
const addColumns = `
|
|
12695
|
+
mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
|
|
12696
|
+
Answer__addColumn(session: $session, columns: $columns) {
|
|
12697
|
+
${bachSessionId}
|
|
12698
|
+
}
|
|
12699
|
+
}
|
|
12700
|
+
`;
|
|
12701
|
+
const getAnswerData = `
|
|
12702
|
+
query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
|
|
12703
|
+
getAnswer(session: $session) {
|
|
12704
|
+
${bachSessionId}
|
|
12705
|
+
answer {
|
|
12706
|
+
id
|
|
12707
|
+
visualizations {
|
|
12708
|
+
id
|
|
12709
|
+
... on TableViz {
|
|
12710
|
+
columns {
|
|
12711
|
+
column {
|
|
12712
|
+
id
|
|
12713
|
+
name
|
|
12714
|
+
type
|
|
12715
|
+
aggregationType
|
|
12716
|
+
dataType
|
|
12717
|
+
}
|
|
12718
|
+
}
|
|
12719
|
+
data(deadline: $deadline, pagination: $dataPaginationParams)
|
|
12720
|
+
}
|
|
12721
|
+
}
|
|
12722
|
+
}
|
|
12723
|
+
}
|
|
12724
|
+
}
|
|
12725
|
+
`;
|
|
12726
|
+
|
|
12727
|
+
// eslint-disable-next-line no-shadow
|
|
12728
|
+
var OperationType;
|
|
12729
|
+
(function (OperationType) {
|
|
12730
|
+
OperationType["GetChartWithData"] = "GetChartWithData";
|
|
12731
|
+
OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
|
|
12732
|
+
})(OperationType || (OperationType = {}));
|
|
12998
12733
|
/**
|
|
12999
|
-
*
|
|
12734
|
+
* Class representing the answer service provided with the
|
|
12735
|
+
* custom action payload. This service could be used to run
|
|
12736
|
+
* graphql queries in the context of the answer on which the
|
|
12737
|
+
* custom action was triggered.
|
|
13000
12738
|
*
|
|
13001
|
-
* @
|
|
12739
|
+
* @example
|
|
12740
|
+
* ```js
|
|
12741
|
+
* embed.on(EmbedEvent.CustomAction, e => {
|
|
12742
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
12743
|
+
* 'col name 1'
|
|
12744
|
+
* ]);
|
|
12745
|
+
* const data = await underlying.fetchData(0, 100);
|
|
12746
|
+
* })
|
|
12747
|
+
* ```
|
|
12748
|
+
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
12749
|
+
* @group Events
|
|
13002
12750
|
*/
|
|
13003
|
-
|
|
13004
|
-
(function (AuthStatus) {
|
|
13005
|
-
/**
|
|
13006
|
-
* Emits when the SDK fails to authenticate
|
|
13007
|
-
*/
|
|
13008
|
-
AuthStatus["FAILURE"] = "FAILURE";
|
|
13009
|
-
/**
|
|
13010
|
-
* Emits when the SDK authenticates successfully
|
|
13011
|
-
*/
|
|
13012
|
-
AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
|
|
12751
|
+
class AnswerService {
|
|
13013
12752
|
/**
|
|
13014
|
-
*
|
|
12753
|
+
* Should not need to be called directly.
|
|
12754
|
+
*
|
|
12755
|
+
* @param session
|
|
12756
|
+
* @param answer
|
|
12757
|
+
* @param thoughtSpotHost
|
|
12758
|
+
* @param selectedPoints
|
|
13015
12759
|
*/
|
|
13016
|
-
|
|
12760
|
+
constructor(session, answer, thoughtSpotHost, selectedPoints) {
|
|
12761
|
+
this.session = session;
|
|
12762
|
+
this.answer = answer;
|
|
12763
|
+
this.thoughtSpotHost = thoughtSpotHost;
|
|
12764
|
+
this.selectedPoints = selectedPoints;
|
|
12765
|
+
this.session = removeTypename(session);
|
|
12766
|
+
}
|
|
13017
12767
|
/**
|
|
13018
|
-
*
|
|
12768
|
+
* Get the details about the source used in the answer.
|
|
12769
|
+
* This can be used to get the list of all columns in the data source for example.
|
|
13019
12770
|
*/
|
|
13020
|
-
|
|
12771
|
+
async getSourceDetail() {
|
|
12772
|
+
const sourceId = this.answer.sources[0].header.guid;
|
|
12773
|
+
return getSourceDetail(this.thoughtSpotHost, sourceId);
|
|
12774
|
+
}
|
|
13021
12775
|
/**
|
|
13022
|
-
*
|
|
13023
|
-
* popup is waiting to be triggered either programmatically
|
|
13024
|
-
* or by the trigger button.
|
|
12776
|
+
* Remove columnIds and return updated answer session.
|
|
13025
12777
|
*
|
|
13026
|
-
* @
|
|
13027
|
-
|
|
13028
|
-
AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
|
|
13029
|
-
})(AuthStatus || (AuthStatus = {}));
|
|
13030
|
-
/**
|
|
13031
|
-
* Events which can be triggered on the emitter returned from {@link init}.
|
|
13032
|
-
*
|
|
13033
|
-
* @group Authentication / Init
|
|
13034
|
-
*/
|
|
13035
|
-
var AuthEvent;
|
|
13036
|
-
(function (AuthEvent) {
|
|
13037
|
-
/**
|
|
13038
|
-
* Manually trigger the SSO popup. This is useful when
|
|
13039
|
-
* authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
|
|
12778
|
+
* @param columnIds
|
|
12779
|
+
* @returns
|
|
13040
12780
|
*/
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
*/
|
|
13046
|
-
function notifyAuthSDKSuccess() {
|
|
13047
|
-
{
|
|
13048
|
-
logger.error('SDK not initialized');
|
|
13049
|
-
return;
|
|
13050
|
-
}
|
|
13051
|
-
}
|
|
13052
|
-
/**
|
|
13053
|
-
*
|
|
13054
|
-
*/
|
|
13055
|
-
function notifyAuthSuccess() {
|
|
13056
|
-
{
|
|
13057
|
-
logger.error('SDK not initialized');
|
|
13058
|
-
return;
|
|
13059
|
-
}
|
|
13060
|
-
}
|
|
13061
|
-
/**
|
|
13062
|
-
*
|
|
13063
|
-
* @param failureType
|
|
13064
|
-
*/
|
|
13065
|
-
function notifyAuthFailure(failureType) {
|
|
13066
|
-
{
|
|
13067
|
-
logger.error('SDK not initialized');
|
|
13068
|
-
return;
|
|
13069
|
-
}
|
|
13070
|
-
}
|
|
13071
|
-
/**
|
|
13072
|
-
*
|
|
13073
|
-
*/
|
|
13074
|
-
function notifyLogout() {
|
|
13075
|
-
{
|
|
13076
|
-
logger.error('SDK not initialized');
|
|
13077
|
-
return;
|
|
12781
|
+
async removeColumns(columnIds) {
|
|
12782
|
+
return this.executeQuery(removeColumns, {
|
|
12783
|
+
logicalColumnIds: columnIds,
|
|
12784
|
+
});
|
|
13078
12785
|
}
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
12786
|
+
/**
|
|
12787
|
+
* Add columnIds and return updated answer session.
|
|
12788
|
+
*
|
|
12789
|
+
* @param columnIds
|
|
12790
|
+
* @returns
|
|
12791
|
+
*/
|
|
12792
|
+
async addColumns(columnIds) {
|
|
12793
|
+
return this.executeQuery(addColumns, {
|
|
12794
|
+
columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
|
|
12795
|
+
});
|
|
13088
12796
|
}
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
*/
|
|
13111
|
-
async function isLoggedIn(thoughtSpotHost) {
|
|
13112
|
-
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
13113
|
-
let response = null;
|
|
13114
|
-
try {
|
|
13115
|
-
response = await fetchSessionInfoService(authVerificationUrl);
|
|
13116
|
-
const sessionInfoResp = await response.json();
|
|
13117
|
-
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
13118
|
-
// Store user session details from session info
|
|
13119
|
-
initSession(sessionDetails);
|
|
13120
|
-
releaseVersion = sessionInfoResp.releaseVersion;
|
|
12797
|
+
/**
|
|
12798
|
+
* Fetch data from the answer.
|
|
12799
|
+
*
|
|
12800
|
+
* @param offset
|
|
12801
|
+
* @param size
|
|
12802
|
+
* @returns
|
|
12803
|
+
*/
|
|
12804
|
+
async fetchData(offset = 0, size = 1000) {
|
|
12805
|
+
const { answer } = await this.executeQuery(getAnswerData, {
|
|
12806
|
+
deadline: 0,
|
|
12807
|
+
dataPaginationParams: {
|
|
12808
|
+
isClientPaginated: true,
|
|
12809
|
+
offset,
|
|
12810
|
+
size,
|
|
12811
|
+
},
|
|
12812
|
+
});
|
|
12813
|
+
const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
|
|
12814
|
+
return {
|
|
12815
|
+
columns,
|
|
12816
|
+
data,
|
|
12817
|
+
};
|
|
13121
12818
|
}
|
|
13122
|
-
|
|
13123
|
-
|
|
12819
|
+
/**
|
|
12820
|
+
* Fetch the data for the answer as a CSV blob. This might be
|
|
12821
|
+
* quicker for larger data.
|
|
12822
|
+
*
|
|
12823
|
+
* @param userLocale
|
|
12824
|
+
* @param includeInfo Include the CSV header in the output
|
|
12825
|
+
* @returns Response
|
|
12826
|
+
*/
|
|
12827
|
+
async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
|
|
12828
|
+
const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
|
|
12829
|
+
return tokenizedFetch(fetchUrl, {
|
|
12830
|
+
credentials: 'include',
|
|
12831
|
+
});
|
|
13124
12832
|
}
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
*/
|
|
13136
|
-
function isAtSSORedirectUrl() {
|
|
13137
|
-
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
|
|
13138
|
-
}
|
|
13139
|
-
/**
|
|
13140
|
-
* Remove the SSO redirect URL marker
|
|
13141
|
-
*/
|
|
13142
|
-
function removeSSORedirectUrlMarker() {
|
|
13143
|
-
// Note (sunny): This will leave a # around even if it was not in the URL
|
|
13144
|
-
// to begin with. Trying to remove the hash by changing window.location will
|
|
13145
|
-
// reload the page which we don't want. We'll live with adding an
|
|
13146
|
-
// unnecessary hash to the parent page URL until we find any use case where
|
|
13147
|
-
// that creates an issue.
|
|
13148
|
-
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
|
|
13149
|
-
}
|
|
13150
|
-
/**
|
|
13151
|
-
* Perform token based authentication
|
|
13152
|
-
*
|
|
13153
|
-
* @param embedConfig The embed configuration
|
|
13154
|
-
*/
|
|
13155
|
-
const doTokenAuth = async (embedConfig) => {
|
|
13156
|
-
const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
|
|
13157
|
-
if (!authEndpoint && !getAuthToken) {
|
|
13158
|
-
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12833
|
+
/**
|
|
12834
|
+
* Just get the internal URL for this answer's data
|
|
12835
|
+
* as a CSV blob.
|
|
12836
|
+
*
|
|
12837
|
+
* @param userLocale
|
|
12838
|
+
* @param includeInfo
|
|
12839
|
+
* @returns
|
|
12840
|
+
*/
|
|
12841
|
+
getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
|
|
12842
|
+
return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
|
|
13159
12843
|
}
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
12844
|
+
/**
|
|
12845
|
+
* Get underlying data given a point and the output column names.
|
|
12846
|
+
* In case of a context menu action, the selectedPoints are
|
|
12847
|
+
* automatically passed.
|
|
12848
|
+
*
|
|
12849
|
+
* @param outputColumnNames
|
|
12850
|
+
* @param selectedPoints
|
|
12851
|
+
* @example
|
|
12852
|
+
* ```js
|
|
12853
|
+
* embed.on(EmbedEvent.CustomAction, e => {
|
|
12854
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
12855
|
+
* 'col name 1' // The column should exist in the data source.
|
|
12856
|
+
* ]);
|
|
12857
|
+
* const data = await underlying.fetchData(0, 100);
|
|
12858
|
+
* })
|
|
12859
|
+
* ```
|
|
12860
|
+
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
12861
|
+
*/
|
|
12862
|
+
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
12863
|
+
if (!selectedPoints && !this.selectedPoints) {
|
|
12864
|
+
throw new Error('Needs to be triggered in context of a point');
|
|
13166
12865
|
}
|
|
13167
|
-
|
|
13168
|
-
|
|
12866
|
+
if (!selectedPoints) {
|
|
12867
|
+
selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
|
|
13169
12868
|
}
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
|
|
13173
|
-
|
|
13174
|
-
|
|
13175
|
-
|
|
12869
|
+
const sourceDetail = await this.getSourceDetail();
|
|
12870
|
+
const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
|
|
12871
|
+
const unAggAnswer = await graphqlQuery({
|
|
12872
|
+
query: getUnaggregatedAnswerSession,
|
|
12873
|
+
variables: {
|
|
12874
|
+
session: this.session,
|
|
12875
|
+
columns: selectedPoints,
|
|
12876
|
+
},
|
|
12877
|
+
thoughtSpotHost: this.thoughtSpotHost,
|
|
12878
|
+
});
|
|
12879
|
+
const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
|
|
12880
|
+
const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
|
|
12881
|
+
.map((c) => c.column.referencedColumns[0].guid));
|
|
12882
|
+
const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
|
|
12883
|
+
if (columnsToAdd.length) {
|
|
12884
|
+
await unaggAnswerSession.addColumns(columnsToAdd);
|
|
13176
12885
|
}
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
/**
|
|
13181
|
-
* Validate embedConfig parameters required for cookielessTokenAuth
|
|
13182
|
-
*
|
|
13183
|
-
* @param embedConfig The embed configuration
|
|
13184
|
-
*/
|
|
13185
|
-
const doCookielessTokenAuth = async (embedConfig) => {
|
|
13186
|
-
const { authEndpoint, getAuthToken } = embedConfig;
|
|
13187
|
-
if (!authEndpoint && !getAuthToken) {
|
|
13188
|
-
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
13189
|
-
}
|
|
13190
|
-
let authSuccess = false;
|
|
13191
|
-
try {
|
|
13192
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
13193
|
-
if (authToken) {
|
|
13194
|
-
authSuccess = true;
|
|
12886
|
+
const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
|
|
12887
|
+
if (columnsToRemove.length) {
|
|
12888
|
+
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
13195
12889
|
}
|
|
12890
|
+
return unaggAnswerSession;
|
|
13196
12891
|
}
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
|
|
13216
|
-
loggedInStatus = response.ok;
|
|
13217
|
-
if (embedConfig.detectCookieAccessSlow) {
|
|
13218
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13219
|
-
}
|
|
12892
|
+
/**
|
|
12893
|
+
* Execute a custom graphql query in the context of the answer.
|
|
12894
|
+
*
|
|
12895
|
+
* @param query graphql query
|
|
12896
|
+
* @param variables graphql variables
|
|
12897
|
+
* @returns
|
|
12898
|
+
*/
|
|
12899
|
+
async executeQuery(query, variables) {
|
|
12900
|
+
const data = await graphqlQuery({
|
|
12901
|
+
query,
|
|
12902
|
+
variables: {
|
|
12903
|
+
session: this.session,
|
|
12904
|
+
...variables,
|
|
12905
|
+
},
|
|
12906
|
+
thoughtSpotHost: this.thoughtSpotHost,
|
|
12907
|
+
isCompositeQuery: false,
|
|
12908
|
+
});
|
|
12909
|
+
this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
|
|
12910
|
+
return data;
|
|
13220
12911
|
}
|
|
13221
|
-
|
|
13222
|
-
|
|
12912
|
+
/**
|
|
12913
|
+
* Get the internal session details for the answer.
|
|
12914
|
+
*
|
|
12915
|
+
* @returns
|
|
12916
|
+
*/
|
|
12917
|
+
getSession() {
|
|
12918
|
+
return this.session;
|
|
13223
12919
|
}
|
|
13224
|
-
|
|
13225
|
-
};
|
|
12920
|
+
}
|
|
13226
12921
|
/**
|
|
13227
12922
|
*
|
|
13228
|
-
* @param
|
|
13229
|
-
* @param
|
|
13230
|
-
* @param triggerText
|
|
12923
|
+
* @param sourceDetail
|
|
12924
|
+
* @param colNames
|
|
13231
12925
|
*/
|
|
13232
|
-
|
|
13233
|
-
const
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
};
|
|
13241
|
-
const containerEl = getDOMNode(triggerContainer);
|
|
13242
|
-
if (containerEl) {
|
|
13243
|
-
containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
|
|
13244
|
-
const authElem = document.getElementById('ts-auth-btn');
|
|
13245
|
-
authElem.textContent = triggerText;
|
|
13246
|
-
authElem.addEventListener('click', openPopup, { once: true });
|
|
13247
|
-
}
|
|
13248
|
-
samlCompletionPromise = samlCompletionPromise
|
|
13249
|
-
|| new Promise((resolve, reject) => {
|
|
13250
|
-
window.addEventListener('message', (e) => {
|
|
13251
|
-
if (e.data.type === exports.EmbedEvent.SAMLComplete) {
|
|
13252
|
-
e.source.close();
|
|
13253
|
-
resolve();
|
|
13254
|
-
}
|
|
13255
|
-
});
|
|
13256
|
-
});
|
|
13257
|
-
return samlCompletionPromise;
|
|
12926
|
+
function getGuidsFromColumnNames(sourceDetail, colNames) {
|
|
12927
|
+
const cols = sourceDetail.columns.reduce((colSet, col) => {
|
|
12928
|
+
colSet[col.name] = col;
|
|
12929
|
+
return colSet;
|
|
12930
|
+
}, {});
|
|
12931
|
+
return new Set(colNames.map((colName) => {
|
|
12932
|
+
const col = cols[colName];
|
|
12933
|
+
return col.id;
|
|
12934
|
+
}));
|
|
13258
12935
|
}
|
|
13259
12936
|
/**
|
|
13260
|
-
* Perform SAML authentication
|
|
13261
12937
|
*
|
|
13262
|
-
* @param
|
|
13263
|
-
* @param ssoEndPoint
|
|
12938
|
+
* @param selectedPoints
|
|
13264
12939
|
*/
|
|
13265
|
-
|
|
13266
|
-
const
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
12940
|
+
function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
|
|
12941
|
+
const underlyingDataPoint = [];
|
|
12942
|
+
/**
|
|
12943
|
+
*
|
|
12944
|
+
* @param colVal
|
|
12945
|
+
*/
|
|
12946
|
+
function addPointFromColVal(colVal) {
|
|
12947
|
+
var _a;
|
|
12948
|
+
const dataType = colVal.column.dataType;
|
|
12949
|
+
const id = colVal.column.id;
|
|
12950
|
+
let dataValue;
|
|
12951
|
+
if (dataType === 'DATE') {
|
|
12952
|
+
if (Number.isFinite(colVal.value)) {
|
|
12953
|
+
dataValue = [{
|
|
12954
|
+
epochRange: {
|
|
12955
|
+
startEpoch: colVal.value,
|
|
12956
|
+
},
|
|
12957
|
+
}];
|
|
12958
|
+
// Case for custom calendar.
|
|
12959
|
+
}
|
|
12960
|
+
else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
|
|
12961
|
+
dataValue = [{
|
|
12962
|
+
epochRange: {
|
|
12963
|
+
startEpoch: colVal.value.v.s,
|
|
12964
|
+
endEpoch: colVal.value.v.e,
|
|
12965
|
+
},
|
|
12966
|
+
}];
|
|
12967
|
+
}
|
|
13271
12968
|
}
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
loggedInStatus = false;
|
|
13280
|
-
return;
|
|
13281
|
-
}
|
|
13282
|
-
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
13283
|
-
if (embedConfig.inPopup) {
|
|
13284
|
-
await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
|
|
13285
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13286
|
-
return;
|
|
13287
|
-
}
|
|
13288
|
-
window.location.href = ssoURL;
|
|
13289
|
-
};
|
|
13290
|
-
const doSamlAuth = async (embedConfig) => {
|
|
13291
|
-
const { thoughtSpotHost } = embedConfig;
|
|
13292
|
-
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
13293
|
-
// loaded again and the same JS will execute again.
|
|
13294
|
-
const ssoRedirectUrl = embedConfig.inPopup
|
|
13295
|
-
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
13296
|
-
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
13297
|
-
// bring back the page to the same URL
|
|
13298
|
-
const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
13299
|
-
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
13300
|
-
return loggedInStatus;
|
|
13301
|
-
};
|
|
13302
|
-
const doOIDCAuth = async (embedConfig) => {
|
|
13303
|
-
const { thoughtSpotHost } = embedConfig;
|
|
13304
|
-
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
13305
|
-
// loaded again and the same JS will execute again.
|
|
13306
|
-
const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
|
|
13307
|
-
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
13308
|
-
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
13309
|
-
// bring back the page to the same URL
|
|
13310
|
-
const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
13311
|
-
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
13312
|
-
return loggedInStatus;
|
|
13313
|
-
};
|
|
13314
|
-
/**
|
|
13315
|
-
* Perform authentication on the ThoughtSpot cluster
|
|
13316
|
-
*
|
|
13317
|
-
* @param embedConfig The embed configuration
|
|
13318
|
-
*/
|
|
13319
|
-
const authenticate = async (embedConfig) => {
|
|
13320
|
-
const { authType } = embedConfig;
|
|
13321
|
-
switch (authType) {
|
|
13322
|
-
case AuthType.SSO:
|
|
13323
|
-
case AuthType.SAMLRedirect:
|
|
13324
|
-
case AuthType.SAML:
|
|
13325
|
-
return doSamlAuth(embedConfig);
|
|
13326
|
-
case AuthType.OIDC:
|
|
13327
|
-
case AuthType.OIDCRedirect:
|
|
13328
|
-
return doOIDCAuth(embedConfig);
|
|
13329
|
-
case AuthType.AuthServer:
|
|
13330
|
-
case AuthType.TrustedAuthToken:
|
|
13331
|
-
return doTokenAuth(embedConfig);
|
|
13332
|
-
case AuthType.TrustedAuthTokenCookieless:
|
|
13333
|
-
return doCookielessTokenAuth(embedConfig);
|
|
13334
|
-
case AuthType.Basic:
|
|
13335
|
-
return doBasicAuth(embedConfig);
|
|
13336
|
-
default:
|
|
13337
|
-
return Promise.resolve(true);
|
|
12969
|
+
else {
|
|
12970
|
+
dataValue = [{ value: colVal.value }];
|
|
12971
|
+
}
|
|
12972
|
+
underlyingDataPoint.push({
|
|
12973
|
+
columnId: colVal.column.id,
|
|
12974
|
+
dataValue,
|
|
12975
|
+
});
|
|
13338
12976
|
}
|
|
12977
|
+
selectedPoints.forEach((p) => {
|
|
12978
|
+
p.selectedAttributes.forEach(addPointFromColVal);
|
|
12979
|
+
});
|
|
12980
|
+
return underlyingDataPoint;
|
|
12981
|
+
}
|
|
12982
|
+
|
|
12983
|
+
var eventemitter3 = createCommonjsModule(function (module) {
|
|
12984
|
+
|
|
12985
|
+
var has = Object.prototype.hasOwnProperty
|
|
12986
|
+
, prefix = '~';
|
|
12987
|
+
|
|
12988
|
+
/**
|
|
12989
|
+
* Constructor to create a storage for our `EE` objects.
|
|
12990
|
+
* An `Events` instance is a plain object whose properties are event names.
|
|
12991
|
+
*
|
|
12992
|
+
* @constructor
|
|
12993
|
+
* @private
|
|
12994
|
+
*/
|
|
12995
|
+
function Events() {}
|
|
12996
|
+
|
|
12997
|
+
//
|
|
12998
|
+
// We try to not inherit from `Object.prototype`. In some engines creating an
|
|
12999
|
+
// instance in this way is faster than calling `Object.create(null)` directly.
|
|
13000
|
+
// If `Object.create(null)` is not supported we prefix the event names with a
|
|
13001
|
+
// character to make sure that the built-in object properties are not
|
|
13002
|
+
// overridden or used as an attack vector.
|
|
13003
|
+
//
|
|
13004
|
+
if (Object.create) {
|
|
13005
|
+
Events.prototype = Object.create(null);
|
|
13006
|
+
|
|
13007
|
+
//
|
|
13008
|
+
// This hack is needed because the `__proto__` property is still inherited in
|
|
13009
|
+
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
|
13010
|
+
//
|
|
13011
|
+
if (!new Events().__proto__) prefix = false;
|
|
13012
|
+
}
|
|
13013
|
+
|
|
13014
|
+
/**
|
|
13015
|
+
* Representation of a single event listener.
|
|
13016
|
+
*
|
|
13017
|
+
* @param {Function} fn The listener function.
|
|
13018
|
+
* @param {*} context The context to invoke the listener with.
|
|
13019
|
+
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
|
13020
|
+
* @constructor
|
|
13021
|
+
* @private
|
|
13022
|
+
*/
|
|
13023
|
+
function EE(fn, context, once) {
|
|
13024
|
+
this.fn = fn;
|
|
13025
|
+
this.context = context;
|
|
13026
|
+
this.once = once || false;
|
|
13027
|
+
}
|
|
13028
|
+
|
|
13029
|
+
/**
|
|
13030
|
+
* Add a listener for a given event.
|
|
13031
|
+
*
|
|
13032
|
+
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
13033
|
+
* @param {(String|Symbol)} event The event name.
|
|
13034
|
+
* @param {Function} fn The listener function.
|
|
13035
|
+
* @param {*} context The context to invoke the listener with.
|
|
13036
|
+
* @param {Boolean} once Specify if the listener is a one-time listener.
|
|
13037
|
+
* @returns {EventEmitter}
|
|
13038
|
+
* @private
|
|
13039
|
+
*/
|
|
13040
|
+
function addListener(emitter, event, fn, context, once) {
|
|
13041
|
+
if (typeof fn !== 'function') {
|
|
13042
|
+
throw new TypeError('The listener must be a function');
|
|
13043
|
+
}
|
|
13044
|
+
|
|
13045
|
+
var listener = new EE(fn, context || emitter, once)
|
|
13046
|
+
, evt = prefix ? prefix + event : event;
|
|
13047
|
+
|
|
13048
|
+
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
|
|
13049
|
+
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
|
|
13050
|
+
else emitter._events[evt] = [emitter._events[evt], listener];
|
|
13051
|
+
|
|
13052
|
+
return emitter;
|
|
13053
|
+
}
|
|
13054
|
+
|
|
13055
|
+
/**
|
|
13056
|
+
* Clear event by name.
|
|
13057
|
+
*
|
|
13058
|
+
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
13059
|
+
* @param {(String|Symbol)} evt The Event name.
|
|
13060
|
+
* @private
|
|
13061
|
+
*/
|
|
13062
|
+
function clearEvent(emitter, evt) {
|
|
13063
|
+
if (--emitter._eventsCount === 0) emitter._events = new Events();
|
|
13064
|
+
else delete emitter._events[evt];
|
|
13065
|
+
}
|
|
13066
|
+
|
|
13067
|
+
/**
|
|
13068
|
+
* Minimal `EventEmitter` interface that is molded against the Node.js
|
|
13069
|
+
* `EventEmitter` interface.
|
|
13070
|
+
*
|
|
13071
|
+
* @constructor
|
|
13072
|
+
* @public
|
|
13073
|
+
*/
|
|
13074
|
+
function EventEmitter() {
|
|
13075
|
+
this._events = new Events();
|
|
13076
|
+
this._eventsCount = 0;
|
|
13077
|
+
}
|
|
13078
|
+
|
|
13079
|
+
/**
|
|
13080
|
+
* Return an array listing the events for which the emitter has registered
|
|
13081
|
+
* listeners.
|
|
13082
|
+
*
|
|
13083
|
+
* @returns {Array}
|
|
13084
|
+
* @public
|
|
13085
|
+
*/
|
|
13086
|
+
EventEmitter.prototype.eventNames = function eventNames() {
|
|
13087
|
+
var names = []
|
|
13088
|
+
, events
|
|
13089
|
+
, name;
|
|
13090
|
+
|
|
13091
|
+
if (this._eventsCount === 0) return names;
|
|
13092
|
+
|
|
13093
|
+
for (name in (events = this._events)) {
|
|
13094
|
+
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
|
13095
|
+
}
|
|
13096
|
+
|
|
13097
|
+
if (Object.getOwnPropertySymbols) {
|
|
13098
|
+
return names.concat(Object.getOwnPropertySymbols(events));
|
|
13099
|
+
}
|
|
13100
|
+
|
|
13101
|
+
return names;
|
|
13102
|
+
};
|
|
13103
|
+
|
|
13104
|
+
/**
|
|
13105
|
+
* Return the listeners registered for a given event.
|
|
13106
|
+
*
|
|
13107
|
+
* @param {(String|Symbol)} event The event name.
|
|
13108
|
+
* @returns {Array} The registered listeners.
|
|
13109
|
+
* @public
|
|
13110
|
+
*/
|
|
13111
|
+
EventEmitter.prototype.listeners = function listeners(event) {
|
|
13112
|
+
var evt = prefix ? prefix + event : event
|
|
13113
|
+
, handlers = this._events[evt];
|
|
13114
|
+
|
|
13115
|
+
if (!handlers) return [];
|
|
13116
|
+
if (handlers.fn) return [handlers.fn];
|
|
13117
|
+
|
|
13118
|
+
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
|
13119
|
+
ee[i] = handlers[i].fn;
|
|
13120
|
+
}
|
|
13121
|
+
|
|
13122
|
+
return ee;
|
|
13123
|
+
};
|
|
13124
|
+
|
|
13125
|
+
/**
|
|
13126
|
+
* Return the number of listeners listening to a given event.
|
|
13127
|
+
*
|
|
13128
|
+
* @param {(String|Symbol)} event The event name.
|
|
13129
|
+
* @returns {Number} The number of listeners.
|
|
13130
|
+
* @public
|
|
13131
|
+
*/
|
|
13132
|
+
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
|
13133
|
+
var evt = prefix ? prefix + event : event
|
|
13134
|
+
, listeners = this._events[evt];
|
|
13135
|
+
|
|
13136
|
+
if (!listeners) return 0;
|
|
13137
|
+
if (listeners.fn) return 1;
|
|
13138
|
+
return listeners.length;
|
|
13139
|
+
};
|
|
13140
|
+
|
|
13141
|
+
/**
|
|
13142
|
+
* Calls each of the listeners registered for a given event.
|
|
13143
|
+
*
|
|
13144
|
+
* @param {(String|Symbol)} event The event name.
|
|
13145
|
+
* @returns {Boolean} `true` if the event had listeners, else `false`.
|
|
13146
|
+
* @public
|
|
13147
|
+
*/
|
|
13148
|
+
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
|
13149
|
+
var evt = prefix ? prefix + event : event;
|
|
13150
|
+
|
|
13151
|
+
if (!this._events[evt]) return false;
|
|
13152
|
+
|
|
13153
|
+
var listeners = this._events[evt]
|
|
13154
|
+
, len = arguments.length
|
|
13155
|
+
, args
|
|
13156
|
+
, i;
|
|
13157
|
+
|
|
13158
|
+
if (listeners.fn) {
|
|
13159
|
+
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
|
|
13160
|
+
|
|
13161
|
+
switch (len) {
|
|
13162
|
+
case 1: return listeners.fn.call(listeners.context), true;
|
|
13163
|
+
case 2: return listeners.fn.call(listeners.context, a1), true;
|
|
13164
|
+
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
|
|
13165
|
+
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
|
13166
|
+
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
|
13167
|
+
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
|
13168
|
+
}
|
|
13169
|
+
|
|
13170
|
+
for (i = 1, args = new Array(len -1); i < len; i++) {
|
|
13171
|
+
args[i - 1] = arguments[i];
|
|
13172
|
+
}
|
|
13173
|
+
|
|
13174
|
+
listeners.fn.apply(listeners.context, args);
|
|
13175
|
+
} else {
|
|
13176
|
+
var length = listeners.length
|
|
13177
|
+
, j;
|
|
13178
|
+
|
|
13179
|
+
for (i = 0; i < length; i++) {
|
|
13180
|
+
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
|
|
13181
|
+
|
|
13182
|
+
switch (len) {
|
|
13183
|
+
case 1: listeners[i].fn.call(listeners[i].context); break;
|
|
13184
|
+
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
|
|
13185
|
+
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
|
|
13186
|
+
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
|
|
13187
|
+
default:
|
|
13188
|
+
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
|
|
13189
|
+
args[j - 1] = arguments[j];
|
|
13190
|
+
}
|
|
13191
|
+
|
|
13192
|
+
listeners[i].fn.apply(listeners[i].context, args);
|
|
13193
|
+
}
|
|
13194
|
+
}
|
|
13195
|
+
}
|
|
13196
|
+
|
|
13197
|
+
return true;
|
|
13198
|
+
};
|
|
13199
|
+
|
|
13200
|
+
/**
|
|
13201
|
+
* Add a listener for a given event.
|
|
13202
|
+
*
|
|
13203
|
+
* @param {(String|Symbol)} event The event name.
|
|
13204
|
+
* @param {Function} fn The listener function.
|
|
13205
|
+
* @param {*} [context=this] The context to invoke the listener with.
|
|
13206
|
+
* @returns {EventEmitter} `this`.
|
|
13207
|
+
* @public
|
|
13208
|
+
*/
|
|
13209
|
+
EventEmitter.prototype.on = function on(event, fn, context) {
|
|
13210
|
+
return addListener(this, event, fn, context, false);
|
|
13211
|
+
};
|
|
13212
|
+
|
|
13213
|
+
/**
|
|
13214
|
+
* Add a one-time listener for a given event.
|
|
13215
|
+
*
|
|
13216
|
+
* @param {(String|Symbol)} event The event name.
|
|
13217
|
+
* @param {Function} fn The listener function.
|
|
13218
|
+
* @param {*} [context=this] The context to invoke the listener with.
|
|
13219
|
+
* @returns {EventEmitter} `this`.
|
|
13220
|
+
* @public
|
|
13221
|
+
*/
|
|
13222
|
+
EventEmitter.prototype.once = function once(event, fn, context) {
|
|
13223
|
+
return addListener(this, event, fn, context, true);
|
|
13224
|
+
};
|
|
13225
|
+
|
|
13226
|
+
/**
|
|
13227
|
+
* Remove the listeners of a given event.
|
|
13228
|
+
*
|
|
13229
|
+
* @param {(String|Symbol)} event The event name.
|
|
13230
|
+
* @param {Function} fn Only remove the listeners that match this function.
|
|
13231
|
+
* @param {*} context Only remove the listeners that have this context.
|
|
13232
|
+
* @param {Boolean} once Only remove one-time listeners.
|
|
13233
|
+
* @returns {EventEmitter} `this`.
|
|
13234
|
+
* @public
|
|
13235
|
+
*/
|
|
13236
|
+
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
|
13237
|
+
var evt = prefix ? prefix + event : event;
|
|
13238
|
+
|
|
13239
|
+
if (!this._events[evt]) return this;
|
|
13240
|
+
if (!fn) {
|
|
13241
|
+
clearEvent(this, evt);
|
|
13242
|
+
return this;
|
|
13243
|
+
}
|
|
13244
|
+
|
|
13245
|
+
var listeners = this._events[evt];
|
|
13246
|
+
|
|
13247
|
+
if (listeners.fn) {
|
|
13248
|
+
if (
|
|
13249
|
+
listeners.fn === fn &&
|
|
13250
|
+
(!once || listeners.once) &&
|
|
13251
|
+
(!context || listeners.context === context)
|
|
13252
|
+
) {
|
|
13253
|
+
clearEvent(this, evt);
|
|
13254
|
+
}
|
|
13255
|
+
} else {
|
|
13256
|
+
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
|
13257
|
+
if (
|
|
13258
|
+
listeners[i].fn !== fn ||
|
|
13259
|
+
(once && !listeners[i].once) ||
|
|
13260
|
+
(context && listeners[i].context !== context)
|
|
13261
|
+
) {
|
|
13262
|
+
events.push(listeners[i]);
|
|
13263
|
+
}
|
|
13264
|
+
}
|
|
13265
|
+
|
|
13266
|
+
//
|
|
13267
|
+
// Reset the array, or remove it completely if we have no more listeners.
|
|
13268
|
+
//
|
|
13269
|
+
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
|
|
13270
|
+
else clearEvent(this, evt);
|
|
13271
|
+
}
|
|
13272
|
+
|
|
13273
|
+
return this;
|
|
13274
|
+
};
|
|
13275
|
+
|
|
13276
|
+
/**
|
|
13277
|
+
* Remove all listeners, or those of the specified event.
|
|
13278
|
+
*
|
|
13279
|
+
* @param {(String|Symbol)} [event] The event name.
|
|
13280
|
+
* @returns {EventEmitter} `this`.
|
|
13281
|
+
* @public
|
|
13282
|
+
*/
|
|
13283
|
+
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
|
13284
|
+
var evt;
|
|
13285
|
+
|
|
13286
|
+
if (event) {
|
|
13287
|
+
evt = prefix ? prefix + event : event;
|
|
13288
|
+
if (this._events[evt]) clearEvent(this, evt);
|
|
13289
|
+
} else {
|
|
13290
|
+
this._events = new Events();
|
|
13291
|
+
this._eventsCount = 0;
|
|
13292
|
+
}
|
|
13293
|
+
|
|
13294
|
+
return this;
|
|
13295
|
+
};
|
|
13296
|
+
|
|
13297
|
+
//
|
|
13298
|
+
// Alias methods names because people roll like that.
|
|
13299
|
+
//
|
|
13300
|
+
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
13301
|
+
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
|
|
13302
|
+
|
|
13303
|
+
//
|
|
13304
|
+
// Expose the prefix.
|
|
13305
|
+
//
|
|
13306
|
+
EventEmitter.prefixed = prefix;
|
|
13307
|
+
|
|
13308
|
+
//
|
|
13309
|
+
// Allow `EventEmitter` to be imported as module namespace.
|
|
13310
|
+
//
|
|
13311
|
+
EventEmitter.EventEmitter = EventEmitter;
|
|
13312
|
+
|
|
13313
|
+
//
|
|
13314
|
+
// Expose the module.
|
|
13315
|
+
//
|
|
13316
|
+
{
|
|
13317
|
+
module.exports = EventEmitter;
|
|
13318
|
+
}
|
|
13319
|
+
});
|
|
13320
|
+
|
|
13321
|
+
/** Used as references for various `Number` constants. */
|
|
13322
|
+
var INFINITY = 1 / 0;
|
|
13323
|
+
|
|
13324
|
+
/**
|
|
13325
|
+
* Creates a set object of `values`.
|
|
13326
|
+
*
|
|
13327
|
+
* @private
|
|
13328
|
+
* @param {Array} values The values to add to the set.
|
|
13329
|
+
* @returns {Object} Returns the new set.
|
|
13330
|
+
*/
|
|
13331
|
+
var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? noop_1 : function(values) {
|
|
13332
|
+
return new _Set(values);
|
|
13339
13333
|
};
|
|
13340
13334
|
|
|
13341
13335
|
/* eslint-disable camelcase */
|
|
@@ -13551,8 +13545,6 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
|
|
|
13551
13545
|
});
|
|
13552
13546
|
}
|
|
13553
13547
|
|
|
13554
|
-
var name="@thoughtspot/visual-embed-sdk";var version="1.28.0-alpha.5";var description="ThoughtSpot Embed SDK";var module="lib/src/index.js";var main="dist/tsembed.js";var types="lib/src/index.d.ts";var files=["dist/**","lib/**","src/**","cjs/**"];var exports$1={".":{"import":"./lib/src/index.js",require:"./cjs/src/index.js",types:"./lib/src/index.d.ts"},"./react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"},"./lib/src/react":{"import":"./lib/src/react/all-types-export.js",require:"./cjs/src/react/all-types-export.js",types:"./lib/src/react/all-types-export.d.ts"}};var typesVersions={"*":{react:["./lib/src/react/all-types-export.d.ts"]}};var scripts={lint:"eslint 'src/**'","lint:fix":"eslint 'src/**/*.*' --fix",tsc:"tsc -p . --incremental false; tsc -p . --incremental false --module commonjs --outDir cjs",start:"gatsby develop","build:gatsby":"npm run clean:gatsby && gatsby build --prefix-paths","build:gatsby:noprefix":"npm run clean:gatsby && gatsby build","serve:gatsby":"gatsby serve","clean:gatsby":"gatsby clean","build-and-publish":"npm run build:gatsby && npm run publish","bundle-dts-file":"dts-bundle --name @thoughtspot/visual-embed-sdk --out visual-embed-sdk.d.ts --main lib/src/index.d.ts","bundle-dts":"dts-bundle --name ../../dist/visual-embed-sdk --main lib/src/index.d.ts --outputAsModuleFolder=true","bundle-dts-react":"dts-bundle --name ../../../dist/visual-embed-sdk-react --main lib/src/react/index.d.ts --outputAsModuleFolder=true","bundle-dts-react-full":"dts-bundle --name ../../../dist/visual-embed-sdk-react-full --main lib/src/react/all-types-export.d.ts --outputAsModuleFolder=true",build:"rollup -c",watch:"rollup -cw","docs-cmd":"node scripts/gatsby-commands.js",docgen:"typedoc --tsconfig tsconfig.json --theme typedoc-theme","test-sdk":"jest -c jest.config.sdk.js --runInBand","test-docs":"jest -c jest.config.docs.js",test:"npm run test-sdk && npm run test-docs",posttest:"cat ./coverage/sdk/lcov.info | coveralls","is-publish-allowed":"node scripts/is-publish-allowed.js",prepublishOnly:"npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build","check-size":"npm run build && size-limit","publish-dev":"npm publish --tag dev","publish-prod":"npm publish --tag latest"};var peerDependencies={react:"> 16.8.0","react-dom":"> 16.8.0"};var dependencies={algoliasearch:"^4.10.5",classnames:"^2.3.1",dompurify:"^2.3.4","eslint-plugin-comment-length":"^0.9.2","eslint-plugin-jsdoc":"^46.9.0",eventemitter3:"^4.0.7","gatsby-plugin-vercel":"^1.0.3","html-react-parser":"^1.4.12",lodash:"^4.17.21","mixpanel-browser":"^2.45.0","ts-deepmerge":"^6.0.2",tslib:"^2.5.3","use-deep-compare-effect":"^1.8.1"};var devDependencies={"@mdx-js/mdx":"^1.6.22","@mdx-js/react":"^1.6.22","@react-icons/all-files":"^4.1.0","@rollup/plugin-commonjs":"^18.0.0","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^11.2.1","@rollup/plugin-replace":"^5.0.2","@size-limit/preset-big-lib":"^8.2.6","@testing-library/dom":"^7.31.0","@testing-library/jest-dom":"^5.14.1","@testing-library/react":"^11.2.7","@testing-library/user-event":"^13.1.8","@types/jest":"^22.2.3","@types/mixpanel-browser":"^2.35.6","@types/react-test-renderer":"^17.0.1","@typescript-eslint/eslint-plugin":"^4.6.0","@typescript-eslint/parser":"^4.6.0",asciidoctor:"^2.2.1","babel-jest":"^26.6.3","babel-preset-gatsby":"^1.10.0","command-line-args":"^5.1.1",coveralls:"^3.1.0","current-git-branch":"^1.1.0","dts-bundle":"^0.7.3",eslint:"^7.12.1","eslint-config-airbnb-base":"^14.2.0","eslint-config-prettier":"^6.15.0","eslint-import-resolver-typescript":"^2.3.0","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.1.4","eslint-plugin-react-hooks":"^4.2.0","fs-extra":"^10.0.0",gatsby:"3.13.1","gatsby-plugin-algolia":"^0.22.2","gatsby-plugin-catch-links":"^3.1.0","gatsby-plugin-env-variables":"^2.1.0","gatsby-plugin-intl":"^0.3.3","gatsby-plugin-manifest":"^3.2.0","gatsby-plugin-output":"^0.1.3","gatsby-plugin-sass":"6.7.0","gatsby-plugin-sitemap":"^4.10.0","gatsby-source-filesystem":"3.1.0","gatsby-transformer-asciidoc":"2.1.0","gatsby-transformer-rehype":"2.0.0","gh-pages":"^3.1.0","highlight.js":"^10.6.0","html-to-text":"^8.0.0","identity-obj-proxy":"^3.0.0","istanbul-merge":"^1.1.1",jest:"^26.6.3","jest-fetch-mock":"^3.0.3",jsdom:"^17.0.0","node-sass":"^8.0.0",prettier:"2.1.2",react:"^16.14.0","react-dom":"^16.14.0","react-resizable":"^1.11.0","react-resize-detector":"^6.6.0","react-test-renderer":"^17.0.2","react-use-flexsearch":"^0.1.1",rollup:"2.30.0","rollup-plugin-typescript2":"0.27.3","ts-jest":"^26.5.5","ts-loader":"8.0.4",typedoc:"0.21.6","typedoc-plugin-toc-group":"thoughtspot/typedoc-plugin-toc-group",typescript:"^4.9.4","url-search-params-polyfill":"^8.1.0",util:"^0.12.4"};var author="ThoughtSpot";var email="support@thoughtspot.com";var license="ThoughtSpot Development Tools End User License Agreement";var directories={lib:"lib"};var repository={type:"git",url:"git+https://github.com/thoughtspot/visual-embed-sdk.git"};var publishConfig={registry:"https://registry.npmjs.org"};var keywords=["thoughtspot","everywhere","embed","sdk","analytics"];var bugs={url:"https://github.com/thoughtspot/visual-embed-sdk/issues"};var homepage="https://github.com/thoughtspot/visual-embed-sdk#readme";var globals={window:{}};var pkgInfo = {name:name,version:version,description:description,module:module,main:main,types:types,files:files,exports:exports$1,typesVersions:typesVersions,"size-limit":[{path:"dist/tsembed.js",limit:"44 kB"}],scripts:scripts,peerDependencies:peerDependencies,dependencies:dependencies,devDependencies:devDependencies,author:author,email:email,license:license,directories:directories,repository:repository,publishConfig:publishConfig,keywords:keywords,bugs:bugs,homepage:homepage,globals:globals};
|
|
13555
|
-
|
|
13556
13548
|
/**
|
|
13557
13549
|
* Copyright (c) 2022
|
|
13558
13550
|
*
|
|
@@ -14785,7 +14777,7 @@ mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!]
|
|
|
14785
14777
|
}
|
|
14786
14778
|
getEmbedParams() {
|
|
14787
14779
|
var _a;
|
|
14788
|
-
const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL = true, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
|
|
14780
|
+
const { hideResults, expandAllDataSource, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL = true, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, } = this.viewConfig;
|
|
14789
14781
|
const queryParams = this.getBaseQueryParams();
|
|
14790
14782
|
queryParams[Param.HideActions] = [
|
|
14791
14783
|
...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
|