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